1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package de.mindcrimeilab.xsanalyzer;
19
20 import java.beans.PropertyChangeListener;
21 import java.beans.PropertyChangeSupport;
22 import java.util.HashSet;
23 import java.util.LinkedList;
24 import java.util.List;
25 import java.util.Set;
26 import java.util.Stack;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.xerces.xs.XSAttributeDeclaration;
31 import org.apache.xerces.xs.XSAttributeUse;
32 import org.apache.xerces.xs.XSComplexTypeDefinition;
33 import org.apache.xerces.xs.XSConstants;
34 import org.apache.xerces.xs.XSElementDeclaration;
35 import org.apache.xerces.xs.XSModel;
36 import org.apache.xerces.xs.XSModelGroup;
37 import org.apache.xerces.xs.XSNamedMap;
38 import org.apache.xerces.xs.XSObject;
39 import org.apache.xerces.xs.XSObjectList;
40 import org.apache.xerces.xs.XSParticle;
41 import org.apache.xerces.xs.XSSimpleTypeDefinition;
42 import org.apache.xerces.xs.XSTerm;
43 import org.apache.xerces.xs.XSTypeDefinition;
44
45 import de.mindcrimeilab.xsanalyzer.util.XSModelHelper;
46 import de.mindcrimeilab.xsanalyzer.xsext.AnonymousTypeFactory;
47
48
49
50
51
52
53
54
55
56
57
58
59 public class XsModelWalker {
60
61 public static final String PC_CURRENT_COMPONENT_NAME = XsModelWalker.class.getName() + ".pc.currentComponentName";
62
63 private static final Log logger = LogFactory.getLog("xsAnalyzerApplicationLogger");
64
65 private final PropertyChangeSupport changeSupport;
66
67 private final Stack<XSObject> seenComponents;
68
69 private final List<XsComponentWorker> workerList;
70
71 private final Set<XSObject> analyzedComponents;
72
73 public XsModelWalker() {
74 changeSupport = new PropertyChangeSupport(this);
75 seenComponents = new Stack<XSObject>();
76 analyzedComponents = new HashSet<XSObject>();
77 workerList = new LinkedList<XsComponentWorker>();
78 }
79
80
81
82
83
84
85 public void addPropertyChangeListener(PropertyChangeListener listener) {
86 changeSupport.addPropertyChangeListener(listener);
87 }
88
89
90
91
92
93
94
95 public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
96 changeSupport.addPropertyChangeListener(propertyName, listener);
97 }
98
99
100
101
102
103 public PropertyChangeListener[] getPropertyChangeListeners() {
104 return changeSupport.getPropertyChangeListeners();
105 }
106
107
108
109
110
111
112 public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
113 return changeSupport.getPropertyChangeListeners(propertyName);
114 }
115
116
117
118
119
120
121 public boolean hasListeners(String propertyName) {
122 return changeSupport.hasListeners(propertyName);
123 }
124
125
126
127
128
129 public void removePropertyChangeListener(PropertyChangeListener listener) {
130 changeSupport.removePropertyChangeListener(listener);
131 }
132
133
134
135
136
137
138
139 public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
140 changeSupport.removePropertyChangeListener(propertyName, listener);
141 }
142
143
144
145 public boolean addWorker(XsComponentWorker worker) {
146 return workerList.add(worker);
147 }
148
149 public boolean addWorkers(List<XsComponentWorker> workerList) {
150 return workerList.addAll(workerList);
151 }
152
153 public boolean removeWorker(XsComponentWorker worker) {
154 return workerList.remove(worker);
155 }
156
157 public void clearWorkers() {
158 workerList.clear();
159 }
160
161 public void walkModel(XSModel model) {
162 List<? extends XSObject> globalComponents = initialize(model);
163
164 for (XSObject object : globalComponents) {
165 XsModelWalker.logger.debug("Global component [{" + object.getNamespace() + "}:" + object.getName() + "]");
166 visitComponent(object, null);
167 }
168 }
169
170 private void visitComponent(XSObject object, XSObject parent) {
171 if (seenComponents.contains(object) || analyzedComponents.contains(object)) { return; }
172 seenComponents.push(object);
173
174 changeSupport.firePropertyChange(XsModelWalker.PC_CURRENT_COMPONENT_NAME, null, object.getName());
175
176 final XSTypeDefinition typeDefinition;
177 switch (object.getType()) {
178 case XSConstants.TYPE_DEFINITION:
179 XSTypeDefinition type = (XSTypeDefinition) object;
180 if (type.getAnonymous()) {
181 XsModelWalker.logger.debug("Handling anonymous type");
182 type = AnonymousTypeFactory.getProxy(type);
183 }
184 typeDefinition = onVisitTypeDefinition(type, parent);
185 break;
186 case XSConstants.ELEMENT_DECLARATION:
187 XSElementDeclaration elementDeclaration = (XSElementDeclaration) object;
188 typeDefinition = onVisitElementDeclaration(elementDeclaration, parent);
189
190 break;
191 case XSConstants.ATTRIBUTE_DECLARATION:
192 throw new RuntimeException("Not implemented yet - XSConstants.ATTRIBUTE_DECLARATION !");
193 case XSConstants.NOTATION_DECLARATION:
194 throw new RuntimeException("Not implemented yet - XSConstants.NOTATION_DECLARATION !");
195 case XSConstants.MODEL_GROUP_DEFINITION:
196 throw new RuntimeException("Not implemented yet - XSConstants.MODEL_GROUP_DEFINITION !");
197 default:
198 XsModelWalker.logger.info("Unknown component type [" + object.getType() + "]");
199 typeDefinition = null;
200 break;
201 }
202
203 if (null != typeDefinition) {
204
205 XsModelWalker.logger.debug("==> of base type [{" + typeDefinition.getNamespace() + "}:" + typeDefinition.getName() + "]");
206 visitComponent(typeDefinition, object);
207 }
208
209 seenComponents.pop();
210 analyzedComponents.add(object);
211 }
212
213 private XSTypeDefinition onVisitTypeDefinition(XSTypeDefinition type, XSObject parent) {
214 final XSTypeDefinition baseType;
215 switch (type.getTypeCategory()) {
216 case XSTypeDefinition.COMPLEX_TYPE:
217 XsModelWalker.logger.debug("==> Found complex type definition");
218 XSComplexTypeDefinition ctypedef = (XSComplexTypeDefinition) type;
219 baseType = onVisitComplexTypeDefinition(ctypedef, parent);
220
221 break;
222 case XSTypeDefinition.SIMPLE_TYPE:
223 XsModelWalker.logger.debug("==> Found simple type definition");
224 XSSimpleTypeDefinition stypedef = (XSSimpleTypeDefinition) type;
225 baseType = onVisitSimpleTypeDefinition(stypedef, parent);
226 break;
227 default:
228 baseType = null;
229 break;
230 }
231
232
233
234
235
236 return baseType;
237 }
238
239
240
241
242
243
244
245 private XSTypeDefinition onVisitSimpleTypeDefinition(XSSimpleTypeDefinition stypedef, XSObject parent) {
246 executeWorker(stypedef, parent);
247
248
249 switch (stypedef.getVariety()) {
250 case XSSimpleTypeDefinition.VARIETY_ABSENT:
251
252 XsModelWalker.logger.debug("==> Found simple type variety absent");
253 break;
254 case XSSimpleTypeDefinition.VARIETY_ATOMIC:
255
256 XsModelWalker.logger.debug("==> Found simple type variety atomic");
257 break;
258 case XSSimpleTypeDefinition.VARIETY_LIST:
259
260 XsModelWalker.logger.debug("==> Found simple type variety list");
261 XSSimpleTypeDefinition itemType = stypedef.getItemType();
262 visitComponent(itemType, stypedef);
263 break;
264 case XSSimpleTypeDefinition.VARIETY_UNION:
265
266 XsModelWalker.logger.debug("==> Found simple type variety union");
267 XSObjectList unionedTypes = stypedef.getMemberTypes();
268 if (null != unionedTypes) {
269 for (int i = 0; i < unionedTypes.getLength(); ++i) {
270 visitComponent(unionedTypes.item(i), stypedef);
271 }
272 }
273 break;
274 default:
275 XsModelWalker.logger.warn("-------------- UNKNOWN SIMPLE TYPE VARIETY OF TYPE [" + stypedef.getVariety() + "]");
276 throw new RuntimeException("Unexpected branch selection - Not implemented");
277 }
278
279 return XSModelHelper.getBaseType(stypedef);
280 }
281
282 private XSTypeDefinition onVisitElementDeclaration(XSElementDeclaration elementDeclaration, XSObject parent) {
283 executeWorker(elementDeclaration, parent);
284 XSTypeDefinition typedef = elementDeclaration.getTypeDefinition();
285 return typedef;
286 }
287
288 private XSTypeDefinition onVisitComplexTypeDefinition(XSComplexTypeDefinition ctypedef, XSObject parent) {
289 executeWorker(ctypedef, parent);
290
291 XSObjectList attributes = ctypedef.getAttributeUses();
292 onVisitAttributes(attributes, ctypedef);
293
294 XSParticle particle = ctypedef.getParticle();
295 if (null != particle) {
296 XSTerm term = particle.getTerm();
297
298
299 onVisitTerm(ctypedef, term);
300 }
301
302 return ctypedef.getBaseType();
303 }
304
305
306
307
308
309 private void onVisitTerm(XSComplexTypeDefinition ctypedef, XSTerm term) {
310 short termType = term.getType();
311
312 switch (termType) {
313 case XSConstants.MODEL_GROUP:
314 XsModelWalker.logger.debug("==> found model group");
315 XSModelGroup group = (XSModelGroup) term;
316 XSObjectList list = group.getParticles();
317 for (int i = 0; i < list.getLength(); ++i) {
318 XSParticle part = (XSParticle) list.item(i);
319 XSTerm item = part.getTerm();
320 XsModelWalker.logger.debug("==--> embedded [{" + item.getNamespace() + "}:" + item.getName() + "]");
321 onVisitTerm(ctypedef, item);
322 }
323 break;
324 case XSConstants.ELEMENT_DECLARATION:
325 XsModelWalker.logger.debug("==> found element declaration");
326 visitComponent(term, ctypedef);
327 break;
328 case XSConstants.WILDCARD:
329 XsModelWalker.logger.debug("==> found wildcard");
330
331
332 break;
333 default:
334 XsModelWalker.logger.warn("-------------- UNKNOWN PARTICLE TYPE OF TYPE [" + termType + "]");
335 throw new RuntimeException("Unexpected branch selection - Not implemented");
336 }
337 }
338
339 private void onVisitAttributes(XSObjectList attributeUsesList, XSObject parent) {
340 for (int i = 0; i < attributeUsesList.getLength(); ++i) {
341 XSAttributeUse xsAttribute = (XSAttributeUse) attributeUsesList.item(i);
342
343
344 XSAttributeDeclaration xsAttributeType = xsAttribute.getAttrDeclaration();
345
346 XsModelWalker.logger.debug("--> Attribute [{" + xsAttributeType.getNamespace() + "}:" + xsAttributeType.getName() + "]");
347
348 executeWorker(xsAttributeType, parent);
349
350
351
352
353
354
355
356
357
358
359
360 XSComplexTypeDefinition ctypedef = xsAttributeType.getEnclosingCTDefinition();
361 if (null != ctypedef) {
362 visitComponent(ctypedef, parent);
363 }
364
365 visitComponent(xsAttributeType.getTypeDefinition(), parent);
366 }
367
368 }
369
370 private List<? extends XSObject> initialize(XSModel model) {
371 List<? extends XSObject> global = new LinkedList<XSObject>();
372
373
374
375
376
377
378
379
380
381
382
383 XSNamedMap typesMap = model.getComponents(XSConstants.TYPE_DEFINITION);
384 XSModelHelper.addComponents(typesMap, global);
385
386
387 XSNamedMap elementsMap = model.getComponents(XSConstants.ELEMENT_DECLARATION);
388
389 XSModelHelper.addComponents(elementsMap, global);
390
391 return global;
392 }
393
394 private void executeWorker(XSObject object, XSObject parent) {
395 for (XsComponentWorker worker : workerList) {
396 if (worker.isSupported(object)) {
397 worker.execute(object, parent);
398 }
399 }
400 }
401 }