KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xquark > xml > xqueryevaluator > eval > SAX2TypedDOM


1 /*
2  * This file belongs to the XQuark distribution.
3  * Copyright (C) 2003 XQuark Group.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307.
18  * You can also get it at http://www.gnu.org/licenses/lgpl.html
19  *
20  * For more information on this software, see http://www.xquark.org.
21  */

22
23 package org.xquark.xml.xqueryevaluator.eval;
24
25 import java.util.*;
26
27 import org.w3c.dom.Attr JavaDoc;
28 import org.w3c.dom.Comment JavaDoc;
29 import org.xml.sax.Attributes JavaDoc;
30 import org.xml.sax.SAXException JavaDoc;
31 import org.xml.sax.ext.LexicalHandler JavaDoc;
32 import org.xml.sax.helpers.DefaultHandler JavaDoc;
33 import org.xquark.mediator.DOMUtils.BufferTuple;
34 import org.xquark.mediator.DOMUtils.EvaluationVisitor;
35 import org.xquark.mediator.DOMUtils.Tuple;
36 import org.xquark.mediator.plan.DynamicContext;
37 import org.xquark.mediator.runtime.MediatorException;
38 import org.xquark.schema.Type;
39 import org.xquark.schema.validation.ElementPSVInfoset;
40 import org.xquark.schema.validation.PSVInfoset;
41 import org.xquark.schema.validation.SchemaValidationContext;
42 import org.xquark.util.NamespaceContextStack;
43 import org.xquark.util.SAXConstants;
44 import org.xquark.xpath.Axis;
45 import org.xquark.xpath.NodeKind;
46 import org.xquark.xpath.datamodel.*;
47 import org.xquark.xquery.parser.*;
48 import org.xquark.xquery.parser.primitivefunctions.fnfunctions.FunctionDOC;
49 import org.xquark.xquery.parser.util.Constants;
50
51 /**
52  *
53  */

54 public class SAX2TypedDOM extends DefaultHandler JavaDoc implements LexicalHandler JavaDoc {
55     // **********************************************************************
56
// * VERSIONING
57
// **********************************************************************
58

59     private static final String JavaDoc RCSRevision = "$Revision: 1.11 $";
60     private static final String JavaDoc RCSName = "$Name: $";
61
62     private SchemaValidationContext svc = null;
63     private BufferTuple buffer = null;
64     private DynamicContext context = null;
65     private XQueryExpression whereClause = null;
66     private ArrayList computedVars = new ArrayList();
67     private EvaluationVisitor evaluator = null;
68     private List rootFilters = new ArrayList();
69     private NamespaceContextStack nsStack = null;
70
71     private ArrayList contexts = new ArrayList(32);
72     private int level = 0;
73     private List bindings = new ArrayList();
74
75     private TypedDocumentImpl doc = new TypedDocumentImpl();
76     private TypedNode currentNode = null;
77     private HashSet usedURI = new HashSet();
78     private HashSet declaredURI = new HashSet();
79     private StringBuffer JavaDoc charsRead = new StringBuffer JavaDoc();
80
81     public SAX2TypedDOM(FLWRExpression flwr, BufferTuple buffer, DynamicContext context, ArrayList paths, SchemaValidationContext svc) throws MediatorException {
82         this.buffer = buffer;
83         this.context = context;
84         this.svc = svc;
85         this.nsStack = flwr.getParentModule().getDeclarations();
86         this.evaluator = new EvaluationVisitor(svc.getSchemaManager());
87         this.whereClause = flwr.getWhereClause();
88         List variables = flwr.getVariables();
89         for (int i = 0; i < variables.size(); i++) {
90             Variable v = (Variable) variables.get(i);
91             List steps = v.getExpression().getSteps();
92             XQueryExpression rootExpr;
93             List prefix = null;
94             if (steps == null) {
95                 rootExpr = v.getExpression();
96             } else {
97                 rootExpr = ((Step) steps.get(0)).getExpression();
98             }
99             if (rootExpr instanceof FunctionDOC) {
100                 if (v.getBindingType() == Constants.FOR_BINDINGTYPE) {
101                     XPathExpr[] pathExprs = buildXPath(steps);
102                     for (int k = 0; k < pathExprs.length; k++) {
103                         VariableFilter rootFilter = new VariableFilter(v.toString(), pathExprs[k]);
104                         rootFilters.add(rootFilter);
105                     }
106                 } else {
107                     VariableFilter rootFilter = new VariableFilter("", new XPathExpr());
108                     rootFilters.add(rootFilter);
109                     int index = buffer.getPathIndex(v.toString());
110                     if (index != -1) {
111                         XPathExpr[] pathExprs = buildXPath(steps);
112                         for (int k = 0; k < pathExprs.length; k++) {
113                             rootFilter.addSubFilter(index, pathExprs[k]);
114                         }
115                     }
116                     prefix = steps;
117                 }
118                 for (int j = 0; j < paths.size(); j++) {
119                     XQueryExpression expr = (XQueryExpression) paths.get(j);
120                     // Remove the variable from paths list: it can be a Variable or a LocExpr of length 1
121
if (expr instanceof LocatedExpression && expr.getSteps().size() > 1) {
122                         int index = buffer.getPathIndex(((LocatedExpression) expr).toString());
123                         XPathExpr[] pathExprs = buildXPath(expr.getSteps(), prefix);
124                         for (int k = 0; k < pathExprs.length; k++) {
125                             for (int l = 0; l < rootFilters.size(); l++) {
126                                 ((VariableFilter) rootFilters.get(l)).addSubFilter(index, pathExprs[k]);
127                             }
128                         }
129                     }
130                 }
131             } else if (steps == null) {
132                 computedVars.add(v);
133             } else {
134                 // TODO: What do we do here??
135
throw new RuntimeException JavaDoc("TODO");
136             }
137         }
138     }
139
140     private XPathExpr[] buildXPath(List steps, List prefix) throws MediatorException {
141         XPathExpr[] paths = { new XPathExpr()};
142         if (prefix != null) {
143             for (int i = 1; i < prefix.size(); i++) {
144                 paths = addStep(paths, (Step) prefix.get(i));
145             }
146         }
147         if (steps != null) {
148             for (int i = 1; i < steps.size(); i++) {
149                 paths = addStep(paths, (Step) steps.get(i));
150             }
151         }
152         for (int i = 0; i < paths.length; i++) {
153             paths[i].removeLastSelfNodeStep();
154         }
155         return paths;
156     }
157
158     private XPathExpr[] buildXPath(List steps) throws MediatorException {
159         return buildXPath(steps, null);
160     }
161
162     private XPathExpr[] addStep(XPathExpr[] paths, Step step) throws MediatorException {
163         QName stepName = null;
164         boolean isSelf = false;
165         boolean isAnyLevel = false;
166         XQueryExpression stepExpr = step.getExpression();
167         switch (step.getAxis()) {
168             case Axis.DESCENDANT_OR_SELF :
169                 isAnyLevel = true;
170                 // pass through
171
case Axis.SELF :
172                 isSelf = true;
173                 // pass through
174
case Axis.CHILD :
175                 if (stepExpr instanceof QName) {
176                     stepName = (QName) stepExpr;
177                     for (int i = 0; i < paths.length; i++) {
178                         XPathExpr pathExpr = paths[i];
179                         pathExpr.addElementStep(stepName.getNameSpace(), stepName.getLocalName(), isAnyLevel, isSelf);
180                     }
181                 } else if (stepExpr instanceof NodeTest) {
182                     switch (((NodeTest) stepExpr).getKind()) {
183                         case NodeKind.NODE :
184                             for (int i = 0; i < paths.length; i++) {
185                                 XPathExpr pathExpr = paths[i];
186                                 pathExpr.addNodeStep(isAnyLevel, isSelf);
187                             }
188                             break;
189                         case NodeKind.TEXT :
190                             for (int i = 0; i < paths.length; i++) {
191                                 XPathExpr pathExpr = paths[i];
192                                 pathExpr.addTextStep(isAnyLevel, isSelf);
193                             }
194                             break;
195                         default :
196                             throw new MediatorException("Unsupported XPath expression");
197                     }
198                 } else {
199                     throw new MediatorException("Unsupported XPath expression");
200                 }
201                 break;
202             case Axis.ATTRIBUTE :
203                 stepName = (QName) step.getExpression();
204                 for (int i = 0; i < paths.length; i++) {
205                     XPathExpr pathExpr = paths[i];
206                     pathExpr.addAttributeStep(stepName.getNameSpace(), stepName.getLocalName(), isAnyLevel);
207                 }
208                 break;
209             case Axis.NONE :
210                 if (stepExpr instanceof ListOpUNIONExpression) {
211                     ArrayList steps1 = ((ListOpUNIONExpression) stepExpr).getExpression1().getSteps();
212                     ArrayList steps2 = ((ListOpUNIONExpression) stepExpr).getExpression2().getSteps();
213                     if (steps1 == null || steps2 == null)
214                         throw new MediatorException("Unsupported XPath expression");
215                     XPathExpr[] paths1 = paths;
216                     XPathExpr[] paths2 = new XPathExpr[paths.length];
217                     for (int i = 0; i < paths.length; i++) {
218                         paths2[i] = (XPathExpr) paths[i].clone();
219                     }
220                     for (int i = 0; i < steps1.size(); i++)
221                         paths1 = addStep(paths1, (Step) steps1.get(i));
222                     for (int i = 0; i < steps2.size(); i++)
223                         paths2 = addStep(paths2, (Step) steps2.get(i));
224                     paths = new XPathExpr[paths1.length + paths2.length];
225                     System.arraycopy(paths1, 0, paths, 0, paths1.length);
226                     System.arraycopy(paths2, 0, paths, paths1.length, paths1.length);
227                 } else {
228                     throw new MediatorException("Unsupported XPath expression");
229                 }
230                 break;
231             default :
232                 throw new MediatorException("Unsupported XPath expression");
233         }
234         return paths;
235     }
236
237     private void reset() {
238         level = 0;
239         contexts.clear();
240         bindings.clear();
241         contexts.add(new FilterContext(rootFilters));
242     }
243
244     private FilterContext pushContext(String JavaDoc uri, String JavaDoc localName) {
245         FilterContext parent = getCurrentContext();
246         FilterContext current;
247         level++;
248         if (level == contexts.size())
249             contexts.add(new FilterContext());
250         current = getCurrentContext();
251         current.initialize(uri, localName, parent);
252         return current;
253     }
254
255     private void popContext() throws MediatorException {
256         getCurrentContext().cleanup();
257         level--;
258     }
259
260     private FilterContext getCurrentContext() {
261         return getContext(level);
262     }
263
264     private FilterContext getContext(int i) {
265         return (FilterContext) contexts.get(i);
266     }
267
268     private void filterTuple(Tuple tuple) throws MediatorException {
269         try {
270             for (int i = 0; i < computedVars.size(); i++) {
271                 Variable var = (Variable) computedVars.get(i);
272                 int index = buffer.getPathIndex(var.getStringValue());
273                 evaluator.reset(tuple);
274                 var.getExpression().accept(evaluator);
275                 tuple.addNodesAtIndex(index, evaluator.getResNodes());
276             }
277             tuple.fillIdentifiers();
278             if (whereClause != null) {
279                 context.addCurrentTuple(tuple);
280                 evaluator.reset(context.getCurrentTuples());
281                 evaluator.setReturnType(EvaluationVisitor.BOOLEAN_TYPE);
282                 whereClause.accept(evaluator);
283                 context.deleteCurrentTuple(tuple);
284                 if (evaluator.getVerdict())
285                     buffer.add(tuple);
286             } else
287                 buffer.add(tuple);
288         } catch (XQueryException xe) {
289             throw new MediatorException(xe.getMessage(), xe);
290         }
291     }
292
293     private TypedAttribute buildAttribute(PSVInfoset infoset, String JavaDoc value) {
294         TypedAttribute attr = (TypedAttribute) doc.createAttributeNS(infoset.getNamespaceURI(), infoset.getLocalName());
295         if (infoset.getNormalizedValue() != null)
296             attr.setNodeValue(infoset.getNormalizedValue());
297         else
298             attr.setNodeValue(value);
299         if (infoset.getActualValue() != null)
300             attr.setTypedValue(infoset.getActualValue());
301         else
302             attr.setTypedValue(value);
303         if (infoset.getType() != null)
304             attr.setType(infoset.getType());
305         else
306             attr.setType(svc.getSchemaManager().getAnySimpleType());
307         attr.setDeclaration(infoset.getDeclaration());
308         return attr;
309     }
310
311     private TypedValue buildValue(String JavaDoc value, PSVInfoset infoset) {
312         TypedValue tv = (TypedValue) doc.createTextNode(value);
313         Type type = null;
314         if (infoset != null)
315             type = infoset.getType();
316         if (type != null && type.getValueType() != null) {
317             tv.setType(type.getValueType());
318             tv.setTypedValue(infoset.getActualValue());
319             tv.setNodeValue(infoset.getNormalizedValue());
320         } else {
321             // TODO: Check if typing is needed here. A Text node might be enough
322
tv.setType(svc.getSchemaManager().getAnySimpleType());
323             tv.setTypedValue(value);
324             tv.setNodeValue(value);
325         }
326         return tv;
327     }
328
329     private Attr JavaDoc buildPrefixAttribute(String JavaDoc prefix, String JavaDoc uri) {
330         if (prefix == null || prefix.length() == 0) {
331             prefix = "xmlns";
332         } else {
333             prefix = "xmlns:" + prefix;
334         }
335         Attr JavaDoc attr = doc.createAttributeNS(SAXConstants.XMLNS_URI, prefix);
336         attr.setValue(uri);
337         return attr;
338     }
339
340     private Comment JavaDoc buildComment(char[] chars, int start, int length) {
341         return doc.createComment(new String JavaDoc(chars, start, length));
342     }
343
344     public void startDocument() throws SAXException JavaDoc {
345         reset();
346         FilterContext context = getCurrentContext();
347         if (context.isNodeNeeded()) {
348             context.filterDocument(doc);
349             currentNode = doc;
350         }
351     }
352
353     public void endDocument() throws SAXException JavaDoc {
354         try {
355             popContext();
356         } catch (MediatorException e) {
357             throw new SAXException JavaDoc(e);
358         }
359     }
360
361     public void startElement(String JavaDoc uri, String JavaDoc local, String JavaDoc raw, Attributes JavaDoc atts) throws SAXException JavaDoc {
362         FilterContext context = getCurrentContext();
363         if (charsRead.length() > 0) {
364             TypedValue tv = null;
365             String JavaDoc value = charsRead.toString();
366             charsRead.setLength(0);
367             tv = context.filterValue(null, value);
368             if (currentNode != null) {
369                 if (tv == null) {
370                     tv = buildValue(value, null);
371                 }
372                 currentNode.appendChild(tv);
373             }
374         }
375         context = pushContext(uri, local);
376         TypedElement el = null;
377         ElementPSVInfoset epsvis = svc.getCurrentInfoset();
378         if (currentNode != null || context.isNodeNeeded()) {
379             el = (TypedElement) doc.createElementNS(uri, local);
380             el.setType(epsvis.getType());
381             el.setDeclaration(epsvis.getDeclaration());
382             context.filterNode(el);
383             // Handle prefix declarations
384
if (currentNode == null) {
385                 // New root:
386
usedURI.clear();
387                 usedURI.add(uri);
388                 declaredURI.clear();
389                 declaredURI.addAll(epsvis.getNamespaceURIs());
390             }
391             Iterator it = epsvis.getDeclaredPrefixes().iterator();
392             while (it.hasNext()) {
393                 String JavaDoc prefix = (String JavaDoc) it.next();
394                 String JavaDoc nsURI = epsvis.getNamespaceURI(prefix);
395                 // Keep only previous declarations in declaredURI
396
if (currentNode == null)
397                     declaredURI.remove(nsURI);
398                 // Prefixes declared in the query
399
Collection knownPrefixes = nsStack.getPrefixes(nsURI);
400                 if (knownPrefixes.isEmpty()) {
401                     el.setAttributeNode(buildPrefixAttribute(prefix, nsURI));
402                 }
403             }
404         }
405         for (int i = 0; i < atts.getLength(); i++) {
406             PSVInfoset infoset = epsvis.getAttributePSVInfoset(i);
407
408             /* XXX: The schema implementation guarantees that SAX
409              * and PSVI attributes have the same order, so this works
410              */

411             String JavaDoc attrValue = atts.getValue(i);
412             TypedAttribute attr = null;
413             attr = context.filterAttribute(infoset, attrValue);
414             if (el != null) {
415                 if (attr == null)
416                     attr = buildAttribute(infoset, attrValue);
417                 el.setAttributeNode(attr);
418                 usedURI.add(atts.getURI(i));
419             }
420         }
421         if (currentNode != null) {
422             currentNode.appendChild(el);
423         }
424         currentNode = el;
425     }
426
427     public void characters(char[] ch, int start, int length) throws SAXException JavaDoc {
428         charsRead.append(ch, start, length);
429     }
430
431     public void endElement(String JavaDoc uri, String JavaDoc local, String JavaDoc raw) throws SAXException JavaDoc {
432         FilterContext context = getCurrentContext();
433         ElementPSVInfoset epsvis = svc.getCurrentInfoset();
434         if (charsRead.length() > 0) {
435             TypedValue tv = null;
436             String JavaDoc value = charsRead.toString();
437             charsRead.setLength(0);
438             tv = context.filterValue(epsvis, value);
439             if (currentNode != null) {
440                 if (tv == null) {
441                     tv = buildValue(value, epsvis);
442                 }
443                 currentNode.appendChild(tv);
444             }
445         }
446         if (currentNode != null) {
447             if (currentNode.getParentNode() == null) {
448                 Iterator it = usedURI.iterator();
449                 while (it.hasNext()) {
450                     String JavaDoc used = (String JavaDoc) it.next();
451                     if (declaredURI.contains(used) && nsStack.getPrefixes(used).isEmpty()) {
452                         String JavaDoc prefix = epsvis.getPrefix(used);
453                         ((TypedElement) currentNode).setAttributeNode(buildPrefixAttribute(prefix, used));
454                     }
455                 }
456             }
457             currentNode = (TypedNode) currentNode.getParentNode();
458         }
459         try {
460             popContext();
461         } catch (MediatorException e) {
462             throw new SAXException JavaDoc(e);
463         }
464     }
465
466     /* (non-Javadoc)
467      * @see org.xml.sax.ext.LexicalHandler#startDTD(java.lang.String, java.lang.String, java.lang.String)
468      */

469     public void startDTD(String JavaDoc arg0, String JavaDoc arg1, String JavaDoc arg2) throws SAXException JavaDoc {
470     }
471
472     /* (non-Javadoc)
473      * @see org.xml.sax.ext.LexicalHandler#endDTD()
474      */

475     public void endDTD() throws SAXException JavaDoc {
476     }
477
478     /* (non-Javadoc)
479      * @see org.xml.sax.ext.LexicalHandler#startEntity(java.lang.String)
480      */

481     public void startEntity(String JavaDoc arg0) throws SAXException JavaDoc {
482     }
483
484     /* (non-Javadoc)
485      * @see org.xml.sax.ext.LexicalHandler#endEntity(java.lang.String)
486      */

487     public void endEntity(String JavaDoc arg0) throws SAXException JavaDoc {
488     }
489
490     /* (non-Javadoc)
491      * @see org.xml.sax.ext.LexicalHandler#startCDATA()
492      */

493     public void startCDATA() throws SAXException JavaDoc {
494     }
495
496     /* (non-Javadoc)
497      * @see org.xml.sax.ext.LexicalHandler#endCDATA()
498      */

499     public void endCDATA() throws SAXException JavaDoc {
500     }
501
502     /* (non-Javadoc)
503      * @see org.xml.sax.ext.LexicalHandler#comment(char[], int, int)
504      */

505     public void comment(char[] chars, int start, int length) throws SAXException JavaDoc {
506         FilterContext context = getCurrentContext();
507         ElementPSVInfoset epsvis = svc.getCurrentInfoset();
508         if (charsRead.length() > 0) {
509             TypedValue tv = null;
510             String JavaDoc value = charsRead.toString();
511             charsRead.setLength(0);
512             tv = context.filterValue(epsvis, value);
513             if (currentNode != null) {
514                 if (tv == null) {
515                     tv = buildValue(value, epsvis);
516                 }
517                 currentNode.appendChild(tv);
518             }
519         }
520         if (currentNode != null)
521             currentNode.appendChild(buildComment(chars, start, length));
522     }
523
524     class FilterContext {
525
526         private boolean nodeNeeded = false;
527         private List filters = new ArrayList();
528         private boolean bindingRoot = false;
529
530         FilterContext(List fList) {
531             Tuple tuple = null;
532             for (int i = 0; i < fList.size(); i++) {
533                 VariableFilter xf = (VariableFilter) fList.get(i);
534                 filters.add(xf);
535                 if (xf.isDone()) {
536                     if (xf.isBinding()) {
537                         bindingRoot = bindingRoot || bindings.isEmpty();
538                         if (tuple == null) {
539                             tuple = buffer.newTuple();
540                             bindings.add(tuple);
541                         }
542                         xf.setTuple(tuple);
543                     }
544                     nodeNeeded = nodeNeeded || xf.isNodeNeeded();
545                     List subFilters = xf.getSubFilters();
546                     if (subFilters != null) {
547                         Iterator itsub = subFilters.iterator();
548                         while (itsub.hasNext()) {
549                             NodeFilter sub = (NodeFilter) itsub.next();
550                             filters.add(sub);
551                             if (sub.isDone() || sub.matchSelfNode())
552                                 nodeNeeded = nodeNeeded || sub.isNodeNeeded();
553                         }
554                     }
555                 }
556             }
557         }
558
559         FilterContext() {
560         }
561
562         /**
563          * @param uri
564          * @param localName
565          * @param parent
566          */

567         void initialize(String JavaDoc uri, String JavaDoc localName, FilterContext parent) {
568             if (uri != null && uri.length() == 0)
569                 uri = null;
570             filters.clear();
571             nodeNeeded = parent.isNodeNeeded();
572             Tuple tuple = null;
573             Iterator it = parent.filters.iterator();
574             while (it.hasNext()) {
575                 NodeFilter xf = (NodeFilter) it.next();
576                 if (xf.pushElement(uri, localName)) {
577                     filters.add(xf);
578                     /*
579                      * Special case: the filter is forked when there is a
580                      * descendant-or-self step.
581                      */

582                     if (xf.matchDescendantOrSelfStep(uri, localName)) {
583                         xf = (NodeFilter) xf.fork(uri, localName);
584                         filters.add(xf);
585                     }
586                     if (xf.isDone() || xf.matchSelf(uri, localName)) {
587                         if (xf.isBinding()) {
588                             bindingRoot = bindingRoot || bindings.isEmpty();
589                             if (tuple == null) {
590                                 tuple = buffer.newTuple();
591                                 bindings.add(tuple);
592                             }
593                             xf.setTuple(tuple);
594                         }
595                         nodeNeeded = nodeNeeded || xf.isNodeNeeded();
596                         List subFilters = xf.getSubFilters();
597                         if (subFilters != null) {
598                             Iterator itsub = subFilters.iterator();
599                             while (itsub.hasNext()) {
600                                 NodeFilter sub = (NodeFilter) itsub.next();
601                                 sub.skipSelfStep(uri, localName);
602                                 filters.add(sub);
603                                 if (sub.isDone() || sub.matchSelf(uri, localName))
604                                     nodeNeeded = nodeNeeded || sub.isNodeNeeded();
605                             }
606                         }
607                     }
608                 }
609             }
610         }
611
612         /**
613          * @param node
614          */

615         public void filterDocument(TypedDocument doc) {
616             Iterator it = filters.iterator();
617             while (it.hasNext()) {
618                 NodeFilter xf = (NodeFilter) it.next();
619                 if (xf.isDone() || xf.matchSelfNode()) {
620                     xf.setDOMNode(doc);
621                 }
622             }
623         }
624
625         /**
626          * @param node
627          */

628         public void filterNode(TypedElement node) {
629             Iterator it = filters.iterator();
630             while (it.hasNext()) {
631                 NodeFilter xf = (NodeFilter) it.next();
632                 String JavaDoc uri = node.getNamespaceURI();
633                 if (uri.length() == 0)
634                     uri = null;
635                 if (xf.isDone() || xf.matchSelf(uri, node.getLocalName())) {
636                     xf.setDOMNode(node);
637                 }
638             }
639         }
640
641         /**
642          * @param infoset
643          * @param value
644          */

645         public TypedAttribute filterAttribute(PSVInfoset infoset, String JavaDoc value) {
646             String JavaDoc uri = infoset.getNamespaceURI();
647             String JavaDoc name = infoset.getLocalName();
648             TypedAttribute attr = null;
649             if (uri != null && uri.length() == 0)
650                 uri = null;
651             Tuple tuple = null;
652             Iterator it = filters.iterator();
653             while (it.hasNext()) {
654                 NodeFilter xf = (NodeFilter) it.next();
655                 if (xf.matchAttribute(uri, name)) {
656                     if (attr == null) {
657                         attr = buildAttribute(infoset, value);
658                     }
659                     if (xf.isBinding()) {
660                         bindingRoot = bindingRoot || bindings.isEmpty();
661                         if (tuple == null) {
662                             tuple = buffer.newTuple();
663                             bindings.add(tuple);
664                         }
665                         xf = (NodeFilter) xf.clone();
666                         xf.setTuple(tuple);
667                     }
668                     xf.setDOMNode(attr);
669                 }
670             }
671             return attr;
672         }
673
674         public TypedValue filterValue(PSVInfoset infoset, String JavaDoc value) {
675             TypedValue tv = null;
676             Tuple tuple = null;
677             Iterator it = filters.iterator();
678             while (it.hasNext()) {
679                 NodeFilter xf = (NodeFilter) it.next();
680                 if (xf.matchText()) {
681                     if (tv == null) {
682                         tv = buildValue(value, infoset);
683                     }
684                     if (xf.isBinding()) {
685                         bindingRoot = bindingRoot || bindings.isEmpty();
686                         if (tuple == null) {
687                             tuple = buffer.newTuple();
688                             bindings.add(tuple);
689                         }
690                         xf = (NodeFilter) xf.clone();
691                         xf.setTuple(tuple);
692                     }
693                     xf.setDOMNode(tv);
694                     List subFilters = xf.getSubFilters();
695                     if (subFilters != null) {
696                         Iterator itsub = subFilters.iterator();
697                         while (itsub.hasNext()) {
698                             NodeFilter sub = (NodeFilter) itsub.next();
699                             if (sub.matchSelfText())
700                                 sub.setDOMNode(tv);
701                         }
702                     }
703                 }
704             }
705             return tv;
706         }
707
708         void flushBindings() throws MediatorException {
709             if (bindingRoot) {
710                 Iterator it = bindings.iterator();
711                 while (it.hasNext()) {
712                     filterTuple((Tuple) it.next());
713                 }
714                 bindings.clear();
715                 bindingRoot = false;
716             }
717         }
718
719         /**
720          * @return
721          */

722         boolean isNodeNeeded() {
723             return nodeNeeded;
724         }
725
726         void cleanup() throws MediatorException {
727             Iterator it = filters.iterator();
728             while (it.hasNext()) {
729                 NodeFilter xf = (NodeFilter) it.next();
730                 xf.popElement();
731                 xf.setTuple(null);
732             }
733             filters.clear();
734             flushBindings();
735         }
736     }
737
738     static abstract class NodeFilter extends XPathFilter {
739
740         protected List subFilters = null;
741         int colIndex;
742
743         /**
744          * @param xpath
745          */

746         public NodeFilter(XPathExpr xpath, int colIndex) {
747             super(xpath);
748             this.colIndex = colIndex;
749         }
750
751         List getSubFilters() {
752             return subFilters;
753         }
754
755         NodeFilter addSubFilter(int index, XPathExpr xpath) {
756             SubPathFilter sub = new SubPathFilter(this, index, xpath);
757             if (subFilters == null)
758                 subFilters = new ArrayList();
759             subFilters.add(sub);
760             return sub;
761         }
762
763         abstract boolean isNodeNeeded();
764
765         /* (non-Javadoc)
766          * @see org.xquark.xml.xqueryevaluator.eval.SAX2TypedDOM.NodeFilter#setDOMNode(org.xquark.dom.typed.TypedNode)
767          */

768         void setDOMNode(TypedNode node) {
769             if (colIndex != -1) {
770                 Tuple t = getTuple();
771                 if (t != null) {
772                     List nodes = t.getNodesAtIndex(colIndex);
773                     if (nodes == null || node != nodes.get(nodes.size() - 1))
774                         t.addNodeAtIndex(colIndex, node);
775                 }
776             }
777         }
778
779         abstract boolean isBinding();
780
781         abstract void setTuple(Tuple tuple);
782
783         abstract Tuple getTuple();
784     }
785
786     class VariableFilter extends NodeFilter {
787
788         String JavaDoc name;
789         Tuple tuple = null;
790
791         /**
792          * @param xpath
793          */

794         VariableFilter(String JavaDoc name, XPathExpr xpath) {
795             super(xpath, buffer.getPathIndex(name));
796         }
797
798         protected Object JavaDoc clone() {
799             VariableFilter result = (VariableFilter) super.clone();
800             result.tuple = null;
801             if (subFilters != null) {
802                 result.subFilters = new ArrayList(subFilters.size());
803                 for (int i = 0; i < subFilters.size(); i++) {
804                     SubPathFilter sub = (SubPathFilter) subFilters.get(i);
805                     result.addSubFilter(sub.colIndex, sub.xpath);
806                 }
807             }
808             return result;
809         }
810
811         boolean isNodeNeeded() {
812             return colIndex != -1;
813         }
814
815         boolean isBinding() {
816             return true;
817         }
818
819         Tuple getTuple() {
820             return tuple;
821         }
822
823         void setTuple(Tuple tuple) {
824             this.tuple = tuple;
825         }
826
827     }
828
829     static class SubPathFilter extends NodeFilter {
830
831         NodeFilter parent;
832
833         /**
834          * @param xpath
835          */

836         public SubPathFilter(NodeFilter parent, int index, XPathExpr xpath) {
837             super(xpath, index);
838             this.parent = parent;
839         }
840
841         /* (non-Javadoc)
842          * @see org.xquark.xml.xqueryevaluator.eval.SAX2TypedDOM.NodeFilter#isNodeNeeded()
843          */

844         boolean isNodeNeeded() {
845             return true;
846         }
847
848         boolean isBinding() {
849             return false;
850         }
851
852         /* (non-Javadoc)
853          * @see org.xquark.xml.xqueryevaluator.eval.SAX2TypedDOM.NodeFilter#getTuple()
854          */

855
856         Tuple getTuple() {
857             return parent.getTuple();
858         }
859
860         void setTuple(Tuple tuple) {
861         }
862
863     }
864
865 }
866
Popular Tags