You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by af...@apache.org on 2014/06/03 08:57:15 UTC

svn commit: r1599430 [4/5] - in /openoffice/trunk/main/ooxml: ./ source/ source/framework/ source/framework/JavaOOXMLParser/ source/framework/JavaOOXMLParser/.settings/ source/framework/JavaOOXMLParser/src/ source/framework/JavaOOXMLParser/src/org/ sou...

Added: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/RequestVisitor.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/RequestVisitor.java?rev=1599430&view=auto
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/RequestVisitor.java (added)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/RequestVisitor.java Tue Jun  3 06:57:13 2014
@@ -0,0 +1,119 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.schema.model.optimize;
+
+import org.apache.openoffice.ooxml.schema.model.base.INode;
+import org.apache.openoffice.ooxml.schema.model.base.NodeVisitorAdapter;
+import org.apache.openoffice.ooxml.schema.model.base.QualifiedName;
+import org.apache.openoffice.ooxml.schema.model.complex.ComplexType;
+import org.apache.openoffice.ooxml.schema.model.complex.Element;
+import org.apache.openoffice.ooxml.schema.model.complex.ElementReference;
+import org.apache.openoffice.ooxml.schema.model.complex.Extension;
+import org.apache.openoffice.ooxml.schema.model.complex.GroupReference;
+import org.apache.openoffice.ooxml.schema.model.schema.Schema;
+import org.apache.openoffice.ooxml.schema.model.simple.List;
+import org.apache.openoffice.ooxml.schema.model.simple.SimpleTypeReference;
+import org.apache.openoffice.ooxml.schema.model.simple.Union;
+
+/** A visitor that is called for all nodes of a complex or simple type to mark
+ *  the referenced types as being used.
+ */
+public class RequestVisitor
+    extends NodeVisitorAdapter
+{
+    RequestVisitor (
+        final Schema aSourceSchema,
+        final SchemaOptimizer aOptimizer)
+    {
+        maSourceSchema = aSourceSchema;
+        maSchemaOptimizer = aOptimizer;
+    }
+    
+    
+    @Override public void Visit (final ComplexType aComplexType)
+    {
+        for (final INode aAttribute : aComplexType.GetAttributes())
+            maSchemaOptimizer.RequestType(aAttribute);
+    }
+
+    @Override public void Visit (final Element aElement)
+    {
+        final QualifiedName aName = aElement.GetTypeName();
+        if (aName == null)
+            throw new RuntimeException(
+                String.format("element '%s' has no type, defined at %s",
+                aElement.toString(),
+                aElement.GetLocation()));
+        maSchemaOptimizer.RequestType(aName);
+    }
+    @Override public void Visit (final ElementReference aElementReference)
+    {
+        Visit(aElementReference.GetReferencedElement(maSourceSchema));
+    }
+    @Override public void Visit (final Extension aExtension)
+    {
+        maSchemaOptimizer.RequestType(aExtension.GetBaseTypeName());
+    }
+    @Override public void Visit (final GroupReference aReference)
+    {
+        maSchemaOptimizer.RequestType(aReference.GetReferencedGroup(maSourceSchema));
+    }
+    @Override public void Visit (final List aList)
+    {
+        maSchemaOptimizer.RequestType(aList.GetItemType());
+    }
+    @Override public void Visit (final SimpleTypeReference aReference)
+    {
+        maSchemaOptimizer.RequestType(aReference.GetReferencedSimpleType(maSourceSchema));
+    }
+    @Override public void Visit (final Union aUnion)
+    {
+    }
+    
+    @Override public void Default (final INode aNode)
+    {
+        switch (aNode.GetNodeType())
+        {
+            case All:
+            case Any:
+            case BuiltIn:
+            case Choice:
+            case ComplexContent:
+            case ComplexType:
+            case Group:
+            case List:
+            case OccurrenceIndicator:
+            case Sequence:
+            case SimpleContent:
+            case SimpleType:
+                break;
+            default:
+                throw new RuntimeException(
+                    String.format("don't know how to request %s which was defined at %s",
+                        aNode.toString(),
+                        aNode.GetLocation()));
+        }
+    }
+    
+    private final Schema maSourceSchema;
+    private final SchemaOptimizer maSchemaOptimizer;
+}

Added: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/SchemaOptimizer.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/SchemaOptimizer.java?rev=1599430&view=auto
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/SchemaOptimizer.java (added)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/SchemaOptimizer.java Tue Jun  3 06:57:13 2014
@@ -0,0 +1,119 @@
+package org.apache.openoffice.ooxml.schema.model.optimize;
+
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.Set;
+
+import org.apache.openoffice.ooxml.schema.iterator.NodeIterator;
+import org.apache.openoffice.ooxml.schema.model.base.INode;
+import org.apache.openoffice.ooxml.schema.model.base.INodeVisitor;
+import org.apache.openoffice.ooxml.schema.model.base.Node;
+import org.apache.openoffice.ooxml.schema.model.base.NodeType;
+import org.apache.openoffice.ooxml.schema.model.base.QualifiedName;
+import org.apache.openoffice.ooxml.schema.model.complex.Element;
+import org.apache.openoffice.ooxml.schema.model.schema.Schema;
+
+public class SchemaOptimizer
+{
+    public SchemaOptimizer (final Schema aOriginalSchema)
+    {
+        maOriginalSchema = aOriginalSchema;
+        maOptimizedSchema = new Schema();
+        maTodoList = new LinkedList<>();
+        maProcessedTypes = new HashSet<>();
+        
+        maRequestVisitor = new RequestVisitor(maOriginalSchema, this);
+    }
+    
+    
+    
+    
+    public Schema Run ()
+    {
+        // Copy over the top-level elements.  They are the seeds in the use chain of types.
+        for (final Element aElement : maOriginalSchema.TopLevelElements.GetUnsorted())
+            maOptimizedSchema.TopLevelElements.Add(aElement);
+              
+        // Seed the todo list with the types to which the top-level elements lead.
+        for (final Element aElement : maOriginalSchema.TopLevelElements.GetUnsorted())
+            RequestType(aElement.GetTypeName());
+        
+        ProcessTodoList();
+
+        return maOptimizedSchema;
+    }
+    
+    
+    
+    
+    void RequestType (final QualifiedName aName)
+    {
+        final Node aNode = maOriginalSchema.GetTypeForName(aName);
+        if (aNode == null)
+            throw new RuntimeException("there is no type named '"+aName+"' in the schema");
+        else
+            RequestType(aNode);
+    }
+    
+    
+    
+    
+    void RequestType (final INode aNode)
+    {
+        if (aNode.GetNodeType() == NodeType.SimpleTypeReference)
+            System.out.println(aNode);
+        if ( ! maProcessedTypes.contains(aNode))
+        {
+            maProcessedTypes.add(aNode);
+            maTodoList.add(aNode);
+        }
+    }
+    
+
+    
+    
+    /** Process each entry in the todo list until it is empty.
+     *  Each type in it is used and inserted into the optimized schema.
+     */
+    private void ProcessTodoList ()
+    {
+        final INodeVisitor aVisitor = new ProcessTypeVisitor(
+            maOriginalSchema,
+            maOptimizedSchema,
+            this);
+        while ( ! maTodoList.isEmpty())
+        {
+            final INode aNode = maTodoList.poll();
+            aNode.AcceptVisitor(aVisitor);
+            
+            // Request used namespaces.
+            final QualifiedName aName = aNode.GetName();
+            if (aName != null)
+                maOptimizedSchema.Namespaces.ProvideNamespace(aName.GetNamespaceURI(), aName.GetNamespacePrefix());
+        }
+    }
+    
+    
+    
+    
+    /** Iterate over all nodes in the given type definition.
+     *  References to types are inserted into the todo list.
+     */
+    void RequestReferencedTypes (final Node aRoot)
+    {
+        for (final INode aNode : new NodeIterator(aRoot))
+        {
+            aNode.AcceptVisitor(maRequestVisitor);
+        }
+    }
+    
+    
+    
+    
+    private final Schema maOriginalSchema;
+    private final Schema maOptimizedSchema;
+    private final Queue<INode> maTodoList;
+    private final Set<INode> maProcessedTypes;
+    private final RequestVisitor maRequestVisitor;
+}

Added: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/NamespaceMap.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/NamespaceMap.java?rev=1599430&view=auto
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/NamespaceMap.java (added)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/NamespaceMap.java Tue Jun  3 06:57:13 2014
@@ -0,0 +1,144 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.schema.model.schema;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/** Map between namespace prefixes and URIs.
+ *  While namespace URIs can have different prefixes in different schemas,
+ *  we will use only one prefix in the OOXML parser.  This class
+ *  provides these global prefixes. 
+ */
+public class NamespaceMap
+    implements Iterable<Entry<String, String>>
+{
+    public NamespaceMap ()
+    {
+        maURIToPrefixMap = new HashMap<>(maPredefinedURIToPrefixMap);
+        
+        // Hack to cover the older file format.
+        maURIToPrefixMap.put("http://schemas.openxmlformats.org/drawingml/2006/main", "a06");
+        maURIToPrefixMap.put("http://purl.oclc.org/ooxml/drawingml/main", "a12");
+
+        maURIToPrefixMap.put("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", "wp06");
+        maURIToPrefixMap.put("http://purl.oclc.org/ooxml/drawingml/wordprocessingDrawing", "wp12");
+
+        maURIToPrefixMap.put("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w06");
+        maURIToPrefixMap.put("http://purl.oclc.org/ooxml/wordprocessingml/main", "w12");
+
+        maURIToPrefixMap.put("http://schemas.openxmlformats.org/drawingml/2006/picture", "dpct06");
+        maURIToPrefixMap.put("http://purl.oclc.org/ooxml/drawingml/picture", "dpct12");
+        
+        maURIToPrefixMap.put("http://schemas.openxmlformats.org/officeDocument/2006/math", "m06");
+        maURIToPrefixMap.put("http://purl.oclc.org/ooxml/officeDocument/math", "m12");
+        
+        maURIToPrefixMap.put("http://purl.oclc.org/ooxml/officeDocument/relationships", "r12");
+    }
+    
+    
+    
+    
+    public void ProvideNamespace (
+        final String sNamespaceURI,
+        final String sDefaultPrefix)
+    {
+        if ( ! maURIToPrefixMap.containsKey(sNamespaceURI))
+        {
+            final String sPrefix;
+            if (sDefaultPrefix != null)
+            {
+                // Check if we can use the given prefix.
+                if (IsPrefixUsed(sDefaultPrefix))
+                {
+                    // Prefix is already used.  We have to create a new and unique one.
+                    sPrefix = new String(new byte[]{(byte)('A'+maURIToPrefixMap.size())});
+                }
+                else
+                {
+                    // Use the given prefix.
+                    sPrefix = sDefaultPrefix;
+                }
+            }
+            else
+            {
+                // Namespace is used without prefix.  Don't invent one.
+                // It is OK that the resulting null value is not unique.
+                sPrefix = null;
+            }
+
+            maURIToPrefixMap.put(sNamespaceURI, sPrefix);
+        }
+    }
+    
+    
+    
+    
+    public String GetNamespacePrefix (final String sURI)
+    {
+        return maURIToPrefixMap.get(sURI);
+    }
+    
+    
+    
+    
+    public Iterator<Entry<String,String>> iterator ()
+    {
+        return maURIToPrefixMap.entrySet().iterator();
+    }
+    
+    
+    
+    
+    public Object GetCount()
+    {
+        return maURIToPrefixMap.size();
+    }
+
+    
+    
+    
+    private boolean IsPrefixUsed (final String sPrefix)
+    {
+        for (final String sUsedPrefix : maURIToPrefixMap.values())
+        {
+            if (sUsedPrefix == null)
+                continue;
+            if (sUsedPrefix.equals(sPrefix))
+                return true;
+        }
+        return false;
+    }
+    
+    
+    
+    
+    private final Map<String,String> maURIToPrefixMap;
+    private final static Map<String,String> maPredefinedURIToPrefixMap;
+    static
+    {
+        maPredefinedURIToPrefixMap =  new HashMap<>();
+        maPredefinedURIToPrefixMap.put("http://www.w3.org/2001/XMLSchema", "xsd");
+    }
+}

Added: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/Schema.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/Schema.java?rev=1599430&view=auto
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/Schema.java (added)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/Schema.java Tue Jun  3 06:57:13 2014
@@ -0,0 +1,96 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.schema.model.schema;
+
+import org.apache.openoffice.ooxml.schema.model.attribute.Attribute;
+import org.apache.openoffice.ooxml.schema.model.attribute.AttributeGroup;
+import org.apache.openoffice.ooxml.schema.model.base.Node;
+import org.apache.openoffice.ooxml.schema.model.base.QualifiedName;
+import org.apache.openoffice.ooxml.schema.model.complex.ComplexType;
+import org.apache.openoffice.ooxml.schema.model.complex.Element;
+import org.apache.openoffice.ooxml.schema.model.complex.Group;
+import org.apache.openoffice.ooxml.schema.model.optimize.SchemaOptimizer;
+import org.apache.openoffice.ooxml.schema.model.simple.BuiltIn;
+import org.apache.openoffice.ooxml.schema.model.simple.SimpleType;
+
+/** Representation of a set of schema files (typically one master file and the included schema filed.)
+ */
+public class Schema
+{
+    public Schema ()
+    {
+        Namespaces = new NamespaceMap();
+        ComplexTypes = new TypeContainer<>();
+        SimpleTypes = new TypeContainer<>();
+        Groups = new TypeContainer<>();
+        AttributeGroups = new TypeContainer<>();
+        Attributes = new TypeContainer<>();
+        TopLevelElements = new TypeContainer<>();
+        
+        // Initialize the list of simple types with all known built ins (
+        // these are implicitly defined).
+        for (final BuiltIn aType : BuiltIn.GetTypes())
+            SimpleTypes.Add(aType);
+    }
+    
+    
+    
+    
+    public Node GetTypeForName (final QualifiedName aName)
+    {
+        final String sTypeName = aName.GetDisplayName();
+        
+        if (ComplexTypes.Contains(sTypeName))
+            return ComplexTypes.Get(sTypeName);
+        else if (SimpleTypes.Contains(sTypeName))
+            return SimpleTypes.Get(sTypeName);
+        else if (Groups.Contains(sTypeName))
+            return Groups.Get(sTypeName);
+        else if (TopLevelElements.Contains(sTypeName))
+            return TopLevelElements.Get(sTypeName);
+        else
+            return null;
+    }
+
+    
+    
+    
+    /** Create a new schema object that contains only the used types, i.e.
+     *  types that are reachable via element transitions, starting with the 
+     *  top level elements.
+     */
+    public Schema GetOptimizedSchema ()
+    {
+        return new SchemaOptimizer(this).Run();
+    }
+    
+    
+    
+    
+    public final NamespaceMap Namespaces;
+    public final TypeContainer<ComplexType> ComplexTypes;
+    public final TypeContainer<SimpleType> SimpleTypes;
+    public final TypeContainer<Group> Groups;
+    public final TypeContainer<AttributeGroup> AttributeGroups;
+    public final TypeContainer<Attribute> Attributes;
+    public final TypeContainer<Element> TopLevelElements;
+}

Added: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/TypeContainer.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/TypeContainer.java?rev=1599430&view=auto
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/TypeContainer.java (added)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/TypeContainer.java Tue Jun  3 06:57:13 2014
@@ -0,0 +1,100 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.schema.model.schema;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.openoffice.ooxml.schema.model.base.Node;
+import org.apache.openoffice.ooxml.schema.model.base.QualifiedName;
+
+public class TypeContainer<T extends Node>
+{
+    TypeContainer ()
+    {
+        maTypes = new HashMap<>();
+    }
+    
+    
+    
+    
+    public void Add (final T aType)
+    {
+        maTypes.put(aType.GetName().GetDisplayName(), aType);
+    }
+
+
+    
+
+    public T Get (final QualifiedName aName)
+    {
+        return maTypes.get(aName.GetDisplayName());
+    }
+
+    
+    
+    
+    public T Get (final String sPrefixedName)
+    {
+        return maTypes.get(sPrefixedName);
+    }
+    
+    
+    
+    
+    public boolean Contains (final String sPrefixedName)
+    {
+        return maTypes.containsKey(sPrefixedName);
+    }
+    
+    
+    
+    
+    public int GetCount ()
+    {
+        return maTypes.size();
+    }
+
+    
+    
+    
+    public Iterable<T> GetUnsorted ()
+    {
+        return maTypes.values();
+    }
+
+    
+    
+    
+    public Iterable<T> GetSorted ()
+    {
+        final Set<T> aSortedItems = new TreeSet<T>(maTypes.values());
+        return aSortedItems;
+    }    
+    
+    
+    
+
+    Map<String,T> maTypes;
+}

Added: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/BuiltIn.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/BuiltIn.java?rev=1599430&view=auto
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/BuiltIn.java (added)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/BuiltIn.java Tue Jun  3 06:57:13 2014
@@ -0,0 +1,146 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.schema.model.simple;
+
+import java.util.Vector;
+
+import org.apache.openoffice.ooxml.schema.model.base.INodeVisitor;
+import org.apache.openoffice.ooxml.schema.model.base.NodeType;
+import org.apache.openoffice.ooxml.schema.model.base.QualifiedName;
+
+/** Representation of built in types.
+ */
+public class BuiltIn
+    extends SimpleType
+{
+    public enum Type
+    {
+        String,
+        Token,
+        Byte,
+        UnsignedByte,
+        Short,
+        UnsignedShort,
+        Int,
+        UnsignedInt,
+        Integer,
+        Long,
+        Float,
+        Double,
+        Boolean,
+        Base64Binary,
+        DateTime,
+        AnyURI
+    }
+    public static final String XsdNamespace = "http://www.w3.org/2001/XMLSchema";
+    
+    
+    
+    
+    public static Vector<BuiltIn> GetTypes ()
+    {
+        final Vector<BuiltIn> aTypes = new Vector<>();
+        for (final Type eType : Type.values())
+            aTypes.add(new BuiltIn(eType));
+        return aTypes;
+    }
+    
+    
+    
+    
+    protected BuiltIn (
+        final Type eType)
+    {
+        super(null, GetNameForType(eType), null);
+        meType = eType;
+    }
+
+    
+    
+    
+    @Override
+    public NodeType GetNodeType ()
+    {
+        return NodeType.BuiltIn;
+    }
+    
+    
+    
+    
+    public Type GetBuiltInType ()
+    {
+        return meType;
+    }
+    
+    
+    
+    
+    @Override
+    public void AcceptVisitor (final INodeVisitor aVisitor)
+    {
+        aVisitor.Visit(this);
+    }
+    
+    
+    
+    
+    private static QualifiedName GetNameForType (final Type eType)
+    {
+        final String sTypeName;
+        switch (eType)
+        {
+            case String: sTypeName = "string"; break;
+            case Token: sTypeName = "token"; break;
+            case Byte: sTypeName = "byte"; break;
+            case UnsignedByte: sTypeName = "unsignedByte"; break;
+            case Short: sTypeName = "short"; break;
+            case UnsignedShort: sTypeName = "unsignedShort"; break;
+            case Int: sTypeName = "int"; break;
+            case UnsignedInt: sTypeName = "unsignedInt"; break;
+            case Integer: sTypeName = "integer"; break;
+            case Long: sTypeName = "long"; break;
+            case Float: sTypeName = "float"; break;
+            case Double: sTypeName = "double"; break;
+            case Boolean: sTypeName = "boolean"; break;
+            case Base64Binary: sTypeName = "base64Binary"; break;
+            case DateTime: sTypeName = "dateTime"; break;
+            case AnyURI: sTypeName = "anyURI"; break;
+            default:
+                throw new RuntimeException();
+        }
+        return new QualifiedName(XsdNamespace, "xsd", sTypeName);
+    }
+    
+    
+    
+    
+    @Override
+    public String toString ()
+    {
+        return "builtin "+GetName().GetDisplayName();
+    }
+    
+    
+    
+    
+    private final Type meType;
+}

Added: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/List.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/List.java?rev=1599430&view=auto
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/List.java (added)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/List.java Tue Jun  3 06:57:13 2014
@@ -0,0 +1,84 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.schema.model.simple;
+
+import org.apache.openoffice.ooxml.schema.model.base.INodeVisitor;
+import org.apache.openoffice.ooxml.schema.model.base.Location;
+import org.apache.openoffice.ooxml.schema.model.base.Node;
+import org.apache.openoffice.ooxml.schema.model.base.NodeType;
+import org.apache.openoffice.ooxml.schema.model.base.QualifiedName;
+
+/** Representation of the 'list' XML schema element.
+ *  It is similar to an array of objects that are all of the same simple type.
+ */
+public class List
+    extends Node
+{
+    public List (
+        final Node aParent,
+        final QualifiedName aItemType,
+        final Location aLocation)
+    {
+        super(aParent, null, aLocation);
+        maItemType = aItemType;
+    }
+    
+    
+    
+    
+    @Override
+    public NodeType GetNodeType ()
+    {
+        return NodeType.List;
+    }
+
+
+
+
+    @Override
+    public void AcceptVisitor (final INodeVisitor aVisitor)
+    {
+        aVisitor.Visit(this);
+    }
+    
+    
+    
+    
+    public QualifiedName GetItemType ()
+    {
+        return maItemType;
+    }
+    
+    
+    
+    
+    @Override
+    public String toString ()
+    {
+        return "list of "+maItemType.GetDisplayName()+" items";
+    }
+    
+    
+    
+    
+    private final QualifiedName maItemType;
+}

Added: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/Restriction.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/Restriction.java?rev=1599430&view=auto
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/Restriction.java (added)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/Restriction.java Tue Jun  3 06:57:13 2014
@@ -0,0 +1,210 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.schema.model.simple;
+
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
+
+import org.apache.openoffice.ooxml.schema.model.base.INodeVisitor;
+import org.apache.openoffice.ooxml.schema.model.base.Location;
+import org.apache.openoffice.ooxml.schema.model.base.Node;
+import org.apache.openoffice.ooxml.schema.model.base.NodeType;
+
+/** Representation of the 'restriction' XML schema element.
+ *  It defines constraints on a another simple type.
+ *  Examples for such restrictions are minimum and maximum values
+ *  (inclusive or exclusive), patterns or length constraints of strings,
+ *  sets of valid values. 
+ */
+public class Restriction
+    extends Node
+{
+    public Restriction (
+        final Node aParent,
+        final String sBaseType,
+        final Location aLocation)
+    {
+        super(aParent, null, aLocation);
+        msBaseType = sBaseType;
+        maEnumerations = new TreeSet<>();
+    }
+    
+    
+    
+    @Override
+    public void AcceptVisitor (final INodeVisitor aVisitor)
+    {
+        aVisitor.Visit(this);
+    }
+
+
+
+    @Override
+    public NodeType GetNodeType()
+    {
+        return NodeType.Restriction;
+    }
+
+    
+    
+    
+    @Override
+    public String toString ()
+    {
+        final StringBuffer aBuffer = new StringBuffer("restriction based on ");
+        aBuffer.append(msBaseType);
+        
+        if (mnMinInclusive != null)
+        {
+            aBuffer.append(",minInclusive=");
+            aBuffer.append(mnMinInclusive);
+        }
+        if (mnMinExclusive != null)
+        {
+            aBuffer.append(",minExclusive=");
+            aBuffer.append(mnMinExclusive);
+        }
+        if (mnMaxInclusive != null)
+        {
+            aBuffer.append(",maxInclusive=");
+            aBuffer.append(mnMaxInclusive);
+        }
+        if (mnMaxExclusive != null)
+        {
+            aBuffer.append(",maxExclusive=");
+            aBuffer.append(mnMaxExclusive);
+        }
+        if (mnLength != null)
+        {
+            aBuffer.append(",length=");
+            aBuffer.append(mnLength);
+        }
+        if (mnMinLength != null)
+        {
+            aBuffer.append(",minLength=");
+            aBuffer.append(mnMinLength);
+        }
+        if (mnMaxLength != null)
+        {
+            aBuffer.append(",maxLength=");
+            aBuffer.append(mnMaxLength);
+        }
+        if (maPattern != null)
+        {
+            aBuffer.append(",pattern=\"");
+            aBuffer.append(maPattern);
+            aBuffer.append('"');
+        }
+        if ( ! maEnumerations.isEmpty())
+        {
+            aBuffer.append(",enumerations");
+            aBuffer.append(maEnumerations);
+        }
+        return aBuffer.toString();
+    }
+    
+    
+    
+    public void AddEnumeration (final String sValue)
+    {
+        maEnumerations.add(sValue);
+    }
+    
+    
+    
+    
+    public void SetMinInclusive (final String sValue)
+    {
+        mnMinInclusive = Double.parseDouble(sValue);
+    }
+    
+    
+    
+    
+    public void SetMinExclusive (final String sValue)
+    {
+        mnMinExclusive = Double.parseDouble(sValue);
+    }
+    
+    
+    
+    
+    public void SetMaxInclusive (final String sValue)
+    {
+        mnMaxInclusive = Double.parseDouble(sValue);
+    }
+    
+    
+    
+    
+    public void SetMaxExclusive (final String sValue)
+    {
+        mnMaxExclusive = Double.parseDouble(sValue);
+    }
+    
+
+    
+    
+    public void SetLength (final String sValue)
+    {
+        mnLength = Integer.parseInt(sValue);
+    }
+    
+
+    
+    
+    public void SetMinLength (final String sValue)
+    {
+        mnMinLength = Integer.parseInt(sValue);
+    }
+    
+
+    
+    
+    public void SetMaxLength (final String sValue)
+    {
+        mnMaxLength = Integer.parseInt(sValue);
+    }
+    
+    
+    
+    
+    public void SetPattern (final String sValue)
+    {
+        maPattern = Pattern.compile(sValue);
+    }
+    
+    
+    
+    
+    private final String msBaseType;
+    private final Set<String> maEnumerations;
+    private Double mnMinInclusive;
+    private Double mnMinExclusive;
+    private Double mnMaxInclusive;
+    private Double mnMaxExclusive;
+    private Integer mnLength;
+    private Integer mnMinLength;
+    private Integer mnMaxLength;
+    private Pattern maPattern;
+}

Added: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/SimpleContent.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/SimpleContent.java?rev=1599430&view=auto
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/SimpleContent.java (added)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/SimpleContent.java Tue Jun  3 06:57:13 2014
@@ -0,0 +1,56 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.schema.model.simple;
+
+import org.apache.openoffice.ooxml.schema.model.base.INodeVisitor;
+import org.apache.openoffice.ooxml.schema.model.base.Location;
+import org.apache.openoffice.ooxml.schema.model.base.Node;
+import org.apache.openoffice.ooxml.schema.model.base.NodeType;
+
+public class SimpleContent
+    extends Node
+{
+    public SimpleContent (
+        final Node aParent,
+        final Location aLocation)
+    {
+        super(aParent, null, aLocation);
+    }
+
+    
+    
+    
+    @Override
+    public void AcceptVisitor (final INodeVisitor aVisitor)
+    {
+        aVisitor.Visit(this);
+    }
+
+    
+    
+    
+    @Override
+    public NodeType GetNodeType()
+    {
+        return NodeType.SimpleContent;
+    }
+}

Added: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/SimpleType.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/SimpleType.java?rev=1599430&view=auto
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/SimpleType.java (added)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/SimpleType.java Tue Jun  3 06:57:13 2014
@@ -0,0 +1,121 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.schema.model.simple;
+
+import org.apache.openoffice.ooxml.schema.model.base.INodeVisitor;
+import org.apache.openoffice.ooxml.schema.model.base.Location;
+import org.apache.openoffice.ooxml.schema.model.base.Node;
+import org.apache.openoffice.ooxml.schema.model.base.NodeType;
+import org.apache.openoffice.ooxml.schema.model.base.QualifiedName;
+
+/** Representation of the 'simpleType' XML schema element.
+ *  Simple types are used for attributes or the text of elements.
+ */
+public class SimpleType
+    extends Node
+{
+    public SimpleType (
+        final Node aParent,
+        final QualifiedName aName,
+        final Location aLocation)
+    {
+        super(aParent, aName, aLocation);
+        maRestriction = null;
+        maFinalValues = null;
+    }
+    
+    
+    
+    
+    @Override
+    public NodeType GetNodeType ()
+    {
+        return NodeType.SimpleType;
+    }
+    
+    
+    
+
+    public void SetRestriction (final Restriction aRestriction)
+    {
+        assert(maRestriction==null);
+        maRestriction = aRestriction;
+    }
+
+
+    
+    
+    public Restriction GetRestriction ()
+    {
+        return maRestriction;
+    }
+
+    
+    
+
+    public void SetFinal (final String[] aFinalValues)
+    {
+        maFinalValues = aFinalValues;
+    }
+    
+    
+    
+    
+    public boolean IsFinal (final String sCatgery)
+    {
+        if (maFinalValues != null)
+        {   
+            for (final String sFinal : maFinalValues)
+            {
+                if (sFinal.equals(sCatgery))
+                    return true;
+                else if (sFinal.equals("#all"))
+                    return true;
+            }
+        }
+        return false;
+    }
+
+    
+    
+    
+    @Override
+    public void AcceptVisitor (final INodeVisitor aVisitor)
+    {
+        aVisitor.Visit(this);
+    }
+
+    
+    
+    
+    @Override
+    public String toString ()
+    {
+        return "simple type "+GetName().GetDisplayName();
+    }
+    
+    
+    
+    
+    private Restriction maRestriction;
+    private String[] maFinalValues;
+}

Added: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/SimpleTypeReference.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/SimpleTypeReference.java?rev=1599430&view=auto
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/SimpleTypeReference.java (added)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/SimpleTypeReference.java Tue Jun  3 06:57:13 2014
@@ -0,0 +1,107 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.schema.model.simple;
+
+import org.apache.openoffice.ooxml.schema.model.base.INode;
+import org.apache.openoffice.ooxml.schema.model.base.INodeReference;
+import org.apache.openoffice.ooxml.schema.model.base.INodeVisitor;
+import org.apache.openoffice.ooxml.schema.model.base.Location;
+import org.apache.openoffice.ooxml.schema.model.base.Node;
+import org.apache.openoffice.ooxml.schema.model.base.NodeType;
+import org.apache.openoffice.ooxml.schema.model.base.QualifiedName;
+import org.apache.openoffice.ooxml.schema.model.schema.Schema;
+
+public class SimpleTypeReference
+    extends Node
+    implements INodeReference
+{
+    public SimpleTypeReference (
+        final Node aParent,
+        final QualifiedName aReferencedTypeName,
+        final Location aLocation)
+    {
+        super(aParent, null, aLocation);
+        maReferencedTypeName = aReferencedTypeName;        
+    }
+    
+    
+    
+    
+    public SimpleType GetReferencedSimpleType (final Schema aSchema)
+    {
+        final Node aType = aSchema.GetTypeForName(maReferencedTypeName);
+        if (aType == null)
+            throw new RuntimeException("there is no type named '"+maReferencedTypeName+"' in the schema");
+        else if (aType.GetNodeType()!=NodeType.SimpleType && aType.GetNodeType()!=NodeType.BuiltIn)
+            throw new RuntimeException("name '"+maReferencedTypeName+"' references a "+aType.GetNodeType()+" not a simple type or builtin");
+        else
+            return (SimpleType)aType;
+    }
+    
+    
+    
+    
+    @Override
+    public INode GetReferencedNode (final Schema aSchema)
+    {
+        return GetReferencedSimpleType(aSchema);
+    }
+
+        
+    
+    
+    public QualifiedName GetReferencedTypeName()
+    {
+        return maReferencedTypeName;
+    }
+
+    
+    
+    
+    @Override
+    public void AcceptVisitor (final INodeVisitor aVisitor)
+    {
+        aVisitor.Visit(this);
+    }
+
+    
+    
+    
+    @Override
+    public NodeType GetNodeType ()
+    {
+        return NodeType.SimpleTypeReference;
+    }
+    
+    
+    
+    @Override
+    public String toString ()
+    {
+        return "reference to simple type "+maReferencedTypeName;
+    }
+    
+    
+    
+    
+    private final QualifiedName maReferencedTypeName;
+}

Added: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/Union.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/Union.java?rev=1599430&view=auto
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/Union.java (added)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/simple/Union.java Tue Jun  3 06:57:13 2014
@@ -0,0 +1,68 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.schema.model.simple;
+
+import org.apache.openoffice.ooxml.schema.model.base.INodeVisitor;
+import org.apache.openoffice.ooxml.schema.model.base.Location;
+import org.apache.openoffice.ooxml.schema.model.base.Node;
+import org.apache.openoffice.ooxml.schema.model.base.NodeType;
+
+/** Representation of the 'union' XML schema element.
+ *  Its set of valid values is the union of all of its children. 
+ */
+public class Union
+    extends Node
+{
+    public Union (
+        final Node aParent,
+        final Location aLocation)
+    {
+        super(aParent, null, aLocation);
+    }
+    
+    
+    
+    
+    @Override
+    public NodeType GetNodeType ()
+    {
+        return NodeType.Union;
+    }
+
+
+
+
+    @Override
+    public void AcceptVisitor (final INodeVisitor aVisitor)
+    {
+        aVisitor.Visit(this);
+    }
+    
+    
+    
+    
+    @Override
+    public String toString ()
+    {
+        return "union";
+    }
+}

Added: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/SchemaParser.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/SchemaParser.java?rev=1599430&view=auto
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/SchemaParser.java (added)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/SchemaParser.java Tue Jun  3 06:57:13 2014
@@ -0,0 +1,1185 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.schema.parser;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.openoffice.ooxml.schema.model.attribute.Attribute;
+import org.apache.openoffice.ooxml.schema.model.attribute.AttributeGroup;
+import org.apache.openoffice.ooxml.schema.model.attribute.AttributeGroupReference;
+import org.apache.openoffice.ooxml.schema.model.attribute.AttributeReference;
+import org.apache.openoffice.ooxml.schema.model.base.INode;
+import org.apache.openoffice.ooxml.schema.model.base.Location;
+import org.apache.openoffice.ooxml.schema.model.base.Node;
+import org.apache.openoffice.ooxml.schema.model.base.QualifiedName;
+import org.apache.openoffice.ooxml.schema.model.complex.All;
+import org.apache.openoffice.ooxml.schema.model.complex.Any;
+import org.apache.openoffice.ooxml.schema.model.complex.Choice;
+import org.apache.openoffice.ooxml.schema.model.complex.ComplexContent;
+import org.apache.openoffice.ooxml.schema.model.complex.ComplexType;
+import org.apache.openoffice.ooxml.schema.model.complex.Element;
+import org.apache.openoffice.ooxml.schema.model.complex.ElementReference;
+import org.apache.openoffice.ooxml.schema.model.complex.Extension;
+import org.apache.openoffice.ooxml.schema.model.complex.Group;
+import org.apache.openoffice.ooxml.schema.model.complex.GroupReference;
+import org.apache.openoffice.ooxml.schema.model.complex.OccurrenceIndicator;
+import org.apache.openoffice.ooxml.schema.model.complex.Sequence;
+import org.apache.openoffice.ooxml.schema.model.schema.Schema;
+import org.apache.openoffice.ooxml.schema.model.simple.List;
+import org.apache.openoffice.ooxml.schema.model.simple.Restriction;
+import org.apache.openoffice.ooxml.schema.model.simple.SimpleContent;
+import org.apache.openoffice.ooxml.schema.model.simple.SimpleType;
+import org.apache.openoffice.ooxml.schema.model.simple.SimpleTypeReference;
+import org.apache.openoffice.ooxml.schema.model.simple.Union;
+
+
+/** Parser for single schema file.
+ *  Imports and includes of other schema files are stored and can be retrieved
+ *  by calling GetImportedSchemas().
+ *  
+ *  Typical usage:
+ *  1) Create SchemaParser for top-level schema file.
+ *  2) Call Parse().
+ *  3) Repeat the same recursively for all imported schemas (as returned by
+ *     GetImportedSchemas()).
+ *  
+ *  All top level types (complex types, simple types, elements, etc.) are
+ *  stored in the given Schema object.
+ */
+public class SchemaParser
+{
+    public SchemaParser (
+        final File aSchemaFile,
+        final Schema aSchema)
+    {
+        maSchema = aSchema;
+        maReader = GetStreamReader(aSchemaFile);
+        msBasename = aSchemaFile.getName();
+        maDirectory = aSchemaFile.getParentFile();
+        maLocalNamespaceMap = new HashMap<>();
+        maImportedSchemas = new Vector<>();
+        maLastLocation = null;
+    }
+    
+    
+    
+    
+    /** Parse the schema file.
+     *  @return
+     *      Return false if there is any error.
+     * @throws XMLStreamException 
+     */
+    public void Parse ()
+        throws XMLStreamException
+    {
+        if (maReader == null)
+            return;
+        
+        while (maReader.hasNext())
+        {
+            final int nCode = maReader.next();
+            switch (nCode)
+            {
+                case XMLStreamReader.START_ELEMENT:
+                    if (maReader.getLocalName().equals("schema"))
+                    {
+                        ProcessNamespaceDefinitions();
+                        ParseSchema();
+                        
+                        maLastLocation = maReader.getLocation();
+                    }
+                    else
+                    {
+                        throw CreateErrorException("expecting top level element to be 'schema'");
+                    }
+                    break;
+                    
+                case XMLStreamReader.END_DOCUMENT:
+                    return;
+                    
+                default:
+                    throw CreateErrorException("unexpected XML event %d", nCode);
+            }
+        }
+    }
+    
+    
+    
+    
+    public Iterable<File> GetImportedSchemaFilenames ()
+    {
+        return maImportedSchemas;
+    }
+    
+    
+    
+    
+    public int GetLineCount ()
+    {
+        if (maLastLocation != null)
+            return maLastLocation.getLineNumber();
+        else
+            return 0;
+    }
+    
+    
+    
+    
+    public int GetByteCount ()
+    {
+        if (maLastLocation != null)
+            return maLastLocation.getCharacterOffset();
+        else
+            return 0;
+    }
+    
+    
+    
+    
+    /** Process the namespace definitions in the outer 'schema' element.
+     */
+    private void ProcessNamespaceDefinitions ()
+    {
+        for (int nIndex=0; nIndex<maReader.getNamespaceCount(); ++nIndex)
+        {
+            final String sPrefix = maReader.getNamespacePrefix(nIndex);
+            final String sURI = maReader.getNamespaceURI(nIndex);
+            maLocalNamespaceMap.put(sPrefix, sURI);
+            maSchema.Namespaces.ProvideNamespace(sURI, sPrefix);
+        }
+        msTargetNamespace = GetAttributeValue("targetNamespace");
+        maLocalNamespaceMap.put(null, msTargetNamespace);
+        maSchema.Namespaces.ProvideNamespace(msTargetNamespace, null);
+    }
+    
+    
+    
+    
+    private void ParseSchema ()
+        throws XMLStreamException
+    {
+        while (true)
+        {
+            switch (Next())
+            {
+                case XMLStreamReader.START_ELEMENT:
+                    ProcessTopLevelStartElement();
+                    break;
+                    
+                case XMLStreamReader.END_ELEMENT:
+                    return;
+            
+                default:
+                    throw CreateErrorException("unexpected event (expteced START_ELEMENT): %d", maReader.getEventType());
+            }
+        }
+    }
+    
+    
+    
+    
+    private void ProcessTopLevelStartElement ()
+        throws XMLStreamException
+    {
+        assert(GetAttributeValue("minOccurs") == null);
+        assert(GetAttributeValue("maxOccurs") == null);
+        
+        switch (maReader.getLocalName())
+        {
+            case "attribute":
+                maSchema.Attributes.Add(ParseAttribute());
+                break;
+            
+            case "attributeGroup":
+                maSchema.AttributeGroups.Add(ParseAttributeGroup());
+                break;
+
+            case "complexType":
+                maSchema.ComplexTypes.Add(ParseComplexType());
+                break;
+                
+            case "element":
+                maSchema.TopLevelElements.Add(ParseElement(null));
+                break;
+                
+            case "group":
+                maSchema.Groups.Add(ParseGroup(null));
+                break;
+                
+            case "import":
+                ParseImport();
+                break;
+                
+            case "include":
+                ParseInclude();
+                break;
+
+            case "simpleType":
+                maSchema.SimpleTypes.Add(ParseSimpleType(null));
+                break;
+                
+            default:
+                throw CreateErrorException("unexpected top level element %s", maReader.getLocalName());
+        }
+    }
+    
+    
+    
+    
+    private void ProcessStartElement (final Node aParent)
+        throws XMLStreamException
+    {
+        final String sMinimumOccurrence = GetOptionalAttributeValue("minOccurs", "1");
+        final String sMaximumOccurrence = GetOptionalAttributeValue("maxOccurs", "1");
+        
+        final Node aLocalParent;
+        if ( ! (sMinimumOccurrence.equals("1") && sMaximumOccurrence.equals("1")))
+        {
+            // Occurrence does not only have default values (min=max=1).
+            // Have to create an intermediate node for the occurrence indicator.
+            final OccurrenceIndicator aIndicator = new OccurrenceIndicator(
+                aParent, 
+                sMinimumOccurrence, 
+                sMaximumOccurrence,
+                GetLocation());
+            aParent.AddChild(aIndicator);
+            aLocalParent = aIndicator;
+        }
+        else
+            aLocalParent = aParent;
+        
+        switch (maReader.getLocalName())
+        {
+            case "all":
+                aLocalParent.AddChild(ParseAll(aLocalParent));
+                break;
+
+            case "any":
+                aLocalParent.AddChild(ParseAny(aLocalParent));
+                break;
+
+            case "attribute":
+                aLocalParent.AddAttribute(ParseAttributeOrReference());
+                break;
+                
+            case "attributeGroup":
+                aLocalParent.AddAttribute(ParseAttributeGroupOrReference());
+                break;
+                
+            case "choice":
+                aLocalParent.AddChild(ParseChoice(aLocalParent));
+                break;
+
+            case "complexContent":
+                aLocalParent.AddChild(ParseComplexContent(aLocalParent));
+                break;
+
+            case "element":
+                aLocalParent.AddChild(ParseElementOrReference(aLocalParent));
+                break;
+
+            case "extension":
+                aLocalParent.AddChild(ParseExtension(aLocalParent));
+                break;
+
+            case "group":
+                aLocalParent.AddChild(ParseGroupOrReference(aLocalParent));
+                break;
+
+            case "list":
+                aLocalParent.AddChild(ParseList(aLocalParent));
+                break;
+
+            case "sequence":
+                aLocalParent.AddChild(ParseSequence(aLocalParent));
+                break;
+                
+            case "simpleContent":
+                aLocalParent.AddChild(ParseSimpleContent(aLocalParent));
+                break;
+                
+            default:
+                throw CreateErrorException("unsupported content type %s", maReader.getLocalName());
+        }
+    }
+    
+    
+    
+    
+    private void IgnoreAnnotation ()
+        throws XMLStreamException
+    {
+        IgnoreContent();
+    }
+
+    
+    
+    
+    private void IgnoreContent ()
+        throws XMLStreamException
+    {
+        while(true)
+        {
+            switch(maReader.next())
+            {
+                case XMLStreamReader.START_ELEMENT:
+                    IgnoreContent();
+                    break;
+                    
+                case XMLStreamReader.END_ELEMENT:
+                    return;
+                    
+                case XMLStreamReader.COMMENT:
+                case XMLStreamReader.CHARACTERS:
+                    break;
+
+                default:
+                    throw CreateErrorException(
+                        "unexpected XML event %d while ignoring content",
+                        maReader.getEventType());
+            }
+        }
+    }
+    
+    
+    
+    
+    private All ParseAll (final Node aParent)
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("minOccurs", "maxOccurs"));
+        
+        final All aAll = new All(aParent, GetLocation());
+        ParseContent(aAll);
+        return aAll;        
+    }
+    
+    
+    
+    
+    private Any ParseAny (final Node aParent)
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("minOccurs", "maxOccurs", "namespace", "processContents"));
+        
+        final Any aAny = new Any(aParent, GetAttributeValue("processContents"), GetLocation());
+        ExpectEndElement("ParseAny");
+        return aAny;        
+    }
+    
+    
+    
+    
+    private AttributeGroup ParseAttributeGroup ()
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("name"));
+
+        final AttributeGroup aGroup = new AttributeGroup(GetOptionalQualifiedName("name"), GetLocation());
+        
+        while (true)
+        {
+            switch (Next())
+            {
+                case XMLStreamReader.START_ELEMENT:
+                    if ( ! maReader.getLocalName().equals("attribute"))
+                        throw CreateErrorException(
+                            "attributeGroup expects element 'attribute' but got %s",
+                            maReader.getLocalName());
+                    else
+                        aGroup.AddAttribute(ParseAttributeOrReference());
+                    break;
+                    
+                case XMLStreamReader.END_ELEMENT:
+                    return aGroup;
+                    
+                default:
+                    throw CreateErrorException(
+                        "unexpected event when parsing attributeGroup: %d",
+                        maReader.getEventType());
+            }
+        }
+    }
+    
+    
+    
+    
+    private INode ParseAttributeGroupOrReference ()
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("ref"));
+
+        final INode aGroup;
+        if (GetAttributeValue("schemaLocation") != null)
+        {
+            aGroup = ParseAttributeGroup();
+        }
+        else
+        {
+            aGroup = new AttributeGroupReference(
+                CreateQualifiedName(
+                    GetAttributeValue("ref")),
+                GetLocation());
+            ExpectEndElement("attribute group or reference");
+        }
+        return aGroup;
+    }
+    
+    
+    
+    
+    private INode ParseAttributeOrReference ()
+        throws XMLStreamException
+    {
+        final INode aAttribute;
+        if (GetAttributeValue("name") != null)
+        {
+            aAttribute = ParseAttribute();
+        }
+        else
+        {
+            assert(HasOnlyAttributes("default", "fixed", "ref", "use"));
+            
+            aAttribute = new AttributeReference(
+                GetQualifiedName("ref"),
+                GetOptionalAttributeValue("use", "optional"),
+                GetOptionalAttributeValue("default", null),
+                GetOptionalAttributeValue("fixed", null),
+                GetLocation());
+            ExpectEndElement("attribute reference");
+        }
+        return aAttribute;
+    }
+    
+    
+    
+    
+    private Attribute ParseAttribute ()
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("default", "fixed", "name", "type", "use"));
+
+        final Attribute aAttribute = new Attribute(
+            GetQualifiedName("name"),
+            GetQualifiedName("type"),
+            GetOptionalAttributeValue("use", "optional"),
+            GetOptionalAttributeValue("default", null),
+            GetOptionalAttributeValue("fixed", null),
+            GetLocation());
+        ExpectEndElement("attribute");
+        
+        return aAttribute;
+    }
+
+
+
+    private Choice ParseChoice (final Node aParent)
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("minOccurs", "maxOccurs"));
+        
+        final Choice aChoice = new Choice(aParent, GetLocation());
+        ParseContent(aChoice);
+        return aChoice;
+    }
+
+    
+    
+    
+    private ComplexContent ParseComplexContent (final Node aParent)
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("minOccurs", "maxOccurs"));
+        
+        final ComplexContent aNode = new ComplexContent(aParent, GetLocation());
+        ParseContent(aNode);
+        return aNode;
+    }
+
+    
+    
+    
+    private ComplexType ParseComplexType ()
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("mixed", "name"));        
+        
+        final ComplexType aComplexType = new ComplexType(
+            null,
+            GetQualifiedName("name"),
+            GetLocation());
+        
+        ParseContent(aComplexType);
+        
+        return aComplexType;
+    }
+    
+    
+    
+    
+    private Element ParseElement (final Node aParent)
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("minOccurs", "maxOccurs", "name", "type"));
+        
+        final Element aElement = new Element(
+            aParent,
+            GetQualifiedName("name"),
+            GetQualifiedName("type"),
+            GetLocation());
+        
+        ExpectEndElement("element");
+        
+        return aElement;
+    }
+    
+
+    
+    
+    private Element ParseElementOrReference (final Node aParent)
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("minOccurs", "maxOccurs", "name", "ref", "type"));
+
+        final Element aElement;
+        final String sName = GetOptionalAttributeValue("name", null);
+        if (sName != null)
+        {
+            aElement = ParseElement(aParent);
+        }
+        else
+        {
+            final String sElementReference = GetOptionalAttributeValue("ref",  null);
+            if (sElementReference != null)
+            {
+                ExpectEndElement("element reference");
+                aElement = new ElementReference(
+                    aParent,
+                    CreateQualifiedName(sElementReference),
+                    GetLocation());
+            }
+            else
+            {
+                throw CreateErrorException("element has no name and no ref");
+            }
+        }
+        return aElement;
+    }
+    
+    
+    
+    
+    private Extension ParseExtension (final Node aParent)
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("base", "minOccurs", "maxOccurs"));
+        
+        final Extension aNode = new Extension(
+            aParent,
+            CreateQualifiedName(GetAttributeValue("base")),
+            GetLocation());
+        ParseContent(aNode);
+        return aNode;
+    }
+
+    
+    
+    
+    private Group ParseGroup (final Node aParent)
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("name"));
+
+        final Group aGroup = new Group(
+            aParent,
+            GetQualifiedName("name"),
+            GetLocation());
+        ParseContent(aGroup);
+        return aGroup;
+    }
+
+    
+    
+    
+    private Node ParseGroupOrReference (final Node aParent)
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("minOccurs", "maxOccurs", "name", "ref"));
+        
+        final Node aGroup;
+        final String sName = GetOptionalAttributeValue("name", null);
+        if (sName != null)
+        {
+            aGroup = ParseGroup(aParent);
+        }
+        else
+        {
+            final String sGroupReference = GetOptionalAttributeValue("ref",  null);
+            if (sGroupReference != null)
+            {
+                ExpectEndElement("group reference");
+                aGroup = new GroupReference(
+                    aParent,
+                    CreateQualifiedName(sGroupReference),
+                    GetLocation());
+            }
+            else
+            {
+                throw CreateErrorException("group has no name and no ref");
+            }
+        }
+        return aGroup;
+    }
+    
+
+    
+    
+    private Restriction ParseRestriction (final Node aParent)
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("base", "value"));
+
+        final Restriction aRestriction = new Restriction(
+            aParent,
+            GetAttributeValue("base"),
+            GetLocation());
+        
+        while (true)
+        {
+            switch (Next())
+            {
+                case XMLStreamReader.START_ELEMENT:
+                    final String sValue = GetAttributeValue("value");
+                    switch (maReader.getLocalName())
+                    {
+                        case "enumeration":
+                            aRestriction.AddEnumeration(sValue);
+                            break;
+                            
+                        case "minInclusive":
+                            aRestriction.SetMinInclusive(sValue);
+                            break;
+
+                        case "minExclusive":
+                            aRestriction.SetMinExclusive(sValue);
+                            break;
+
+                        case "maxInclusive":
+                            aRestriction.SetMaxInclusive(sValue);
+                            break;
+
+                        case "maxExclusive":
+                            aRestriction.SetMaxExclusive(sValue);
+                            break;
+
+                        case "length":
+                            aRestriction.SetLength(sValue);
+                            break;
+
+                        case "minLength":
+                            aRestriction.SetMinLength(sValue);
+                            break;
+
+                        case "maxLength":
+                            aRestriction.SetMaxLength(sValue);
+                            break;
+
+                        case "pattern":
+                            aRestriction.SetPattern(sValue);
+                            break;
+
+                        default:
+                            throw CreateErrorException("unsupported restriction type "+maReader.getLocalName());
+                    }
+                    ExpectEndElement("restriction");
+                    break;
+
+                case XMLStreamReader.END_ELEMENT:
+                    return aRestriction;
+                    
+                default:
+                    throw CreateErrorException("unexpected XML event while parsing restrictions: %d", maReader.getEventType());
+            }
+        }
+    }
+
+    
+    
+    
+    private List ParseList (final Node aParent)
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("itemType"));
+        
+        final List aList = new List(
+            aParent,
+            GetQualifiedName("itemType"),
+            GetLocation());
+        ExpectEndElement("list");
+        return aList;
+    }
+
+
+    
+    
+    private Sequence ParseSequence (final Node aParent)
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("minOccurs", "maxOccurs", "name"));
+        
+        final Sequence aSequence = new Sequence(
+            aParent,
+            GetOptionalQualifiedName("name"),
+            GetLocation());
+        ParseContent(aSequence);
+        return aSequence;
+    }
+
+    
+    
+
+    private SimpleContent ParseSimpleContent (final Node aParent)
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("minOccurs", "maxOccurs"));
+        
+        final SimpleContent aSimpleContent = new SimpleContent(
+            aParent,
+            GetLocation());
+        ParseContent(aSimpleContent);
+        return aSimpleContent;
+    }
+
+    
+    
+
+    private SimpleType ParseSimpleType (final Node aParent) 
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("final", "name"));
+        
+        final SimpleType aType = new SimpleType(
+            aParent,
+            GetQualifiedName("name"),
+            GetLocation());
+        final String sFinalValue = GetOptionalAttributeValue("final", null);
+        if (sFinalValue != null)
+            aType.SetFinal(sFinalValue.split("\\s+"));
+        
+        while (true)
+        {
+            switch (Next())
+            {
+                case XMLStreamReader.START_ELEMENT:
+                    switch(maReader.getLocalName())
+                    {
+                        case "list":
+                            aType.AddChild(ParseList(aType));
+                            break;
+                            
+                        case "restriction":
+                            aType.SetRestriction(ParseRestriction(aType));
+                            break;
+
+                        case "union":
+                            aType.AddChild(ParseUnion(aType));
+                            break;
+                            
+                        default:
+                            throw CreateErrorException("unsupported simple type part %s", maReader.getLocalName());
+                    }
+                    break;
+                    
+                case XMLStreamReader.END_ELEMENT:
+                    return aType;
+                    
+                default:
+                    throw CreateErrorException("unexpected XML event in ParseSimpleType: %s", maReader.getEventType());
+            }
+        }
+    }
+    
+    
+    
+    
+    private Union ParseUnion (final Node aParent)
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("memberTypes"));
+        
+        final Union aUnion = new Union(
+            aParent,
+            GetLocation());
+        final String[] aMemberTypes = GetAttributeValue("memberTypes").split("\\s+");
+        for (int nIndex=0; nIndex<aMemberTypes.length; ++nIndex)
+            aUnion.AddChild(
+                new SimpleTypeReference(
+                    aUnion,
+                    CreateQualifiedName(aMemberTypes[nIndex]),
+                    GetLocation()));
+
+        ParseContent(aUnion);
+            
+        return aUnion;
+    }
+    
+    
+    private void ParseContent (final Node aParent)
+        throws XMLStreamException
+    {
+        while(true)
+        {
+            switch(Next())
+            {
+                case XMLStreamReader.START_ELEMENT:
+                    ProcessStartElement(aParent);
+                    break;
+                    
+                case XMLStreamReader.END_ELEMENT:
+                    return;
+                    
+                default:
+                    throw CreateErrorException(
+                        "unexpected XML event %d while parsing content of %s",
+                        maReader.getEventType(),
+                        aParent.toString());
+            }
+        }
+    }
+    
+    
+    
+    
+    private void ParseImport ()
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("id", "namespace", "schemaLocation"));
+        
+        final String sFilename = GetOptionalAttributeValue("schemaLocation", null);
+        if (sFilename == null)
+        {
+            final String sNamespaceName = GetAttributeValue("namespace");
+            if (sNamespaceName.equals(XmlNamespace.NamespaceURI))
+            {
+                XmlNamespace.Apply(maSchema);
+                maLocalNamespaceMap.put(XmlNamespace.NamespacePrefix, XmlNamespace.NamespaceURI);
+            }
+            else
+                throw CreateErrorException("invalid import");
+        }
+        else
+        {
+            maImportedSchemas.add(new File(maDirectory, sFilename));
+        }
+        
+        ExpectEndElement("import");
+    }
+    
+
+    
+
+    private void ParseInclude ()
+        throws XMLStreamException
+    {
+        assert(HasOnlyAttributes("id", "schemaLocation"));
+        
+        final String sFilename = GetOptionalAttributeValue("schemaLocation", null);
+        if (sFilename == null)
+        {
+            throw CreateErrorException("invalid include");
+        }
+        else
+        {
+            maImportedSchemas.add(new File(maDirectory, sFilename));
+        }
+        
+        ExpectEndElement("include");
+    }
+    
+
+    
+
+    private void ExpectEndElement (final String sCaller)
+        throws XMLStreamException
+    {
+        final int nNextEvent = Next();
+        if (nNextEvent != XMLStreamReader.END_ELEMENT)
+            throw CreateErrorException("expected END_ELEMENT of %s but got %s",
+                sCaller,
+                nNextEvent);
+    }
+    
+    
+    
+    
+    /** Return the next relevant token from the XML stream.
+     *  Ignores comments.
+     *  @return
+     *      Returns the event code of the next relevant XML event or END_DOCUMENT when the end of the file has been reached.
+     */
+    private int Next ()
+        throws XMLStreamException
+    {
+        while (maReader.hasNext())
+        {
+            switch (maReader.next())
+            {
+                case XMLStreamReader.COMMENT:
+                    // Ignore comments.
+                    break;
+                    
+                case XMLStreamReader.CHARACTERS:
+                    // Ignore whitespace.
+                    if (maReader.getText().matches("^\\s+$"))
+                        break;
+                    else
+                    {
+                        // Character events are not expected in schema files
+                        // and therefore not supported. 
+                        // Alternatively, they could easily be ignored.
+                        throw CreateErrorException("unexpected CHARACTERS event with text [%s]", maReader.getText());
+                    }
+
+                case XMLStreamReader.START_ELEMENT:
+                    switch (maReader.getLocalName())
+                    {
+                        case "annotation":
+                            IgnoreAnnotation();
+                            break;
+                        case "unique":
+                            // Not supported.
+                            IgnoreContent();
+                            break;
+                        default:
+                            return XMLStreamReader.START_ELEMENT;
+                    }
+                    break;
+
+                default:
+                    return maReader.getEventType();
+            }
+        }
+        return XMLStreamReader.END_DOCUMENT;
+    }
+    
+    
+    
+    
+    private String GetAttributeValue (final String sAttributeLocalName)
+    {
+        return maReader.getAttributeValue(null, sAttributeLocalName);
+    }
+    
+    
+    
+    
+    private String GetOptionalAttributeValue (
+        final String sAttributeLocalName,
+        final String sDefaultValue)
+    {
+        final String sValue = maReader.getAttributeValue(null, sAttributeLocalName);
+        if (sValue == null)
+            return sDefaultValue;
+        else
+            return sValue;
+    }
+    
+    
+    
+    
+    /** Read the specified attribute and return its value as QualifiedName object.
+     */
+    private QualifiedName GetQualifiedName (final String sAttributeLocalName)
+    {
+        final String sName = maReader.getAttributeValue(null, sAttributeLocalName);
+        if (sName == null)
+            throw CreateErrorException(
+                "did not find a qualified name as value of attribute '%s' at %s:%s",
+                sAttributeLocalName,
+                msBasename,
+                maReader.getLocation());
+        else
+            return CreateQualifiedName(sName);
+    }
+    
+    
+    
+    
+    private QualifiedName GetOptionalQualifiedName (final String sAttributeLocalName)
+    {
+        final String sName = maReader.getAttributeValue(null, sAttributeLocalName);
+        if (sName == null)
+            return null;
+        else
+            return CreateQualifiedName(sName);
+    }
+    
+    
+    
+    
+    /** Create a QualifiedName object from the given string.
+     * @param sName
+     *     May or may not contain a namespace prefix (separated from the name
+     *     by a colon).
+     */
+    private QualifiedName CreateQualifiedName (final String sName)
+    {
+        final String[] aParts = sName.split(":");
+        final String sNamespaceURL;
+        final String sLocalPart;
+        switch (aParts.length)
+        {
+            case 1:
+                // sName only consists of a local part.
+                // Set the namespace URL to that of the default namespace.
+                sNamespaceURL = maLocalNamespaceMap.get(null);
+                sLocalPart = aParts[0];
+                break;
+                
+            case 2:
+                // sName is of the form prefix:local.
+                sNamespaceURL = maLocalNamespaceMap.get(aParts[0]);
+                sLocalPart = aParts[1];
+                break;
+                
+            default:
+                throw new RuntimeException(
+                    "the string '"+sName+"' can not be transformed into a qualified name");
+        }
+        if (sNamespaceURL == null)
+            throw CreateErrorException("can not determine namespace for '%s'", sName);
+        // Transform the local namespace prefix into a global namespace prefix
+        // (different schema files can use different prefixes for the same
+        // namespace URI).
+        final String sGlobalNamespacePrefix = maSchema.Namespaces.GetNamespacePrefix(sNamespaceURL);
+        return new QualifiedName(
+            sNamespaceURL,
+            sGlobalNamespacePrefix,
+            sLocalPart);
+    }
+    
+    
+    
+    
+    /** Create an XMLStreamReader for the given file.
+     *  Returns null when there is an error. 
+     */
+    private static XMLStreamReader GetStreamReader (final File aSchemaFile)
+    {
+        final XMLInputFactory aFactory = (XMLInputFactory)XMLInputFactory.newInstance();
+        aFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
+        aFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
+        aFactory.setProperty(XMLInputFactory.IS_COALESCING, false);
+        
+        try
+        {
+            return aFactory.createXMLStreamReader(
+                aSchemaFile.getName(),
+                new FileInputStream(aSchemaFile));
+        }
+        catch (Exception aException)
+        {
+            aException.printStackTrace();
+            return null;
+        }
+    }
+    
+    
+    
+    
+    private RuntimeException CreateErrorException (
+        final String sFormat, 
+        final Object ... aArgumentList)
+    {
+        return new RuntimeException(String.format(sFormat, aArgumentList)
+            + String.format(" in %s at L%dC%dP%d",
+                msBasename,
+                maReader.getLocation().getLineNumber(),
+                maReader.getLocation().getColumnNumber(),
+                maReader.getLocation().getCharacterOffset()));
+    }
+    
+    
+    
+    
+    /** This predicate is only used for debugging to assert
+     *  that no unsupported attributes are present.
+     *  If there where then the parser has to be extended.
+     */
+    private boolean HasOnlyAttributes (final String ... aAttributeNameList)
+    {
+        for (int nIndex=0,nCount=maReader.getAttributeCount(); nIndex<nCount; ++nIndex)
+        {
+            final String sAttributeName = maReader.getAttributeLocalName(nIndex); 
+            boolean bFound = false;
+            for (final String sName : aAttributeNameList)
+                if (sAttributeName.equals(sName))
+                {
+                    bFound = true;
+                    break;
+                }
+            if ( ! bFound)
+            {
+                // Attribute name was not found in the given list.
+                System.err.printf("attribute '%s' is not handled\n", sAttributeName);
+                return false;
+            }
+        }
+        return true;
+    }
+    
+
+    
+    
+    private Location GetLocation ()
+    {
+        final javax.xml.stream.Location aLocation = maReader.getLocation();
+        return new Location(
+            msBasename,
+            aLocation.getLineNumber(),
+            aLocation.getColumnNumber(),
+            aLocation.getCharacterOffset());
+    }
+    
+    
+    
+    
+    private final Schema maSchema;
+    private final XMLStreamReader maReader;
+    private final String msBasename;
+    private final File maDirectory;
+    private String msTargetNamespace;
+    /// Map of namespace prefix to URI, local to the currently read schema file.
+    private final Map<String,String> maLocalNamespaceMap;
+    /// The names of other schema files referenced by import elements.
+    private final Vector<File> maImportedSchemas;
+    /// Some values for tracking the number of read bytes and lines. 
+    private javax.xml.stream.Location maLastLocation;
+}