KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > impl > xs > XSWildcardDecl


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.xerces.impl.xs;
18
19 import org.apache.xerces.xs.StringList;
20 import org.apache.xerces.xs.XSAnnotation;
21 import org.apache.xerces.xs.XSConstants;
22 import org.apache.xerces.xs.XSNamespaceItem;
23 import org.apache.xerces.xs.XSWildcard;
24 import org.apache.xerces.impl.xs.util.StringListImpl;
25
26 /**
27  * The XML representation for a wildcard declaration
28  * schema component is an <any> or <anyAttribute> element information item
29  *
30  * @xerces.internal
31  *
32  * @author Sandy Gao, IBM
33  * @author Rahul Srivastava, Sun Microsystems Inc.
34  *
35  * @version $Id: XSWildcardDecl.java,v 1.17 2004/10/06 15:14:55 mrglavas Exp $
36  */

37 public class XSWildcardDecl implements XSWildcard {
38
39     public static final String JavaDoc ABSENT = null;
40
41     // the type of wildcard: any, other, or list
42
public short fType = NSCONSTRAINT_ANY;
43     // the type of process contents: strict, lax, or skip
44
public short fProcessContents = PC_STRICT;
45     // the namespace list:
46
// for NSCONSTRAINT_LIST, it means one of the namespaces in the list
47
// for NSCONSTRAINT_NOT, it means not any of the namespaces in the list
48
public String JavaDoc[] fNamespaceList;
49
50     // optional annotation
51
public XSAnnotationImpl fAnnotation = null;
52
53     // I'm trying to implement the following constraint exactly as what the
54
// spec describes. Sometimes it seems redundant, and sometimes there seems
55
// to be much easier solutions. But it makes it easy to understand,
56
// easy to maintain, and easy to find a bug (either in the code, or in the
57
// spec). -SG
58
//
59
// NOTE: Schema spec only requires that ##other not(tNS,absent).
60
// The way we store ##other is not(NS1,NS2,...,NSN), which covers
61
// what's required by Schema, and allows future enhanced features.
62
//
63
// In the following in-line comments:
64
// - Bullet removed from w3c specification.
65
// + Bullet added as proposed by Sandy Gao, IBM.
66
// / Since we store ##other as not(NS1,NS2,...,NSN), we need to put some
67
// comments on where we didn't follow the spec exactly.
68
// * When we really support not(NS1,NS2,...,NSN), we need to revisit these items.
69

70     /**
71      * Validation Rule: Wildcard allows Namespace Name
72      */

73     public boolean allowNamespace(String JavaDoc namespace) {
74         // For a value which is either a namespace name or absent to be valid with respect to a wildcard constraint (the value of a {namespace constraint}) one of the following must be true:
75

76         // 1 The constraint must be any.
77
if (fType == NSCONSTRAINT_ANY)
78             return true;
79
80         // 2 All of the following must be true:
81
// 2.1 The constraint is a pair of not and a namespace name or absent ([Definition:] call this the namespace test).
82
// 2.2 The value must not be identical to the namespace test.
83
// 2.3 The value must not be absent.
84
// / we store ##other as not(list), so our actual rule is
85
// / 2 The constraint is a pair of not and a set, and the value is not in such set.
86
if (fType == NSCONSTRAINT_NOT) {
87             boolean found = false;
88             int listNum = fNamespaceList.length;
89             for (int i = 0; i < listNum && !found; i++) {
90                 if (namespace == fNamespaceList[i])
91                     found = true;
92             }
93
94             if (!found)
95                 return true;
96         }
97
98         // 3 The constraint is a set, and the value is identical to one of the members of the set.
99
if (fType == NSCONSTRAINT_LIST) {
100             int listNum = fNamespaceList.length;
101             for (int i = 0; i < listNum; i++) {
102                 if (namespace == fNamespaceList[i])
103                     return true;
104             }
105         }
106
107         // none of the above conditions applied, so return false.
108
return false;
109     }
110
111     /**
112      * Schema Component Constraint: Wildcard Subset
113      */

114     public boolean isSubsetOf(XSWildcardDecl superWildcard) {
115         // if the super is null (not expressible), return false
116
if (superWildcard == null)
117             return false;
118
119         // For a namespace constraint (call it sub) to be an intensional subset of another
120
// namespace constraint (call it super) one of the following must be true:
121

122         // 1 super must be any.
123
if (superWildcard.fType == NSCONSTRAINT_ANY) {
124             return true;
125         }
126
127         // 2 All of the following must be true:
128
// 2.1 sub must be a pair of not and a namespace name or absent.
129
// 2.2 super must be a pair of not and the same value.
130
// * we can't just compare whether the namespace are the same value
131
// since we store other as not(list)
132
if (fType == NSCONSTRAINT_NOT) {
133             if (superWildcard.fType == NSCONSTRAINT_NOT &&
134                 fNamespaceList[0] == superWildcard.fNamespaceList[0]) {
135                 return true;
136             }
137         }
138
139         // 3 All of the following must be true:
140
// 3.1 sub must be a set whose members are either namespace names or absent.
141
// 3.2 One of the following must be true:
142
// 3.2.1 super must be the same set or a superset thereof.
143
// -3.2.2 super must be a pair of not and a namespace name or absent and
144
// that value must not be in sub's set.
145
// +3.2.2 super must be a pair of not and a namespace name or absent and
146
// either that value or absent must not be in sub's set.
147
// * since we store ##other as not(list), we acturally need to make sure
148
// that none of the namespaces in super.list is in sub.list.
149
if (fType == NSCONSTRAINT_LIST) {
150             if (superWildcard.fType == NSCONSTRAINT_LIST &&
151                 subset2sets(fNamespaceList, superWildcard.fNamespaceList)) {
152                 return true;
153             }
154
155             if (superWildcard.fType == NSCONSTRAINT_NOT &&
156                 !elementInSet(superWildcard.fNamespaceList[0], fNamespaceList) &&
157                 !elementInSet(ABSENT, fNamespaceList)) {
158                 return true;
159             }
160         }
161
162         // none of the above conditions applied, so return false.
163
return false;
164
165     } // isSubsetOf
166

167     /**
168      * Check whether this wildcard has a weaker process contents than the super.
169      */

170     public boolean weakerProcessContents(XSWildcardDecl superWildcard) {
171         return fProcessContents == XSWildcardDecl.PC_LAX &&
172                superWildcard.fProcessContents == XSWildcardDecl.PC_STRICT ||
173                fProcessContents == XSWildcardDecl.PC_SKIP &&
174                superWildcard.fProcessContents != XSWildcardDecl.PC_SKIP;
175     }
176
177     /**
178      * Schema Component Constraint: Attribute Wildcard Union
179      */

180     public XSWildcardDecl performUnionWith(XSWildcardDecl wildcard,
181                                            short processContents) {
182         // if the other wildcard is not expressible, the result is still not expressible
183
if (wildcard == null)
184             return null;
185
186         // For a wildcard's {namespace constraint} value to be the intensional union of two
187
// other such values (call them O1 and O2): the appropriate case among the following
188
// must be true:
189

190         XSWildcardDecl unionWildcard = new XSWildcardDecl();
191         unionWildcard.fProcessContents = processContents;
192
193         // 1 If O1 and O2 are the same value, then that value must be the value.
194
if (areSame(wildcard)) {
195             unionWildcard.fType = fType;
196             unionWildcard.fNamespaceList = fNamespaceList;
197         }
198
199         // 2 If either O1 or O2 is any, then any must be the value.
200
else if ( (fType == NSCONSTRAINT_ANY) || (wildcard.fType == NSCONSTRAINT_ANY) ) {
201             unionWildcard.fType = NSCONSTRAINT_ANY;
202         }
203
204         // 3 If both O1 and O2 are sets of (namespace names or absent), then the union of
205
// those sets must be the value.
206
else if ( (fType == NSCONSTRAINT_LIST) && (wildcard.fType == NSCONSTRAINT_LIST) ) {
207             unionWildcard.fType = NSCONSTRAINT_LIST;
208             unionWildcard.fNamespaceList = union2sets(fNamespaceList, wildcard.fNamespaceList);
209         }
210
211         // -4 If the two are negations of different namespace names, then the intersection
212
// is not expressible.
213
// +4 If the two are negations of different namespace names or absent, then
214
// a pair of not and absent must be the value.
215
// * now we store ##other as not(list), the result should be
216
// not(intersection of two lists).
217
else if (fType == NSCONSTRAINT_NOT && wildcard.fType == NSCONSTRAINT_NOT) {
218             unionWildcard.fType = NSCONSTRAINT_NOT;
219             unionWildcard.fNamespaceList = new String JavaDoc[2];
220             unionWildcard.fNamespaceList[0] = ABSENT;
221             unionWildcard.fNamespaceList[1] = ABSENT;
222         }
223
224         // 5 If either O1 or O2 is a pair of not and a namespace name and the other is a set of
225
// (namespace names or absent), then The appropriate case among the following must be true:
226
// -5.1 If the set includes the negated namespace name, then any must be the value.
227
// -5.2 If the set does not include the negated namespace name, then whichever of O1 or O2
228
// is a pair of not and a namespace name must be the value.
229
// +5.1 If the negated value is a namespace name, then The appropriate case
230
// among the following must be true:
231
// +5.1.1 If the set includes both the namespace name and absent, then any
232
// must be the value.
233
// +5.1.2 If the set includes the namespace name but does not include
234
// absent, then a pair of not and absent must be the value.
235
// +5.1.3 If the set does not include the namespace name but includes
236
// absent, then the union is not expressible.
237
// +5.1.4 If the set does not include either the namespace name or absent,
238
// then whichever of O1 or O2 is a pair of not and a namespace name must be
239
// the value.
240
// +5.2 If the negated value is absent, then The appropriate case among the
241
// following must be true:
242
// +5.2.1 If the set includes absent, then any must be the value.
243
// +5.2.2 If the set does not include absent, then whichever of O1 or O2 is
244
// a pair of not and a namespace name must be the value.
245
// * when we have not(list), the operation is just not(otherlist-list)
246
else if ( ((fType == NSCONSTRAINT_NOT) && (wildcard.fType == NSCONSTRAINT_LIST)) ||
247                   ((fType == NSCONSTRAINT_LIST) && (wildcard.fType == NSCONSTRAINT_NOT)) ) {
248             String JavaDoc[] other = null;
249             String JavaDoc[] list = null;
250
251             if (fType == NSCONSTRAINT_NOT) {
252                 other = fNamespaceList;
253                 list = wildcard.fNamespaceList;
254             }
255             else {
256                 other = wildcard.fNamespaceList;
257                 list = fNamespaceList;
258             }
259
260             boolean foundAbsent = elementInSet(ABSENT, list);
261
262             if (other[0] != ABSENT) {
263                 boolean foundNS = elementInSet(other[0], list);
264                 if (foundNS && foundAbsent) {
265                     unionWildcard.fType = NSCONSTRAINT_ANY;
266                 } else if (foundNS && !foundAbsent) {
267                     unionWildcard.fType = NSCONSTRAINT_NOT;
268                     unionWildcard.fNamespaceList = new String JavaDoc[2];
269                     unionWildcard.fNamespaceList[0] = ABSENT;
270                     unionWildcard.fNamespaceList[1] = ABSENT;
271                 } else if (!foundNS && foundAbsent) {
272                     return null;
273                 } else { // !foundNS && !foundAbsent
274
unionWildcard.fType = NSCONSTRAINT_NOT;
275                     unionWildcard.fNamespaceList = other;
276                 }
277             } else { // other[0] == ABSENT
278
if (foundAbsent) {
279                     unionWildcard.fType = NSCONSTRAINT_ANY;
280                 } else { // !foundAbsent
281
unionWildcard.fType = NSCONSTRAINT_NOT;
282                     unionWildcard.fNamespaceList = other;
283                 }
284             }
285         }
286
287         return unionWildcard;
288
289     } // performUnionWith
290

291     /**
292      * Schema Component Constraint: Attribute Wildcard Intersection
293      */

294     public XSWildcardDecl performIntersectionWith(XSWildcardDecl wildcard,
295                                                   short processContents) {
296         // if the other wildcard is not expressible, the result is still not expressible
297
if (wildcard == null)
298             return null;
299
300         // For a wildcard's {namespace constraint} value to be the intensional intersection of
301
// two other such values (call them O1 and O2): the appropriate case among the following
302
// must be true:
303

304         XSWildcardDecl intersectWildcard = new XSWildcardDecl();
305         intersectWildcard.fProcessContents = processContents;
306
307         // 1 If O1 and O2 are the same value, then that value must be the value.
308
if (areSame(wildcard)) {
309             intersectWildcard.fType = fType;
310             intersectWildcard.fNamespaceList = fNamespaceList;
311         }
312
313         // 2 If either O1 or O2 is any, then the other must be the value.
314
else if ( (fType == NSCONSTRAINT_ANY) || (wildcard.fType == NSCONSTRAINT_ANY) ) {
315             // both cannot be ANY, if we have reached here.
316
XSWildcardDecl other = this;
317
318             if (fType == NSCONSTRAINT_ANY)
319                 other = wildcard;
320
321             intersectWildcard.fType = other.fType;
322             intersectWildcard.fNamespaceList = other.fNamespaceList;
323         }
324
325         // -3 If either O1 or O2 is a pair of not and a namespace name and the other is a set of
326
// (namespace names or absent), then that set, minus the negated namespace name if
327
// it was in the set, must be the value.
328
// +3 If either O1 or O2 is a pair of not and a namespace name and the other
329
// is a set of (namespace names or absent), then that set, minus the negated
330
// namespace name if it was in the set, then minus absent if it was in the
331
// set, must be the value.
332
// * when we have not(list), the operation is just list-otherlist
333
else if ( ((fType == NSCONSTRAINT_NOT) && (wildcard.fType == NSCONSTRAINT_LIST)) ||
334                   ((fType == NSCONSTRAINT_LIST) && (wildcard.fType == NSCONSTRAINT_NOT)) ) {
335             String JavaDoc[] list = null;
336             String JavaDoc[] other = null;
337
338             if (fType == NSCONSTRAINT_NOT) {
339                 other = fNamespaceList;
340                 list = wildcard.fNamespaceList;
341             }
342             else {
343                 other = wildcard.fNamespaceList;
344                 list = fNamespaceList;
345             }
346
347             int listSize = list.length;
348             String JavaDoc[] intersect = new String JavaDoc[listSize];
349             int newSize = 0;
350             for (int i = 0; i < listSize; i++) {
351                 if (list[i] != other[0] && list[i] != ABSENT)
352                     intersect[newSize++] = list[i];
353             }
354
355             intersectWildcard.fType = NSCONSTRAINT_LIST;
356             intersectWildcard.fNamespaceList = new String JavaDoc[newSize];
357             System.arraycopy(intersect, 0, intersectWildcard.fNamespaceList, 0, newSize);
358         }
359
360         // 4 If both O1 and O2 are sets of (namespace names or absent), then the intersection of those
361
// sets must be the value.
362
else if ( (fType == NSCONSTRAINT_LIST) && (wildcard.fType == NSCONSTRAINT_LIST) ) {
363             intersectWildcard.fType = NSCONSTRAINT_LIST;
364             intersectWildcard.fNamespaceList = intersect2sets(fNamespaceList, wildcard.fNamespaceList);
365         }
366
367         // -5 If the two are negations of different namespace names, then the intersection is not expressible.
368
// +5 If the two are negations of namespace names or absent, then The
369
// appropriate case among the following must be true:
370
// +5.1 If the two are negations of different namespace names, then the
371
// intersection is not expressible.
372
// +5.2 If one of the two is a pair of not and absent, the other must be
373
// the value.
374
// * when we have not(list), the operation is just not(onelist+otherlist)
375
else if (fType == NSCONSTRAINT_NOT && wildcard.fType == NSCONSTRAINT_NOT) {
376             if (fNamespaceList[0] != ABSENT && wildcard.fNamespaceList[0] != ABSENT)
377                 return null;
378
379             XSWildcardDecl other = this;
380             if (fNamespaceList[0] == ABSENT)
381                 other = wildcard;
382
383             intersectWildcard.fType = other.fType;
384             intersectWildcard.fNamespaceList = other.fNamespaceList;
385         }
386
387         return intersectWildcard;
388
389     } // performIntersectionWith
390

391     private boolean areSame(XSWildcardDecl wildcard) {
392         if (fType == wildcard.fType) {
393             // ##any, true
394
if (fType == NSCONSTRAINT_ANY)
395                 return true;
396
397             // ##other, only check the negated value
398
// * when we support not(list), we need to check in the same way
399
// as for NSCONSTRAINT_LIST.
400
if (fType == NSCONSTRAINT_NOT)
401                 return fNamespaceList[0] == wildcard.fNamespaceList[0];
402
403             // ## list, must have the same length,
404
// and each item in one list must appear in the other one
405
// (we are assuming that there are no duplicate items in a list)
406
if (fNamespaceList.length == wildcard.fNamespaceList.length) {
407                 for (int i=0; i<fNamespaceList.length; i++) {
408                     if (!elementInSet(fNamespaceList[i], wildcard.fNamespaceList))
409                         return false;
410                 }
411                 return true;
412             }
413         }
414
415         return false;
416     } // areSame
417

418     String JavaDoc[] intersect2sets(String JavaDoc[] one, String JavaDoc[] theOther){
419         String JavaDoc[] result = new String JavaDoc[Math.min(one.length,theOther.length)];
420
421         // simple implemention,
422
int count = 0;
423         for (int i=0; i<one.length; i++) {
424             if (elementInSet(one[i], theOther))
425                 result[count++] = one[i];
426         }
427
428         String JavaDoc[] result2 = new String JavaDoc[count];
429         System.arraycopy(result, 0, result2, 0, count);
430
431         return result2;
432     }
433
434     String JavaDoc[] union2sets(String JavaDoc[] one, String JavaDoc[] theOther){
435         String JavaDoc[] result1 = new String JavaDoc[one.length];
436
437         // simple implemention,
438
int count = 0;
439         for (int i=0; i<one.length; i++) {
440             if (!elementInSet(one[i], theOther))
441                 result1[count++] = one[i];
442         }
443
444         String JavaDoc[] result2 = new String JavaDoc[count+theOther.length];
445         System.arraycopy(result1, 0, result2, 0, count);
446         System.arraycopy(theOther, 0, result2, count, theOther.length);
447
448         return result2;
449     }
450
451     boolean subset2sets(String JavaDoc[] subSet, String JavaDoc[] superSet){
452         for (int i=0; i<subSet.length; i++) {
453             if (!elementInSet(subSet[i], superSet))
454                 return false;
455         }
456
457         return true;
458     }
459
460     boolean elementInSet(String JavaDoc ele, String JavaDoc[] set){
461         boolean found = false;
462         for (int i=0; i<set.length && !found; i++) {
463             if (ele==set[i])
464                 found = true;
465         }
466
467         return found;
468     }
469
470     /**
471      * get the string description of this wildcard
472      */

473     private String JavaDoc fDescription = null;
474     public String JavaDoc toString() {
475         if (fDescription == null) {
476             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
477             buffer.append("WC[");
478             switch (fType) {
479             case NSCONSTRAINT_ANY:
480                 buffer.append(SchemaSymbols.ATTVAL_TWOPOUNDANY);
481                 break;
482             case NSCONSTRAINT_NOT:
483                 buffer.append(SchemaSymbols.ATTVAL_TWOPOUNDOTHER);
484                 buffer.append(":\"");
485                 if (fNamespaceList[0] != null)
486                     buffer.append(fNamespaceList[0]);
487                 buffer.append("\"");
488                 break;
489             case NSCONSTRAINT_LIST:
490                 if (fNamespaceList.length == 0)
491                     break;
492                 buffer.append("\"");
493                 if (fNamespaceList[0] != null)
494                     buffer.append(fNamespaceList[0]);
495                 buffer.append("\"");
496                 for (int i = 1; i < fNamespaceList.length; i++) {
497                     buffer.append(",\"");
498                     if (fNamespaceList[i] != null)
499                         buffer.append(fNamespaceList[i]);
500                     buffer.append("\"");
501                 }
502                 break;
503             }
504             buffer.append("]");
505             fDescription = buffer.toString();
506         }
507
508         return fDescription;
509     }
510     
511     /**
512      * Get the type of the object, i.e ELEMENT_DECLARATION.
513      */

514     public short getType() {
515         return XSConstants.WILDCARD;
516     }
517
518     /**
519      * The <code>name</code> of this <code>XSObject</code> depending on the
520      * <code>XSObject</code> type.
521      */

522     public String JavaDoc getName() {
523         return null;
524     }
525
526     /**
527      * The namespace URI of this node, or <code>null</code> if it is
528      * unspecified. defines how a namespace URI is attached to schema
529      * components.
530      */

531     public String JavaDoc getNamespace() {
532         return null;
533     }
534
535     /**
536      * Namespace constraint: A constraint type: any, not, list.
537      */

538     public short getConstraintType() {
539         return fType;
540     }
541
542     /**
543      * Namespace constraint. For <code>constraintType</code>
544      * LIST_NSCONSTRAINT, the list contains allowed namespaces. For
545      * <code>constraintType</code> NOT_NSCONSTRAINT, the list contains
546      * disallowed namespaces.
547      */

548     public StringList getNsConstraintList() {
549         return new StringListImpl(fNamespaceList, fNamespaceList == null ? 0 : fNamespaceList.length);
550     }
551
552     /**
553      * {process contents} One of skip, lax or strict. Valid constants values
554      * are: PC_SKIP, PC_LAX, PC_STRICT.
555      */

556     public short getProcessContents() {
557         return fProcessContents;
558     }
559
560     /**
561      * String valid of {process contents}. One of "skip", "lax" or "strict".
562      */

563     public String JavaDoc getProcessContentsAsString() {
564         switch (fProcessContents) {
565             case XSWildcardDecl.PC_SKIP: return "skip";
566             case XSWildcardDecl.PC_LAX: return "lax";
567             case XSWildcardDecl.PC_STRICT: return "strict";
568             default: return "invalid value";
569         }
570     }
571
572     /**
573      * Optional. Annotation.
574      */

575     public XSAnnotation getAnnotation() {
576         return fAnnotation;
577     }
578
579
580     /**
581      * @see org.apache.xerces.xs.XSObject#getNamespaceItem()
582      */

583     public XSNamespaceItem getNamespaceItem() {
584         // REVISIT: implement
585
return null;
586     }
587
588 } // class XSWildcardDecl
589
Popular Tags