~ubuntu-branches/ubuntu/precise/classpath/precise

« back to all changes in this revision

Viewing changes to gnu/xml/validation/xmlschema/XMLSchemaBuilder.java

  • Committer: Bazaar Package Importer
  • Author(s): Michael Koch
  • Date: 2006-05-27 16:11:15 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20060527161115-h6e39eposdt5snb6
Tags: 2:0.91-3
* Install header files to /usr/include/classpath.
* debian/control: classpath: Conflict with jamvm < 1.4.3 and
  cacao < 0.96 (Closes: #368172).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* XMLSchemaBuilder.java -- 
 
2
   Copyright (C) 2006  Free Software Foundation, Inc.
 
3
 
 
4
This file is part of GNU Classpath.
 
5
 
 
6
GNU Classpath is free software; you can redistribute it and/or modify
 
7
it under the terms of the GNU General Public License as published by
 
8
the Free Software Foundation; either version 2, or (at your option)
 
9
any later version.
 
10
 
 
11
GNU Classpath is distributed in the hope that it will be useful, but
 
12
WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
General Public License for more details.
 
15
 
 
16
You should have received a copy of the GNU General Public License
 
17
along with GNU Classpath; see the file COPYING.  If not, write to the
 
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
19
02110-1301 USA.
 
20
 
 
21
Linking this library statically or dynamically with other modules is
 
22
making a combined work based on this library.  Thus, the terms and
 
23
conditions of the GNU General Public License cover the whole
 
24
combination.
 
25
 
 
26
As a special exception, the copyright holders of this library give you
 
27
permission to link this library with independent modules to produce an
 
28
executable, regardless of the license terms of these independent
 
29
modules, and to copy and distribute the resulting executable under
 
30
terms of your choice, provided that you also meet, for each linked
 
31
independent module, the terms and conditions of the license of that
 
32
module.  An independent module is a module which is not derived from
 
33
or based on this library.  If you modify this library, you may extend
 
34
this exception to your version of the library, but you are not
 
35
obligated to do so.  If you do not wish to do so, delete this
 
36
exception statement from your version. */
 
37
 
 
38
package gnu.xml.validation.xmlschema;
 
39
 
 
40
import java.util.LinkedHashSet;
 
41
import java.util.List;
 
42
import java.util.Set;
 
43
import java.util.StringTokenizer;
 
44
import javax.xml.XMLConstants;
 
45
import javax.xml.namespace.QName;
 
46
import org.relaxng.datatype.DatatypeException;
 
47
import org.relaxng.datatype.DatatypeLibrary;
 
48
import org.relaxng.datatype.helpers.DatatypeLibraryLoader;
 
49
import org.w3c.dom.NamedNodeMap;
 
50
import org.w3c.dom.Node;
 
51
import gnu.xml.validation.datatype.Annotation;
 
52
import gnu.xml.validation.datatype.AtomicSimpleType;
 
53
import gnu.xml.validation.datatype.ListSimpleType;
 
54
import gnu.xml.validation.datatype.SimpleType;
 
55
import gnu.xml.validation.datatype.Type;
 
56
import gnu.xml.validation.datatype.UnionSimpleType;
 
57
 
 
58
/**
 
59
 * Parses an XML Schema DOM tree, constructing a compiled internal
 
60
 * representation.
 
61
 *
 
62
 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
 
63
 */
 
64
class XMLSchemaBuilder
 
65
{
 
66
 
 
67
  XMLSchema schema;
 
68
  final DatatypeLibrary typeLibrary;
 
69
 
 
70
  XMLSchemaBuilder()
 
71
  {
 
72
    final String ns = XMLConstants.W3C_XML_SCHEMA_NS_URI;
 
73
    typeLibrary = new DatatypeLibraryLoader().createDatatypeLibrary(ns);
 
74
  }
 
75
 
 
76
  void parseSchema(Node node)
 
77
    throws DatatypeException
 
78
  {
 
79
    String uri = node.getNamespaceURI();
 
80
    String name = node.getLocalName();
 
81
    if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 
82
        node.getNodeType() == Node.ELEMENT_NODE)
 
83
      {
 
84
        if ("schema".equals(name))
 
85
          {
 
86
            NamedNodeMap attrs = node.getAttributes();
 
87
            String targetNamespace = getAttribute(attrs, "targetNamespace");
 
88
            String version = getAttribute(attrs, "version");
 
89
            String fd = getAttribute(attrs, "finalDefault");
 
90
            int finalDefault = parseFullDerivationSet(fd);
 
91
            String bd = getAttribute(attrs, "blockDefault");
 
92
            int blockDefault = parseBlockSet(bd);
 
93
            String afd = getAttribute(attrs, "attributeFormDefault");
 
94
            boolean attributeFormQualified = "qualified".equals(afd);
 
95
            String efd = getAttribute(attrs, "elementFormDefault");
 
96
            boolean elementFormQualified = "qualified".equals(efd);
 
97
            schema = new XMLSchema(targetNamespace, version,
 
98
                                   finalDefault, blockDefault,
 
99
                                   attributeFormQualified,
 
100
                                   elementFormQualified);
 
101
            for (Node child = node.getFirstChild(); child != null;
 
102
                 child = child.getNextSibling())
 
103
              {
 
104
                parseTopLevelElement(child);
 
105
              }
 
106
            return;
 
107
          }
 
108
      }
 
109
    // TODO throw schema exception
 
110
  }
 
111
 
 
112
  void parseTopLevelElement(Node node)
 
113
    throws DatatypeException
 
114
  {
 
115
    String uri = node.getNamespaceURI();
 
116
    String name = node.getLocalName();
 
117
    if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 
118
        node.getNodeType() == Node.ELEMENT_NODE)
 
119
      {
 
120
        if ("element".equals(name))
 
121
          {
 
122
            ElementDeclaration ed =
 
123
              (ElementDeclaration) parseElement(node, null);
 
124
            schema.elementDeclarations.put(ed.name, ed);
 
125
            // TODO
 
126
          }
 
127
        else if ("attribute".equals(name))
 
128
          {
 
129
            AttributeDeclaration ad =
 
130
              (AttributeDeclaration) parseAttribute(node, true);
 
131
            schema.attributeDeclarations.put(ad.name, ad);
 
132
            // TODO
 
133
          }
 
134
        else if ("type".equals(name))
 
135
          {
 
136
            // TODO
 
137
          }
 
138
        else if ("group".equals(name))
 
139
          {
 
140
            // TODO
 
141
          }
 
142
        else if ("attributeGroup".equals(name))
 
143
          {
 
144
            // TODO
 
145
          }
 
146
        else if ("notation".equals(name))
 
147
          {
 
148
            // TODO
 
149
          }
 
150
        else if ("identityConstraint".equals(name))
 
151
          {
 
152
            // TODO
 
153
          }
 
154
      }
 
155
    // TODO throw schema exception
 
156
  }
 
157
 
 
158
  Object parseAttribute(Node node, boolean scope)
 
159
    throws DatatypeException
 
160
  {
 
161
    NamedNodeMap attrs = node.getAttributes();
 
162
    String def = getAttribute(attrs, "default");
 
163
    String fixed = getAttribute(attrs, "fixed");
 
164
    int constraintType = AttributeDeclaration.NONE;
 
165
    String constraintValue = null;
 
166
    if (def != null)
 
167
      {
 
168
        constraintType = AttributeDeclaration.DEFAULT;
 
169
        constraintValue = def;
 
170
      }
 
171
    else if (fixed != null)
 
172
      {
 
173
        constraintType = AttributeDeclaration.FIXED;
 
174
        constraintValue = fixed;
 
175
      }
 
176
    // TODO form = (qualified | unqualified)
 
177
    String attrName = getAttribute(attrs, "name");
 
178
    String attrNamespace = getAttribute(attrs, "targetNamespace");
 
179
    String ref = getAttribute(attrs, "ref");
 
180
    String use = getAttribute(attrs, "use");
 
181
    String type = getAttribute(attrs, "type");
 
182
    SimpleType datatype = (type == null) ? null :
 
183
      parseSimpleType(asQName(type, node));
 
184
    Annotation annotation = null;
 
185
    for (Node child = node.getFirstChild(); child != null;
 
186
         child = child.getNextSibling())
 
187
      {
 
188
        String uri = child.getNamespaceURI();
 
189
        String name = child.getLocalName();
 
190
        if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 
191
            child.getNodeType() == Node.ELEMENT_NODE)
 
192
          {
 
193
            if ("annotation".equals(name))
 
194
              {
 
195
                annotation = parseAnnotation(child);
 
196
              }
 
197
            else if ("simpleType".equals(name))
 
198
              {
 
199
                datatype = parseSimpleType(child);
 
200
              }
 
201
            else
 
202
              {
 
203
                // TODO throw schema exception
 
204
              }
 
205
          }
 
206
      }
 
207
    if (scope)
 
208
      {
 
209
        return new AttributeDeclaration(scope,
 
210
                                        constraintType,
 
211
                                        constraintValue,
 
212
                                        new QName(attrNamespace, attrName),
 
213
                                        datatype,
 
214
                                        annotation);
 
215
      }
 
216
    else 
 
217
      {
 
218
        boolean required = "required".equals(use);
 
219
        // TODO ref
 
220
        AttributeDeclaration decl = (ref == null) ?
 
221
              new AttributeDeclaration(scope,
 
222
                                       AttributeDeclaration.NONE,
 
223
                                       null,
 
224
                                       new QName(attrNamespace, attrName),
 
225
                                       datatype,
 
226
                                       annotation) :
 
227
              /*schema.getAttributeDeclaration(ref)*/ null;
 
228
        return new AttributeUse(required,
 
229
                                constraintType,
 
230
                                constraintValue,
 
231
                                decl);
 
232
      }
 
233
  }
 
234
 
 
235
  int parseFullDerivationSet(String value)
 
236
  {
 
237
    int ret = XMLSchema.FINAL_NONE;
 
238
    if ("#all".equals(value))
 
239
      {
 
240
        ret = XMLSchema.FINAL_ALL;
 
241
      }
 
242
    else
 
243
      {
 
244
        StringTokenizer st = new StringTokenizer(value, " ");
 
245
        while (st.hasMoreTokens())
 
246
          {
 
247
            String token = st.nextToken();
 
248
            if ("extension".equals(token))
 
249
              {
 
250
                ret |= XMLSchema.FINAL_EXTENSION;
 
251
              }
 
252
            else if ("restriction".equals(token))
 
253
              {
 
254
                ret |= XMLSchema.FINAL_RESTRICTION;
 
255
              }
 
256
            else if ("list".equals(token))
 
257
              {
 
258
                ret |= XMLSchema.FINAL_LIST;
 
259
              }
 
260
            else if ("union".equals(token))
 
261
              {
 
262
                ret |= XMLSchema.FINAL_UNION;
 
263
              }
 
264
          }
 
265
      }
 
266
    return ret;
 
267
  }
 
268
 
 
269
  int parseSimpleTypeDerivationSet(String value)
 
270
  {
 
271
    int ret = XMLSchema.FINAL_NONE;
 
272
    if ("#all".equals(value))
 
273
      {
 
274
        ret = XMLSchema.FINAL_LIST |
 
275
          XMLSchema.FINAL_UNION |
 
276
          XMLSchema.FINAL_RESTRICTION;
 
277
      }
 
278
    else
 
279
      {
 
280
        StringTokenizer st = new StringTokenizer(value, " ");
 
281
        while (st.hasMoreTokens())
 
282
          {
 
283
            String token = st.nextToken();
 
284
            if ("list".equals(token))
 
285
              {
 
286
                ret |= XMLSchema.FINAL_LIST;
 
287
              }
 
288
            else if ("union".equals(token))
 
289
              {
 
290
                ret |= XMLSchema.FINAL_UNION;
 
291
              }
 
292
            else if ("restriction".equals(token))
 
293
              {
 
294
                ret |= XMLSchema.FINAL_RESTRICTION;
 
295
              }
 
296
          }
 
297
      }
 
298
    return ret;
 
299
  }
 
300
 
 
301
  int parseComplexTypeDerivationSet(String value)
 
302
  {
 
303
    int ret = XMLSchema.FINAL_NONE;
 
304
    if ("#all".equals(value))
 
305
      {
 
306
        ret = XMLSchema.FINAL_EXTENSION | XMLSchema.FINAL_RESTRICTION;
 
307
      }
 
308
    else
 
309
      {
 
310
        StringTokenizer st = new StringTokenizer(value, " ");
 
311
        while (st.hasMoreTokens())
 
312
          {
 
313
            String token = st.nextToken();
 
314
            if ("extension".equals(token))
 
315
              {
 
316
                ret |= XMLSchema.FINAL_EXTENSION;
 
317
              }
 
318
            else if ("restriction".equals(token))
 
319
              {
 
320
                ret |= XMLSchema.FINAL_RESTRICTION;
 
321
              }
 
322
          }
 
323
      }
 
324
    return ret;
 
325
  }
 
326
 
 
327
  int parseBlockSet(String value)
 
328
  {
 
329
    int ret = XMLSchema.BLOCK_NONE;
 
330
    if ("#all".equals(value))
 
331
      {
 
332
        ret = XMLSchema.BLOCK_ALL;
 
333
      }
 
334
    else
 
335
      {
 
336
        StringTokenizer st = new StringTokenizer(value, " ");
 
337
        while (st.hasMoreTokens())
 
338
          {
 
339
            String token = st.nextToken();
 
340
            if ("extension".equals(token))
 
341
              {
 
342
                ret |= XMLSchema.BLOCK_EXTENSION;
 
343
              }
 
344
            else if ("restriction".equals(token))
 
345
              {
 
346
                ret |= XMLSchema.BLOCK_RESTRICTION;
 
347
              }
 
348
            else if ("substitution".equals(token))
 
349
              {
 
350
                ret |= XMLSchema.BLOCK_SUBSTITUTION;
 
351
              }
 
352
          }
 
353
      }
 
354
    return ret;
 
355
  }
 
356
 
 
357
  int parseComplexTypeBlockSet(String value)
 
358
  {
 
359
    int ret = XMLSchema.BLOCK_NONE;
 
360
    if ("#all".equals(value))
 
361
      {
 
362
        ret = XMLSchema.BLOCK_EXTENSION | XMLSchema.BLOCK_RESTRICTION;
 
363
      }
 
364
    else
 
365
      {
 
366
        StringTokenizer st = new StringTokenizer(value, " ");
 
367
        while (st.hasMoreTokens())
 
368
          {
 
369
            String token = st.nextToken();
 
370
            if ("extension".equals(token))
 
371
              {
 
372
                ret |= XMLSchema.BLOCK_EXTENSION;
 
373
              }
 
374
            else if ("restriction".equals(token))
 
375
              {
 
376
                ret |= XMLSchema.BLOCK_RESTRICTION;
 
377
              }
 
378
          }
 
379
      }
 
380
    return ret;
 
381
  }
 
382
 
 
383
  Object parseElement(Node node, ElementDeclaration parent)
 
384
    throws DatatypeException
 
385
  {
 
386
    NamedNodeMap attrs = node.getAttributes();
 
387
    Integer minOccurs = null;
 
388
    Integer maxOccurs = null;
 
389
    Node parentNode = node.getParentNode();
 
390
    boolean notTopLevel = !"schema".equals(parentNode.getLocalName());
 
391
    if (notTopLevel)
 
392
      {
 
393
        String ref = getAttribute(attrs, "ref");
 
394
        if (ref != null)
 
395
          {
 
396
            minOccurs = getOccurrence(getAttribute(attrs, "minOccurs"));
 
397
            maxOccurs = getOccurrence(getAttribute(attrs, "maxOccurs"));
 
398
            // TODO resolve top-level element declaration
 
399
            ElementDeclaration ad = null;
 
400
            return new Particle(minOccurs, maxOccurs, ad);
 
401
          }
 
402
      }
 
403
    String elementName = getAttribute(attrs, "name");
 
404
    String elementNamespace = getAttribute(attrs, "targetNamespace");
 
405
    String type = getAttribute(attrs, "type");
 
406
    Type datatype = (type != null) ?
 
407
      parseSimpleType(asQName(type, node)) : null;
 
408
    int scope = (parent == null) ?
 
409
      XMLSchema.GLOBAL :
 
410
      XMLSchema.LOCAL;
 
411
    String def = getAttribute(attrs, "default");
 
412
    String fixed = getAttribute(attrs, "fixed");
 
413
    int constraintType = AttributeDeclaration.NONE;
 
414
    String constraintValue = null;
 
415
    if (def != null)
 
416
      {
 
417
        constraintType = AttributeDeclaration.DEFAULT;
 
418
        constraintValue = def;
 
419
      }
 
420
    else if (fixed != null)
 
421
      {
 
422
        constraintType = AttributeDeclaration.FIXED;
 
423
        constraintValue = fixed;
 
424
      }
 
425
    String sg = getAttribute(attrs, "substitutionGroup");
 
426
    QName substitutionGroup = QName.valueOf(sg);
 
427
    String sgPrefix = substitutionGroup.getPrefix();
 
428
    if (sgPrefix != null && !"".equals(sgPrefix))
 
429
      {
 
430
        String sgName = substitutionGroup.getLocalPart();
 
431
        String sgNamespace = node.lookupNamespaceURI(sgPrefix);
 
432
        substitutionGroup = new QName(sgNamespace, sgName);
 
433
      }
 
434
    
 
435
    String block = getAttribute(attrs, "block");
 
436
    int substitutionGroupExclusions = (block == null) ?
 
437
      schema.blockDefault :
 
438
      parseBlockSet(block);
 
439
    String final_ = getAttribute(attrs, "final");
 
440
    int disallowedSubstitutions = (final_ == null) ?
 
441
      schema.finalDefault :
 
442
      parseFullDerivationSet(final_);
 
443
    
 
444
    boolean nillable = "true".equals(getAttribute(attrs, "nillable"));
 
445
    boolean isAbstract = "true".equals(getAttribute(attrs, "abstract"));
 
446
    
 
447
    if (notTopLevel)
 
448
      {
 
449
        minOccurs = getOccurrence(getAttribute(attrs, "minOccurs"));
 
450
        maxOccurs = getOccurrence(getAttribute(attrs, "maxOccurs"));
 
451
        String form = getAttribute(attrs, "form");
 
452
        if (form != null)
 
453
          {
 
454
            if ("qualified".equals(form))
 
455
              {
 
456
                elementNamespace = schema.targetNamespace;
 
457
              }
 
458
          }
 
459
        else if (schema.elementFormQualified)
 
460
          {
 
461
            elementNamespace = schema.targetNamespace;
 
462
          }
 
463
      }
 
464
    ElementDeclaration ed =
 
465
      new ElementDeclaration(new QName(elementNamespace, elementName),
 
466
                             datatype,
 
467
                             scope, parent,
 
468
                             constraintType, constraintValue,
 
469
                             nillable,
 
470
                             substitutionGroup, 
 
471
                             substitutionGroupExclusions, 
 
472
                             disallowedSubstitutions,
 
473
                             isAbstract);
 
474
    
 
475
    for (Node child = node.getFirstChild(); child != null;
 
476
         child = child.getNextSibling())
 
477
      {
 
478
        String uri = child.getNamespaceURI();
 
479
        String name = child.getLocalName();
 
480
        if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 
481
            child.getNodeType() == Node.ELEMENT_NODE)
 
482
          {
 
483
            if ("annotation".equals(name))
 
484
              {
 
485
                ed.annotation = parseAnnotation(child);
 
486
              }
 
487
            else if ("simpleType".equals(name) && datatype == null)
 
488
              {
 
489
                ed.datatype = parseSimpleType(child);
 
490
              }
 
491
            else if ("complexType".equals(name) && datatype == null)
 
492
              {
 
493
                ed.datatype = parseComplexType(child, ed);
 
494
              }
 
495
            else
 
496
              {
 
497
                // throw schema exception
 
498
              }
 
499
          }
 
500
      }
 
501
 
 
502
    if (notTopLevel)
 
503
      {
 
504
        return new Particle(minOccurs, maxOccurs, ed);
 
505
      }
 
506
    else
 
507
      {
 
508
        return ed;
 
509
      }
 
510
  }
 
511
 
 
512
  Integer getOccurrence(String value)
 
513
  {
 
514
    if (value == null)
 
515
      {
 
516
        return new Integer(1);
 
517
      }
 
518
    else if ("unbounded".equals(value))
 
519
      {
 
520
        return null;
 
521
      }
 
522
    else
 
523
      {
 
524
        return new Integer(value);
 
525
      }
 
526
  }
 
527
 
 
528
  SimpleType parseSimpleType(QName typeName)
 
529
    throws DatatypeException
 
530
  {
 
531
    SimpleType type = (SimpleType) schema.types.get(typeName);
 
532
    if (!XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(typeName.getNamespaceURI()))
 
533
      return null;
 
534
    String localName = typeName.getLocalPart();
 
535
    return (SimpleType) typeLibrary.createDatatype(localName);
 
536
  }
 
537
 
 
538
  SimpleType parseSimpleType(Node simpleType)
 
539
    throws DatatypeException
 
540
  {
 
541
    NamedNodeMap attrs = simpleType.getAttributes();
 
542
    String typeFinal = getAttribute(attrs, "final");
 
543
    if (typeFinal == null)
 
544
      {
 
545
        Node schema = simpleType.getParentNode();
 
546
        while (schema != null && !"schema".equals(schema.getLocalName()))
 
547
          {
 
548
            schema = schema.getParentNode();
 
549
          }
 
550
        if (schema != null)
 
551
          {
 
552
            NamedNodeMap schemaAttrs = schema.getAttributes();
 
553
            typeFinal = getAttribute(schemaAttrs, "finalDefault");
 
554
          }
 
555
      }
 
556
    int typeFinality = parseSimpleTypeDerivationSet(typeFinal);
 
557
    QName typeName = asQName(getAttribute(attrs, "name"), simpleType);
 
558
    int variety = 0;
 
559
    Set facets = new LinkedHashSet();
 
560
    int fundamentalFacets = 0; // TODO
 
561
    SimpleType baseType = null; // TODO
 
562
    Annotation annotation = null;
 
563
    // TODO use DatatypeBuilder
 
564
    for (Node child = simpleType.getFirstChild(); child != null;
 
565
         child = child.getNextSibling())
 
566
      {
 
567
        String uri = child.getNamespaceURI();
 
568
        String name = child.getLocalName();
 
569
        if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 
570
            child.getNodeType() == Node.ELEMENT_NODE)
 
571
          {
 
572
            if ("annotation".equals(name))
 
573
              {
 
574
                annotation = parseAnnotation(child);
 
575
              }
 
576
            else if ("restriction".equals(name))
 
577
              {
 
578
                // TODO
 
579
              }
 
580
            else if ("list".equals(name))
 
581
              {
 
582
                variety = SimpleType.LIST;
 
583
                // TODO
 
584
              }
 
585
            else if ("union".equals(name))
 
586
              {
 
587
                variety = SimpleType.UNION;
 
588
                // TODO
 
589
              }
 
590
          }
 
591
      }
 
592
    return new SimpleType(typeName, variety, facets, fundamentalFacets,
 
593
                          baseType, annotation);
 
594
  }
 
595
 
 
596
  Type parseComplexType(Node complexType, ElementDeclaration parent)
 
597
    throws DatatypeException
 
598
  {
 
599
    NamedNodeMap attrs = complexType.getAttributes();
 
600
    QName typeName = asQName(getAttribute(attrs, "name"), complexType);
 
601
    boolean isAbstract = "true".equals(getAttribute(attrs, "abstract"));
 
602
    String block = getAttribute(attrs, "block");
 
603
    int prohibitedSubstitutions = (block == null) ?
 
604
      schema.blockDefault :
 
605
      parseComplexTypeBlockSet(block);
 
606
    String final_ = getAttribute(attrs, "final");
 
607
    int finality = (final_ == null) ?
 
608
      schema.finalDefault :
 
609
      parseComplexTypeDerivationSet(final_);
 
610
    ComplexType type = new ComplexType(typeName, isAbstract,
 
611
                                       prohibitedSubstitutions, finality);
 
612
    boolean mixed = "true".equals(getAttribute(attrs, "mixed"));
 
613
    for (Node child = complexType.getFirstChild(); child != null;
 
614
         child = child.getNextSibling())
 
615
      {
 
616
        String uri = child.getNamespaceURI();
 
617
        String name = child.getLocalName();
 
618
        if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 
619
            child.getNodeType() == Node.ELEMENT_NODE)
 
620
          {
 
621
            if ("simpleContent".equals(name))
 
622
              {
 
623
                parseSimpleContent(child, type);
 
624
              }
 
625
          }
 
626
      }
 
627
    if (mixed)
 
628
      {
 
629
        type.contentType = XMLSchema.CONTENT_MIXED;
 
630
      } 
 
631
    return type;
 
632
  }
 
633
 
 
634
  void parseSimpleContent(Node simpleContent, ComplexType type)
 
635
    throws DatatypeException
 
636
  {
 
637
    for (Node child = simpleContent.getFirstChild(); child != null;
 
638
         child = child.getNextSibling())
 
639
      {
 
640
        String uri = child.getNamespaceURI();
 
641
        String name = child.getLocalName();
 
642
        if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 
643
            child.getNodeType() == Node.ELEMENT_NODE)
 
644
          {
 
645
            if ("annotation".equals(name))
 
646
              {
 
647
                type.annotations.add(parseAnnotation(child));
 
648
              }
 
649
            else if ("restriction".equals(name))
 
650
              {
 
651
                type.derivationMethod = XMLSchema.FINAL_RESTRICTION;
 
652
                parseRestriction(child, type);
 
653
              }
 
654
            else if ("extension".equals(name))
 
655
              {
 
656
                type.derivationMethod = XMLSchema.FINAL_EXTENSION;
 
657
                parseExtension(child, type);
 
658
              }
 
659
          }
 
660
      }
 
661
  }
 
662
 
 
663
  void parseRestriction(Node restriction, ComplexType type)
 
664
    throws DatatypeException
 
665
  {
 
666
    NamedNodeMap attrs = restriction.getAttributes();
 
667
    String base = getAttribute(attrs, "base");
 
668
    QName baseType = asQName(base, restriction);
 
669
    SimpleType simpleType = null;
 
670
    for (Node child = restriction.getFirstChild(); child != null;
 
671
         child = child.getNextSibling())
 
672
      {
 
673
        String uri = child.getNamespaceURI();
 
674
        String name = child.getLocalName();
 
675
        if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 
676
            child.getNodeType() == Node.ELEMENT_NODE)
 
677
          {
 
678
            if ("annotation".equals(name))
 
679
              {
 
680
                type.annotations.add(parseAnnotation(child));
 
681
              }
 
682
            else if ("simpleType".equals(name))
 
683
              {
 
684
                type.contentType = XMLSchema.CONTENT_SIMPLE;
 
685
                simpleType = parseSimpleType(child);
 
686
              }
 
687
            else if ("minExclusive".equals(name))
 
688
              {
 
689
              }
 
690
            else if ("minInclusive".equals(name))
 
691
              {
 
692
              }
 
693
            else if ("maxExclusive".equals(name))
 
694
              {
 
695
              }
 
696
            else if ("maxInclusive".equals(name))
 
697
              {
 
698
              }
 
699
            else if ("totalDigits".equals(name))
 
700
              {
 
701
              }
 
702
            else if ("fractionDigits".equals(name))
 
703
              {
 
704
              }
 
705
            else if ("length".equals(name))
 
706
              {
 
707
              }
 
708
            else if ("minLength".equals(name))
 
709
              {
 
710
              }
 
711
            else if ("maxLength".equals(name))
 
712
              {
 
713
              }
 
714
            else if ("enumeration".equals(name))
 
715
              {
 
716
              }
 
717
            else if ("whiteSpace".equals(name))
 
718
              {
 
719
              }
 
720
            else if ("pattern".equals(name))
 
721
              {
 
722
              }
 
723
            else if ("attribute".equals(name))
 
724
              {
 
725
                AttributeUse use =
 
726
                  (AttributeUse) parseAttribute(child, false);
 
727
                schema.attributeDeclarations.put(use.declaration.name,
 
728
                                                 use.declaration);
 
729
                type.attributeUses.add(use);
 
730
              }
 
731
            else if ("attributeGroup".equals(name))
 
732
              {
 
733
                NamedNodeMap agAttrs = child.getAttributes();
 
734
                String ref = getAttribute(agAttrs, "ref");
 
735
                QName ag = asQName(ref, child);
 
736
                type.attributeUses.add(ag);
 
737
              }
 
738
            else if ("anyAttribute".equals(name))
 
739
              {
 
740
                type.attributeWildcard = parseAnyAttribute(child);
 
741
              }
 
742
          }
 
743
      }
 
744
  }
 
745
 
 
746
  void parseExtension(Node extension, ComplexType type)
 
747
    throws DatatypeException
 
748
  {
 
749
    NamedNodeMap attrs = extension.getAttributes();
 
750
    String base = getAttribute(attrs, "base");
 
751
    QName baseType = asQName(base, extension);
 
752
    for (Node child = extension.getFirstChild(); child != null;
 
753
         child = child.getNextSibling())
 
754
      {
 
755
        String uri = child.getNamespaceURI();
 
756
        String name = child.getLocalName();
 
757
        if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 
758
            child.getNodeType() == Node.ELEMENT_NODE)
 
759
          {
 
760
            if ("annotation".equals(name))
 
761
              {
 
762
                type.annotations.add(parseAnnotation(child));
 
763
              }
 
764
            else if ("attribute".equals(name))
 
765
              {
 
766
                AttributeUse use =
 
767
                  (AttributeUse) parseAttribute(child, false);
 
768
                schema.attributeDeclarations.put(use.declaration.name,
 
769
                                                 use.declaration);
 
770
                type.attributeUses.add(use);
 
771
              }
 
772
            else if ("attributeGroup".equals(name))
 
773
              {
 
774
                NamedNodeMap agAttrs = child.getAttributes();
 
775
                String ref = getAttribute(agAttrs, "ref");
 
776
                QName ag = asQName(ref, child);
 
777
                type.attributeUses.add(ag);
 
778
              }
 
779
            else if ("anyAttribute".equals(name))
 
780
              {
 
781
                type.attributeWildcard = parseAnyAttribute(child);
 
782
              }
 
783
          }
 
784
      }
 
785
  }
 
786
 
 
787
  AnyAttribute parseAnyAttribute(Node node)
 
788
  {
 
789
    NamedNodeMap attrs = node.getAttributes();
 
790
    String namespace = getAttribute(attrs, "namespace");
 
791
    String pc = getAttribute(attrs, "processContents");
 
792
    int processContents = AnyAttribute.STRICT;
 
793
    if ("lax".equals(pc))
 
794
      {
 
795
        processContents = AnyAttribute.LAX;
 
796
      }
 
797
    else if ("skip".equals(pc))
 
798
      {
 
799
        processContents = AnyAttribute.SKIP;
 
800
      }
 
801
    AnyAttribute ret = new AnyAttribute(namespace, processContents);
 
802
    for (Node child = node.getFirstChild(); child != null;
 
803
         child = child.getNextSibling())
 
804
      {
 
805
        String uri = child.getNamespaceURI();
 
806
        String name = child.getLocalName();
 
807
        if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
 
808
            child.getNodeType() == Node.ELEMENT_NODE)
 
809
          {
 
810
            if ("annotation".equals(name))
 
811
              {
 
812
                ret.annotation = parseAnnotation(child);
 
813
              }
 
814
          }
 
815
      }
 
816
    return ret;
 
817
  }
 
818
 
 
819
  Annotation parseAnnotation(Node node)
 
820
  {
 
821
    // TODO
 
822
    return null;
 
823
  }
 
824
 
 
825
  private static String getAttribute(NamedNodeMap attrs, String name)
 
826
  {
 
827
    Node attr = attrs.getNamedItem(name);
 
828
    return (attr == null) ? null : attr.getNodeValue();
 
829
  }
 
830
 
 
831
  private static QName asQName(String text, Node resolver)
 
832
  {
 
833
    QName name = QName.valueOf(text);
 
834
    String prefix = name.getPrefix();
 
835
    if (prefix != null && prefix.length() > 0)
 
836
      {
 
837
        String uri = resolver.lookupNamespaceURI(prefix);
 
838
        name = new QName(uri, name.getLocalPart());
 
839
      }
 
840
    return name;
 
841
  }
 
842
  
 
843
}
 
844