KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xquark > xquery > typing > ComputeSubTypeVisitor


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.xquery.typing;
24
25 import java.util.*;
26
27 import org.xquark.schema.*;
28 import org.xquark.xpath.Axis;
29 import org.xquark.xpath.NodeKind;
30 import org.xquark.xpath.StepExpr;
31 import org.xquark.xquery.parser.QName;
32 import org.xquark.xquery.parser.XQueryException;
33
34 public class ComputeSubTypeVisitor extends DefaultQTypeVisitor {
35
36     private List historyList = null;
37     private PrimeList resultList = null;
38     private QType resultQType = null;
39     private StepExpr step = null;
40     private SchemaManager schemamanager = null;
41     private byte axis = Axis.NONE;
42     private byte kind = NodeKind.NONE;
43     private QType ANYELT = null;
44     private QType ANYATT = null;
45     // private QType STRING_0_1 = null;
46
// private QType STRING_1_1 = null;
47
// private QType STRING_0_N = null;
48
private QType TEXT_0_1 = null;
49     private QType TEXT_1_1 = null;
50     private QType TEXT_0_N = null;
51
52     public ComputeSubTypeVisitor() {
53         historyList = new ArrayList();
54         resultList = new PrimeList();
55     }
56
57     public void reset(byte contextType, StepExpr step, SchemaManager schemamanager) throws XQueryException {
58         this.step = step;
59         this.schemamanager = schemamanager;
60         historyList.clear();
61         resultList.clear();
62         resultQType = null;
63         axis = step.getAxis();
64         kind = step.getKindTest();
65         if (ANYELT == null)
66             ANYELT = new QTypeElement(new QName("*", null, "*", null, null), schemamanager.getType(SchemaConstants.XMLSCHEMA_URI, TypeVisitor.SC_ANYTYPE), QType.OCC_0_N);
67         if (ANYATT == null)
68             ANYATT = new QTypeAttribute(new QName("*", null, "*", null, null), (SimpleType) schemamanager.getAnySimpleType());
69         if (TEXT_0_1 == null)
70             TEXT_0_1 = new QTypeText((SimpleType) schemamanager.getAnySimpleType(), QType.OCC_0_1);
71         if (TEXT_1_1 == null)
72             TEXT_1_1 = new QTypeText((SimpleType) schemamanager.getAnySimpleType(), QType.OCC_0_N);
73         if (TEXT_0_N == null)
74             TEXT_0_N = new QTypeText((SimpleType) schemamanager.getAnySimpleType(), QType.OCC_0_N);
75     }
76
77     public QType getResultQType() {
78         return resultQType;
79     }
80
81     public void visit(QType arg) throws XQueryException {
82         resultQType = null;
83     }
84
85     public void visit(QTypeText arg) throws XQueryException {
86         resultQType = null;
87         Type type = arg.getType();
88         switch (kind) {
89             case NodeKind.TEXT :
90                 // -> self::text()
91
switch (axis) {
92                     case Axis.SELF :
93                         resultQType = arg;
94                         break;
95                         // not possible
96
case Axis.CHILD :
97                     case Axis.DESCENDANT :
98                     case Axis.DESCENDANT_OR_SELF :
99                     case Axis.PARENT :
100                     case Axis.ANCESTOR :
101                     case Axis.ANCESTOR_OR_SELF :
102                     case Axis.ATTRIBUTE :
103                     case Axis.FOLLOWING :
104                     case Axis.FOLLOWING_SIBLING :
105                     case Axis.NAMESPACE :
106                     case Axis.PRECEDING :
107                     case Axis.PRECEDING_SIBLING :
108                         break;
109                 }
110                 break;
111             case NodeKind.NODE :
112                 // -> self::node()
113
// -> parent::node()
114
switch (axis) {
115                     case Axis.SELF :
116                     case Axis.DESCENDANT_OR_SELF :
117                         resultQType = arg;
118                         break;
119                         // not supported
120
case Axis.PARENT :
121                         break;
122                         // not possible
123
case Axis.CHILD :
124                     case Axis.DESCENDANT :
125                     case Axis.ANCESTOR :
126                     case Axis.ANCESTOR_OR_SELF :
127                     case Axis.ATTRIBUTE :
128                     case Axis.FOLLOWING :
129                     case Axis.FOLLOWING_SIBLING :
130                     case Axis.NAMESPACE :
131                     case Axis.PRECEDING :
132                     case Axis.PRECEDING_SIBLING :
133                         break;
134                 }
135                 break;
136             case NodeKind.ELEMENT :
137                 // -> parent::NT
138
switch (axis) {
139                     // not supported
140
case Axis.PARENT :
141                         break;
142                         // not possible
143
case Axis.SELF :
144                     case Axis.CHILD :
145                     case Axis.DESCENDANT :
146                     case Axis.DESCENDANT_OR_SELF :
147                     case Axis.ANCESTOR :
148                     case Axis.ANCESTOR_OR_SELF :
149                     case Axis.ATTRIBUTE :
150                     case Axis.FOLLOWING :
151                     case Axis.FOLLOWING_SIBLING :
152                     case Axis.NAMESPACE :
153                     case Axis.PRECEDING :
154                     case Axis.PRECEDING_SIBLING :
155                         break;
156                 }
157                 break;
158         }
159     }
160
161     public void visit(QTypeAttribute arg) throws XQueryException {
162         resultQType = null;
163         Type type = arg.getType();
164         switch (kind) {
165             case NodeKind.NODE :
166                 // -> self::node()
167
// -> parent::node()
168
switch (axis) {
169                     case Axis.SELF :
170                     case Axis.DESCENDANT_OR_SELF :
171                         resultQType = arg;
172                         break;
173                         // not supported
174
case Axis.PARENT :
175                         break;
176                         // not possible
177
case Axis.CHILD :
178                     case Axis.DESCENDANT :
179                     case Axis.ANCESTOR :
180                     case Axis.ANCESTOR_OR_SELF :
181                     case Axis.ATTRIBUTE :
182                     case Axis.FOLLOWING :
183                     case Axis.FOLLOWING_SIBLING :
184                     case Axis.NAMESPACE :
185                     case Axis.PRECEDING :
186                     case Axis.PRECEDING_SIBLING :
187                         break;
188                 }
189                 break;
190             case NodeKind.ELEMENT :
191                 // -> parent::NT
192
switch (axis) {
193                     // not supported
194
case Axis.PARENT :
195                         break;
196                         // not possible
197
case Axis.SELF :
198                     case Axis.CHILD :
199                     case Axis.DESCENDANT :
200                     case Axis.DESCENDANT_OR_SELF :
201                     case Axis.ANCESTOR :
202                     case Axis.ANCESTOR_OR_SELF :
203                     case Axis.ATTRIBUTE :
204                     case Axis.FOLLOWING :
205                     case Axis.FOLLOWING_SIBLING :
206                     case Axis.NAMESPACE :
207                     case Axis.PRECEDING :
208                     case Axis.PRECEDING_SIBLING :
209                         break;
210                 }
211                 break;
212         }
213     }
214
215     // public void visit(QTypeComment arg) throws XQueryException {
216
// visit((QTypeNode) arg);
217
// }
218

219     public void visit(QTypeDocument arg) throws XQueryException {
220         resultQType = null;
221         if (arg.getQType() != null) {
222             switch (kind) {
223                 case NodeKind.ATTRIBUTE :
224                 case NodeKind.TEXT :
225                     // error
226
return;
227                 case NodeKind.NODE :
228                     // -> self::node()
229
// -> child::node()
230
// -> descendant-or-self::node()
231
// -> descendant::node()
232
switch (axis) {
233                         case Axis.SELF :
234                             resultQType = arg;
235                             break;
236                         case Axis.CHILD :
237                         case Axis.DESCENDANT :
238                             arg.getQType().accept(this);
239                             break;
240                         case Axis.DESCENDANT_OR_SELF :
241                             arg.getQType().accept(this);
242                             if (resultQType == null)
243                                 resultQType = arg;
244                             else {
245                                 if (resultQType instanceof QTypeUnion) {
246                                     List list = ((QTypeUnion) resultQType).getPrimeList();
247                                     list.add(arg);
248                                     resultQType = new QTypeUnion(list, ((QTypeUnion) resultQType).getOccurence());
249                                 } else {
250                                     List list = new ArrayList(2);
251                                     list.add(arg);
252                                     list.add(resultQType);
253                                 }
254                             }
255                             break;
256                     }
257                     break;
258                     // case NodeKind.ELEMENT :
259
// // -> self::NT
260
// // -> child::NT
261
// // -> descendant-or-self::NT
262
// // -> descendant::NT
263
// arg.getQType().accept(this);
264
// break;
265
}
266         }
267         if (resultQType != null)
268             return;
269         if (kind == NodeKind.ELEMENT) {
270             String JavaDoc namespace = step.getNameSpace();
271             String JavaDoc localname = step.getLocalName();
272             if (namespace != null && namespace.equals("*")) {
273
274                 Collection schemas = schemamanager.getSchemas();
275                 for (Iterator it = schemas.iterator(); it.hasNext();) {
276                     Schema schema = (Schema) it.next();
277                     ElementDeclaration eltdecl = schema.getElementDeclaration(localname);
278                     if (eltdecl != null) {
279                         resultQType = new QTypeElement(new QName(namespace, null, localname, null, null), eltdecl, eltdecl.getType());
280                         break;
281                     }
282                 }
283                 if (resultQType == null && arg.isFromDocument())
284                     resultQType = new QTypeElement(new QName(namespace, null, localname, null, null), schemamanager.getType(SchemaConstants.XMLSCHEMA_URI, TypeVisitor.SC_ANYTYPE));
285
286             } else {
287                 ElementDeclaration eltdecl = schemamanager.getElementDeclaration(namespace, localname);
288                 if (eltdecl != null)
289                     resultQType = new QTypeElement(new QName(namespace, null, localname, null, null), eltdecl.getType());
290                 else if (arg.isFromDocument())
291                     resultQType = new QTypeElement(new QName(namespace, null, localname, null, null), schemamanager.getType(SchemaConstants.XMLSCHEMA_URI, TypeVisitor.SC_ANYTYPE));
292                 // }
293
}
294             //if (resultQType != null) arg.setQType(resultQType);
295
} else {
296             if (arg.getQType() == null)
297                 return;
298             arg.getQType().accept(this);
299         }
300     }
301     /* TODO
302      * typing should use anysimpletype not string
303      */

304     public void visit(QTypeElement arg) throws XQueryException {
305         resultQType = null;
306         Type type = arg.getType();
307         switch (kind) {
308             case NodeKind.TEXT :
309                 // -> child::text()
310
// -> descendant-or-self::text()
311
// -> descendant::text()
312
switch (axis) {
313                     // supported
314
case Axis.CHILD :
315                     case Axis.DESCENDANT_OR_SELF :
316                         if (type.getValueType() != null) {
317                             resultQType = TEXT_0_1;
318                         } else if (type.getContentType() == Type.MIXED) {
319                             resultQType = TEXT_0_N;
320                         } else {
321                             resultQType = null;
322                         }
323                         // break if axis is child or resultQType is Multiple
324
if (axis == Axis.CHILD || (resultQType != null && resultQType.isMultiple()))
325                             break;
326                     case Axis.DESCENDANT :
327                         // add current resultQType
328
resultList.add(resultQType);
329                         // reset step axis
330
axis = Axis.DESCENDANT_OR_SELF;
331                         Collection decls = type.getElementDeclarations();
332                         if (decls != null && !decls.isEmpty()) {
333                             Iterator it = decls.iterator();
334                             while (it.hasNext()) {
335                                 // test stop condition
336
Declaration decl = (Declaration) it.next();
337                                 StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
338                                 if (decl.getNamespace() != null) {
339                                     buf.append(decl.getNamespace());
340                                     buf.append(":");
341                                 }
342                                 buf.append(decl.getName());
343                                 // this is to handle recursions
344
if (historyList.contains(buf.toString())) {
345                                     continue;
346                                 }
347                                 historyList.add(buf.toString());
348                                 QType tmpQType = null;
349                                 try {
350                                     tmpQType = getQTypeFromDeclaration(decl);
351                                 } catch (XQueryException e) {
352                                     // do nothing
353
}
354                                 if (tmpQType != null) {
355                                     tmpQType.accept(this);
356                                     resultList.add(resultQType);
357                                 }
358                                 historyList.remove(buf.toString());
359                                 // to stop recursion
360
if (resultQType.isMultiple())
361                                     break;
362                                 // erase 02/09/2003
363
/*
364                                 if (resultList.size() > 1) {
365                                     resultQType = TEXT_0_N;
366                                     break;
367                                 }
368                                 */

369                             }
370                         }
371                         break;
372                         // not supported
373
// not possible
374
case Axis.ANCESTOR :
375                     case Axis.ANCESTOR_OR_SELF :
376                     case Axis.ATTRIBUTE :
377                     case Axis.FOLLOWING :
378                     case Axis.FOLLOWING_SIBLING :
379                     case Axis.NAMESPACE :
380                     case Axis.PARENT :
381                     case Axis.PRECEDING :
382                     case Axis.PRECEDING_SIBLING :
383                     case Axis.SELF :
384                         break;
385                 }
386                 break;
387             case NodeKind.NODE :
388                 // -> self::node()
389
// -> child::node()
390
// -> descendant-or-self::node()
391
// -> descendant::node()
392
switch (axis) {
393                     // supported
394
case Axis.SELF :
395                         resultQType = arg;
396                         break;
397                     case Axis.CHILD :
398                         ArrayList list = new ArrayList();
399                         if (type.getValueType() != null) {
400                             list.add(TEXT_0_1);
401                         } else if (((ComplexType) type).getContentType() == Type.MIXED) {
402                             list.add(TEXT_0_N);
403                         }
404                         Collection col = type.getElementDeclarations();
405                         if (col != null && !col.isEmpty()) {
406                             Iterator it = col.iterator();
407                             while (it.hasNext()) {
408                                 ElementDeclaration eltDecl = (ElementDeclaration) it.next();
409                                 try {
410                                     QType tmpQType = getQTypeFromDeclaration(eltDecl);
411                                     if (tmpQType != null && !list.contains(tmpQType))
412                                         list.add(tmpQType);
413                                 } catch (XQueryException e) {
414                                     // do nothing
415
}
416                             }
417                         } else {
418                             if (compareQNames(type.getNamespace(), type.getName(), SchemaConstants.XMLSCHEMA_URI, SchemaConstants.ANY_TYPE))
419                                 list.add(new QTypeElement(arg.getName(), type));
420                         }
421                         if (!list.isEmpty()) {
422                             if (list.size() > 1)
423                                 resultQType = new QTypeUnion(list);
424                             else
425                                 resultQType = (QType) list.get(0);
426                         }
427                         break;
428                     case Axis.DESCENDANT_OR_SELF :
429                     case Axis.DESCENDANT :
430                         // make union of processing instruction, comment, element, text
431
// TODO
432
// test for complex type and mixed
433
if (type.getValueType() != null) {
434                             resultList.add(TEXT_0_1);
435                         } else if (((ComplexType) type).getContentType() == Type.MIXED) {
436                             resultList.add(TEXT_0_N);
437                         }
438                         // add current type
439
if (axis == Axis.DESCENDANT_OR_SELF)
440                             resultList.add(arg);
441                         // reset step axis
442
axis = Axis.DESCENDANT_OR_SELF;
443                         // add test for anyType
444
if (arg.getType().getName() != null && arg.getType().getName().equals(TypeVisitor.SC_ANYTYPE) && !resultList.contains(ANYELT)) {
445                             resultList.add(ANYELT);
446                         }
447                         // first get all elements
448
Collection decls = type.getElementDeclarations();
449                         if (decls != null && !decls.isEmpty()) {
450                             Iterator it = decls.iterator();
451                             while (it.hasNext()) {
452                                 Declaration decl = (Declaration) it.next();
453                                 StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
454                                 if (decl.getNamespace() != null) {
455                                     buf.append(decl.getNamespace());
456                                     buf.append(":");
457                                 }
458                                 buf.append(decl.getName());
459                                 if (historyList.contains(buf.toString())) { // this is to handle recursions
460
continue;
461                                 }
462                                 historyList.add(buf.toString());
463                                 QType tmpQType = null;
464                                 try {
465                                     tmpQType = getQTypeFromDeclaration(decl);
466                                 } catch (XQueryException e) {
467                                     // do nothing
468
}
469                                 if (tmpQType != null) {
470                                     tmpQType.accept(this);
471                                     resultList.add(resultQType);
472                                 }
473                                 historyList.remove(buf.toString());
474                             }
475                         }
476                         if (historyList.isEmpty()) {
477                             if (resultList.size() == 1)
478                                 resultQType = (QType) resultList.get(0);
479                             else if (!resultList.isEmpty())
480                                 resultQType = new QTypeUnion(resultList);
481                             resultList.clear();
482                         }
483                         break;
484                         // not supported
485
case Axis.ANCESTOR :
486                     case Axis.ANCESTOR_OR_SELF :
487                     case Axis.ATTRIBUTE :
488                     case Axis.FOLLOWING :
489                     case Axis.FOLLOWING_SIBLING :
490                     case Axis.NAMESPACE :
491                     case Axis.PARENT :
492                     case Axis.PRECEDING :
493                     case Axis.PRECEDING_SIBLING :
494                         break;
495                         // not possible
496
}
497                 break;
498             case NodeKind.ATTRIBUTE :
499                 break;
500             case NodeKind.ELEMENT :
501                 // -> self::NT
502
// -> child::NT
503
// -> descendant-or-self::NT
504
// -> descendant::NT
505
// -> attribute::NT
506
String JavaDoc namespace = step.getNameSpace();
507                 String JavaDoc localname = step.getLocalName();
508                 Type argType = arg.getType();
509                 switch (axis) {
510                     // supported
511
case Axis.ATTRIBUTE :
512                         if (argType.getName() != null && argType.getName().equals(TypeVisitor.SC_ANYTYPE)) {
513                             // TODO maybe test if the namespace exists ...
514
resultQType = new QTypeAttribute(new QName(namespace, null, localname, null, null),schemamanager.getAnySimpleType());
515                             // TODO maybe clone is necessary ....
516
} else {
517                             AttributeDeclaration attDecl = type.getAttributeDeclaration(namespace, localname);
518                             if (attDecl == null) {
519                                 //if (namespace == null) namespace = "";
520
if (localname == null)
521                                     localname = "";
522                                 Collection decls = type.getAttributeDeclarations();
523                                 if (decls != null && !decls.isEmpty()) {
524                                     Iterator it = decls.iterator();
525                                     ArrayList list = new ArrayList();
526                                     while (it.hasNext()) {
527                                         AttributeDeclaration decl = (AttributeDeclaration) it.next();
528                                         if (compareQNames(namespace, localname, decl.getNamespace(), decl.getName())) {
529                                             QType tmpQType = null;
530                                             try {
531                                                 tmpQType = getQTypeFromDeclaration(decl);
532                                             } catch (XQueryException e) {
533                                                 // do nothing
534
}
535                                             if (tmpQType != null && !list.contains(tmpQType))
536                                                 list.add(tmpQType);
537                                         }
538                                     }
539                                     if (!list.isEmpty())
540                                         //if (list.size() > 1) obj = new QTypeSequence(list);
541
if (list.size() > 1)
542                                             resultQType = new QTypeUnion(list);
543                                         else
544                                             resultQType = (QType) list.get(0);
545                                 }
546                             } else { //if (resultQType == null) {
547
try {
548                                     resultQType = this.getQTypeFromDeclaration((Declaration) attDecl);
549                                 } catch (XQueryException e) {
550                                     // do nothing
551
resultQType = null;
552                                 }
553                             }
554                         }
555                         break;
556                     case Axis.CHILD :
557                         if (type.getValueType() != null || type.getContentType() == Type.EMPTY)
558                             break;
559                         Utils.getSubType((Particle) ((ComplexType) type).getContentModel().getModel(), namespace, localname, schemamanager);
560                         resultQType = Utils.getOccurrenceVisitor().getQType();
561                         break;
562                     case Axis.DESCENDANT_OR_SELF :
563                     case Axis.SELF :
564                         QName argqname = (QName) arg.getName();
565                         if (compareQNames(namespace, localname, argqname.getNameSpace(), argqname.getLocalName())) {
566                             resultQType = new QTypeElement(new QName(namespace, null, localname, null, null), argType, QType.OCC_0_N);
567                         }
568                         if (axis == Axis.SELF)
569                             break;
570                         // add current to history
571
resultList.add(resultQType);
572                     case Axis.DESCENDANT :
573                         // reset step axis
574
axis = Axis.DESCENDANT_OR_SELF;
575                         // iterate on sub elements
576
Collection decls = type.getElementDeclarations();
577                         if (decls != null && !decls.isEmpty()) {
578                             Iterator it = decls.iterator();
579                             while (it.hasNext()) {
580                                 Declaration decl = (Declaration) it.next();
581                                 StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
582                                 if (decl.getNamespace() != null) {
583                                     buf.append(decl.getNamespace());
584                                     buf.append(":");
585                                 }
586                                 buf.append(decl.getName());
587                                 if (historyList.contains(buf.toString())) { // this is to handle recursions
588
continue;
589                                 }
590                                 historyList.add(buf.toString());
591                                 QType tmpQType = null;
592                                 try {
593                                     tmpQType = getQTypeFromDeclaration(decl);
594                                 } catch (XQueryException e) {
595                                     // do nothing
596
}
597                                 if (tmpQType != null) {
598                                     tmpQType.accept(this);
599                                     resultList.add(resultQType);
600                                 }
601                                 historyList.remove(buf.toString());
602                             }
603                         }
604                         if (historyList.isEmpty()) {
605                             if (resultList.size() == 1)
606                                 resultQType = (QType) resultList.get(0);
607                             else if (!resultList.isEmpty())
608                                 resultQType = new QTypeUnion(resultList);
609                             resultList.clear();
610                         }
611                         break;
612                         // not supported
613
case Axis.ANCESTOR :
614                     case Axis.ANCESTOR_OR_SELF :
615                     case Axis.FOLLOWING :
616                     case Axis.FOLLOWING_SIBLING :
617                     case Axis.NAMESPACE :
618                     case Axis.PARENT :
619                     case Axis.PRECEDING :
620                     case Axis.PRECEDING_SIBLING :
621                         break;
622                 }
623                 break;
624             case NodeKind.COMMENT :
625                 // -> self::comment()
626
// -> child::comment()
627
// -> descendant-or-self::comment()
628
// -> descendant::comment()
629
resultQType = new QTypeComment(QType.OCC_0_N);
630                 break;
631             case NodeKind.PI :
632                 // -> self::processing-intruction()
633
// -> child::processing-intruction()
634
// -> descendant-or-self::processing-intruction()
635
// -> descendant::processing-intruction()
636
resultQType = new QTypeProcessingInstruction();
637                 break;
638                 // not supported
639
case NodeKind.DOCUMENT :
640             case NodeKind.NAMESPACE :
641                 break;
642         }
643     }
644     // public void visit(QTypeProcessingInstruction arg) throws XQueryException {
645
// visit((QTypeNode) arg);
646
// }
647

648     public void visit(QTypeSequence arg) throws XQueryException {
649         resultQType = null;
650         ArrayList newList = new ArrayList();
651         Iterator it = arg.getPrimeList().iterator();
652         while (it.hasNext()) {
653             QType qtype = (QType) it.next();
654             qtype.accept(this);
655             if (resultQType != null) {
656                 newList.add(resultQType);
657             }
658         }
659         if (!newList.isEmpty()) {
660             if (newList.size() == 1)
661                 resultQType = (QType) newList.get(0);
662             else
663                 resultQType = new QTypeSequence(newList);
664         }
665     }
666
667     public void visit(QTypeUnion arg) throws XQueryException {
668         resultQType = null;
669         ArrayList newList = new ArrayList();
670         Iterator it = arg.getPrimeList().iterator();
671         while (it.hasNext()) {
672             QType qtype = (QType) it.next();
673             qtype.accept(this);
674             if (resultQType != null && !newList.contains(resultQType)) {
675                 newList.add(resultQType);
676             }
677         }
678         if (!newList.isEmpty()) {
679             if (newList.size() == 1)
680                 resultQType = (QType) newList.get(0);
681             else
682                 resultQType = new QTypeUnion(newList);
683         }
684     }
685     // public void visit(QTypeNode arg) throws XQueryException {
686
// visit((QTypeItem) arg);
687
// }
688
// public void visit(QTypePrime arg) throws XQueryException {
689
// visit((QType) arg);
690
// }
691
// public void visit(QTypeItem arg) throws XQueryException {
692
// visit((QType) arg);
693
// }
694

695     // private methods
696
private QType getQTypeFromDeclaration(Declaration decl) throws XQueryException {
697         if (decl == null)
698             throw new TypeException("Expression not found in metadata");
699         QType retQType = null;
700         QName qname = new QName(decl.getNamespace(), null, decl.getName(), null, null);
701         if (decl instanceof AttributeDeclaration)
702             retQType = new QTypeAttribute(qname, (AttributeDeclaration)decl, (SimpleType) decl.getType());
703         if (decl instanceof ElementDeclaration) {
704             boolean multi = false;
705             ElementDeclaration eltDecl = (ElementDeclaration) decl;
706             SchemaScope scopeType = eltDecl.getScope();
707             if (scopeType != null && scopeType instanceof ComplexType) {
708                 int size[] = { 0, 0 };
709                 size = ((ComplexType) scopeType).getDeclarationOccurrence(eltDecl.getNamespace(), eltDecl.getName());
710                 if (size != null && size[1] > 1)
711                     multi = true;
712             }
713             retQType = new QTypeElement(qname, decl.getType(), multi ? QType.OCC_0_N : QType.OCC_1_1);
714         }
715         return retQType;
716     }
717
718     private boolean compareQNames(String JavaDoc nameSpace1, String JavaDoc localName1, String JavaDoc nameSpace2, String JavaDoc localName2) {
719         // conditions
720
// ( NS1 == * || NS2 == * || ( NS1 empty && NS2 empty) || NS1 == NS2 ) && LN1 != null && LN2 != null && (LN1 = LN2 || LN1 = * || LN2 = *)
721
boolean sameNS = false;
722         if (!sameNS && (nameSpace1 == null || nameSpace1.length() == 0) && (nameSpace2 == null || nameSpace2.length() == 0))
723             sameNS = true;
724         if (!sameNS && nameSpace1 != null && (nameSpace1.equals("*") || nameSpace1.equals(nameSpace2)))
725             sameNS = true;
726         if (!sameNS && nameSpace2 != null && nameSpace2.equals("*"))
727             sameNS = true;
728         if (sameNS && localName1 != null && localName1 != null && (localName1.equals(localName2) || localName1.equals("*") || localName2.equals("*")))
729             return true;
730         return false;
731     }
732 }
733
Popular Tags