1 // Copyright 2000-2005 the Contributors, as shown in the revision logs.
2 // Licensed under the Apache Public Source License 2.0 ("the License").
3 // You may not use this file except in compliance with the License.
7 import org.ibex.util.*;
15 public String name = null;
16 public String cdata = null;
17 public int numattrs = 0;
18 public String[] attrs = null;
19 public String uri = null;
20 private int delta = 0;
23 public Node(Node n) { copyFrom(n); }
24 public final void clear() { name = null; cdata = null; numattrs = 0; delta = 0; uri = null; }
25 public final void copyFrom(Node n) {
26 name=n.name; cdata=n.cdata; numattrs=n.numattrs; delta=n.delta; uri=n.uri;
27 if (n.attrs == null) { attrs = null; return; }
28 attrs = new String[n.attrs.length]; System.arraycopy(n.attrs, 0, attrs, 0, attrs.length); }
29 public final String attr(String key) {
30 for(int i=0; i<numattrs; i++) if (key.equals(attrs[i*2])) return attrs[i*2+1]; return null; }
32 public static abstract class Stream {
33 public static final Stream NULL = new Stream() { public boolean _read(Node n) { return false; } };
34 public static interface Functor { public Node.Stream wrap(Node.Stream in); }
35 public static class ConstantFunctor implements Functor {
36 private final Node.Stream stream;
37 public ConstantFunctor(Node.Stream stream) { this.stream = stream; }
38 public Node.Stream wrap(Node.Stream in) { return stream; }
40 public static abstract class Filter extends Stream {
43 public Filter(Stream upstream) { this.upstream = upstream; }
44 public boolean upstreamRead(Node n) { upstream = upstream.simplify(); return upstream.read(n); }
45 public void wrapUpstream(Functor f) { upstream = f.wrap(upstream); }
46 public Filter graft(Functor f, Node n) {
47 upstream = new Graft((upstream instanceof Peekable) ? (Peekable)upstream : new Peekable(upstream), n, f);
52 public Stream simplify() { return this; }
53 protected abstract boolean _read(Node n);
54 public final boolean read(Node n) { n.clear(); if (!_read(n)) { n.clear(); return false; } return true; }
56 public static class Peekable extends Filter {
57 public Peekable(Stream s) { super(s); }
58 private Node pending = null;
59 public boolean peek(Node n) {
60 if (pending == null) {
62 if (!upstreamRead(n2)) return false;
68 public boolean _read(Node n) {
69 if (pending != null) { n.copyFrom(pending); pending = null; return true; }
70 return upstreamRead(n);
74 private static class Graft extends Filter {
75 private Stream inner2;
79 boolean simple = false;
80 private Node pending = new Node();
81 public Graft(final Peekable a, final Node n, final Functor f) {
83 upstream = inner2 = new Stream() {
84 public boolean _read(Node n) {
85 if (!Graft.this.a.peek(n)) return false;
86 if (net + n.delta <= 0) return false;
92 if (__read(pending)) pending.delta = n.delta;
95 public boolean _read(Node n) {
96 if (pending != null) { n.copyFrom(pending); pending = null; return true; }
97 boolean ret = __read(n);
98 if (ret) total += n.delta;
101 public boolean __read(Node n) {
102 if (simple) return a.read(n);
103 if (upstreamRead(n)) return true;
104 while(inner2.read(n));
105 if (!a.read(n)) return false;
106 n.delta += net - total;
112 public static class Join extends Node.Stream {
113 final Node.Stream s1, s2;
114 boolean s1Done = false;
115 public Join(Node.Stream s1, Node.Stream s2) { this.s1=s1; this.s2=s2; }
116 protected boolean _read(Node n) {
117 if (!s1Done) return s2._read(n);
118 boolean ret = s1._read(n);
119 if (ret) return true;
125 public static class FromXML extends Node.Stream {
126 private final XML.Stream xml;
127 private XML.Elem parent = null;
129 private int currentdelta = 0;
130 public FromXML(Reader r) { this.xml = new XML.Stream(r); }
131 protected boolean _read(Node n) { try {
132 Object ret = xml.next();
133 if (ret == null) return false;
134 if (ret instanceof XML.Text) {
135 n.cdata = ((XML.Text)ret).t;
136 n.delta = xml.getDepth() - currentdelta;
137 currentdelta = xml.getDepth();
140 XML.Elem e = (XML.Elem)ret;
141 n.name = e.getLocalName();
143 n.numattrs = e.getAttributes().attrSize();
144 n.delta = xml.getDepth() - currentdelta;
145 currentdelta = xml.getDepth();
146 if (n.attrs == null || n.attrs.length < n.numattrs*2) n.attrs = new String[n.numattrs*4];
147 for(int i=0; i<n.numattrs; i++) {
148 n.attrs[i*2] = e.getAttributes().getKey(i);
149 n.attrs[i*2+1] = e.getAttributes().getVal(i);
152 } catch (Exception e) { throw new RuntimeException(e); } }
155 public void toXML(Writer writer) throws IOException {
157 do { if (!read(n)) n = null; } while (n!=null && n.cdata != null);
160 private Node toXML(Writer w, Node n) throws IOException {
161 final String name = n.name;
162 if (n.cdata != null) {
164 if (!read(n)) n = null;
168 for(int i=0; i < n.numattrs * 2; i+=2) {
172 w.write(n.attrs[i+1]);
175 if (!read(n)) n = null;
176 if (n == null || n.delta <= 0) {
180 while(n != null && n.delta > 0) { n = toXML(w, n); }
186 if (n != null) n.delta++;