1
2
3
4
5
6
7
8 package de.nierbeck.timeTrack.model.impl.runtime;
9
10 import java.util.HashMap;
11 import java.util.HashSet;
12 import java.util.Iterator;
13 import java.util.Map;
14
15 import javax.xml.bind.ValidationEvent;
16 import javax.xml.bind.ValidationEventHandler;
17 import javax.xml.bind.helpers.NotIdentifiableEventImpl;
18 import javax.xml.bind.helpers.ValidationEventImpl;
19 import javax.xml.bind.helpers.ValidationEventLocatorImpl;
20
21 import org.xml.sax.SAXException;
22
23 import com.sun.xml.bind.ProxyGroup;
24 import com.sun.xml.bind.serializer.AbortSerializationException;
25 import com.sun.xml.bind.validator.Messages;
26
27 /***
28 * Maintains information that needs to be stored across validations of multiple
29 * objects.
30 *
31 * Specifically, this object is responsible for:
32 *
33 * <ol>
34 * <li>detecting a cycle in a content tree by keeping track of objects that
35 * were validated.
36 *
37 * <li>keeping an instance of NamespaceContextImpl, which is shared by all
38 * MSVValidators.
39 *
40 * <li>keeping a reference to {@link ValidationErrorHandler}. MSVValidators
41 * should use this error handler to report any error.
42 * </ol>
43 */
44 class ValidationContext {
45 final DefaultJAXBContextImpl jaxbContext;
46
47 /***
48 * @param validateID
49 * if true, ID/IDREF validation will be performed.
50 */
51 ValidationContext(DefaultJAXBContextImpl _context,
52 ValidationEventHandler _eventHandler, boolean validateID) {
53 this.jaxbContext = _context;
54 this.eventHandler = _eventHandler;
55 this.validateID = validateID;
56 }
57
58
59
60
61
62
63
64 /*** Set of all validated objects. Used to detect a cycle. */
65 private final HashSet validatedObjects = new HashSet();
66
67 /***
68 * Validates the sub-tree rooted at <code>vo</code> and reports any
69 * errors/warnings to the error handler.
70 */
71 public void validate(ValidatableObject vo) throws SAXException {
72 if (validatedObjects.add(ProxyGroup.unwrap(vo))) {
73
74 MSVValidator.validate(jaxbContext, this, vo);
75 } else {
76
77 reportEvent(vo, Messages.format(Messages.CYCLE_DETECTED));
78 }
79 }
80
81
82
83
84
85
86
87 /*** namespace context. */
88 private final NamespaceContextImpl nsContext = new NamespaceContextImpl(
89 null);
90
91 public NamespaceContextImpl getNamespaceContext() {
92 return nsContext;
93 }
94
95
96
97
98
99
100 /*** ID/IDREF validation is done only when this flag is true. */
101 private final boolean validateID;
102
103 private final HashSet IDs = new HashSet();
104
105 private final HashMap IDREFs = new HashMap();
106
107 public String onID(XMLSerializable owner, String value) throws SAXException {
108
109 if (!validateID)
110 return value;
111
112 if (!IDs.add(value)) {
113
114
115
116 reportEvent(jaxbContext.getGrammarInfo().castToValidatableObject(
117 owner), Messages.format(Messages.DUPLICATE_ID, value));
118 }
119
120 return value;
121 }
122
123 public String onIDREF(XMLSerializable referer, String value)
124 throws SAXException {
125 if (!validateID)
126 return value;
127
128 if (IDs.contains(value))
129 return value;
130
131
132 IDREFs.put(value, referer);
133
134 return value;
135 }
136
137 /*** Tests if all IDREFs have corresponding IDs. */
138 protected void reconcileIDs() throws SAXException {
139 if (!validateID)
140 return;
141
142 for (Iterator itr = IDREFs.entrySet().iterator(); itr.hasNext();) {
143 Map.Entry e = (Map.Entry) itr.next();
144
145 if (IDs.contains(e.getKey()))
146 continue;
147
148
149 ValidatableObject source = (ValidatableObject) e.getValue();
150 reportEvent(source, new NotIdentifiableEventImpl(
151 ValidationEvent.ERROR, Messages.format(
152 Messages.ID_NOT_FOUND, e.getKey()),
153 new ValidationEventLocatorImpl(source)));
154 }
155
156 IDREFs.clear();
157 }
158
159
160
161
162
163
164 private final ValidationEventHandler eventHandler;
165
166 /***
167 * Reports an error to the application.
168 */
169 public void reportEvent(ValidatableObject source, String formattedMessage)
170 throws AbortSerializationException {
171 reportEvent(source, new ValidationEventImpl(ValidationEvent.ERROR,
172 formattedMessage, new ValidationEventLocatorImpl(source)));
173 }
174
175 /***
176 * Reports an error to the client. This version should be used when an
177 * exception is thrown from sub-modules.
178 */
179 public void reportEvent(ValidatableObject source, Exception nestedException)
180 throws AbortSerializationException {
181 reportEvent(source, new ValidationEventImpl(ValidationEvent.ERROR,
182 nestedException.toString(), new ValidationEventLocatorImpl(
183 source), nestedException));
184 }
185
186 public void reportEvent(ValidatableObject source, ValidationEvent event)
187 throws AbortSerializationException {
188 boolean r;
189
190 try {
191 r = eventHandler.handleEvent(event);
192 } catch (RuntimeException re) {
193
194
195 r = false;
196 }
197
198 if (!r) {
199
200 throw new AbortSerializationException(event.getMessage());
201 }
202 }
203
204 }