openoffice-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a.@apache.org
Subject svn commit: r1602077 [2/2] - in /openoffice/trunk/main/ooxml/source/framework: JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ SchemaParser/src/org/apache/openoffice/ooxml/schema/ SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/ S...
Date Thu, 12 Jun 2014 07:15:25 GMT
Modified: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/ValidatingCreator.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/ValidatingCreator.java?rev=1602077&r1=1602076&r2=1602077&view=diff
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/ValidatingCreator.java (original)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/ValidatingCreator.java Thu Jun 12 07:15:24 2014
@@ -22,42 +22,57 @@
 package org.apache.openoffice.ooxml.schema.automaton;
 
 import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Iterator;
+import java.util.Stack;
 import java.util.Vector;
 
+import org.apache.openoffice.ooxml.schema.iterator.DereferencingNodeIterator;
+import org.apache.openoffice.ooxml.schema.iterator.PermutationIterator;
 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.INodeVisitor;
+import org.apache.openoffice.ooxml.schema.model.base.Location;
+import org.apache.openoffice.ooxml.schema.model.base.NodeVisitorAdapter;
+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.ComplexTypeReference;
 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.SchemaBase;
+import org.apache.openoffice.ooxml.schema.model.simple.BuiltIn;
+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;
 
 /** Create a set of validating stack automatons for a set of schemas.
  *  There is one DFA (deterministic finite automaton) for each complex type and
  *  one for the top level elements. 
  */
 public class ValidatingCreator
+    extends CreatorBase
+    implements INodeVisitor
 {
     public ValidatingCreator (
         final SchemaBase aSchemaBase,
         final File aLogFile)
     {
-        maSchemaBase = aSchemaBase;
-        maStateContainer = new StateContainer();
-
-        PrintStream aLog = null;
-        try
-        {
-            aLog = new PrintStream(new FileOutputStream(aLogFile));
-        }
-        catch (FileNotFoundException e)
-        {
-            e.printStackTrace();
-        }
-        maLog = aLog;
+        super(aSchemaBase, aLogFile);
+        maContextStack = new Stack<>();
+        maCurrentContext = null;
     }
     
     
@@ -89,29 +104,23 @@ public class ValidatingCreator
     
     private FiniteAutomaton CreateForTopLevelElements ()
     {
-        final Map<State,Vector<Attribute>> aAttributes = new HashMap<>();
-        
-        final StateContext aStateContext = new StateContext(
+        maStateContext = new StateContext(
             maStateContainer,
             "<top-level>");
-        final State aEndState = aStateContext.CreateEndState();
+        final State aEndState = maStateContext.CreateEndState();
         
-        final INodeVisitor aVisitor = new ValidatingCreatorVisitor(
-            aAttributes,
-            aStateContext,
-            maSchemaBase,
-            maLog,
-            "",
-            aStateContext.GetStartState(),
-            aStateContext.GetStartState(),
-            aEndState);
+        assert(maContextStack.isEmpty());
+        msLogIndentation = "";
 
         // top level elements
         for (final Element aElement : maSchemaBase.TopLevelElements.GetSorted())
-            aElement.AcceptVisitor(aVisitor);
+            ProcessType(
+                aElement,
+                maStateContext.GetStartState(),
+                maStateContext.GetStartState(),
+                aEndState);
         
-        return new FiniteAutomaton(aStateContext);
-
+        return new FiniteAutomaton(maStateContext, null);
     }
     
     
@@ -119,29 +128,641 @@ public class ValidatingCreator
     
     private FiniteAutomaton CreateForComplexType (final ComplexType aComplexType)
     {
-        final Map<State,Vector<Attribute>> aAttributes = new HashMap<>();
-
-        final StateContext aStateContext = new StateContext(
+        maStateContext = new StateContext(
             maStateContainer,
             aComplexType.GetName().GetStateName());
-        final State aEndState = aStateContext.CreateEndState();
-        aComplexType.AcceptVisitor(
-            new ValidatingCreatorVisitor(
-                aAttributes,
-                aStateContext,
-                maSchemaBase,
-                maLog,
-                "",
-                aStateContext.GetStartState(),
-                aStateContext.GetStartState(),
-                aEndState));
-        return new FiniteAutomaton(aStateContext);
+        maAttributes = new Vector<>();
+        final State aEndState = maStateContext.CreateEndState();
+        ProcessType(
+            aComplexType,
+            maStateContext.GetStartState(),
+            maStateContext.GetStartState(),
+            aEndState);
+        return new FiniteAutomaton(
+            maStateContext, 
+            maAttributes);
+    }
+    
+    
+    
+    
+    @Override
+    public void Visit (final All aAll)
+    {
+        AddComment("All");
+        ProcessAttributes(aAll);
+
+        // Make a transformation of the children into a choice of sequences that
+        // can then be processed by already existing Visit() methods.
+        // These sequences enumerate all permutations of the original children.
+        final INode aReplacement = GetAllReplacement(aAll);
+        
+        final State aLocalStartState = maStateContext.CreateState(
+            maCurrentContext.BaseState,
+            "As");
+        final State aLocalEndState = maStateContext.CreateState(
+            maCurrentContext.BaseState,
+            "Ae");
+
+        StartBlock();
+        AddEpsilonTransition(maCurrentContext.StartState, aLocalStartState);
+        ProcessType(
+            aReplacement,
+            maStateContext.CreateState(maCurrentContext.BaseState, "A"),
+            aLocalStartState,
+            aLocalEndState);
+        AddEpsilonTransition(aLocalEndState, maCurrentContext.EndState);
+        EndBlock();
+    }
+    
+    
+    
+
+    @Override
+    public void Visit (final Any aAny)
+    {
+        assert(aAny.GetChildCount() == 0);
+        
+        AddComment("Any");
+        ProcessAttributes(aAny);
+
+        AddSkipTransition(
+            maCurrentContext.StartState,
+            new SkipData(
+                aAny.GetProcessContentsFlag(),
+                aAny.GetNamespaces()));
+        AddEpsilonTransition(maCurrentContext.StartState, maCurrentContext.EndState);
+    }
+
+
+
+
+    @Override
+    public void Visit (final ComplexContent aComplexContent)
+    {
+        assert(aComplexContent.GetChildCount() == 1);
+
+        AddComment ("Complex Content.");
+        ProcessAttributes(aComplexContent);
+        
+        StartBlock();
+        ProcessType(
+            aComplexContent.GetChildren().iterator().next(),
+            maCurrentContext.BaseState,
+            maCurrentContext.StartState,
+            maCurrentContext.EndState);
+        EndBlock();
+    }
+
+
+
+
+    @Override
+    public void Visit (final ComplexType aComplexType)
+    {
+        if (maLog != null)
+        {
+            maLog.print("\n");
+            AddComment ("Complex Type %s defined in %s.",
+                aComplexType.GetName().GetDisplayName(),
+                aComplexType.GetLocation());
+        }
+        ProcessAttributes(aComplexType);
+
+        StartBlock();
+        maLog.printf("%sstarting at state %s\n", msLogIndentation, maCurrentContext.StartState.GetFullname());
+        
+        if (GetElementCount(aComplexType) == 0)
+        {
+            // There are elements. Therefore there will be no transitions.
+            // The start state is accepting and the end state is not necessary.
+            maCurrentContext.StartState.SetIsAccepting();
+            maStateContext.RemoveState(maCurrentContext.EndState);
+        }
+
+        for (final INode aChild : aComplexType.GetChildren())
+            ProcessType(aChild, maCurrentContext.BaseState, maCurrentContext.StartState, maCurrentContext.EndState);
+        
+        EndBlock();
+    }
+
+
+
+
+    @Override
+    public void Visit (final ComplexTypeReference aNode)
+    {
+        throw new RuntimeException("can not handle "+aNode.toString());
+    }
+
+
+
+
+    @Override
+    public void Visit (final Choice aChoice)
+    {
+        AddComment("Choice");
+        ProcessAttributes(aChoice);
+
+        final State aLocalStartState = maStateContext.CreateState(maCurrentContext.BaseState, "Cs");
+        final State aLocalEndState = maStateContext.CreateState(maCurrentContext.BaseState, "Ce");
+        StartBlock();
+        AddEpsilonTransition(maCurrentContext.StartState, aLocalStartState);
+        
+        int nStateIndex = 0;
+        for (final INode aChild : aChoice.GetChildren())
+        {
+            ProcessType(
+                aChild,
+                maStateContext.CreateState(maCurrentContext.BaseState, "C"+nStateIndex++),
+                aLocalStartState,
+                aLocalEndState);
+        }
+        AddEpsilonTransition(aLocalEndState, maCurrentContext.EndState);
+        EndBlock();
+    }
+
+
+
+
+    @Override
+    public void Visit (final Element aElement)
+    {
+        assert(aElement.GetChildCount()==0);
+        
+        AddComment("Element: on '%s' go from %s to %s via %s",
+            aElement.GetElementName().GetDisplayName(),
+            maCurrentContext.StartState.GetFullname(),
+            maCurrentContext.EndState.GetFullname(),
+            aElement.GetTypeName().GetStateName());
+        ProcessAttributes(aElement);
+        
+        final Transition aTransition = new Transition(
+            maCurrentContext.StartState,
+            maCurrentContext.EndState,
+            aElement.GetElementName(),
+            aElement.GetTypeName().GetStateName());
+        maCurrentContext.StartState.AddTransition(aTransition);
+    }
+
+
+
+
+    @Override
+    public void Visit (final ElementReference aReference)
+    {
+        assert(aReference.GetChildCount() == 0);
+        
+        AddComment("Element reference to %s", aReference.GetReferencedElementName());
+        ProcessAttributes(aReference);
+        
+        final Element aElement = aReference.GetReferencedElement(maSchemaBase);
+        if (aElement == null)
+            throw new RuntimeException("can't find referenced element "+aReference.GetReferencedElementName());
+        StartBlock();
+        ProcessType(aElement, maCurrentContext.BaseState, maCurrentContext.StartState, maCurrentContext.EndState);
+        EndBlock();
+    }
+
+
+
+
+    /** Treat extension nodes like sequences (for now).
+     */
+    @Override
+    public void Visit (final Extension aExtension)
+    {
+        assert(aExtension.GetChildCount() <= 1);
+        
+        AddComment("Extension of base type %s", aExtension.GetBaseTypeName());
+        ProcessAttributes(aExtension);
+
+        final Vector<INode> aNodes = aExtension.GetTypeNodes(maSchemaBase);
+        
+        StartBlock();
+        int nStateIndex = 0;
+        State aCurrentState = maStateContext.CreateState(maCurrentContext.BaseState, "E"+nStateIndex++);
+        AddEpsilonTransition(maCurrentContext.StartState, aCurrentState);
+        
+        State aNextState = maStateContext.CreateState(maCurrentContext.BaseState, "E"+nStateIndex++);
+        ProcessType(aExtension.GetReferencedNode(maSchemaBase), aCurrentState, aCurrentState, aNextState);
+        aCurrentState = aNextState;
+        
+        for (final INode aChild : aNodes)
+        {
+            aNextState = maStateContext.CreateState(maCurrentContext.BaseState, "E"+nStateIndex++);
+            ProcessType(aChild, aCurrentState, aCurrentState, aNextState);
+            aCurrentState = aNextState;
+        }
+        AddEpsilonTransition(aCurrentState, maCurrentContext.EndState);
+        EndBlock();
+    }
+
+
+
+
+    @Override
+    public void Visit (final Group aGroup)
+    {
+        assert(aGroup.GetChildCount() == 1);
+        
+        AddComment("Group %s", aGroup.GetName());
+        ProcessAttributes(aGroup);
+        
+        StartBlock();
+        final State aGroupBaseState = maStateContext.CreateState(maCurrentContext.BaseState, "G"); 
+        ProcessType(
+            aGroup.GetOnlyChild(),
+            aGroupBaseState,
+            maCurrentContext.StartState,
+            maCurrentContext.EndState);
+        EndBlock();
+    }
+
+
+
+
+    @Override
+    public void Visit (final GroupReference aReference)
+    {
+        AddComment("Group reference to %s", aReference.GetReferencedGroupName());
+        ProcessAttributes(aReference);
+
+        final Group aGroup = aReference.GetReferencedGroup(maSchemaBase);
+        if (aGroup == null)
+            throw new RuntimeException("can't find referenced group "+aReference.GetReferencedGroupName());
+
+        StartBlock();
+        ProcessType(aGroup, maCurrentContext.BaseState, maCurrentContext.StartState, maCurrentContext.EndState);
+        EndBlock();
+    }
+
+
+
+
+    /** An occurrence indicator defines how many times the single child can occur.
+     *  The minimum value defines the mandatory number of times.  The maximum value
+     *  defines the optional number. 
+     */
+    @Override
+    public void Visit (final OccurrenceIndicator aOccurrence)
+    {
+        assert(aOccurrence.GetChildCount() == 1);
+        
+        AddComment("OccurrenceIndicator %s->%s",
+            aOccurrence.GetDisplayMinimum(),
+            aOccurrence.GetDisplayMaximum());
+        ProcessAttributes(aOccurrence);
+
+        StartBlock();
+        
+        final INode aChild = aOccurrence.GetChildren().iterator().next();
+        
+        int nIndex = 0;
+        State aCurrentState = maStateContext.CreateState(maCurrentContext.BaseState, "O"+nIndex++);
+        AddEpsilonTransition(maCurrentContext.StartState, aCurrentState);
+
+        if (aOccurrence.GetMinimum() == 0)
+        {
+            // A zero minimum means that all occurrences are optional.
+            // Add a short circuit from start to end.
+            AddComment("Occurrence: make whole element optional (min==0)");
+            AddEpsilonTransition(maCurrentContext.StartState, maCurrentContext.EndState);
+        }
+        else
+        {
+            // Write a row of mandatory transitions for the minimum.
+            for (; nIndex<=aOccurrence.GetMinimum(); ++nIndex)
+            {
+                // Add transition i-1 -> i (i == nIndex).
+                final State aNextState = maStateContext.CreateState(maCurrentContext.BaseState, "O"+nIndex);
+                AddComment("Occurrence: move from %d -> %d (%s -> %s) (minimum)",
+                    nIndex-1,
+                    nIndex,
+                    aCurrentState,
+                    aNextState);
+                StartBlock();
+                ProcessType(aChild, aCurrentState, aCurrentState, aNextState);
+                EndBlock();
+                aCurrentState = aNextState;                    
+            }
+        }
+        
+        if (aOccurrence.GetMaximum() == OccurrenceIndicator.unbounded)
+        {
+            // Write loop on last state when max is unbounded.
+            
+            // last -> loop
+            final State aLoopState = maStateContext.CreateState(maCurrentContext.BaseState, "OL");
+            AddComment("Occurrence: forward to loop (maximum)");
+            AddEpsilonTransition(aCurrentState, aLoopState);
+            
+            // loop -> loop
+            AddComment("Occurrence: loop");
+            StartBlock();
+            ProcessType(aChild, aLoopState, aLoopState, aLoopState);
+            EndBlock();
+            
+            // -> end
+            AddComment("Occurrence: forward to local end");
+            AddEpsilonTransition(aLoopState, maCurrentContext.EndState);
+        }
+        else
+        {
+            // Write a row of optional transitions for the maximum.
+            for (; nIndex<=aOccurrence.GetMaximum(); ++nIndex)
+            {
+                if (nIndex > 0)
+                {
+                    // i-1 -> end
+                    AddComment("Occurrence: make %d optional (maximum)", nIndex-1);
+                    AddEpsilonTransition(aCurrentState, maCurrentContext.EndState);
+                }
+                
+                // i-1 -> i
+                final State aNextState = maStateContext.CreateState(maCurrentContext.BaseState, "O"+nIndex);
+                AddComment("Occurrence: %d -> %d (%s -> %s) (maximum)",
+                    nIndex-1,
+                    nIndex,
+                    aCurrentState,
+                    aNextState);
+                StartBlock();
+                ProcessType(aChild, aCurrentState, aCurrentState, aNextState);
+                EndBlock();
+                
+                aCurrentState = aNextState;
+            }
+            
+            // max -> end
+            AddComment("Occurrence: forward to local end");
+            AddEpsilonTransition(aCurrentState, maCurrentContext.EndState);
+        }
+        EndBlock();
+    }
+    
+    
+
+
+    /** Ordered sequence of nodes.
+     *  For n nodes create states S0 to Sn where Si and Si+1 become start and
+     *  end states for the i-th child.
+     */ 
+    @Override
+    public void Visit (final Sequence aSequence)
+    {
+        AddComment("Sequence.");
+        ProcessAttributes(aSequence);
+
+        StartBlock();
+        int nStateIndex = 0;
+        State aCurrentState = maStateContext.CreateState(maCurrentContext.BaseState, "S"+nStateIndex++);
+        AddEpsilonTransition(maCurrentContext.StartState, aCurrentState);
+        for (final INode aChild : aSequence.GetChildren())
+        {
+            final State aNextState = maStateContext.CreateState(maCurrentContext.BaseState, "S"+nStateIndex++);
+            ProcessType(aChild, aCurrentState, aCurrentState, aNextState);
+            aCurrentState = aNextState;
+        }
+        AddEpsilonTransition(aCurrentState, maCurrentContext.EndState);
+        EndBlock();
+    }
+
+
+
+
+    @Override
+    public void Visit (final BuiltIn aNode)
+    {
+        throw new RuntimeException("can not handle "+aNode.toString());
+    }
+
+
+
+
+    @Override
+    public void Visit (final List aNode)
+    {
+        throw new RuntimeException("can not handle "+aNode.toString());
+    }
+
+
+
+
+    @Override
+    public void Visit (final Restriction aNode)
+    {
+        throw new RuntimeException("can not handle "+aNode.toString());
+    }
+
+
+
+    @Override
+    public void Visit (final SimpleContent aNode)
+    {
+        AddComment("SimpleContent.");
+        ProcessAttributes(aNode);
+
+        for (final INode aChild : aNode.GetChildren())
+            ProcessType(aChild, maCurrentContext.BaseState, maCurrentContext.StartState, maCurrentContext.EndState);
+    }
+
+
+
+
+    @Override
+    public void Visit (final SimpleType aNode)
+    {
+        AddComment("SimpleContent.");
+        for (final INode aChild : aNode.GetChildren())
+            ProcessType(aChild, maCurrentContext.BaseState, maCurrentContext.StartState, maCurrentContext.EndState);
+    }
+
+
+
+
+    @Override
+    public void Visit (final SimpleTypeReference aNode)
+    {
+        throw new RuntimeException("can not handle "+aNode.toString());
+    }
+
+
+
+
+    @Override
+    public void Visit (final Union aNode)
+    {
+        throw new RuntimeException("can not handle "+aNode.toString());
+    }
+
+
+
+
+    @Override
+    public void Visit (final AttributeGroup aNode)
+    {
+        throw new RuntimeException("can not handle "+aNode.toString());
+    }
+
+
+
+
+    @Override
+    public void Visit (final AttributeReference aNode)
+    {
+        throw new RuntimeException("can not handle "+aNode.toString());
+    }
+
+
+
+
+    @Override
+    public void Visit (final Attribute aNode)
+    {
+        throw new RuntimeException("can not handle "+aNode.toString());
+    }
+
+
+
+
+    @Override
+    public void Visit (final AttributeGroupReference aNode)
+    {
+        throw new RuntimeException("can not handle "+aNode.toString());
+    }
+
+    
+    
+    
+    private void ProcessType (
+        final INode aNode,
+        final State aBaseState,
+        final State aStartState,
+        final State aEndState)
+    {
+        maContextStack.push(maCurrentContext);
+        maCurrentContext = new Context(aBaseState, aStartState, aEndState);
+        aNode.AcceptVisitor(this);
+        maCurrentContext = maContextStack.pop();
+    }
+
+
+    
+    
+    private void AddEpsilonTransition (
+        final State aStartState,
+        final State aEndState)
+    {
+        // Silently ignore epsilon transitions from a state to itself.
+        // They may indicate a problem but usually are just artifacts
+        // that can be safely ignored.
+        if (aStartState == aEndState)
+            return;
+        else
+        {
+            final EpsilonTransition aTransition = new EpsilonTransition(
+                aStartState,
+                aEndState);
+            aStartState.AddEpsilonTransition(aTransition);
+
+            if (maLog != null)
+            {
+                maLog.printf("%sepsilon transition from %s to %s\n",
+                    msLogIndentation,
+                    aStartState.GetFullname(),
+                    aEndState.GetFullname());
+            }
+        }
+    }
+    
+    
+    
+    
+    private int GetElementCount (final INode aNode)
+    {
+        
+        class Visitor extends NodeVisitorAdapter
+        {
+            int nElementCount = 0;
+            @Override public void Visit (final Element aElement)
+            {
+                ++nElementCount;
+            }
+            int GetElementCount ()
+            {
+                return nElementCount;
+            }
+        };
+        final Visitor aVisitor = new Visitor();
+        for (final INode aChildNode : new DereferencingNodeIterator(aNode, maSchemaBase, false))
+        {
+            aChildNode.AcceptVisitor(aVisitor);
+        }
+        return aVisitor.GetElementCount();
+    }
+    
+    
+    
+    
+    private INode GetAllReplacement (final All aAll)
+    {
+        // By default each child of this node can appear exactly once, however
+        // the order is undefined.  This corresponds to an enumeration of all
+        // permutations of the children.
+        
+        // Set up an array of all children.  This array will be modified to contain
+        // all permutations.
+        final INode[] aNodes = new INode[aAll.GetChildCount()];
+        final Iterator<INode> aChildren = aAll.GetChildren().iterator();
+        for (int nIndex=0; aChildren.hasNext(); ++nIndex)
+            aNodes[nIndex] = aChildren.next();
+
+        final Location aLocation = aAll.GetLocation();
+        final Choice aChoice = new Choice(aAll, aLocation);
+        
+        // Treat every permutation as sequence so that the whole set of permutations
+        // is equivalent to a choice of sequences.
+        int nCount = 0;
+        for (final PermutationIterator<INode> aIterator = new PermutationIterator<>(aNodes); aIterator.HasMore(); aIterator.Next())
+        {
+            // Create a Sequence node for the current permutation and add it as
+            // choice to the Choice node.
+            final Sequence aSequence = new Sequence(aChoice, null, aLocation);
+            aChoice.AddChild(aSequence);
+            
+            for (final INode aNode : aNodes)
+                aSequence.AddChild(aNode);
+            
+            ++nCount;
+        }
+        System.out.printf("there are %d permutations\n", nCount);
+        
+        return aChoice;
+    }
+
+    
+    
+    
+    class Context
+    {
+        Context (
+            final State aBaseState,
+            final State aStartState,
+            final State aEndState)
+        {
+            BaseState = aBaseState;
+            StartState = aStartState;
+            EndState = aEndState;
+        }
+        final State BaseState;
+        final State StartState;
+        final State EndState;
     }
 
     
     
     
-    private final SchemaBase maSchemaBase;
-    private final StateContainer maStateContainer;
-    private final PrintStream maLog;
+    private StateContext maStateContext;
+    private final Stack<Context> maContextStack;
+    private Context maCurrentContext;
 }

Modified: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/generator/ParserTablesGenerator.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/generator/ParserTablesGenerator.java?rev=1602077&r1=1602076&r2=1602077&view=diff
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/generator/ParserTablesGenerator.java (original)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/generator/ParserTablesGenerator.java Thu Jun 12 07:15:24 2014
@@ -25,16 +25,22 @@ import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.PrintStream;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.TreeMap;
+import java.util.TreeSet;
 
 import org.apache.openoffice.ooxml.schema.automaton.FiniteAutomaton;
 import org.apache.openoffice.ooxml.schema.automaton.FiniteAutomatonContainer;
 import org.apache.openoffice.ooxml.schema.automaton.SkipData;
 import org.apache.openoffice.ooxml.schema.automaton.State;
 import org.apache.openoffice.ooxml.schema.automaton.Transition;
+import org.apache.openoffice.ooxml.schema.model.attribute.Attribute;
+import org.apache.openoffice.ooxml.schema.model.attribute.AttributeBase.Use;
 import org.apache.openoffice.ooxml.schema.model.schema.NamespaceMap;
+import org.apache.openoffice.ooxml.schema.parser.FormDefault;
 
 public class ParserTablesGenerator
 {
@@ -44,7 +50,8 @@ public class ParserTablesGenerator
     {
         maAutomatons = aAutomatons;
         maNamespaces = aNamespaces;
-        maElementNameToIdMap = new TreeMap<>();
+        maNameToIdMap = new TreeMap<>();
+        maPrefixToIdMap = new HashMap<>();
         maStateNameToIdMap = new TreeMap<>();
     }
     
@@ -55,13 +62,16 @@ public class ParserTablesGenerator
         final File aParseTableFile)
     {
         final long nStartTime = System.currentTimeMillis();
-        
+
+        SetupNameList();
         AssignNameIds();
         
         try
         {
             final PrintStream aOut = new PrintStream(new FileOutputStream(aParseTableFile));
+            
             WriteNamespaceList(aOut);
+            WriteNameList(aOut);
             WriteGlobalStartEndStates(aOut);
             WriteNameList(aOut);
             WriteAutomatonList(aOut);
@@ -81,27 +91,57 @@ public class ParserTablesGenerator
     
     
     
+    private void SetupNameList ()
+    {
+        final Set<String> aNames = new TreeSet<>();
+        
+        // Add the element names.
+        for (final FiniteAutomaton aAutomaton : maAutomatons.GetAutomatons())
+            for (final Transition aTransition : aAutomaton.GetTransitions())
+            {
+                if (aTransition.GetElementName() == null)
+                    throw new RuntimeException();
+                aNames.add(aTransition.GetElementName().GetLocalPart());
+            }
+        
+        // Add the attribute names.
+        for (final FiniteAutomaton aAutomaton : maAutomatons.GetAutomatons())
+            for (final Attribute aAttribute : aAutomaton.GetAttributes())
+                aNames.add(aAttribute.GetName().GetLocalPart());
+        
+        // Create unique ids for the names.
+        int nIndex = 1;
+        maNameToIdMap.clear();
+        for (final String sName : aNames)
+            maNameToIdMap.put(sName, nIndex++);
+        
+        // Create unique ids for namespace prefixes.
+        nIndex = 1;
+        maPrefixToIdMap.clear();
+        for (final Entry<String, String> aEntry : maNamespaces)
+        {
+            maPrefixToIdMap.put(aEntry.getValue(), nIndex++);
+        }
+    }
+    
+    
+    
+    
     /** During the largest part of the parsing process, states and elements are 
      *  identified not via their name but via a unique id.
      *  That allows a fast lookup.
      */
     private void AssignNameIds ()
     {
-        maElementNameToIdMap.clear();
         maStateNameToIdMap.clear();
         int nIndex = 0;
         
+        // Process state names.
+        final Set<State> aSortedStates = new TreeSet<>();
         for (final State aState : maAutomatons.GetStates())
+            aSortedStates.add(aState);
+        for (final State aState : aSortedStates)
             maStateNameToIdMap.put(aState.GetFullname(), nIndex++);
-        for (final Transition aTransition : maAutomatons.GetTransitions())
-        {
-            if (aTransition.GetElementName() == null)
-                continue;
-            // Element names are not necessarily unique.
-            final String sElementName = aTransition.GetElementName().GetStateName();
-            if ( ! maElementNameToIdMap.containsKey(sElementName))
-                maElementNameToIdMap.put(sElementName, nIndex++);
-        }
     }
     
     
@@ -112,8 +152,9 @@ public class ParserTablesGenerator
         aOut.printf("# namespaces\n");
         for (final Entry<String, String> aEntry : maNamespaces)
         {
-            aOut.printf("namespace %-8s %s\n",
+            aOut.printf("namespace %-8s %2d %s\n",
                 aEntry.getValue(),
+                maPrefixToIdMap.get(aEntry.getValue()),
                 aEntry.getKey());
         }
     }
@@ -141,14 +182,15 @@ public class ParserTablesGenerator
     
     private void WriteNameList (final PrintStream aOut)
     {
-        aOut.printf("\n# %d element names\n", maElementNameToIdMap.size());
-        for (final Entry<String, Integer> aEntry : maElementNameToIdMap.entrySet())
+        aOut.printf("\n# %d names\n", maNameToIdMap.size());
+        for (final Entry<String, Integer> aEntry : maNameToIdMap.entrySet())
         {
-            aOut.printf("element-name %4d %s\n",
+            aOut.printf("name %4d %s\n",
                 aEntry.getValue(),
                 aEntry.getKey());
         }
-        aOut.printf("\n# %d state names\n", maStateNameToIdMap.size());
+        
+        aOut.printf("\n# %s states\n",  maStateNameToIdMap.size());
         for (final Entry<String, Integer> aEntry : maStateNameToIdMap.entrySet())
         {
             aOut.printf("state-name %4d %s\n",
@@ -165,23 +207,37 @@ public class ParserTablesGenerator
         for (final FiniteAutomaton aAutomaton : maAutomatons.GetAutomatons())
         {
             aOut.printf("# %s\n", aAutomaton.GetTypeName());
+
+            final State aStartState = aAutomaton.GetStartState();
+            final int nStartStateId = maStateNameToIdMap.get(aStartState.GetFullname());
+
             // Write start state.
-            aOut.printf("start-state %d %s\n",  
-                maStateNameToIdMap.get(aAutomaton.GetStartState().GetFullname()),
-                aAutomaton.GetStartState().GetFullname());
+            aOut.printf("start-state %d %s\n",
+                nStartStateId,
+                aStartState);
+            
             // Write accepting states.
             for (final State aState : aAutomaton.GetAcceptingStates())
+            {
                 aOut.printf("accepting-state %d %s\n",
                     maStateNameToIdMap.get(aState.GetFullname()),
                     aState.GetFullname());
+            }
+            
+            WriteAttributes(
+                aOut,
+                aStartState,
+                aAutomaton.GetAttributes());
+            
             // Write transitions.
             for (final Transition aTransition : aAutomaton.GetTransitions())
             {
                 final Integer nId = maStateNameToIdMap.get(aTransition.GetElementTypeName());
-                aOut.printf("transition %4d %4d %4d %4d  %s %s \"%s\" %s\n",
+                aOut.printf("transition %4d %4d %2d %4d %4d  %s %s \"%s\" %s\n",
                     maStateNameToIdMap.get(aTransition.GetStartState().GetFullname()),
                     maStateNameToIdMap.get(aTransition.GetEndState().GetFullname()),
-                    maElementNameToIdMap.get(aTransition.GetElementName().GetStateName()),
+                    maPrefixToIdMap.get(aTransition.GetElementName().GetNamespacePrefix()),
+                    maNameToIdMap.get(aTransition.GetElementName().GetLocalPart()),
                     nId!=null ? nId : -1,
                     aTransition.GetStartState().GetFullname(),
                     aTransition.GetEndState().GetFullname(),
@@ -202,8 +258,34 @@ public class ParserTablesGenerator
     
     
     
+    private void WriteAttributes (
+        final PrintStream aOut,
+        final State aState,
+        final Iterable<Attribute> aAttributes)
+    {
+        // Write attributes.
+        for (final Attribute aAttribute : aAttributes)
+        {
+            aOut.printf("attribute %4d %2d %c %4d %4d %s %s  %s %s %s\n",
+                maStateNameToIdMap.get(aState.GetFullname()),
+                maPrefixToIdMap.get(aAttribute.GetName().GetNamespacePrefix()),
+                aAttribute.GetFormDefault()==FormDefault.qualified ? 'q' : 'u',
+                maNameToIdMap.get(aAttribute.GetName().GetLocalPart()),
+                maStateNameToIdMap.get(aAttribute.GetTypeName().GetStateName()),
+                aAttribute.GetUse()==Use.Optional ? 'o' : 'u',
+                aAttribute.GetDefault()==null ? "null" : '"'+aAttribute.GetDefault()+'"',
+                aState.GetFullname(),
+                aAttribute.GetName().GetStateName(),
+                aAttribute.GetTypeName().GetStateName());
+        }
+    }
+
+    
+    
+    
     private final FiniteAutomatonContainer maAutomatons;
     private final NamespaceMap maNamespaces;
-    private final Map<String,Integer> maElementNameToIdMap;
+    private final Map<String,Integer> maNameToIdMap;
+    private final Map<String,Integer> maPrefixToIdMap;
     private final Map<String,Integer> maStateNameToIdMap;
 }

Modified: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/iterator/AttributeIterator.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/iterator/AttributeIterator.java?rev=1602077&r1=1602076&r2=1602077&view=diff
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/iterator/AttributeIterator.java (original)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/iterator/AttributeIterator.java Thu Jun 12 07:15:24 2014
@@ -82,7 +82,7 @@ public class AttributeIterator
             }
             @Override public void Visit (final AttributeGroup aAttributeGroup)
             {
-                for (final INode aGroupAttribute : aAttributeGroup.GetChildren())
+                for (final INode aGroupAttribute : aAttributeGroup.GetAttributes())
                     aTodo.add(aGroupAttribute);
             }
             @Override public void Visit (final AttributeGroupReference aAttributeGroupReference)

Added: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/iterator/AttributeNodeIterator.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/iterator/AttributeNodeIterator.java?rev=1602077&view=auto
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/iterator/AttributeNodeIterator.java (added)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/iterator/AttributeNodeIterator.java Thu Jun 12 07:15:24 2014
@@ -0,0 +1,112 @@
+/**************************************************************
+*
+* 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.iterator;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.Vector;
+
+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.INodeVisitor;
+import org.apache.openoffice.ooxml.schema.model.base.NodeVisitorAdapter;
+import org.apache.openoffice.ooxml.schema.model.schema.SchemaBase;
+
+/** This iterator is very similar to the AttributeIterator but it
+ *  a) returns the attributes as INode objects and
+ *  b) includes referencing nodes and group nodes in the iteration and
+ *  c) if there are multiple references to the same attribute then each
+ *     of them is visited.
+ */
+public class AttributeNodeIterator
+    implements Iterable<INode>
+{
+    public AttributeNodeIterator (
+        final INode aNode,
+        final SchemaBase aSchemaBase)
+    {
+        maAttributes = new Vector<INode>();
+        CollectAttributes(aNode, aSchemaBase);
+    }
+    
+    
+    
+    
+    public Iterator<INode> iterator ()
+    {
+        return maAttributes.iterator();
+    }
+    
+    
+    
+    
+    private void CollectAttributes (
+        final INode aType,
+        final SchemaBase aSchemaBase)
+    {
+        final Queue<INode> aTodo = new LinkedList<>();
+        for (final INode aAttribute : aType.GetAttributes())
+            aTodo.add(aAttribute);
+        final INodeVisitor aVisitor = new NodeVisitorAdapter()
+        {
+            @Override public void Visit (final Attribute aAttribute)
+            {
+                maAttributes.add(aAttribute);
+            }
+            @Override public void Visit (final AttributeReference aAttributeReference)
+            {
+                maAttributes.add(aAttributeReference);
+                aTodo.add(aAttributeReference.GetReferencedAttribute(aSchemaBase));
+            }
+            @Override public void Visit (final AttributeGroup aAttributeGroup)
+            {
+                maAttributes.add(aAttributeGroup);
+                for (final INode aGroupAttribute : aAttributeGroup.GetAttributes())
+                    aTodo.add(aGroupAttribute);
+            }
+            @Override public void Visit (final AttributeGroupReference aAttributeGroupReference)
+            {
+                maAttributes.add(aAttributeGroupReference);
+                aTodo.add(aAttributeGroupReference.GetReferencedAttributeGroup(aSchemaBase));
+            }
+            @Override public void Default (final INode aNode)
+            {
+                throw new RuntimeException("can not handle attribute of type "+aNode.GetNodeType());
+            }
+        };
+        while ( ! aTodo.isEmpty())
+        {
+            final INode aAttribute = aTodo.poll();
+            if (aAttribute != null)
+                aAttribute.AcceptVisitor(aVisitor);
+        }
+    }
+    
+    
+    
+    
+    private final Vector<INode> maAttributes;
+}

Modified: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/attribute/Attribute.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/attribute/Attribute.java?rev=1602077&r1=1602076&r2=1602077&view=diff
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/attribute/Attribute.java (original)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/attribute/Attribute.java Thu Jun 12 07:15:24 2014
@@ -25,6 +25,7 @@ import org.apache.openoffice.ooxml.schem
 import org.apache.openoffice.ooxml.schema.model.base.Location;
 import org.apache.openoffice.ooxml.schema.model.base.NodeType;
 import org.apache.openoffice.ooxml.schema.model.base.QualifiedName;
+import org.apache.openoffice.ooxml.schema.parser.FormDefault;
 
 /* Representation of a single attribute.
  */
@@ -37,9 +38,10 @@ public class Attribute
         final String sUse,
         final String sDefault,
         final String sFixed,
+        final FormDefault eFormDefault,
         final Location aLocation)
     {
-        super(aName, sUse, sDefault, sFixed, aLocation);
+        super(aName, sUse, sDefault, sFixed, eFormDefault, aLocation);
         maTypeName = aTypeName;
     }
     
@@ -69,9 +71,9 @@ public class Attribute
         aVisitor.Visit(this);
     }
 
-    
-    
-    
+
+
+
     @Override
     public String toString ()
     {
@@ -86,8 +88,4 @@ public class Attribute
     
     
     private final QualifiedName maTypeName;
-
-
-
-
 }

Modified: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/attribute/AttributeBase.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/attribute/AttributeBase.java?rev=1602077&r1=1602076&r2=1602077&view=diff
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/attribute/AttributeBase.java (original)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/attribute/AttributeBase.java Thu Jun 12 07:15:24 2014
@@ -24,6 +24,7 @@ package org.apache.openoffice.ooxml.sche
 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.parser.FormDefault;
 
 /** Base class for both Attribute and AttributeReference classes.
  */
@@ -43,6 +44,7 @@ public abstract class AttributeBase
         final String sUse,
         final String sDefault,
         final String sFixed,
+        final FormDefault eFormDefault,
         final Location aLocation)
     {
         super(null, aName, aLocation);
@@ -60,6 +62,31 @@ public abstract class AttributeBase
         }
         msDefault = sDefault;
         msFixed = sFixed;
+        meFormDefault = eFormDefault;
+    }
+
+    
+    
+    
+    public FormDefault GetFormDefault()
+    {
+        return meFormDefault;
+    }
+
+    
+    
+    
+    public Use GetUse ()
+    {
+        return meUse;
+    }
+    
+    
+    
+    
+    public String GetDefault()
+    {
+        return msDefault;
     }
     
     
@@ -86,4 +113,5 @@ public abstract class AttributeBase
     private final Use meUse;
     private final String msDefault;
     private final String msFixed;
+    private final FormDefault meFormDefault;
 }

Modified: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/attribute/AttributeReference.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/attribute/AttributeReference.java?rev=1602077&r1=1602076&r2=1602077&view=diff
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/attribute/AttributeReference.java (original)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/attribute/AttributeReference.java Thu Jun 12 07:15:24 2014
@@ -28,6 +28,7 @@ import org.apache.openoffice.ooxml.schem
 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.SchemaBase;
+import org.apache.openoffice.ooxml.schema.parser.FormDefault;
 
 public class AttributeReference
     extends AttributeBase
@@ -38,9 +39,10 @@ public class AttributeReference
         final String sUse,
         final String sDefault,
         final String sFixed,
+        final FormDefault eFormDefault,
         final Location aLocation)
     {
-        super(aReferencedName, sUse, sDefault, sFixed, aLocation);
+        super(aReferencedName, sUse, sDefault, sFixed, eFormDefault, aLocation);
         
         maReferencedName = aReferencedName;
     }
@@ -52,11 +54,13 @@ public class AttributeReference
     {
         final Attribute aAttribute = aSchemaBase.Attributes.Get(maReferencedName);
         if (aAttribute == null)
+        {
             throw new RuntimeException(
                 String.format(
                     "can not find attribute %s, referenced at %s",
                     maReferencedName.GetDisplayName(),
                     GetLocation()));
+        }
         return aAttribute;
     }
     
@@ -98,5 +102,14 @@ public class AttributeReference
     
     
     
+    @Override
+    public String toString ()
+    {
+        return "attribute reference to "+maReferencedName;
+    }
+    
+    
+    
+    
     private final QualifiedName maReferencedName;
 }

Added: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/CopyVisitor.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/CopyVisitor.java?rev=1602077&view=auto
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/CopyVisitor.java (added)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/CopyVisitor.java Thu Jun 12 07:15:24 2014
@@ -0,0 +1,111 @@
+/**************************************************************
+*
+* 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.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.NodeVisitorAdapter;
+import org.apache.openoffice.ooxml.schema.model.complex.ComplexType;
+import org.apache.openoffice.ooxml.schema.model.complex.GroupReference;
+import org.apache.openoffice.ooxml.schema.model.schema.SchemaBase;
+import org.apache.openoffice.ooxml.schema.model.simple.SimpleType;
+
+/** This visitor is called to copy the used types from the source to the target
+ *  schema base.
+ */
+public class CopyVisitor
+    extends NodeVisitorAdapter
+{
+    CopyVisitor (
+        final SchemaBase aSourceSchemaBase,
+        final SchemaBase aTargetSchemaBase)
+    {
+        maSourceSchemaBase = aSourceSchemaBase;
+        maTargetSchemaBase = aTargetSchemaBase;
+    }
+    
+    
+    
+    
+    @Override public void Visit (final ComplexType aComplexType)
+    {
+        maTargetSchemaBase.ComplexTypes.Add(aComplexType);
+    }
+
+    @Override public void Visit (final GroupReference aGroupReference)
+    {
+        maTargetSchemaBase.Groups.Add(
+            aGroupReference.GetReferencedGroup(maSourceSchemaBase));
+    }
+    
+    @Override public void Visit (final SimpleType aSimpleType)
+    {
+        maTargetSchemaBase.SimpleTypes.Add(aSimpleType);
+    }
+    
+    @Override public void Visit (final AttributeReference aAttributeReference)
+    {
+        maTargetSchemaBase.Attributes.Add(
+            aAttributeReference.GetReferencedAttribute(maSourceSchemaBase));
+    }
+    
+    @Override public void Visit (final AttributeGroupReference aAttributeGroupReference)
+    {
+        maTargetSchemaBase.AttributeGroups.Add(
+            aAttributeGroupReference.GetReferencedAttributeGroup(maSourceSchemaBase));
+    }
+    
+    @Override public void Default (final INode aNode)
+    {
+        switch(aNode.GetNodeType())
+        {
+            case All:
+            case Any:
+            case Attribute:
+            case AttributeGroup:
+            case BuiltIn:
+            case Choice:
+            case ComplexContent:
+            case Element:
+            case ElementReference:
+            case Extension:
+            case Group:
+            case List:
+            case OccurrenceIndicator:
+            case Sequence:
+            case SimpleContent:
+            case SimpleTypeReference:
+            case Union:
+                break;
+                
+            default:
+                throw new RuntimeException("don't know how to copy "+aNode.toString());
+        }
+    }
+    
+    
+    
+    
+    private final SchemaBase maSourceSchemaBase;
+    private final SchemaBase maTargetSchemaBase;
+}

Modified: 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=1602077&r1=1602076&r2=1602077&view=diff
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/RequestVisitor.java (original)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/RequestVisitor.java Thu Jun 12 07:15:24 2014
@@ -21,18 +21,17 @@
 
 package org.apache.openoffice.ooxml.schema.model.optimize;
 
+import org.apache.openoffice.ooxml.schema.model.attribute.Attribute;
+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.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.SchemaBase;
 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.
@@ -49,45 +48,45 @@ public class RequestVisitor
     }
     
     
-    @Override public void Visit (final ComplexType aComplexType)
+    @Override public void Visit (final Attribute aAttribute)
     {
-        for (final INode aAttribute : aComplexType.GetAttributes())
-            maSchemaOptimizer.RequestType(aAttribute);
+        maSchemaOptimizer.RequestType(aAttribute.GetTypeName());
     }
 
-    @Override public void Visit (final Element aElement)
+    @Override public void Visit (final AttributeReference aAttributeReference)
     {
-        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);
+        maSchemaOptimizer.RequestType(aAttributeReference.GetReferencedName());
     }
-    @Override public void Visit (final ElementReference aElementReference)
+
+    @Override public void Visit (final AttributeGroupReference aAttributeGroupReference)
     {
-        Visit(aElementReference.GetReferencedElement(maSourceSchemaBase));
+        maSchemaOptimizer.RequestType(aAttributeGroupReference.GetReferencedName());
     }
+
+    @Override public void Visit (final Element aElement)
+    {
+        maSchemaOptimizer.RequestType(aElement.GetTypeName());
+    }
+    
     @Override public void Visit (final Extension aExtension)
     {
         maSchemaOptimizer.RequestType(aExtension.GetBaseTypeName());
     }
+    
     @Override public void Visit (final GroupReference aReference)
     {
         maSchemaOptimizer.RequestType(aReference.GetReferencedGroup(maSourceSchemaBase));
     }
+    
     @Override public void Visit (final List aList)
     {
         maSchemaOptimizer.RequestType(aList.GetItemType());
     }
+    
     @Override public void Visit (final SimpleTypeReference aReference)
     {
         maSchemaOptimizer.RequestType(aReference.GetReferencedSimpleType(maSourceSchemaBase));
     }
-    @Override public void Visit (final Union aUnion)
-    {
-    }
     
     @Override public void Default (final INode aNode)
     {
@@ -95,17 +94,21 @@ public class RequestVisitor
         {
             case All:
             case Any:
+            case AttributeGroup:
             case BuiltIn:
             case Choice:
             case ComplexContent:
             case ComplexType:
+            case ElementReference:
             case Group:
             case List:
             case OccurrenceIndicator:
             case Sequence:
             case SimpleContent:
             case SimpleType:
+            case Union:
                 break;
+
             default:
                 throw new RuntimeException(
                     String.format("don't know how to request %s which was defined at %s",

Modified: 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=1602077&r1=1602076&r2=1602077&view=diff
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/SchemaOptimizer.java (original)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/SchemaOptimizer.java Thu Jun 12 07:15:24 2014
@@ -5,7 +5,8 @@ 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.iterator.AttributeNodeIterator;
+import org.apache.openoffice.ooxml.schema.iterator.DereferencingNodeIterator;
 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;
@@ -14,6 +15,11 @@ import org.apache.openoffice.ooxml.schem
 import org.apache.openoffice.ooxml.schema.model.complex.Element;
 import org.apache.openoffice.ooxml.schema.model.schema.SchemaBase;
 
+/** Optimize the given schema base by creating a new one and adding only those
+ *  complex types, simple types, groups, attributes and attribute groups, that
+ *  are really used, i.e. used by one of the top level elements or by a type or
+ *  group that is in use.
+ */
 public class SchemaOptimizer
 {
     public SchemaOptimizer (
@@ -23,15 +29,6 @@ public class SchemaOptimizer
         maOptimizedSchemaBase = new SchemaBase();
         maTodoList = new LinkedList<>();
         maProcessedTypes = new HashSet<>();
-        
-        maRequestVisitor = new RequestVisitor(maOriginalSchemaBase, this);
-
-        // Copy over the top-level elements.  They are the seeds in the use chain of types.
-        for (final Element aElement : aOriginalSchemaBase.TopLevelElements.GetUnsorted())
-        {
-            maOptimizedSchemaBase.TopLevelElements.Add(aElement);
-            RequestType(aElement.GetTypeName());
-        }        
     }
     
     
@@ -39,9 +36,50 @@ public class SchemaOptimizer
     
     public SchemaBase Run ()
     {
-              
-        ProcessTodoList();
+        // Seed the work list with the top-level elements.
+        for (final Element aElement : maOriginalSchemaBase.TopLevelElements.GetUnsorted())
+        {
+            maOptimizedSchemaBase.TopLevelElements.Add(aElement);
+            RequestType(aElement.GetTypeName());
+        }        
 
+        final INodeVisitor aCopyVisitor = new CopyVisitor(
+            maOriginalSchemaBase,
+            maOptimizedSchemaBase);
+        final INodeVisitor aRequestVisitor = new RequestVisitor(
+            maOriginalSchemaBase,
+            this);
+
+        while ( ! maTodoList.isEmpty())
+        {
+            final INode aNode = maTodoList.poll();
+        
+            // Iterate over all child nodes and attributes.
+            for (final INode aChild : new DereferencingNodeIterator(aNode, maOriginalSchemaBase, true))
+            {
+                aChild.AcceptVisitor(aCopyVisitor);
+                aChild.AcceptVisitor(aRequestVisitor);
+                for (final INode aAttribute : aChild.GetAttributes())
+                    aAttribute.AcceptVisitor(aCopyVisitor);
+                for (final INode aAttribute : new AttributeNodeIterator(aChild, maOriginalSchemaBase))
+                    aAttribute.AcceptVisitor(aRequestVisitor);
+            }
+                
+            // Request used namespaces.
+            final QualifiedName aName = aNode.GetName();
+            if (aName != null)
+                maOptimizedSchemaBase.Namespaces.ProvideNamespace(aName.GetNamespaceURI(), aName.GetNamespacePrefix());
+        }
+        
+        /*
+        System.out.printf("%d original attributes\n", maOriginalSchemaBase.Attributes.GetCount());
+        for (final Attribute aAttribute : maOriginalSchemaBase.Attributes.GetUnsorted())
+            System.out.printf("%s\n",  aAttribute);
+        System.out.printf("%d optimized attributes\n", maOptimizedSchemaBase.Attributes.GetCount());
+        for (final Attribute aAttribute : maOptimizedSchemaBase.Attributes.GetUnsorted())
+            System.out.printf("%s\n",  aAttribute);
+            */
+        
         return maOptimizedSchemaBase;
     }
     
@@ -74,47 +112,8 @@ public class SchemaOptimizer
 
     
     
-    /** 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(
-            maOriginalSchemaBase,
-            maOptimizedSchemaBase,
-            this);
-        while ( ! maTodoList.isEmpty())
-        {
-            final INode aNode = maTodoList.poll();
-            aNode.AcceptVisitor(aVisitor);
-            
-            // Request used namespaces.
-            final QualifiedName aName = aNode.GetName();
-            if (aName != null)
-                maOptimizedSchemaBase.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 SchemaBase maOriginalSchemaBase;
     private final SchemaBase maOptimizedSchemaBase;
     private final Queue<INode> maTodoList;
     private final Set<INode> maProcessedTypes;
-    private final RequestVisitor maRequestVisitor;
 }

Modified: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/SchemaBase.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/SchemaBase.java?rev=1602077&r1=1602076&r2=1602077&view=diff
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/SchemaBase.java (original)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/SchemaBase.java Thu Jun 12 07:15:24 2014
@@ -70,6 +70,10 @@ public class SchemaBase
             return SimpleTypes.Get(sTypeName);
         else if (Groups.Contains(sTypeName))
             return Groups.Get(sTypeName);
+        else if (Attributes.Contains(sTypeName))
+            return Attributes.Get(sTypeName);
+        else if (AttributeGroups.Contains(sTypeName))
+            return AttributeGroups.Get(sTypeName);
         else
             return null;
     }

Added: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/FormDefault.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/FormDefault.java?rev=1602077&view=auto
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/FormDefault.java (added)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/FormDefault.java Thu Jun 12 07:15:24 2014
@@ -0,0 +1,10 @@
+package org.apache.openoffice.ooxml.schema.parser;
+
+/** Enumeration of the form default values for attributes and elements in
+ *  XML documents. 
+ */
+public enum FormDefault
+{
+    qualified,
+    unqualified;
+}

Modified: 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=1602077&r1=1602076&r2=1602077&view=diff
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/SchemaParser.java (original)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/SchemaParser.java Thu Jun 12 07:15:24 2014
@@ -113,7 +113,7 @@ public class SchemaParser
                 case XMLStreamReader.START_ELEMENT:
                     if (maReader.getLocalName().equals("schema"))
                     {
-                        ProcessNamespaceDefinitions();
+                        ProcessSchemaTag();
                         ParseSchema();
                         
                         maLastLocation = maReader.getLocation();
@@ -168,8 +168,18 @@ public class SchemaParser
     
     /** Process the namespace definitions in the outer 'schema' element.
      */
-    private void ProcessNamespaceDefinitions ()
+    private void ProcessSchemaTag ()
     {
+        GetOptionalAttributeValue("id", null);
+        meAttributeFormDefault = FormDefault.valueOf(
+            GetOptionalAttributeValue("attributeFormDefault", "unqualified"));
+        meElementFormDefault = FormDefault.valueOf(
+            GetOptionalAttributeValue("elementFormDefault", "unqualified"));
+        GetOptionalAttributeValue("blockDefault", null);//=(#all|list of (extension|restriction|substitution))
+        GetOptionalAttributeValue("finalDefault", null);//=(#all|list of (extension|restriction|list|union))
+        msTargetNamespace = GetOptionalAttributeValue("targetNamespace", null);
+        GetOptionalAttributeValue("version", null);
+
         for (int nIndex=0; nIndex<maReader.getNamespaceCount(); ++nIndex)
         {
             final String sPrefix = maReader.getNamespacePrefix(nIndex);
@@ -177,7 +187,7 @@ public class SchemaParser
             maLocalNamespaceMap.put(sPrefix, sURI);
             maSchemaBase.Namespaces.ProvideNamespace(sURI, sPrefix);
         }
-        msTargetNamespace = GetAttributeValue("targetNamespace");
+        
         maLocalNamespaceMap.put(null, msTargetNamespace);
         maSchemaBase.Namespaces.ProvideNamespace(msTargetNamespace, null);
     }
@@ -482,6 +492,7 @@ public class SchemaParser
                 GetOptionalAttributeValue("use", "optional"),
                 GetOptionalAttributeValue("default", null),
                 GetOptionalAttributeValue("fixed", null),
+                meAttributeFormDefault,
                 GetLocation());
             ExpectEndElement("attribute reference");
         }
@@ -502,6 +513,7 @@ public class SchemaParser
             GetOptionalAttributeValue("use", "optional"),
             GetOptionalAttributeValue("default", null),
             GetOptionalAttributeValue("fixed", null),
+            meAttributeFormDefault,
             GetLocation());
         ExpectEndElement("attribute");
         
@@ -1193,4 +1205,6 @@ public class SchemaParser
     private final Vector<File> maImportedSchemas;
     /// Some values for tracking the number of read bytes and lines. 
     private javax.xml.stream.Location maLastLocation;
+    private FormDefault meAttributeFormDefault;
+    private FormDefault meElementFormDefault;
 }

Modified: openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/XmlNamespace.java
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/XmlNamespace.java?rev=1602077&r1=1602076&r2=1602077&view=diff
==============================================================================
--- openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/XmlNamespace.java (original)
+++ openoffice/trunk/main/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/XmlNamespace.java Thu Jun 12 07:15:24 2014
@@ -49,6 +49,7 @@ public class XmlNamespace
                 "optional",
                 null,
                 null,
+                FormDefault.unqualified,
                 null));
         
         final SimpleType aType = new SimpleType(null, aStSpaceSimpleTypeName, null);



Mime
View raw message