1 /* |
1 /* |
2 * reserved comment block |
2 * reserved comment block |
3 * DO NOT REMOVE OR ALTER! |
3 * DO NOT REMOVE OR ALTER! |
4 */ |
4 */ |
5 /* |
5 /* |
6 * Copyright 2001-2005 The Apache Software Foundation. |
6 * Licensed to the Apache Software Foundation (ASF) under one or more |
7 * |
7 * contributor license agreements. See the NOTICE file distributed with |
8 * Licensed under the Apache License, Version 2.0 (the "License"); |
8 * this work for additional information regarding copyright ownership. |
9 * you may not use this file except in compliance with the License. |
9 * The ASF licenses this file to You under the Apache License, Version 2.0 |
10 * You may obtain a copy of the License at |
10 * (the "License"); you may not use this file except in compliance with |
|
11 * the License. You may obtain a copy of the License at |
11 * |
12 * |
12 * http://www.apache.org/licenses/LICENSE-2.0 |
13 * http://www.apache.org/licenses/LICENSE-2.0 |
13 * |
14 * |
14 * Unless required by applicable law or agreed to in writing, software |
15 * Unless required by applicable law or agreed to in writing, software |
15 * distributed under the License is distributed on an "AS IS" BASIS, |
16 * distributed under the License is distributed on an "AS IS" BASIS, |
38 */ |
39 */ |
39 public class SubstitutionGroupHandler { |
40 public class SubstitutionGroupHandler { |
40 |
41 |
41 private static final XSElementDecl[] EMPTY_GROUP = new XSElementDecl[0]; |
42 private static final XSElementDecl[] EMPTY_GROUP = new XSElementDecl[0]; |
42 |
43 |
43 // grammar resolver |
44 // global element declaration resolver |
44 XSGrammarBucket fGrammarBucket; |
45 private final XSElementDeclHelper fXSElementDeclHelper; |
45 |
46 |
46 /** |
47 /** |
47 * Default constructor |
48 * Default constructor |
48 */ |
49 */ |
49 public SubstitutionGroupHandler(XSGrammarBucket grammarBucket) { |
50 public SubstitutionGroupHandler(XSElementDeclHelper elementDeclHelper) { |
50 fGrammarBucket = grammarBucket; |
51 fXSElementDeclHelper = elementDeclHelper; |
51 } |
52 } |
52 |
53 |
53 // 3.9.4 Element Sequence Locally Valid (Particle) 2.3.3 |
54 // 3.9.4 Element Sequence Locally Valid (Particle) 2.3.3 |
54 // check whether one element decl matches an element with the given qname |
55 // check whether one element decl matches an element with the given qname |
55 public XSElementDecl getMatchingElemDecl(QName element, XSElementDecl exemplar) { |
56 public XSElementDecl getMatchingElemDecl(QName element, XSElementDecl exemplar) { |
58 return exemplar; |
59 return exemplar; |
59 } |
60 } |
60 |
61 |
61 // if the exemplar is not a global element decl, then it's not possible |
62 // if the exemplar is not a global element decl, then it's not possible |
62 // to be substituted by another element. |
63 // to be substituted by another element. |
63 if (exemplar.fScope != XSConstants.SCOPE_GLOBAL) |
64 if (exemplar.fScope != XSConstants.SCOPE_GLOBAL) { |
64 return null; |
65 return null; |
|
66 } |
65 |
67 |
66 // if the decl blocks substitution, return false |
68 // if the decl blocks substitution, return false |
67 if ((exemplar.fBlock & XSConstants.DERIVATION_SUBSTITUTION) != 0) |
69 if ((exemplar.fBlock & XSConstants.DERIVATION_SUBSTITUTION) != 0) { |
68 return null; |
70 return null; |
69 |
71 } |
70 // get grammar of the element |
72 |
71 SchemaGrammar sGrammar = fGrammarBucket.getGrammar(element.uri); |
73 // get the decl for the element |
72 if (sGrammar == null) |
74 XSElementDecl eDecl = fXSElementDeclHelper.getGlobalElementDecl(element); |
|
75 if (eDecl == null) { |
73 return null; |
76 return null; |
74 |
77 } |
75 // get the decl for the element |
|
76 XSElementDecl eDecl = sGrammar.getGlobalElementDecl(element.localpart); |
|
77 if (eDecl == null) |
|
78 return null; |
|
79 |
78 |
80 // and check by using substitutionGroup information |
79 // and check by using substitutionGroup information |
81 if (substitutionGroupOK(eDecl, exemplar, exemplar.fBlock)) |
80 if (substitutionGroupOK(eDecl, exemplar, exemplar.fBlock)) { |
82 return eDecl; |
81 return eDecl; |
|
82 } |
83 |
83 |
84 return null; |
84 return null; |
85 } |
85 } |
86 |
86 |
87 // 3.3.6 Substitution Group OK (Transitive) |
87 // 3.3.6 Substitution Group OK (Transitive) |
88 // check whether element can substitute exemplar |
88 // check whether element can substitute exemplar |
89 protected boolean substitutionGroupOK(XSElementDecl element, XSElementDecl exemplar, short blockingConstraint) { |
89 protected boolean substitutionGroupOK(XSElementDecl element, XSElementDecl exemplar, short blockingConstraint) { |
90 // For an element declaration (call it D) to be validly substitutable for another element declaration (call it C) subject to a blocking constraint (a subset of {substitution, extension, restriction}, the value of a {disallowed substitutions}) one of the following must be true: |
90 // For an element declaration (call it D) to be validly substitutable for another element declaration (call it C) subject to a blocking constraint (a subset of {substitution, extension, restriction}, the value of a {disallowed substitutions}) one of the following must be true: |
91 // 1. D and C are the same element declaration. |
91 // 1. D and C are the same element declaration. |
92 if (element == exemplar) |
92 if (element == exemplar) { |
93 return true; |
93 return true; |
|
94 } |
94 |
95 |
95 // 2 All of the following must be true: |
96 // 2 All of the following must be true: |
96 // 2.1 The blocking constraint does not contain substitution. |
97 // 2.1 The blocking constraint does not contain substitution. |
97 if ((blockingConstraint & XSConstants.DERIVATION_SUBSTITUTION) != 0) |
98 if ((blockingConstraint & XSConstants.DERIVATION_SUBSTITUTION) != 0) { |
98 return false; |
99 return false; |
|
100 } |
99 |
101 |
100 // 2.2 There is a chain of {substitution group affiliation}s from D to C, that is, either D's {substitution group affiliation} is C, or D's {substitution group affiliation}'s {substitution group affiliation} is C, or . . . |
102 // 2.2 There is a chain of {substitution group affiliation}s from D to C, that is, either D's {substitution group affiliation} is C, or D's {substitution group affiliation}'s {substitution group affiliation} is C, or . . . |
101 XSElementDecl subGroup = element.fSubGroup; |
103 XSElementDecl subGroup = element.fSubGroup; |
102 while (subGroup != null && subGroup != exemplar) { |
104 while (subGroup != null && subGroup != exemplar) { |
103 subGroup = subGroup.fSubGroup; |
105 subGroup = subGroup.fSubGroup; |
104 } |
106 } |
105 |
107 |
106 if (subGroup == null) |
108 if (subGroup == null) { |
107 return false; |
109 return false; |
|
110 } |
108 |
111 |
109 // 2.3 The set of all {derivation method}s involved in the derivation of D's {type definition} from C's {type definition} does not intersect with the union of the blocking constraint, C's {prohibited substitutions} (if C is complex, otherwise the empty set) and the {prohibited substitutions} (respectively the empty set) of any intermediate {type definition}s in the derivation of D's {type definition} from C's {type definition}. |
112 // 2.3 The set of all {derivation method}s involved in the derivation of D's {type definition} from C's {type definition} does not intersect with the union of the blocking constraint, C's {prohibited substitutions} (if C is complex, otherwise the empty set) and the {prohibited substitutions} (respectively the empty set) of any intermediate {type definition}s in the derivation of D's {type definition} from C's {type definition}. |
110 // prepare the combination of {derivation method} and |
113 // prepare the combination of {derivation method} and |
111 // {disallowed substitution} |
114 // {disallowed substitution} |
112 return typeDerivationOK(element.fType, exemplar.fType, blockingConstraint); |
115 return typeDerivationOK(element.fType, exemplar.fType, blockingConstraint); |
113 } |
116 } |
|
117 |
114 private boolean typeDerivationOK(XSTypeDefinition derived, XSTypeDefinition base, short blockingConstraint) { |
118 private boolean typeDerivationOK(XSTypeDefinition derived, XSTypeDefinition base, short blockingConstraint) { |
115 |
119 |
116 short devMethod = 0, blockConstraint = blockingConstraint; |
120 short devMethod = 0, blockConstraint = blockingConstraint; |
117 |
121 |
118 // "derived" should be derived from "base" |
122 // "derived" should be derived from "base" |