~ubuntu-branches/ubuntu/utopic/jing-trang/utopic

« back to all changes in this revision

Viewing changes to mod/convert-to-xsd/src/main/com/thaiopensource/relaxng/output/xsd/ComplexTypeSelector.java

  • Committer: Bazaar Package Importer
  • Author(s): Samuel Thibault
  • Date: 2009-09-01 15:53:03 UTC
  • Revision ID: james.westby@ubuntu.com-20090901155303-2kweef05h5v9j3ni
Tags: upstream-20090818
ImportĀ upstreamĀ versionĀ 20090818

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package com.thaiopensource.relaxng.output.xsd;
 
2
 
 
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;
 
30
 
 
31
import java.util.HashMap;
 
32
import java.util.HashSet;
 
33
import java.util.Iterator;
 
34
import java.util.Map;
 
35
import java.util.Set;
 
36
 
 
37
class ComplexTypeSelector extends SchemaWalker {
 
38
  static class Refs {
 
39
    final Set<Element> referencingElements = new HashSet<Element>();
 
40
    final Set<String> referencingDefinitions = new HashSet<String>();
 
41
    boolean nonTypeReference = false;
 
42
    boolean desirable = false;
 
43
  }
 
44
 
 
45
  static class NamedComplexType {
 
46
    private final boolean mixed;
 
47
 
 
48
    NamedComplexType(boolean mixed) {
 
49
      this.mixed = mixed;
 
50
    }
 
51
  }
 
52
 
 
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();
 
64
 
 
65
  class Transformer extends SchemaTransformer {
 
66
    Transformer(Schema schema) {
 
67
      super(schema);
 
68
    }
 
69
 
 
70
    public AttributeUse visitAttributeGroupRef(AttributeGroupRef a) {
 
71
      if (complexTypeMap.get(a.getName()) != null)
 
72
        return AttributeGroup.EMPTY;
 
73
      return a;
 
74
    }
 
75
 
 
76
    public Particle visitGroupRef(GroupRef p) {
 
77
      if (complexTypeMap.get(p.getName()) != null)
 
78
        return null;
 
79
      return p;
 
80
    }
 
81
 
 
82
    public Particle visitElement(Element p) {
 
83
      return p;
 
84
    }
 
85
 
 
86
    public AttributeUse visitAttribute(Attribute a) {
 
87
      return a;
 
88
    }
 
89
  }
 
90
 
 
91
  class BaseFinder implements ParticleVisitor<String> {
 
92
    public String visitGroupRef(GroupRef p) {
 
93
      if (complexTypeMap.get(p.getName()) != null)
 
94
        return p.getName();
 
95
      return null;
 
96
    }
 
97
 
 
98
    public String visitSequence(ParticleSequence p) {
 
99
      return p.getChildren().get(0).accept(this);
 
100
    }
 
101
 
 
102
    public String visitElement(Element p) {
 
103
      return null;
 
104
    }
 
105
 
 
106
    public String visitWildcardElement(WildcardElement p) {
 
107
      return null;
 
108
    }
 
109
 
 
110
    public String visitRepeat(ParticleRepeat p) {
 
111
      return null;
 
112
    }
 
113
 
 
114
    public String visitChoice(ParticleChoice p) {
 
115
      return null;
 
116
    }
 
117
 
 
118
    public String visitAll(ParticleAll p) {
 
119
      return null;
 
120
    }
 
121
  }
 
122
 
 
123
  ComplexTypeSelector(Schema schema) {
 
124
    this.schema = schema;
 
125
    transformer = new Transformer(schema);
 
126
    schema.accept(this);
 
127
    chooseComplexTypes(groupMap);
 
128
    chooseComplexTypes(simpleTypeMap);
 
129
  }
 
130
 
 
131
  public void visitGroup(GroupDefinition def) {
 
132
    parentDefinition = def.getName();
 
133
    def.getParticle().accept(this);
 
134
    parentDefinition = null;
 
135
  }
 
136
 
 
137
  public void visitSimpleType(SimpleTypeDefinition def) {
 
138
    parentDefinition = def.getName();
 
139
    def.getSimpleType().accept(this);
 
140
    parentDefinition = null;
 
141
  }
 
142
 
 
143
  public void visitAttributeGroup(AttributeGroupDefinition def) {
 
144
    parentDefinition = def.getName();
 
145
    def.getAttributeUses().accept(this);
 
146
    parentDefinition = null;
 
147
  }
 
148
 
 
149
  public void visitRoot(RootDeclaration decl) {
 
150
    undesirable++;
 
151
    decl.getParticle().accept(this);
 
152
    undesirable--;
 
153
  }
 
154
 
 
155
  public VoidValue visitElement(Element p) {
 
156
    Element oldParentElement = parentElement;
 
157
    int oldNonTypeReference = nonTypeReference;
 
158
    int oldExtensionReference = undesirable;
 
159
    parentElement = p;
 
160
    nonTypeReference = 0;
 
161
    undesirable = 0;
 
162
    p.getComplexType().accept(this);
 
163
    undesirable = oldExtensionReference;
 
164
    nonTypeReference = oldNonTypeReference;
 
165
    parentElement = oldParentElement;
 
166
    return VoidValue.VOID;
 
167
  }
 
168
 
 
169
  public VoidValue visitSequence(ParticleSequence p) {
 
170
    Iterator<Particle> iter = p.getChildren().iterator();
 
171
    undesirable++;
 
172
    (iter.next()).accept(this);
 
173
    undesirable--;
 
174
    nonTypeReference++;
 
175
    while (iter.hasNext())
 
176
      (iter.next()).accept(this);
 
177
    nonTypeReference--;
 
178
    return VoidValue.VOID;
 
179
  }
 
180
 
 
181
  public VoidValue visitChoice(ParticleChoice p) {
 
182
    nonTypeReference++;
 
183
    super.visitChoice(p);
 
184
    nonTypeReference--;
 
185
    return VoidValue.VOID;
 
186
  }
 
187
 
 
188
  public VoidValue visitAll(ParticleAll p) {
 
189
    nonTypeReference++;
 
190
    super.visitAll(p);
 
191
    nonTypeReference--;
 
192
    return VoidValue.VOID;
 
193
  }
 
194
 
 
195
  public VoidValue visitRepeat(ParticleRepeat p) {
 
196
    nonTypeReference++;
 
197
    super.visitRepeat(p);
 
198
    nonTypeReference--;
 
199
    return VoidValue.VOID;
 
200
  }
 
201
 
 
202
  public VoidValue visitAttribute(Attribute a) {
 
203
    nonTypeReference++;
 
204
    SimpleType t = a.getType();
 
205
    if (t != null)
 
206
      t.accept(this);
 
207
    nonTypeReference--;
 
208
    return VoidValue.VOID;
 
209
  }
 
210
 
 
211
  public VoidValue visitComplexContent(ComplexTypeComplexContent t) {
 
212
    super.visitComplexContent(t);
 
213
    return VoidValue.VOID;
 
214
  }
 
215
 
 
216
  public VoidValue visitSimpleContent(ComplexTypeSimpleContent t) {
 
217
    super.visitSimpleContent(t);
 
218
    return VoidValue.VOID;
 
219
  }
 
220
 
 
221
  public VoidValue visitUnion(SimpleTypeUnion t) {
 
222
    nonTypeReference++;
 
223
    super.visitUnion(t);
 
224
    nonTypeReference--;
 
225
    return VoidValue.VOID;
 
226
  }
 
227
 
 
228
  public VoidValue visitList(SimpleTypeList t) {
 
229
    nonTypeReference++;
 
230
    super.visitList(t);
 
231
    nonTypeReference--;
 
232
    return VoidValue.VOID;
 
233
  }
 
234
 
 
235
  public VoidValue visitGroupRef(GroupRef p) {
 
236
    noteRef(groupMap, p.getName());
 
237
    return VoidValue.VOID;
 
238
  }
 
239
 
 
240
  public VoidValue visitAttributeGroupRef(AttributeGroupRef a) {
 
241
    noteRef(attributeGroupMap, a.getName());
 
242
    return VoidValue.VOID;
 
243
  }
 
244
 
 
245
  public VoidValue visitRef(SimpleTypeRef t) {
 
246
    // Don't make it a complex type unless there are attributes
 
247
    undesirable++;
 
248
    noteRef(simpleTypeMap, t.getName());
 
249
    undesirable--;
 
250
    return VoidValue.VOID;
 
251
  }
 
252
 
 
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;
 
263
  }
 
264
 
 
265
  static private Refs lookupRefs(Map<String, Refs> map, String name) {
 
266
    Refs refs = map.get(name);
 
267
    if (refs == null) {
 
268
      refs = new Refs();
 
269
      map.put(name, refs);
 
270
    }
 
271
    return refs;
 
272
  }
 
273
 
 
274
  private void chooseComplexTypes(Map<String, Refs> definitionMap) {
 
275
    for (;;) {
 
276
      boolean foundOne = false;
 
277
      for (Map.Entry<String, Refs> entry : definitionMap.entrySet()) {
 
278
        String name = entry.getKey();
 
279
        if (createComplexType(name,
 
280
                              entry.getValue(),
 
281
                              attributeGroupMap.get(name)))
 
282
          foundOne = true;
 
283
      }
 
284
      if (!foundOne)
 
285
        break;
 
286
    }
 
287
  }
 
288
 
 
289
  private boolean createComplexType(String name, Refs childRefs, Refs attributeGroupRefs) {
 
290
    if (complexTypeMap.get(name) != null)
 
291
      return false;
 
292
    if (childRefs.nonTypeReference)
 
293
      return false;
 
294
    if (attributeGroupRefs == null) {
 
295
      if (!childRefs.desirable)
 
296
        return false;
 
297
    }
 
298
    else if (!attributeGroupRefs.referencingDefinitions.equals(childRefs.referencingDefinitions)
 
299
             || !attributeGroupRefs.referencingElements.equals(childRefs.referencingElements))
 
300
      return false;
 
301
    boolean mixed = false;
 
302
    boolean hadReference = false;
 
303
    for (Element elem : childRefs.referencingElements) {
 
304
      boolean m = elem.getComplexType().isMixed();
 
305
      if (m != mixed) {
 
306
        if (hadReference)
 
307
          return false;
 
308
        mixed = m;
 
309
      }
 
310
      hadReference = true;
 
311
    }
 
312
    for (String def : childRefs.referencingDefinitions) {
 
313
      NamedComplexType ct = complexTypeMap.get(def);
 
314
      if (ct == null)
 
315
        return false;
 
316
      if (ct.mixed != mixed) {
 
317
        if (hadReference)
 
318
          return false;
 
319
        mixed = ct.mixed;
 
320
      }
 
321
      hadReference = true;
 
322
    }
 
323
    complexTypeMap.put(name, new NamedComplexType(mixed));
 
324
    return true;
 
325
  }
 
326
 
 
327
 
 
328
  private Particle transformParticle(Particle particle) {
 
329
    if (particle == null)
 
330
      return particle;
 
331
    return particle.accept(transformer);
 
332
  }
 
333
 
 
334
  private AttributeUse transformAttributeUses(AttributeUse atts) {
 
335
    return atts.accept(transformer);
 
336
  }
 
337
 
 
338
  String particleBase(Particle particle) {
 
339
    if (particle == null)
 
340
      return null;
 
341
    return particle.accept(baseFinder);
 
342
  }
 
343
 
 
344
  ComplexTypeComplexContentExtension transformComplexContent(ComplexTypeComplexContent ct) {
 
345
    String base = particleBase(ct.getParticle());
 
346
    if (base != null) {
 
347
      Particle particle = transformParticle(ct.getParticle());
 
348
      return new ComplexTypeComplexContentExtension(transformAttributeUses(ct.getAttributeUses()),
 
349
                                                    particle,
 
350
                                                    particle != null && ct.isMixed(),
 
351
                                                    base);
 
352
    }
 
353
    return new ComplexTypeComplexContentExtension(ct);
 
354
  }
 
355
 
 
356
 
 
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);
 
362
      if (nct != null)
 
363
        return new ComplexTypeSimpleContentExtension(transformAttributeUses(ct.getAttributeUses()), null, name);
 
364
    }
 
365
    return new ComplexTypeSimpleContentExtension(ct);
 
366
  }
 
367
 
 
368
  ComplexTypeComplexContentExtension createComplexTypeForGroup(String name, NamespaceManager nsm) {
 
369
    NamedComplexType ct = complexTypeMap.get(name);
 
370
    if (ct == null)
 
371
      return null;
 
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),
 
378
                                                    ct.mixed,
 
379
                                                    null);
 
380
    return transformComplexContent(new ComplexTypeComplexContent(att,
 
381
                                                                 def.getParticle(),
 
382
                                                                 ct.mixed));
 
383
  }
 
384
 
 
385
  ComplexTypeSimpleContentExtension createComplexTypeForSimpleType(String name) {
 
386
    NamedComplexType ct = complexTypeMap.get(name);
 
387
    if (ct == null)
 
388
      return null;
 
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()));
 
393
  }
 
394
 
 
395
  boolean isComplexType(String name) {
 
396
    return complexTypeMap.get(name) != null;
 
397
  }
 
398
}