1
package com.thaiopensource.relaxng.output.xsd;
3
import com.thaiopensource.relaxng.output.xsd.basic.Attribute;
4
import com.thaiopensource.relaxng.output.xsd.basic.AttributeGroup;
5
import com.thaiopensource.relaxng.output.xsd.basic.AttributeGroupDefinition;
6
import com.thaiopensource.relaxng.output.xsd.basic.AttributeGroupRef;
7
import com.thaiopensource.relaxng.output.xsd.basic.AttributeUse;
8
import com.thaiopensource.relaxng.output.xsd.basic.ComplexTypeComplexContent;
9
import com.thaiopensource.relaxng.output.xsd.basic.ComplexTypeSimpleContent;
10
import com.thaiopensource.relaxng.output.xsd.basic.Element;
11
import com.thaiopensource.relaxng.output.xsd.basic.GroupDefinition;
12
import com.thaiopensource.relaxng.output.xsd.basic.GroupRef;
13
import com.thaiopensource.relaxng.output.xsd.basic.Particle;
14
import com.thaiopensource.relaxng.output.xsd.basic.ParticleAll;
15
import com.thaiopensource.relaxng.output.xsd.basic.ParticleChoice;
16
import com.thaiopensource.relaxng.output.xsd.basic.ParticleRepeat;
17
import com.thaiopensource.relaxng.output.xsd.basic.ParticleSequence;
18
import com.thaiopensource.relaxng.output.xsd.basic.ParticleVisitor;
19
import com.thaiopensource.relaxng.output.xsd.basic.RootDeclaration;
20
import com.thaiopensource.relaxng.output.xsd.basic.Schema;
21
import com.thaiopensource.relaxng.output.xsd.basic.SchemaTransformer;
22
import com.thaiopensource.relaxng.output.xsd.basic.SchemaWalker;
23
import com.thaiopensource.relaxng.output.xsd.basic.SimpleType;
24
import com.thaiopensource.relaxng.output.xsd.basic.SimpleTypeDefinition;
25
import com.thaiopensource.relaxng.output.xsd.basic.SimpleTypeList;
26
import com.thaiopensource.relaxng.output.xsd.basic.SimpleTypeRef;
27
import com.thaiopensource.relaxng.output.xsd.basic.SimpleTypeUnion;
28
import com.thaiopensource.relaxng.output.xsd.basic.WildcardElement;
29
import com.thaiopensource.util.VoidValue;
31
import java.util.HashMap;
32
import java.util.HashSet;
33
import java.util.Iterator;
37
class ComplexTypeSelector extends SchemaWalker {
39
final Set<Element> referencingElements = new HashSet<Element>();
40
final Set<String> referencingDefinitions = new HashSet<String>();
41
boolean nonTypeReference = false;
42
boolean desirable = false;
45
static class NamedComplexType {
46
private final boolean mixed;
48
NamedComplexType(boolean mixed) {
53
private final Map<String, Refs> groupMap = new HashMap<String, Refs>();
54
private final Map<String, Refs> attributeGroupMap = new HashMap<String, Refs>();
55
private final Map<String, Refs> simpleTypeMap = new HashMap<String, Refs>();
56
private String parentDefinition;
57
private Element parentElement;
58
private int nonTypeReference = 0;
59
private int undesirable = 0;
60
private final Map<String, NamedComplexType> complexTypeMap = new HashMap<String, NamedComplexType>();
61
private final Schema schema;
62
private final Transformer transformer;
63
private final ParticleVisitor<String> baseFinder = new BaseFinder();
65
class Transformer extends SchemaTransformer {
66
Transformer(Schema schema) {
70
public AttributeUse visitAttributeGroupRef(AttributeGroupRef a) {
71
if (complexTypeMap.get(a.getName()) != null)
72
return AttributeGroup.EMPTY;
76
public Particle visitGroupRef(GroupRef p) {
77
if (complexTypeMap.get(p.getName()) != null)
82
public Particle visitElement(Element p) {
86
public AttributeUse visitAttribute(Attribute a) {
91
class BaseFinder implements ParticleVisitor<String> {
92
public String visitGroupRef(GroupRef p) {
93
if (complexTypeMap.get(p.getName()) != null)
98
public String visitSequence(ParticleSequence p) {
99
return p.getChildren().get(0).accept(this);
102
public String visitElement(Element p) {
106
public String visitWildcardElement(WildcardElement p) {
110
public String visitRepeat(ParticleRepeat p) {
114
public String visitChoice(ParticleChoice p) {
118
public String visitAll(ParticleAll p) {
123
ComplexTypeSelector(Schema schema) {
124
this.schema = schema;
125
transformer = new Transformer(schema);
127
chooseComplexTypes(groupMap);
128
chooseComplexTypes(simpleTypeMap);
131
public void visitGroup(GroupDefinition def) {
132
parentDefinition = def.getName();
133
def.getParticle().accept(this);
134
parentDefinition = null;
137
public void visitSimpleType(SimpleTypeDefinition def) {
138
parentDefinition = def.getName();
139
def.getSimpleType().accept(this);
140
parentDefinition = null;
143
public void visitAttributeGroup(AttributeGroupDefinition def) {
144
parentDefinition = def.getName();
145
def.getAttributeUses().accept(this);
146
parentDefinition = null;
149
public void visitRoot(RootDeclaration decl) {
151
decl.getParticle().accept(this);
155
public VoidValue visitElement(Element p) {
156
Element oldParentElement = parentElement;
157
int oldNonTypeReference = nonTypeReference;
158
int oldExtensionReference = undesirable;
160
nonTypeReference = 0;
162
p.getComplexType().accept(this);
163
undesirable = oldExtensionReference;
164
nonTypeReference = oldNonTypeReference;
165
parentElement = oldParentElement;
166
return VoidValue.VOID;
169
public VoidValue visitSequence(ParticleSequence p) {
170
Iterator<Particle> iter = p.getChildren().iterator();
172
(iter.next()).accept(this);
175
while (iter.hasNext())
176
(iter.next()).accept(this);
178
return VoidValue.VOID;
181
public VoidValue visitChoice(ParticleChoice p) {
183
super.visitChoice(p);
185
return VoidValue.VOID;
188
public VoidValue visitAll(ParticleAll p) {
192
return VoidValue.VOID;
195
public VoidValue visitRepeat(ParticleRepeat p) {
197
super.visitRepeat(p);
199
return VoidValue.VOID;
202
public VoidValue visitAttribute(Attribute a) {
204
SimpleType t = a.getType();
208
return VoidValue.VOID;
211
public VoidValue visitComplexContent(ComplexTypeComplexContent t) {
212
super.visitComplexContent(t);
213
return VoidValue.VOID;
216
public VoidValue visitSimpleContent(ComplexTypeSimpleContent t) {
217
super.visitSimpleContent(t);
218
return VoidValue.VOID;
221
public VoidValue visitUnion(SimpleTypeUnion t) {
225
return VoidValue.VOID;
228
public VoidValue visitList(SimpleTypeList t) {
232
return VoidValue.VOID;
235
public VoidValue visitGroupRef(GroupRef p) {
236
noteRef(groupMap, p.getName());
237
return VoidValue.VOID;
240
public VoidValue visitAttributeGroupRef(AttributeGroupRef a) {
241
noteRef(attributeGroupMap, a.getName());
242
return VoidValue.VOID;
245
public VoidValue visitRef(SimpleTypeRef t) {
246
// Don't make it a complex type unless there are attributes
248
noteRef(simpleTypeMap, t.getName());
250
return VoidValue.VOID;
253
private void noteRef(Map<String, Refs> map, String name) {
254
Refs refs = lookupRefs(map, name);
255
if (nonTypeReference > 0)
256
refs.nonTypeReference = true;
257
else if (parentElement != null)
258
refs.referencingElements.add(parentElement);
259
else if (parentDefinition != null)
260
refs.referencingDefinitions.add(parentDefinition);
261
if (undesirable == 0)
262
refs.desirable = true;
265
static private Refs lookupRefs(Map<String, Refs> map, String name) {
266
Refs refs = map.get(name);
274
private void chooseComplexTypes(Map<String, Refs> definitionMap) {
276
boolean foundOne = false;
277
for (Map.Entry<String, Refs> entry : definitionMap.entrySet()) {
278
String name = entry.getKey();
279
if (createComplexType(name,
281
attributeGroupMap.get(name)))
289
private boolean createComplexType(String name, Refs childRefs, Refs attributeGroupRefs) {
290
if (complexTypeMap.get(name) != null)
292
if (childRefs.nonTypeReference)
294
if (attributeGroupRefs == null) {
295
if (!childRefs.desirable)
298
else if (!attributeGroupRefs.referencingDefinitions.equals(childRefs.referencingDefinitions)
299
|| !attributeGroupRefs.referencingElements.equals(childRefs.referencingElements))
301
boolean mixed = false;
302
boolean hadReference = false;
303
for (Element elem : childRefs.referencingElements) {
304
boolean m = elem.getComplexType().isMixed();
312
for (String def : childRefs.referencingDefinitions) {
313
NamedComplexType ct = complexTypeMap.get(def);
316
if (ct.mixed != mixed) {
323
complexTypeMap.put(name, new NamedComplexType(mixed));
328
private Particle transformParticle(Particle particle) {
329
if (particle == null)
331
return particle.accept(transformer);
334
private AttributeUse transformAttributeUses(AttributeUse atts) {
335
return atts.accept(transformer);
338
String particleBase(Particle particle) {
339
if (particle == null)
341
return particle.accept(baseFinder);
344
ComplexTypeComplexContentExtension transformComplexContent(ComplexTypeComplexContent ct) {
345
String base = particleBase(ct.getParticle());
347
Particle particle = transformParticle(ct.getParticle());
348
return new ComplexTypeComplexContentExtension(transformAttributeUses(ct.getAttributeUses()),
350
particle != null && ct.isMixed(),
353
return new ComplexTypeComplexContentExtension(ct);
357
ComplexTypeSimpleContentExtension transformSimpleContent(ComplexTypeSimpleContent ct) {
358
SimpleType st = ct.getSimpleType();
359
if (st instanceof SimpleTypeRef) {
360
String name = ((SimpleTypeRef)st).getName();
361
NamedComplexType nct = complexTypeMap.get(name);
363
return new ComplexTypeSimpleContentExtension(transformAttributeUses(ct.getAttributeUses()), null, name);
365
return new ComplexTypeSimpleContentExtension(ct);
368
ComplexTypeComplexContentExtension createComplexTypeForGroup(String name, NamespaceManager nsm) {
369
NamedComplexType ct = complexTypeMap.get(name);
372
AttributeGroupDefinition attDef = schema.getAttributeGroup(name);
373
AttributeUse att = attDef == null ? AttributeGroup.EMPTY : attDef.getAttributeUses();
374
GroupDefinition def = schema.getGroup(name);
375
if (nsm.getGroupDefinitionAbstractElementName(def) != null)
376
return new ComplexTypeComplexContentExtension(att,
377
new GroupRef(def.getParticle().getLocation(), null, name),
380
return transformComplexContent(new ComplexTypeComplexContent(att,
385
ComplexTypeSimpleContentExtension createComplexTypeForSimpleType(String name) {
386
NamedComplexType ct = complexTypeMap.get(name);
389
AttributeGroupDefinition attDef = schema.getAttributeGroup(name);
390
AttributeUse att = attDef == null ? AttributeGroup.EMPTY : attDef.getAttributeUses();
391
return transformSimpleContent(new ComplexTypeSimpleContent(att,
392
schema.getSimpleType(name).getSimpleType()));
395
boolean isComplexType(String name) {
396
return complexTypeMap.get(name) != null;