1
|
|
/*
|
2
|
|
* JBind
|
3
|
|
*
|
4
|
|
* Copyright (c) by Stefan Wachter. All rights reserved.
|
5
|
|
*
|
6
|
|
* Usage, modification, and redistribution is subject to license terms that are
|
7
|
|
* available at 'http://www.jbind.org'. The JBind license is like the
|
8
|
|
* 'Apache Software License V 1.1'.
|
9
|
|
*/
|
10
|
|
package org.jbind.xml.schema.constraint;
|
11
|
|
|
12
|
|
import java.util.ArrayList;
|
13
|
|
import java.util.Collections;
|
14
|
|
import java.util.HashMap;
|
15
|
|
import java.util.Iterator;
|
16
|
|
import java.util.List;
|
17
|
|
import java.util.Map;
|
18
|
|
|
19
|
|
import org.jbind.xml.base.IHasLocation;
|
20
|
|
import org.jbind.xml.base.WhiteSpaceProcessing;
|
21
|
|
import org.jbind.xml.core.constraint.ConstraintType;
|
22
|
|
import org.jbind.xml.core.constraint.IBuiltInConstraint;
|
23
|
|
import org.jbind.xml.core.constraint.ICheckContext;
|
24
|
|
import org.jbind.xml.core.constraint.IConstraint;
|
25
|
|
import org.jbind.xml.core.constraint.IConstraints;
|
26
|
|
import org.jbind.xml.core.constraint.IReferenceConstraint;
|
27
|
|
import org.jbind.xml.msg.IConstraintViolations;
|
28
|
|
import org.jbind.xml.msg.XmlMessages;
|
29
|
|
|
30
|
|
public final class Constraints implements IConstraints {
|
31
|
|
|
32
|
|
private IConstraint[] mySingleConstraints = null;
|
33
|
|
private List[] myMultipleConstraints = null;
|
34
|
|
|
35
|
|
/**
|
36
|
|
*
|
37
|
|
*/
|
38
|
|
private Map myReferenceConstraints = null;
|
39
|
|
|
40
|
|
private WhiteSpaceProcessing myWhiteSpaceProcessing = WhiteSpaceProcessing.NONE;
|
41
|
|
|
42
|
1613
|
public Constraints() {
|
43
|
1613
|
mySingleConstraints = new IConstraint[ConstraintType.getNbSingleConstraintTypes()];
|
44
|
1613
|
myMultipleConstraints = new List[ConstraintType.getNbMultipleConstraintTypes()];
|
45
|
1613
|
for (int i = 0; i < myMultipleConstraints.length; i++) {
|
46
|
17743
|
myMultipleConstraints[i] = new ArrayList();
|
47
|
|
}
|
48
|
|
}
|
49
|
|
|
50
|
701
|
public IConstraints shallowCopy() {
|
51
|
701
|
Constraints res = new Constraints();
|
52
|
701
|
System.arraycopy(mySingleConstraints, 0, res.mySingleConstraints, 0, mySingleConstraints.length);
|
53
|
701
|
for (int i = 0; i < myMultipleConstraints.length; i++) {
|
54
|
7711
|
res.myMultipleConstraints[i].addAll(myMultipleConstraints[i]);
|
55
|
|
}
|
56
|
701
|
if (null != myReferenceConstraints) {
|
57
|
0
|
res.myReferenceConstraints = new HashMap(myReferenceConstraints);
|
58
|
|
}
|
59
|
701
|
res.myWhiteSpaceProcessing = myWhiteSpaceProcessing;
|
60
|
701
|
return res;
|
61
|
|
}
|
62
|
|
|
63
|
6858
|
public void checkConstraints(ICheckContext aContext) {
|
64
|
6858
|
for (Iterator i = iterConstraints(); i.hasNext(); ) {
|
65
|
4841
|
IConstraint c = (IConstraint)i.next();
|
66
|
4841
|
aContext.check(c);
|
67
|
|
}
|
68
|
|
}
|
69
|
|
|
70
|
809
|
private void add(IConstraint aConstraint, boolean aLax, IConstraintViolations aViolations, IHasLocation aHasLocation) {
|
71
|
809
|
ConstraintType ct = aConstraint.getConstraintType();
|
72
|
809
|
int idx = ct.getIndex();
|
73
|
809
|
if (ct.isSingleNotMultiple()) {
|
74
|
733
|
IConstraint c = mySingleConstraints[idx];
|
75
|
733
|
if (c != null) {
|
76
|
174
|
if (aConstraint.isRestriction(c)) {
|
77
|
174
|
if (c.isFinal()) {
|
78
|
0
|
aViolations.add(XmlMessages.triedToRestrictFinalConstraint(aHasLocation));
|
79
|
|
}
|
80
|
174
|
mySingleConstraints[idx] = aConstraint;
|
81
|
|
} else {
|
82
|
0
|
if (!aLax) {
|
83
|
0
|
aViolations.add(XmlMessages.constraintIsNotARestriction(aHasLocation));
|
84
|
|
}
|
85
|
|
}
|
86
|
|
} else {
|
87
|
559
|
mySingleConstraints[idx] = aConstraint;
|
88
|
|
}
|
89
|
|
} else {
|
90
|
76
|
myMultipleConstraints[idx].add(aConstraint);
|
91
|
|
}
|
92
|
809
|
if (aConstraint instanceof IReferenceConstraint) {
|
93
|
28
|
if (null == myReferenceConstraints) {
|
94
|
22
|
myReferenceConstraints = new HashMap(17);
|
95
|
|
}
|
96
|
28
|
IReferenceConstraint rc = (IReferenceConstraint)aConstraint;
|
97
|
28
|
if (null != myReferenceConstraints.put(rc.getConstraintKey(), rc)) {
|
98
|
0
|
aViolations.add(XmlMessages.referenceConstraintKeyNotUnique(rc.getConstraintKey(), aHasLocation));
|
99
|
|
}
|
100
|
|
}
|
101
|
|
}
|
102
|
|
|
103
|
627
|
public void add(IConstraint aConstraint, IConstraintViolations aViolations, IHasLocation aHasLocation) {
|
104
|
627
|
add(aConstraint, true, aViolations, aHasLocation);
|
105
|
|
}
|
106
|
|
|
107
|
670
|
public void add(IConstraints aConstraints, IConstraintViolations aViolations, IHasLocation aHasLocation) {
|
108
|
670
|
for (Iterator i = aConstraints.iterConstraints(); i.hasNext(); ) {
|
109
|
182
|
IConstraint c = (IConstraint)i.next();
|
110
|
182
|
add(c, false, aViolations, aHasLocation);
|
111
|
|
}
|
112
|
670
|
if (WhiteSpaceProcessing.NONE != aConstraints.getWhiteSpaceProcessing()) {
|
113
|
48
|
setWhiteSpaceProcessing(aConstraints.getWhiteSpaceProcessing(), aViolations, aHasLocation);
|
114
|
|
}
|
115
|
|
}
|
116
|
|
|
117
|
12877
|
public List getConstraintList(ConstraintType aConstraintType) {
|
118
|
|
assert !aConstraintType.isSingleNotMultiple() :
|
119
|
|
"constraint type must be 'multiple': " + aConstraintType;
|
120
|
12877
|
return myMultipleConstraints[aConstraintType.getIndex()];
|
121
|
|
}
|
122
|
|
|
123
|
862
|
public IConstraint getConstraint(ConstraintType aConstraintType) {
|
124
|
|
assert aConstraintType.isSingleNotMultiple() :
|
125
|
|
"constraint type must be 'single': " + aConstraintType;
|
126
|
862
|
return mySingleConstraints[aConstraintType.getIndex()];
|
127
|
|
}
|
128
|
|
|
129
|
10245
|
public Iterator iterConstraints(ConstraintType aConstraintType) {
|
130
|
10245
|
if (null == aConstraintType) {
|
131
|
0
|
return iterConstraints();
|
132
|
|
}
|
133
|
10245
|
if (aConstraintType.isSingleNotMultiple()) {
|
134
|
0
|
IConstraint c = mySingleConstraints[aConstraintType.getIndex()];
|
135
|
0
|
if (null != c) {
|
136
|
0
|
return Collections.singletonList(c).iterator();
|
137
|
|
} else {
|
138
|
0
|
return Collections.EMPTY_LIST.iterator();
|
139
|
|
}
|
140
|
|
} else {
|
141
|
10245
|
return getConstraintList(aConstraintType).iterator();
|
142
|
|
}
|
143
|
|
}
|
144
|
|
|
145
|
7544
|
public Iterator iterConstraints() {
|
146
|
7544
|
List l = new ArrayList();
|
147
|
7544
|
for (int i = 0; i < mySingleConstraints.length; i++) {
|
148
|
105616
|
IConstraint c = mySingleConstraints[i];
|
149
|
105616
|
if (null != c) {
|
150
|
4541
|
l.add(c);
|
151
|
|
}
|
152
|
|
}
|
153
|
7544
|
for (int i = 0; i < myMultipleConstraints.length; i++) {
|
154
|
82984
|
l.addAll(myMultipleConstraints[i]);
|
155
|
|
}
|
156
|
7544
|
return l.iterator();
|
157
|
|
}
|
158
|
|
|
159
|
16
|
public boolean hasConstraint(IConstraint aConstraint) {
|
160
|
16
|
boolean res = false;
|
161
|
16
|
for (Iterator i = iterConstraints(); !res && i.hasNext(); ) {
|
162
|
0
|
res = aConstraint == i.next();
|
163
|
|
}
|
164
|
16
|
return res;
|
165
|
|
}
|
166
|
|
|
167
|
|
|
168
|
3269
|
public WhiteSpaceProcessing getWhiteSpaceProcessing() {
|
169
|
3269
|
return myWhiteSpaceProcessing;
|
170
|
|
}
|
171
|
|
|
172
|
96
|
public void setWhiteSpaceProcessing(WhiteSpaceProcessing aWhiteSpaceProcessing, IConstraintViolations aViolations, IHasLocation aHasLocation) {
|
173
|
96
|
if (null != myWhiteSpaceProcessing) {
|
174
|
96
|
if (aWhiteSpaceProcessing.isBefore(myWhiteSpaceProcessing)) {
|
175
|
0
|
aViolations.add(XmlMessages.whiteSpaceProcessingMustNotBeRelaxed(myWhiteSpaceProcessing, aWhiteSpaceProcessing, aHasLocation));
|
176
|
|
}
|
177
|
|
}
|
178
|
96
|
myWhiteSpaceProcessing = aWhiteSpaceProcessing;
|
179
|
|
}
|
180
|
|
|
181
|
207
|
public void setWhiteSpaceProcessing(WhiteSpaceProcessing aWhiteSpaceProcessing) {
|
182
|
207
|
if (null != myWhiteSpaceProcessing) {
|
183
|
|
assert (null == myWhiteSpaceProcessing) || !aWhiteSpaceProcessing.isBefore(myWhiteSpaceProcessing) :
|
184
|
|
"white space processing must not be relaxed.";
|
185
|
|
}
|
186
|
207
|
myWhiteSpaceProcessing = aWhiteSpaceProcessing;
|
187
|
|
}
|
188
|
|
|
189
|
0
|
public IReferenceConstraint getReferenceConstraint(String aKey) {
|
190
|
0
|
return (IReferenceConstraint)myReferenceConstraints.get(aKey);
|
191
|
|
}
|
192
|
|
|
193
|
78
|
public void setBuiltInConstraint(IBuiltInConstraint aConstraint) {
|
194
|
78
|
ConstraintType t = aConstraint.getConstraintType();
|
195
|
78
|
int idx = t.getIndex();
|
196
|
78
|
mySingleConstraints[idx] = aConstraint;
|
197
|
|
}
|
198
|
|
}
|
199
|
|
|