Nodes.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. // Copyright (c) 2003, 2013 Per M.A. Bothner.
  2. // This is free software; for terms and warranty disclaimer see ./COPYING.
  3. package gnu.kawa.xml;
  4. import gnu.mapping.Values;
  5. import gnu.lists.*;
  6. import gnu.xml.*;
  7. /* #ifdef use:org.w3c.dom.Node */
  8. import org.w3c.dom.*;
  9. /* #endif */
  10. /** Manages a sequence of node references.
  11. */
  12. public class Nodes extends Values.FromList<SeqPosition>
  13. implements PositionConsumer,
  14. /* #ifdef use:org.w3c.dom.Node */
  15. org.w3c.dom.NodeList,
  16. /* #endif */
  17. Consumer
  18. {
  19. protected NodeVector vector;
  20. private Nodes(NodeVector nvector) {
  21. super(nvector);
  22. this.vector = nvector;
  23. }
  24. public Nodes() {
  25. this(new NodeVector());
  26. }
  27. public Consumer append(char c) {
  28. maybeStartTextNode();
  29. curFragment.append(c);
  30. return this;
  31. }
  32. public Consumer append(CharSequence csq) {
  33. maybeStartTextNode();
  34. curFragment.append(csq);
  35. return this;
  36. }
  37. public boolean ignoring() {
  38. return false;
  39. }
  40. int nesting = 0;
  41. boolean inAttribute;
  42. NodeTree curNode;
  43. XMLFilter curFragment;
  44. public void writePosition (AbstractSequence seq, int ipos) {
  45. vector.writePosition(seq, ipos);
  46. }
  47. public void writePosition(SeqPosition position) {
  48. vector.writePosition(position);
  49. }
  50. public void writeObject(Object v) {
  51. if (curFragment != null) {
  52. if (nesting == 0
  53. && (v instanceof SeqPosition || v instanceof TreeList))
  54. finishFragment();
  55. else {
  56. curFragment.writeObject(v);
  57. return;
  58. }
  59. }
  60. if (v instanceof SeqPosition) {
  61. writePosition((SeqPosition) v);
  62. return;
  63. }
  64. if (v instanceof TreeList) {
  65. TreeList tlist = (TreeList) v;
  66. writePosition(tlist, 0);
  67. return;
  68. }
  69. handleNonNode();
  70. curFragment.writeObject(v);
  71. return;
  72. }
  73. void maybeStartTextNode ()
  74. {
  75. if (curFragment == null)
  76. {
  77. throw new IllegalArgumentException("non-node where node required");
  78. }
  79. }
  80. void handleNonNode ()
  81. {
  82. if (curFragment == null)
  83. {
  84. throw new ClassCastException("atomic value where node is required");
  85. }
  86. }
  87. public void writeFloat (float v)
  88. {
  89. handleNonNode();
  90. curFragment.writeFloat(v);
  91. }
  92. public void writeDouble (double v)
  93. {
  94. handleNonNode();
  95. curFragment.writeDouble(v);
  96. }
  97. public void writeLong(long v)
  98. {
  99. handleNonNode();
  100. curFragment.writeLong(v);
  101. }
  102. public void writeInt(int v)
  103. {
  104. handleNonNode();
  105. curFragment.writeInt(v);
  106. }
  107. public void writeBoolean (boolean v)
  108. {
  109. handleNonNode();
  110. curFragment.writeBoolean(v);
  111. }
  112. public void write (int v)
  113. {
  114. maybeStartTextNode();
  115. curFragment.write(v);
  116. }
  117. public Consumer append (CharSequence csq, int start, int end) {
  118. maybeStartTextNode();
  119. curFragment.append(csq, start, end);
  120. return this;
  121. }
  122. public void write(char[] buf, int off, int len)
  123. {
  124. maybeStartTextNode();
  125. curFragment.write(buf, off, len);
  126. }
  127. public void write(CharSequence str, int start, int length)
  128. {
  129. maybeStartTextNode();
  130. curFragment.write(str, start, length);
  131. }
  132. public void write (String str)
  133. {
  134. maybeStartTextNode();
  135. curFragment.write(str);
  136. }
  137. private void maybeStartNonTextNode ()
  138. {
  139. if (curFragment != null && nesting == 0)
  140. finishFragment();
  141. if (curFragment == null)
  142. startFragment();
  143. nesting++;
  144. }
  145. private void maybeEndNonTextNode ()
  146. {
  147. if (--nesting == 0)
  148. finishFragment();
  149. }
  150. public void startElement (Object type)
  151. {
  152. maybeStartNonTextNode();
  153. curFragment.startElement(type);
  154. }
  155. public void endElement ()
  156. {
  157. curFragment.endElement();
  158. maybeEndNonTextNode();
  159. }
  160. public void startAttribute(Object attrType)
  161. {
  162. maybeStartNonTextNode();
  163. curFragment.startAttribute(attrType);
  164. inAttribute = true;
  165. }
  166. public void endAttribute()
  167. {
  168. if (! inAttribute)
  169. return;
  170. inAttribute = false;
  171. curFragment.endAttribute();
  172. maybeEndNonTextNode();
  173. }
  174. public void writeComment(char[] chars, int offset, int length)
  175. {
  176. maybeStartNonTextNode();
  177. curFragment.writeComment(chars, offset, length);
  178. maybeEndNonTextNode();
  179. }
  180. public void writeCDATA(char[] chars, int offset, int length)
  181. {
  182. maybeStartNonTextNode();
  183. curFragment.writeCDATA(chars, offset, length);
  184. }
  185. public void writeProcessingInstruction(String target, char[] content,
  186. int offset, int length)
  187. {
  188. maybeStartNonTextNode();
  189. curFragment.writeProcessingInstruction(target, content, offset, length);
  190. maybeEndNonTextNode();
  191. }
  192. public void startDocument()
  193. {
  194. maybeStartNonTextNode();
  195. curFragment.startDocument();
  196. }
  197. public void endDocument()
  198. {
  199. curFragment.endDocument();
  200. maybeEndNonTextNode();
  201. }
  202. public void beginEntity(Object base)
  203. {
  204. maybeStartNonTextNode();
  205. curFragment.beginEntity(base);
  206. }
  207. public void endEntity()
  208. {
  209. curFragment.endEntity();
  210. maybeEndNonTextNode();
  211. }
  212. void startFragment ()
  213. {
  214. curNode = new NodeTree();
  215. curFragment = new XMLFilter(curNode);
  216. writePosition(curNode, 0);
  217. }
  218. void finishFragment ()
  219. {
  220. curNode = null;
  221. curFragment = null;
  222. }
  223. /*
  224. public int size()
  225. {
  226. return count;
  227. }
  228. */
  229. public int getLength()
  230. {
  231. return size();
  232. }
  233. /* #ifdef use:org.w3c.dom.Node */
  234. public Node item(int index)
  235. {
  236. if (index >= size())
  237. return null;
  238. else
  239. return (Node) get(index);
  240. }
  241. /* #endif */
  242. /** Optimization of {@code ((SeqPosition) get(index)).sequence}.
  243. * However returns null instead of throwing IndexOutOfBoundsException
  244. * if {@code index >= count}. */
  245. public AbstractSequence getSeq(int index) {
  246. if (index >= vector.size())
  247. return null;
  248. return vector.getSeq(index);
  249. }
  250. /** Optimization of ((SeqPosition) get(index)). ipos. */
  251. public int getPos(int index) {
  252. return vector.getPos(index);
  253. }
  254. public void consumePosRange (int iposStart, int iposEnd, Consumer out) {
  255. vector.consumePosRange(iposStart, iposEnd, out);
  256. }
  257. public static class NodeVector
  258. extends SimpleVector<SeqPosition>
  259. implements PositionConsumer {
  260. Object[] odata;
  261. int[] idata;
  262. int getLastIndex() { return getGapStart() - 1; }
  263. public int getBufferLength() {
  264. return odata == null ? 0 : odata.length;
  265. }
  266. public void copyBuffer(int length) {
  267. checkCanWrite();
  268. int oldLength = odata == null ? 0 : odata.length;
  269. if (length == -1)
  270. length = oldLength;
  271. if (oldLength != length) {
  272. if (oldLength > length)
  273. oldLength = length;
  274. Object[] otmp = new Object[length];
  275. int[] itmp = new int[length];
  276. if (oldLength != 0) {
  277. System.arraycopy(odata, 0, otmp, 0, oldLength);
  278. System.arraycopy(idata, 0, itmp, 0, oldLength);
  279. }
  280. odata = otmp;
  281. idata = itmp;
  282. }
  283. }
  284. protected Object getBuffer() { throw new Error(); }
  285. protected void setBuffer(Object buffer) { throw new Error(); }
  286. public SeqPosition getRaw(int index) {
  287. Object obj = odata[index];
  288. if (obj instanceof SeqPosition)
  289. return (SeqPosition) obj;
  290. return makeSeqPos((AbstractSequence) obj, idata[index]);
  291. }
  292. public AbstractSequence getSeq(int index) {
  293. return getSeqRaw(effectiveIndex(index));
  294. }
  295. public AbstractSequence getSeqRaw(int index) {
  296. Object obj = odata[index];
  297. if (obj instanceof SeqPosition)
  298. return ((SeqPosition) obj).sequence;
  299. return (AbstractSequence) obj;
  300. }
  301. public int getPos(int index) {
  302. return getPosRaw(effectiveIndex(index));
  303. }
  304. public int getPosRaw(int index) {
  305. Object obj = odata[index];
  306. if (obj instanceof SeqPosition)
  307. return ((SeqPosition) obj).ipos;
  308. return idata[index];
  309. }
  310. protected static SeqPosition makeSeqPos(AbstractSequence seq, int ipos) {
  311. if (seq instanceof NodeTree)
  312. return KNode.make((NodeTree) seq, ipos);
  313. else
  314. return new SeqPosition(seq, ipos);
  315. }
  316. public void setRaw(int index, SeqPosition value) {
  317. checkCanWrite();
  318. odata[index] = value;
  319. idata[index] = 0;
  320. }
  321. protected void setBuffer(int index, AbstractSequence seq, int ipos) {
  322. checkCanWrite();
  323. odata[index] = seq;
  324. idata[index] = ipos;
  325. }
  326. protected void clearBuffer(int start, int count) {
  327. checkCanWrite();
  328. Object[] d = odata;
  329. while (--count >= 0)
  330. d[start++] = null;
  331. }
  332. @Override
  333. protected NodeVector newInstance(int newLength) {
  334. NodeVector nvec = new NodeVector();
  335. if (newLength < 0) {
  336. nvec.odata = this.odata;
  337. nvec.idata = this.idata;
  338. } else {
  339. nvec.odata = new Object[newLength];
  340. nvec.idata = new int[newLength];
  341. }
  342. return nvec;
  343. }
  344. public void writePosition(SeqPosition seq) {
  345. add(seq);
  346. }
  347. public void writePosition(AbstractSequence seq, int ipos) {
  348. int sz = size();
  349. add((SeqPosition) null);
  350. odata[sz] = seq;
  351. idata[sz] = ipos;
  352. }
  353. public void shift(int srcStart, int dstStart, int count) {
  354. checkCanWrite();
  355. System.arraycopy(odata, srcStart, odata, dstStart, count);
  356. System.arraycopy(idata, srcStart, idata, dstStart, count);
  357. }
  358. public void consumePosRange (int iposStart, int iposEnd, Consumer out) {
  359. if (out.ignoring())
  360. return;
  361. int i = nextIndex(iposStart);
  362. int end = nextIndex(iposEnd);
  363. int size = size();
  364. if (end > size)
  365. end = size;
  366. for (; i < end; i++) {
  367. int ii = effectiveIndex(i);
  368. if (out instanceof PositionConsumer) {
  369. PositionConsumer pout = (PositionConsumer) out;
  370. Object obj = odata[ii];
  371. if (obj instanceof SeqPosition)
  372. pout.writePosition((SeqPosition) obj);
  373. else
  374. pout.writePosition((AbstractSequence) obj, idata[ii]);
  375. }
  376. else
  377. out.writeObject(getRaw(ii));
  378. }
  379. }
  380. }
  381. public static KNode root (NodeTree seq, int ipos)
  382. {
  383. int root;
  384. if (seq.gapStart > TreeList.BEGIN_ENTITY_SIZE
  385. && seq.data[0] == TreeList.BEGIN_ENTITY)
  386. root = TreeList.BEGIN_ENTITY_SIZE << 1;
  387. else
  388. root = 0;
  389. return KNode.make(seq, root);
  390. }
  391. }