[Libreoffice-commits] core.git: Branch 'aoo/trunk' - ooxml/source

Andre Fischer af at apache.org
Thu Jun 12 01:07:40 PDT 2014


 ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AcceptingStateTable.java             |    9 
 ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeDescriptor.java             |  112 +
 ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeManager.java                |  178 ++
 ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeProvider.java               |   48 
 ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/NameMap.java                         |   20 
 ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/NamespaceMap.java                    |   52 
 ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/OOXMLParser.java                     |   68 
 ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ParseTableReader.java                |    5 
 ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/SkipStateTable.java                  |    9 
 ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/StateMachine.java                    |  118 +
 ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/TransitionTable.java                 |   23 
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/SchemaReader.java                       |    2 
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/Test.java                               |    1 
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/CreatorBase.java              |  124 +
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/DFACreator.java               |    6 
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/FiniteAutomaton.java          |   17 
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/FiniteAutomatonContainer.java |   13 
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/HopcroftMinimizer.java        |    6 
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/NonValidatingCreator.java     |   70 
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/ValidatingCreator.java        |  727 +++++++++-
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/ValidatingCreatorVisitor.java |  646 --------
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/generator/ParserTablesGenerator.java    |  124 +
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/iterator/AttributeIterator.java         |    2 
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/iterator/AttributeNodeIterator.java     |  112 +
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/attribute/Attribute.java          |    8 
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/attribute/AttributeBase.java      |   28 
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/attribute/AttributeReference.java |   15 
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/CopyVisitor.java         |  111 +
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/ProcessTypeVisitor.java  |  110 -
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/RequestVisitor.java      |   43 
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/optimize/SchemaOptimizer.java     |   93 -
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/model/schema/SchemaBase.java            |    4 
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/FormDefault.java                 |   10 
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/SchemaParser.java                |   20 
 ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/parser/XmlNamespace.java                |    1 
 35 files changed, 1845 insertions(+), 1090 deletions(-)

New commits:
commit d02054a68cb37e3b3d3485116ef835e875928763
Author: Andre Fischer <af at apache.org>
Date:   Thu Jun 12 07:15:24 2014 +0000

    125035: Added support for attributes.

diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AcceptingStateTable.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AcceptingStateTable.java
index 006c187..151cf8a 100644
--- a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AcceptingStateTable.java
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AcceptingStateTable.java
@@ -23,7 +23,6 @@ public class AcceptingStateTable
 
             maAcceptingStates.add(nStateId);
         }
-        Log.Std.printf("read %d accepting states\n",  maAcceptingStates.size());
     }
 
 
@@ -37,5 +36,13 @@ public class AcceptingStateTable
 
 
 
+    public int GetAcceptingStateCount ()
+    {
+        return maAcceptingStates.size();
+    }
+
+
+
+
     private final Set<Integer> maAcceptingStates;
 }
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeDescriptor.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeDescriptor.java
new file mode 100644
index 0000000..a79832a
--- /dev/null
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeDescriptor.java
@@ -0,0 +1,112 @@
+package org.apache.openoffice.ooxml.parser;
+
+/** Store information about a single attribute (per state) that was read
+ *  from the parse table.
+ *
+ *  Note that an attribute that is defined for more than one state has one
+ *  AttributeDescriptor object per state.
+ *
+ */
+public class AttributeDescriptor
+{
+    public AttributeDescriptor (
+        final int nPrefixId,
+        final int nAttributeId,
+        final boolean bCanBeUnqualified,
+        final boolean bIsOptional,
+        final String sDefaultValue,
+        final String sAttributeName,
+        final String sAttributeType)
+    {
+        mnNamespaceId = nPrefixId;
+        mnAttributeId = nAttributeId;
+        mbCanBeUnqualified = bCanBeUnqualified;
+        mbIsOptional = bIsOptional;
+        msDefaultValue = sDefaultValue;
+        msAttributeName = sAttributeName;
+        msAttributeType = sAttributeType;
+    }
+
+
+
+
+    public String GetType()
+    {
+        if (msAttributeType != null)
+            return msAttributeType;
+        else
+            return "<undefined>";
+    }
+
+
+
+
+    public int GetNamespaceId ()
+    {
+        return mnNamespaceId;
+    }
+
+
+
+
+    public int GetNameId ()
+    {
+        return mnAttributeId;
+    }
+
+
+
+
+    public boolean CanBeUnqualified ()
+    {
+        return mbCanBeUnqualified;
+    }
+
+
+
+
+    public boolean IsOptional ()
+    {
+        return mbIsOptional;
+    }
+
+
+
+
+    public String GetDefaultValue ()
+    {
+        return msDefaultValue;
+    }
+
+
+
+
+    public String GetName ()
+    {
+        return msAttributeName;
+    }
+
+
+
+
+    @Override
+    public String toString ()
+    {
+        return String.format(
+            "attribute %s(%d) of type %s",
+            msAttributeName,
+            mnAttributeId,
+            msAttributeType);
+    }
+
+
+
+
+    private final int mnNamespaceId;
+    private final int mnAttributeId;
+    private final boolean mbCanBeUnqualified;
+    private final boolean mbIsOptional;
+    private final String msDefaultValue;
+    private final String msAttributeName;
+    private final String msAttributeType;
+}
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeManager.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeManager.java
index 5c65bdb..c8034d4 100644
--- a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeManager.java
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeManager.java
@@ -22,57 +22,193 @@
 package org.apache.openoffice.ooxml.parser;
 
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
-import java.util.Map.Entry;
+import java.util.Set;
 import java.util.Vector;
 
+
+/** Match a set of attributes from the document with the attribute
+ *  specifications of a state.
+ *
+ */
 public class AttributeManager
 {
-    public AttributeManager (final Vector<String[]> aData)
+    /** Create a new AttributeManager for the attribute specifications that
+     *  are given in the parse table.
+     */
+    public AttributeManager (
+        final Vector<String[]> aData,
+        final NamespaceMap aNamespaceMap,
+        final NameMap aNameMap)
     {
         maStateIdToAttributesMap = new HashMap<>();
+        maNamespaceMap = aNamespaceMap;
+        maNameMap = aNameMap;
+
+        for (final String[] aLine : aData)
+        {
+            final int nStateId = Integer.parseInt(aLine[1]);
+            final int nPrefixId = Integer.parseInt(aLine[2]);
+            final boolean bCanBeUnqualified = aLine[3].startsWith("u");
+            final int nAttributeId = Integer.parseInt(aLine[4]);
+            final String sAttributeType = aLine[5];
+            final boolean bIsOptional = aLine[6].startsWith("o");
+            final String sDefault = UnquoteString(aLine[7]);
+            final String sAttributeName = aLine[8];
+
+            Map<Integer,AttributeDescriptor> aAttributesPerState = maStateIdToAttributesMap.get(nStateId);
+            if (aAttributesPerState == null)
+            {
+                aAttributesPerState = new HashMap<>();
+                maStateIdToAttributesMap.put(nStateId, aAttributesPerState);
+            }
+
+            final AttributeDescriptor aAttributeDescriptor = new AttributeDescriptor(
+                nPrefixId,
+                nAttributeId,
+                bCanBeUnqualified,
+                bIsOptional,
+                sDefault,
+                sAttributeName,
+                sAttributeType);
+
+            aAttributesPerState.put(
+                (nPrefixId<<16)|nAttributeId,
+                aAttributeDescriptor);
+            if (bCanBeUnqualified)
+                aAttributesPerState.put(
+                    nAttributeId,
+                    aAttributeDescriptor);
+        }
     }
 
 
 
 
+    /** For the state with id nStateId, match the attributes from the document
+     *  with the attribute specifications of that state.
+     */
     public void ParseAttributes (
         final int nStateId,
-        final AttributeProvider aAttributeProvider)
+        final AttributeProvider aDocumentAttributes)
     {
-        final Map<String,String> aAttributeDefinitions = maStateIdToAttributesMap.get(nStateId);
-        if (aAttributeDefinitions == null)
+        final Map<Integer,AttributeDescriptor> aAttributesPerState = maStateIdToAttributesMap.get(nStateId);
+        if (aAttributesPerState == null)
         {
-           // if (aAttributeProvider.HasAttributes())
-                //throw new RuntimeException();
+            if (aDocumentAttributes.HasAttributes())
+            {
+                Log.Std.printf("state has not attributes defined but document provides %d attributes\n",
+                    aDocumentAttributes.GetAttributeCount());
+                for (final String[] aEntry : aDocumentAttributes)
+                {
+                    Log.Dbg.printf("    %s -> %s\n", aEntry[0], aEntry[1]);
+                }
+                throw new RuntimeException();
+            }
         }
         else
         {
-            for (final Entry<String,String> aEntry : aAttributeProvider)
+            final Set<AttributeDescriptor> aUsedAttributes = new HashSet<>();
+
+            // Process all attributes from the document.
+            for (final String[] aEntry : aDocumentAttributes)
             {
-                ParseAttributeValue(
-                    aEntry.getKey(),
-                    aEntry.getValue(),
-                    aAttributeDefinitions.get(aEntry.getKey()));
+                final AttributeDescriptor aAttributeDescriptor = ProcessAttribute(
+                    aEntry[0],
+                    aEntry[1],
+                    aEntry[2],
+                    aAttributesPerState);
+                aUsedAttributes.add(aAttributeDescriptor);
+                if (Log.Dbg != null)
+                {
+                    if (aAttributeDescriptor == null)
+                        Log.Dbg.printf("attribute %s%s is not known\n",
+                            aEntry[0]==null ? "" : ":"+aEntry[0],
+                            aEntry[1]);
+                    else
+                        Log.Dbg.printf("attribute %s:%s(%d:%d) has type and value %s\n",
+                            maNamespaceMap.GetDescriptorForId(aAttributeDescriptor.GetNamespaceId()).Prefix,
+                            maNameMap.GetNameForId(aAttributeDescriptor.GetNameId()),
+                            aAttributeDescriptor.GetNamespaceId(),
+                            aAttributeDescriptor.GetNameId(),
+                            aAttributeDescriptor.GetType(),
+                            aEntry[2]);
+                }
             }
+
+            // Check if all required attributes where given.
+            for (final AttributeDescriptor aAttribute : aAttributesPerState.values())
+            {
+                if ( ! aAttribute.IsOptional())
+                {
+                    if ( ! aUsedAttributes.contains(aAttribute))
+                        throw new RuntimeException("attribute '"+aAttribute.GetName()+"' is not present but also not optional");
+                }
+            }
+        }
+    }
+
+
+
+
+    private AttributeDescriptor ProcessAttribute (
+        final String sNamespace,
+        final String sAttributeName,
+        final String sAttributeValue,
+        final Map<Integer,AttributeDescriptor> aAttributesPerState)
+    {
+        final AttributeDescriptor aAttributeDescriptor;
+        if (sNamespace == null)
+        {
+            // Attribute name has no namespace.
+            final int nAttributeNameId = maNameMap.GetIdForName(sAttributeName);
+            aAttributeDescriptor = aAttributesPerState.get(nAttributeNameId);
+        }
+        else
+        {
+            // Attribute name has explicit namespace.
+            final NamespaceMap.NamespaceDescriptor aDescriptor = maNamespaceMap.GetDescriptorForURI(sNamespace);
+            final int nAttributeNameId = maNameMap.GetIdForName(sAttributeName);
+            aAttributeDescriptor = aAttributesPerState.get((aDescriptor.Id<<16) | nAttributeNameId);
+        }
+        return aAttributeDescriptor;
+    }
+
+
+
+
+    /** Remove the quotes around the given string.
+     *  If it has the special value null (without quotes) then the null reference
+     *  is returned.
+     */
+    private String UnquoteString (final String sValue)
+    {
+        if (sValue.equals("null"))
+            return null;
+        else
+        {
+            assert(sValue.startsWith("\""));
+            assert(sValue.endsWith("\""));
+            return sValue.substring(1, sValue.length()-1);
         }
     }
 
 
 
-    private void ParseAttributeValue (
-        final String sName,
-        final String sValue,
-        final String sSimpleTypeName)
+
+    public int GetAttributeCount ()
     {
-        Log.Dbg.printf("attribute %s has type %s and value %s\n",
-            sName,
-            sSimpleTypeName,
-            sValue);
+        int nCount = 0;
+        for (final Map<Integer,AttributeDescriptor> aMap : maStateIdToAttributesMap.values())
+            nCount += aMap.size();
+        return nCount;
     }
 
 
 
 
-    private final Map<String,Map<String,String>> maStateIdToAttributesMap;
+    private final Map<Integer,Map<Integer,AttributeDescriptor>> maStateIdToAttributesMap;
+    private final NamespaceMap maNamespaceMap;
+    private final NameMap maNameMap;
 }
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeProvider.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeProvider.java
index bf9d24c..fda82f4 100644
--- a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeProvider.java
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeProvider.java
@@ -22,12 +22,13 @@
 package org.apache.openoffice.ooxml.parser;
 
 import java.util.Iterator;
-import java.util.Map.Entry;
 
 import javax.xml.stream.XMLStreamReader;
 
+/** Give access to the attributes that are read from an OOXML stream.
+ */
 public class AttributeProvider
-    implements Iterable<Entry<String,String>>
+    implements Iterable<String[]>
 {
     public AttributeProvider(XMLStreamReader aReader)
     {
@@ -52,9 +53,9 @@ public class AttributeProvider
 
 
     @Override
-    public Iterator<Entry<String,String>> iterator ()
+    public Iterator<String[]> iterator ()
     {
-        return new Iterator<Entry<String,String>> ()
+        return new Iterator<String[]> ()
         {
             int nIndex = 0;
             final int nCount = maReader.getAttributeCount();
@@ -64,30 +65,16 @@ public class AttributeProvider
                 return nIndex < nCount;
             }
 
-            @Override public Entry<String, String> next()
+            @Override public String[] next()
             {
-                final Entry<String,String> aEntry = new Entry<String,String>()
-                {
-                    final String msKey = maReader.getAttributeLocalName(nIndex);
-                    final String msValue = maReader.getAttributeValue(nIndex);
-
-                    @Override public String getKey()
-                    {
-                        return msKey;
-                    }
-
-                    @Override public String getValue()
+                final String[] aResult = new String[]
                     {
-                        return msValue;
-                    }
-
-                    @Override public String setValue (final String sValue)
-                    {
-                        return null;
-                    }
-                };
+                        maReader.getAttributeNamespace(nIndex),
+                        maReader.getAttributeLocalName(nIndex),
+                        maReader.getAttributeValue(nIndex)
+                    };
                 ++nIndex;
-                return aEntry;
+                return aResult;
             }
 
             @Override public void remove()
@@ -97,5 +84,16 @@ public class AttributeProvider
         };
     }
 
+
+
+
+    public Integer GetAttributeCount ()
+    {
+        return maReader.getAttributeCount();
+    }
+
+
+
+
     private final XMLStreamReader maReader;
 }
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/NameMap.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/NameMap.java
index 0fffe78..fe4424d 100644
--- a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/NameMap.java
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/NameMap.java
@@ -42,24 +42,14 @@ public class NameMap
                 maIdToNameMap.setSize(nId+1);
             maIdToNameMap.set(nId, aLine[2]);
         }
-
-        if (Log.Dbg != null)
-            Log.Dbg.printf("initialized name map with %d definitions\n", maNameToIdMap.size());
     }
 
 
 
 
     public int GetIdForName (
-        final String sPrefix,
-        final String sElementName)
+        final String sName)
     {
-        final String sName;
-        if (sPrefix == null)
-            sName = sElementName;
-        else
-            sName = sPrefix+"_"+sElementName;
-
         if ( ! maNameToIdMap.containsKey(sName))
             throw new RuntimeException("token '"+sName+"' is not known");
 
@@ -80,6 +70,14 @@ public class NameMap
 
 
 
+    public int GetNameCount ()
+    {
+        return maIdToNameMap.size();
+    }
+
+
+
+
     private final Map<String,Integer> maNameToIdMap;
     private final Vector<String> maIdToNameMap;
 }
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/NamespaceMap.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/NamespaceMap.java
index 214a008..e12f1b5 100644
--- a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/NamespaceMap.java
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/NamespaceMap.java
@@ -27,31 +27,65 @@ import java.util.Vector;
 
 public class NamespaceMap
 {
+    class NamespaceDescriptor
+    {
+        NamespaceDescriptor (final String sPrefix, final int nId)
+        {
+            Prefix = sPrefix;
+            Id = nId;
+        }
+        public final String Prefix;
+        public final int Id;
+    }
     NamespaceMap (final Vector<String[]> aData)
     {
-        maUriToPrefixMap = new HashMap<>();
+        maUriToDescriptorMap = new HashMap<>();
+        maIdToDescriptorMap = new HashMap<>();
 
         for (final String[] aLine : aData)
         {
-            maUriToPrefixMap.put(aLine[2], aLine[1]);
+            final int nId = Integer.parseInt(aLine[2]);
+            final NamespaceDescriptor aDescriptor = new NamespaceDescriptor(aLine[1], nId);
+            maUriToDescriptorMap.put(
+                aLine[3],
+                aDescriptor);
+            maIdToDescriptorMap.put(
+                nId,
+                aDescriptor);
         }
-
-        if (Log.Dbg != null)
-            Log.Dbg.printf("initialized namespace map with %d definitions\n", maUriToPrefixMap.size());
     }
 
 
 
 
-    public String GetPrefixForURI (final String sURI)
+    public NamespaceDescriptor GetDescriptorForURI (final String sURI)
     {
-        if ( ! maUriToPrefixMap.containsKey(sURI))
+        if (sURI == null)
+            throw new RuntimeException("namespace is null");
+        if ( ! maUriToDescriptorMap.containsKey(sURI))
             throw new RuntimeException("namespace '"+sURI+"' is not known");
-        return maUriToPrefixMap.get(sURI);
+        return maUriToDescriptorMap.get(sURI);
+    }
+
+
+
+
+    public NamespaceDescriptor GetDescriptorForId (final int nId)
+    {
+        return maIdToDescriptorMap.get(nId);
+    }
+
+
+
+
+    public int GetNamespaceCount ()
+    {
+        return maUriToDescriptorMap.size();
     }
 
 
 
 
-    private final Map<String,String> maUriToPrefixMap;
+    private final Map<String,NamespaceDescriptor> maUriToDescriptorMap;
+    private final Map<Integer,NamespaceDescriptor> maIdToDescriptorMap;
 }
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/OOXMLParser.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/OOXMLParser.java
index 64abf25..398ff58 100644
--- a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/OOXMLParser.java
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/OOXMLParser.java
@@ -48,8 +48,20 @@ public class OOXMLParser
      */
     public static void main (final String ... aArgumentList)
     {
-        if (aArgumentList.length != 3)
-            throw new RuntimeException("usage: OOXMLParser <parser-tables-path> <XML-input-file> <log-file>");
+        if (aArgumentList.length<2 ||aArgumentList.length>3)
+            throw new RuntimeException("usage: OOXMLParser <parser-tables-path> <XML-input-file> <log-file>?");
+
+        if (aArgumentList.length == 3)
+        {
+            final File aLogFile = new File(aArgumentList[2]);
+            Log.Dbg = new Log(aLogFile);
+            System.out.printf("writing log data to %s\n", aLogFile.toString());
+        }
+        else
+        {
+            Log.Dbg = null;
+            System.out.printf("writing no log data\n");
+        }
 
         long nStartTime = System.currentTimeMillis();
         final StateMachine aMachine = new StateMachine(new File(aArgumentList[0]));
@@ -63,7 +75,7 @@ public class OOXMLParser
             if (aReader != null)
             {
                 nStartTime = System.currentTimeMillis();
-                final int  nElementCount = Parse(aReader, aMachine, new File(aArgumentList[2]));
+                final int  nElementCount = Parse(aReader, aMachine);
                 nEndTime = System.currentTimeMillis();
                 System.out.printf("parsed %d elements in %fs\n",
                     nElementCount,
@@ -77,6 +89,8 @@ public class OOXMLParser
     }
 
 
+
+
     private static InputStream GetInputStream (final String sInputName)
     {
         final InputStream aIn;
@@ -146,11 +160,8 @@ public class OOXMLParser
 
     private static int Parse (
         final XMLStreamReader aReader,
-        final StateMachine aMachine,
-        final File aLogFile)
+        final StateMachine aMachine)
     {
-        Log.Dbg = new Log(aLogFile);
-
         int nElementCount = 0;
         try
         {
@@ -164,7 +175,8 @@ public class OOXMLParser
                         ++nElementCount;
                         if (aMachine.IsInSkipState())
                         {
-                            Log.Dbg.printf("is skip state -> starting to skip\n");
+                            if (Log.Dbg != null)
+                                Log.Dbg.printf("is skip state -> starting to skip\n");
                             nElementCount += Skip(aReader);
                         }
                         else if ( ! aMachine.ProcessStartElement(
@@ -173,7 +185,8 @@ public class OOXMLParser
                             aReader.getLocation(),
                             aAttributeProvider))
                         {
-                            Log.Dbg.printf("starting to skip to recover from error\n");
+                            if (Log.Dbg != null)
+                                Log.Dbg.printf("starting to skip to recover from error\n");
                             nElementCount += Skip(aReader);
                         }
                         break;
@@ -187,7 +200,8 @@ public class OOXMLParser
 
                     case XMLStreamReader.CHARACTERS:
                         final String sText = aReader.getText();
-                        Log.Dbg.printf("text [%s]\n", sText.replace("\n", "\\n"));
+                        if (Log.Dbg != null)
+                            Log.Dbg.printf("text [%s]\n", sText.replace("\n", "\\n"));
                         aMachine.ProcessCharacters(sText);
                         break;
 
@@ -215,11 +229,14 @@ public class OOXMLParser
 
     private static int Skip (final XMLStreamReader aReader)
     {
-        Log.Dbg.printf("starting to skip on %s at L%dC%d\n",
-            aReader.getLocalName(),
-            aReader.getLocation().getLineNumber(),
-            aReader.getLocation().getColumnNumber());
-        Log.Dbg.IncreaseIndentation();
+        if (Log.Dbg != null)
+        {
+            Log.Dbg.printf("starting to skip on %s at L%dC%d\n",
+                aReader.getLocalName(),
+                aReader.getLocation().getLineNumber(),
+                aReader.getLocation().getColumnNumber());
+            Log.Dbg.IncreaseIndentation();
+        }
 
         // We are called when processing a start element.  This means that we are
         // already at relative depth 1.
@@ -235,16 +252,21 @@ public class OOXMLParser
                     case XMLStreamReader.START_ELEMENT:
                         ++nRelativeDepth;
                         ++nElementCount;
-                        Log.Dbg.printf("skipping start element %s\n", aReader.getLocalName());
-                        Log.Dbg.IncreaseIndentation();
+                        if (Log.Dbg != null)
+                        {
+                            Log.Dbg.printf("skipping start element %s\n", aReader.getLocalName());
+                            Log.Dbg.IncreaseIndentation();
+                        }
                         break;
 
                     case XMLStreamReader.END_ELEMENT:
                         --nRelativeDepth;
-                        Log.Dbg.DecreaseIndentation();
+                        if (Log.Dbg != null)
+                            Log.Dbg.DecreaseIndentation();
                         if (nRelativeDepth <= 0)
                         {
-                            Log.Dbg.printf("leaving skip mode on %s\n", aReader.getLocalName());
+                            if (Log.Dbg != null)
+                                Log.Dbg.printf("leaving skip mode on %s\n", aReader.getLocalName());
                             return nElementCount;
                         }
                         break;
@@ -257,7 +279,9 @@ public class OOXMLParser
                         break;
 
                     default:
-                        Log.Dbg.printf("%s\n",  nCode);
+                        if (Log.Dbg != null)
+                            Log.Dbg.printf("%s\n",  nCode);
+                        break;
                 }
             }
         }
@@ -270,8 +294,10 @@ public class OOXMLParser
 
 
 
+
     private static void SkipText (final String sText)
     {
-        Log.Dbg.printf("skipping text [%s]\n", sText.replace("\n", "\\n"));
+        if (Log.Dbg != null)
+            Log.Dbg.printf("skipping text [%s]\n", sText.replace("\n", "\\n"));
     }
 }
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ParseTableReader.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ParseTableReader.java
index b38a2c8..d8426cb 100644
--- a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ParseTableReader.java
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ParseTableReader.java
@@ -30,6 +30,11 @@ public class ParseTableReader
                     break;
                 if (sLine.startsWith("#"))
                     continue;
+
+                // Splitting just at whitespace may be too simple to keep quoted text
+                // (used e.g. for attribute default values) in one peace when
+                // it contains whitespace.  Should this case occur than this
+                // implementation has to be improved.
                 final String aParts[] = sLine.split("\\s+");
 
                 GetSection(aParts[0]).add(aParts);
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/SkipStateTable.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/SkipStateTable.java
index bc0c76b..a609aa7 100644
--- a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/SkipStateTable.java
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/SkipStateTable.java
@@ -24,7 +24,6 @@ public class SkipStateTable
 
             maSkipStates.add(nStateId);
         }
-        Log.Std.printf("read %d skip states\n",  maSkipStates.size());
     }
 
 
@@ -38,5 +37,13 @@ public class SkipStateTable
 
 
 
+    public int GetSkipStateCount ()
+    {
+        return maSkipStates.size();
+    }
+
+
+
+
     private final Set<Integer> maSkipStates;
 }
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/StateMachine.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/StateMachine.java
index 72a2a33..6b19977 100644
--- a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/StateMachine.java
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/StateMachine.java
@@ -33,20 +33,37 @@ public class StateMachine
 {
     public StateMachine (final File aParseTableFile)
     {
+        if (Log.Dbg != null)
+            Log.Dbg.printf("reading parse tables from %s\n", aParseTableFile.toString());
+
         final ParseTableReader aReader = new ParseTableReader(aParseTableFile);
         maNamespaceMap = new NamespaceMap(aReader.GetSection("namespace"));
-        maElementNameMap = new NameMap(aReader.GetSection("element-name"));
+        maNameMap = new NameMap(aReader.GetSection("name"));
         maStateNameMap = new NameMap(aReader.GetSection("state-name"));
         maTransitions = new TransitionTable(aReader.GetSection("transition"));
         maSkipStates = new SkipStateTable(aReader.GetSection("skip"));
         maAcceptingStates = new AcceptingStateTable(aReader.GetSection("accepting-state"));
-        maAttributeManager = new AttributeManager(aReader.GetSection("attribute"));
+        maAttributeManager = new AttributeManager(
+            aReader.GetSection("attribute"),
+            maNamespaceMap,
+            maNameMap);
+
+        System.out.printf("read %d namespace, %d names, %d states (%d skip, %d accept), %d transitions and %d attributes\n",
+                maNamespaceMap.GetNamespaceCount(),
+                maNameMap.GetNameCount(),
+                maStateNameMap.GetNameCount(),
+                maSkipStates.GetSkipStateCount(),
+                maAcceptingStates.GetAcceptingStateCount(),
+                maTransitions.GetTransitionCount(),
+                maAttributeManager.GetAttributeCount());
 
         mnStartStateId = Integer.parseInt(aReader.GetSection("start-state").firstElement()[1]);
         mnEndStateId = Integer.parseInt(aReader.GetSection("end-state").firstElement()[1]);
         mnCurrentStateId = mnStartStateId;
         maStateStack = new Stack<>();
-        Log.Dbg.printf("starting in state _start_ (%d)\n", mnCurrentStateId);
+
+        if (Log.Dbg != null)
+            Log.Dbg.printf("starting in state _start_ (%d)\n", mnCurrentStateId);
     }
 
 
@@ -62,41 +79,49 @@ public class StateMachine
 
         try
         {
-            final String sPrefix = maNamespaceMap.GetPrefixForURI(sNamespaceURI);
-            final int nElementId = maElementNameMap.GetIdForName(sPrefix, sElementName);
-            Log.Dbg.printf("%s:%s(%d) L%dC%d\n",
-                sPrefix,
-                sElementName,
-                nElementId,
-                aLocation.getLineNumber(),
-                aLocation.getColumnNumber());
+            final NamespaceMap.NamespaceDescriptor aDescriptor = maNamespaceMap.GetDescriptorForURI(sNamespaceURI);
+            final int nElementNameId = maNameMap.GetIdForName(sElementName);
+            if (Log.Dbg != null)
+                Log.Dbg.printf("%s:%s(%d:%d) L%dC%d\n",
+                    aDescriptor.Prefix,
+                    sElementName,
+                    aDescriptor.Id,
+                    nElementNameId,
+                    aLocation.getLineNumber(),
+                    aLocation.getColumnNumber());
 
             final Transition aTransition = maTransitions.GetTransition(
                 mnCurrentStateId,
-                nElementId);
+                aDescriptor.Id,
+                nElementNameId);
             if (aTransition == null)
             {
                 final String sText = String.format(
-                    "can not find transition for state %s(%d) and element %s(%d) at L%dC%d\n",
+                    "can not find transition for state %s(%d) and element %s(%d:%d) at L%dC%d\n",
                     maStateNameMap.GetNameForId(mnCurrentStateId),
                     mnCurrentStateId,
-                    maElementNameMap.GetNameForId(nElementId),
-                    nElementId,
+                    aDescriptor.Id,
+                    maNameMap.GetNameForId(nElementNameId),
+                    nElementNameId,
                     aLocation.getLineNumber(),
                     aLocation.getColumnNumber());
                 Log.Err.printf(sText);
-                Log.Dbg.printf(sText);
+                if (Log.Dbg != null)
+                    Log.Dbg.printf(sText);
             }
             else
             {
-                Log.Dbg.printf(" %s(%d) -> %s(%d) via %s(%d)",
-                    maStateNameMap.GetNameForId(mnCurrentStateId),
-                    mnCurrentStateId,
-                    maStateNameMap.GetNameForId(aTransition.GetEndStateId()),
-                    aTransition.GetEndStateId(),
-                    maStateNameMap.GetNameForId(aTransition.GetActionId()),
-                    aTransition.GetActionId());
-                Log.Dbg.printf("\n");
+                if (Log.Dbg != null)
+                {
+                    Log.Dbg.printf(" %s(%d) -> %s(%d) via %s(%d)",
+                        maStateNameMap.GetNameForId(mnCurrentStateId),
+                        mnCurrentStateId,
+                        maStateNameMap.GetNameForId(aTransition.GetEndStateId()),
+                        aTransition.GetEndStateId(),
+                        maStateNameMap.GetNameForId(aTransition.GetActionId()),
+                        aTransition.GetActionId());
+                    Log.Dbg.printf("\n");
+                }
 
                 final int nOldState = mnCurrentStateId;
                 SetCurrentState(aTransition.GetEndStateId());
@@ -108,7 +133,7 @@ public class StateMachine
         }
         catch (RuntimeException aException)
         {
-            System.err.printf("error at line %d and column %d\n",
+            Log.Err.printf("error at line %d and column %d\n",
                 aLocation.getLineNumber(),
                 aLocation.getColumnNumber());
             throw aException;
@@ -127,28 +152,32 @@ public class StateMachine
         if ( ! maAcceptingStates.Contains(mnCurrentStateId)
             && mnCurrentStateId!=-1)
         {
-            Log.Dbg.printf("current state %s(%d) is not an accepting state\n",
-                maStateNameMap.GetNameForId(mnCurrentStateId),
-                mnCurrentStateId);
+            if (Log.Dbg != null)
+                Log.Dbg.printf("current state %s(%d) is not an accepting state\n",
+                    maStateNameMap.GetNameForId(mnCurrentStateId),
+                    mnCurrentStateId);
             throw new RuntimeException("not expecting end element "+sElementName);
         }
 
-        final String sPrefix = maNamespaceMap.GetPrefixForURI(sNamespaceURI);
+        final NamespaceMap.NamespaceDescriptor aDescriptor = maNamespaceMap.GetDescriptorForURI(sNamespaceURI);
 
         final int nOldStateId = mnCurrentStateId;
         SetCurrentState(maStateStack.pop());
 
-        Log.Dbg.DecreaseIndentation();
-        Log.Dbg.printf("/%s:%s L%d%d\n",
-            sPrefix,
-            sElementName,
-            aLocation.getLineNumber(),
-            aLocation.getColumnNumber());
-        Log.Dbg.printf(" %s(%d) <- %s(%d)\n",
-            maStateNameMap.GetNameForId(nOldStateId),
-            nOldStateId,
-            maStateNameMap.GetNameForId(mnCurrentStateId),
-            mnCurrentStateId);
+        if (Log.Dbg != null)
+        {
+            Log.Dbg.DecreaseIndentation();
+            Log.Dbg.printf("/%s:%s L%d%d\n",
+                aDescriptor.Prefix,
+                sElementName,
+                aLocation.getLineNumber(),
+                aLocation.getColumnNumber());
+            Log.Dbg.printf(" %s(%d) <- %s(%d)\n",
+                maStateNameMap.GetNameForId(nOldStateId),
+                nOldStateId,
+                maStateNameMap.GetNameForId(mnCurrentStateId),
+                mnCurrentStateId);
+        }
     }
 
 
@@ -191,17 +220,20 @@ public class StateMachine
         final int nNewState)
     {
         maStateStack.push(mnCurrentStateId);
-        Log.Dbg.IncreaseIndentation();
+        if (Log.Dbg != null)
+            Log.Dbg.IncreaseIndentation();
         final int nActionId = aTransition.GetActionId();
         SetCurrentState(nActionId);
-        maAttributeManager.ParseAttributes(nActionId, aAttributes);
+        maAttributeManager.ParseAttributes(
+            nActionId,
+            aAttributes);
     }
 
 
 
 
     private final NamespaceMap maNamespaceMap;
-    private final NameMap maElementNameMap;
+    private final NameMap maNameMap;
     private final NameMap maStateNameMap;
     private final TransitionTable maTransitions;
     private final AttributeManager maAttributeManager;
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/TransitionTable.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/TransitionTable.java
index 3f0bb65..32326da 100644
--- a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/TransitionTable.java
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/TransitionTable.java
@@ -30,21 +30,20 @@ public class TransitionTable
     public TransitionTable (final Vector<String[]> aData)
     {
         maTransitions = new HashMap<>();
-        int nTransitionCount = 0;
 
         for (final String[] aLine : aData)
         {
             // Create new transition.
             final int nStartStateId = Integer.parseInt(aLine[1]);
             final int nEndStateId = Integer.parseInt(aLine[2]);
-            final int nElementId = Integer.parseInt(aLine[3]);
-            final int nElementStateId = Integer.parseInt(aLine[4]);
+            final int nElementPrefixId = Integer.parseInt(aLine[3]);
+            final int nElementLocalId = Integer.parseInt(aLine[4]);
+            final int nElementStateId = Integer.parseInt(aLine[5]);
             final Transition aTransition = new Transition(
                 nStartStateId,
                 nEndStateId,
-                nElementId,
+                (nElementPrefixId<<16) | nElementLocalId,
                 nElementStateId);
-            ++nTransitionCount;
 
             Map<Integer,Transition> aPerElementTransitions = maTransitions.get(aTransition.GetStartStateId());
             if (aPerElementTransitions == null)
@@ -54,7 +53,6 @@ public class TransitionTable
             }
             aPerElementTransitions.put(aTransition.GetElementId(), aTransition);
         }
-        Log.Std.printf("read %d transitions\n",  nTransitionCount);
     }
 
 
@@ -62,13 +60,22 @@ public class TransitionTable
 
     public Transition GetTransition (
         final int nStateId,
-        final int nElementId)
+        final int nPrefixId,
+        final int nLocalId)
     {
         Map<Integer,Transition> aPerElementTransitions = maTransitions.get(nStateId);
         if (aPerElementTransitions == null)
             return null;
         else
-            return aPerElementTransitions.get(nElementId);
+            return aPerElementTransitions.get((nPrefixId<<16) | nLocalId);
+    }
+
+
+
+
+    public int GetTransitionCount ()
+    {
+        return maTransitions.size();
     }
 
 
diff --git a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/SchemaReader.java b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/SchemaReader.java
index c770a34..a1f5d3f 100644
--- a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/SchemaReader.java
+++ b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/SchemaReader.java
@@ -37,10 +37,10 @@ import javax.xml.stream.XMLStreamException;
 
 import org.apache.openoffice.ooxml.schema.automaton.FiniteAutomatonContainer;
 import org.apache.openoffice.ooxml.schema.automaton.NonValidatingCreator;
-import org.apache.openoffice.ooxml.schema.automaton.FiniteAutomaton;
 import org.apache.openoffice.ooxml.schema.automaton.ValidatingCreator;
 import org.apache.openoffice.ooxml.schema.generator.LogGenerator;
 import org.apache.openoffice.ooxml.schema.generator.ParserTablesGenerator;
+import org.apache.openoffice.ooxml.schema.model.attribute.Attribute;
 import org.apache.openoffice.ooxml.schema.model.schema.Schema;
 import org.apache.openoffice.ooxml.schema.model.schema.SchemaBase;
 import org.apache.openoffice.ooxml.schema.parser.SchemaParser;
diff --git a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/Test.java b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/Test.java
index dff3508..ea2565f 100644
--- a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/Test.java
+++ b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/Test.java
@@ -53,6 +53,7 @@ public class Test
         HopcroftMinimizer.MinimizeDFA (
             new StateContainer(),
             aStates,
+            null,
             System.out);
     }
 }
diff --git a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/CreatorBase.java b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/CreatorBase.java
new file mode 100644
index 0000000..239dba196
--- /dev/null
+++ b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/CreatorBase.java
@@ -0,0 +1,124 @@
+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.Vector;
+
+import org.apache.openoffice.ooxml.schema.iterator.AttributeIterator;
+import org.apache.openoffice.ooxml.schema.iterator.DereferencingNodeIterator;
+import org.apache.openoffice.ooxml.schema.model.attribute.Attribute;
+import org.apache.openoffice.ooxml.schema.model.base.INode;
+import org.apache.openoffice.ooxml.schema.model.schema.SchemaBase;
+
+/** Base class of the creator classes for DFAs and NFAs.
+ */
+public class CreatorBase
+{
+    CreatorBase (
+        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;
+        msLogIndentation = "";
+    }
+
+
+
+
+    protected Vector<Attribute> CollectAttributes (final INode aRoot)
+    {
+        final Vector<Attribute> aAttributes = new Vector<>();
+        for (final INode aNode : new DereferencingNodeIterator(aRoot, maSchemaBase, true))
+            for (final Attribute aAttribute : new AttributeIterator(aNode, maSchemaBase))
+                aAttributes.add(aAttribute);
+        return aAttributes;
+    }
+
+
+
+
+    protected void AddSkipTransition (
+        final State aState,
+        final SkipData aSkipData)
+    {
+        aState.AddSkipData(aSkipData);
+
+        if (maLog != null)
+        {
+            maLog.printf("%sskip state %s\n",
+                msLogIndentation,
+                aState.GetFullname());
+        }
+    }
+
+
+
+
+    protected void ProcessAttributes (final INode aNode)
+    {
+        for (final Attribute aAttribute : new AttributeIterator(aNode, maSchemaBase))
+        {
+            maLog.printf("%sattribute %s\n",
+                msLogIndentation,
+                aAttribute.GetName().GetDisplayName());
+            maAttributes.add(aAttribute);
+        }
+    }
+
+
+
+
+    protected void AddComment (
+        final String sFormat,
+        final Object ... aArgumentList)
+    {
+        if (maLog != null)
+        {
+            maLog.print(msLogIndentation);
+            maLog.print("// ");
+            maLog.printf(sFormat, aArgumentList);
+            maLog.print("\n");
+        }
+    }
+
+
+
+
+    protected void StartBlock ()
+    {
+        if (maLog != null)
+            msLogIndentation += "    ";
+    }
+
+
+
+
+    protected void EndBlock ()
+    {
+        if (maLog != null)
+            msLogIndentation = msLogIndentation.substring(4);
+    }
+
+
+
+
+    protected final SchemaBase maSchemaBase;
+    protected final StateContainer maStateContainer;
+    protected final PrintStream maLog;
+    protected String msLogIndentation;
+    protected Vector<Attribute> maAttributes;
+}
diff --git a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/DFACreator.java b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/DFACreator.java
index a0ba1c3..64b2bcc 100644
--- a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/DFACreator.java
+++ b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/DFACreator.java
@@ -12,6 +12,7 @@ import java.util.TreeMap;
 import java.util.TreeSet;
 import java.util.Vector;
 
+import org.apache.openoffice.ooxml.schema.model.attribute.Attribute;
 import org.apache.openoffice.ooxml.schema.model.base.QualifiedName;
 
 /** Convert an NFA into a DFA via the powerset construction (also called subset
@@ -25,11 +26,14 @@ public class DFACreator
     public static FiniteAutomaton CreateDFAforNFA (
         final StateContainer aDFAStateContainer,
         final StateContext aNFAStateContext,
+        final Vector<Attribute> aAttributes,
         final QualifiedName aTypeName)
     {
         final DFACreator aCreator = new DFACreator(aDFAStateContainer, aNFAStateContext, aTypeName);
         aCreator.CreateDFAforNFA();
-        return new FiniteAutomaton(aCreator.maDFAStateContext);
+        return new FiniteAutomaton(
+            aCreator.maDFAStateContext,
+            aAttributes);
     }
 
 
diff --git a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/FiniteAutomaton.java b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/FiniteAutomaton.java
index 999824c..8c4cf6e 100644
--- a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/FiniteAutomaton.java
+++ b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/FiniteAutomaton.java
@@ -23,6 +23,7 @@ package org.apache.openoffice.ooxml.schema.automaton;
 
 import java.util.Vector;
 
+import org.apache.openoffice.ooxml.schema.model.attribute.Attribute;
 import org.apache.openoffice.ooxml.schema.model.base.QualifiedName;
 
 
@@ -37,9 +38,13 @@ import org.apache.openoffice.ooxml.schema.model.base.QualifiedName;
 public class FiniteAutomaton
 {
     FiniteAutomaton (
-        final StateContext aContext)
+        final StateContext aContext,
+        final Vector<Attribute> aAttributes)
     {
         maStateContext = aContext;
+        maAttributes = aAttributes!=null
+            ? aAttributes
+            : new Vector<Attribute>();
     }
 
 
@@ -92,6 +97,7 @@ public class FiniteAutomaton
         return DFACreator.CreateDFAforNFA(
             aDFAContainer,
             maStateContext,
+            maAttributes,
             aTypeName);
     }
 
@@ -137,5 +143,14 @@ public class FiniteAutomaton
 
 
 
+    public Vector<Attribute> GetAttributes ()
+    {
+        return maAttributes;
+    }
+
+
+
+
     private final StateContext maStateContext;
+    private final Vector<Attribute> maAttributes;
 }
diff --git a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/FiniteAutomatonContainer.java b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/FiniteAutomatonContainer.java
index 5ac2e66..fbd8407 100644
--- a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/FiniteAutomatonContainer.java
+++ b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/FiniteAutomatonContainer.java
@@ -72,18 +72,6 @@ public class FiniteAutomatonContainer
 
 
 
-    public Iterable<Transition> GetTransitions ()
-    {
-        final Vector<Transition> aTransitions = new Vector<>();
-        for (final FiniteAutomaton aAutomaton : maComplexTypeNameToAutomatonMap.values())
-            for (final Transition aTransition : aAutomaton.GetTransitions())
-                aTransitions.add(aTransition);
-        return aTransitions;
-    }
-
-
-
-
     public int GetTransitionCount ()
     {
         int nTransitionCount = 0;
@@ -135,6 +123,7 @@ public class FiniteAutomatonContainer
                 HopcroftMinimizer.MinimizeDFA(
                     aNewStateContainer,
                     aEntry.getValue().GetStateContext(),
+                    aEntry.getValue().GetAttributes(),
                     aLog));
         }
         return aDFAs;
diff --git a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/HopcroftMinimizer.java b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/HopcroftMinimizer.java
index 6d50592..195af7a 100644
--- a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/HopcroftMinimizer.java
+++ b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/HopcroftMinimizer.java
@@ -9,7 +9,9 @@ import java.util.Map.Entry;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.TreeSet;
+import java.util.Vector;
 
+import org.apache.openoffice.ooxml.schema.model.attribute.Attribute;
 import org.apache.openoffice.ooxml.schema.model.base.QualifiedName;
 
 /** Minimize an DFA with respect to its number of states.
@@ -24,6 +26,7 @@ public class HopcroftMinimizer
     public static FiniteAutomaton MinimizeDFA (
         final StateContainer aNewStateContainer,
         final StateContext aOriginalStates,
+        final Vector<Attribute> aAttributes,
         final PrintStream aLog)
     {
         if (aLog != null)
@@ -95,7 +98,8 @@ public class HopcroftMinimizer
 
         // Create and return the new minimized automaton.
         return new FiniteAutomaton(
-            aMinimizedStates);
+            aMinimizedStates,
+            aAttributes);
     }
 
 
diff --git a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/NonValidatingCreator.java b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/NonValidatingCreator.java
index 2b7ec80..2801c51 100644
--- a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/NonValidatingCreator.java
+++ b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/NonValidatingCreator.java
@@ -22,9 +22,6 @@
 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.Vector;
 
 import org.apache.openoffice.ooxml.schema.iterator.DereferencingNodeIterator;
@@ -42,24 +39,13 @@ import org.apache.openoffice.ooxml.schema.model.schema.SchemaBase;
  *  Input files but are not validated to conform to the schemas.
  */
 public class NonValidatingCreator
+    extends CreatorBase
 {
     public NonValidatingCreator (
         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);
     }
 
 
@@ -89,23 +75,40 @@ public class NonValidatingCreator
     private FiniteAutomaton CreateForTopLevelElements (
         final Iterable<Schema> aTopLevelSchemas)
     {
+        AddComment("top level elements");
+        StartBlock();
         final String sTypeName = "<top-level>";
         final StateContext aStateContext = new StateContext(
             maStateContainer,
             sTypeName);
+        final State aStartState = aStateContext.GetStartState();
         final State aEndState = aStateContext.CreateEndState();
 
         // top level elements
         for (final Schema aSchema : aTopLevelSchemas)
+        {
+            AddComment("schema %s", aSchema.GetShortName());
+            StartBlock();
             for (final Element aElement : aSchema.TopLevelElements.GetSorted())
+            {
+                AddComment("Element: on '%s' go from %s to %s via %s",
+                    aElement.GetElementName().GetDisplayName(),
+                    aStartState.GetFullname(),
+                    aEndState.GetFullname(),
+                    aElement.GetTypeName().GetStateName());
+
                 aStateContext.GetStartState().AddTransition(
                     new Transition(
-                        aStateContext.GetStartState(),
+                        aStartState,
                         aEndState,
                         aElement.GetElementName(),
                         aElement.GetTypeName().GetStateName()));
+            }
+            EndBlock();
+        }
+        EndBlock();
 
-        return new FiniteAutomaton(aStateContext);
+        return new FiniteAutomaton(aStateContext, null);
     }
 
 
@@ -113,12 +116,24 @@ public class NonValidatingCreator
 
     private FiniteAutomaton CreateForComplexType (final ComplexType aComplexType)
     {
+        maLog.printf("\n");
+        AddComment ("Complex Type %s defined in %s.",
+            aComplexType.GetName().GetDisplayName(),
+            aComplexType.GetLocation());
+        StartBlock();
+
         final StateContext aStateContext = new StateContext(
             maStateContainer,
             aComplexType.GetName().GetStateName());
 
         for (final Element aElement : CollectElements(aComplexType))
         {
+            AddComment("Element: on '%s' go from %s to %s via %s",
+                aElement.GetElementName().GetDisplayName(),
+                aStateContext.GetStartState().GetFullname(),
+                aStateContext.GetStartState().GetFullname(),
+                aElement.GetTypeName().GetStateName());
+
             aStateContext.GetStartState().AddTransition(
                 new Transition(
                     aStateContext.GetStartState(),
@@ -129,15 +144,23 @@ public class NonValidatingCreator
 
         for (final Any aAny : CollectAnys(aComplexType))
         {
-            aStateContext.GetStartState().AddSkipData(
+            AddSkipTransition(
+                aStateContext.GetStartState(),
                 new SkipData(
                     aAny.GetProcessContentsFlag(),
                     aAny.GetNamespaces()));
         }
 
+        // Collect all attributes.
+        maAttributes = new Vector<>();
+        for (final INode aNode : new DereferencingNodeIterator(aComplexType, maSchemaBase, true))
+            ProcessAttributes(aNode);
+
         aStateContext.GetStartState().SetIsAccepting();
 
-        return new FiniteAutomaton(aStateContext);
+        EndBlock();
+
+        return new FiniteAutomaton(aStateContext, maAttributes);
     }
 
 
@@ -170,11 +193,4 @@ public class NonValidatingCreator
         }
         return aAnys;
     }
-
-
-
-
-    private final SchemaBase maSchemaBase;
-    private final StateContainer maStateContainer;
-    private final PrintStream maLog;
 }
diff --git a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/ValidatingCreator.java b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/ValidatingCreator.java
index 00bf13d..8489299 100644
--- a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/ValidatingCreator.java
+++ b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/ValidatingCreator.java
@@ -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 INodeVisitor aVisitor = new ValidatingCreatorVisitor(
-            aAttributes,
-            aStateContext,
-            maSchemaBase,
-            maLog,
-            "",
-            aStateContext.GetStartState(),
-            aStateContext.GetStartState(),
-            aEndState);
+        final State aEndState = maStateContext.CreateEndState();
+
+        assert(maContextStack.isEmpty());
+        msLogIndentation = "";
 
         // top level elements
         for (final Element aElement : maSchemaBase.TopLevelElements.GetSorted())
-            aElement.AcceptVisitor(aVisitor);
-
-        return new FiniteAutomaton(aStateContext);
+            ProcessType(
+                aElement,
+                maStateContext.GetStartState(),
+                maStateContext.GetStartState(),
+                aEndState);
 
+        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;
 }
diff --git a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/ValidatingCreatorVisitor.java b/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/ValidatingCreatorVisitor.java
deleted file mode 100644
index d374be1..0000000
--- a/ooxml/source/framework/SchemaParser/src/org/apache/openoffice/ooxml/schema/automaton/ValidatingCreatorVisitor.java
+++ /dev/null
@@ -1,646 +0,0 @@
-/**************************************************************
-*
-* 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.automaton;
-
-import java.io.PrintStream;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Vector;
-
-import org.apache.openoffice.ooxml.schema.iterator.AttributeIterator;
-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.base.INode;
-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.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.SimpleContent;
-
-/** A helper class of the ValidatingCreator.
- *
- *  A visitor is called by the ValidatingCreator for each complex type.
- *  Further instances are created and called while iterating over all nodes
- *  of these types.
- */
-public class ValidatingCreatorVisitor
-    extends NodeVisitorAdapter
-{
-    public ValidatingCreatorVisitor (
-        final Map<State,Vector<Attribute>> aAttributes,
-        final StateContext aStateContext,
-        final SchemaBase aSchemaBase,
-        final PrintStream aLog,
-        final String sLogIndentation,
-        final State aBaseState,
-        final State aStartState,
-        final State aEndState)
-    {
-        maAttributes = aAttributes;
-        maStateContext = aStateContext;
-        maSchemaBase = aSchemaBase;
-        maLog = aLog;
-        msLogIndentation = sLogIndentation;
-        maBaseState = aBaseState;
-        maStartState = aStartState;
-        maEndState = aEndState;
-    }
-
-
-
-
-    @Override
-    public void Visit (final All aAll)
-    {
-        AddComment("All");
-
-        // 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(maBaseState, "As");
-        final State aLocalEndState = maStateContext.CreateState(maBaseState, "Ae");
-
-        StartBlock();
-        AddEpsilonTransition(maStartState, aLocalStartState);
-        ProcessType(
-            aReplacement,
-            maStateContext.CreateState(maBaseState, "A"),
-            aLocalStartState,
-            aLocalEndState);
-        AddEpsilonTransition(aLocalEndState, maEndState);
-        EndBlock();
-    }
-
-
-
-
-    @Override
-    public void Visit (final Any aAny)
-    {
-        assert(aAny.GetChildCount() == 0);
-
-        AddComment("Any");
-        AddSkipTransition(
-            maStartState,
-            new SkipData(
-                aAny.GetProcessContentsFlag(),
-                aAny.GetNamespaces()));
-        AddEpsilonTransition(maStartState, maEndState);
-    }
-
-
-
-
-    @Override
-    public void Visit (final Choice aChoice)
-    {
-        AddComment("Choice");
-
-        final State aLocalStartState = maStateContext.CreateState(maBaseState, "Cs");
-        final State aLocalEndState = maStateContext.CreateState(maBaseState, "Ce");
-        StartBlock();
-        AddEpsilonTransition(maStartState, aLocalStartState);
-
-        int nStateIndex = 0;
-        for (final INode aChild : aChoice.GetChildren())
-        {
-            ProcessType(
-                aChild,
-                maStateContext.CreateState(maBaseState, "C"+nStateIndex++),
-                aLocalStartState,
-                aLocalEndState);
-        }
-        AddEpsilonTransition(aLocalEndState, maEndState);
-        EndBlock();
-    }
-
-
-
-
-    @Override
-    public void Visit (final ComplexContent aComplexContent)
-    {
-        assert(aComplexContent.GetChildCount() == 1);
-
-        if (maLog != null)
-            AddComment ("Complex Content.");
-
-        StartBlock();
-        ProcessType(
-            aComplexContent.GetChildren().iterator().next(),
-            maBaseState,
-            maStartState,
-            maEndState);
-        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());
-        }
-
-        StartBlock();
-        maLog.printf("%sstarting at state %s\n", msLogIndentation, maStartState.GetFullname());
-        for (final Attribute aAttribute : new AttributeIterator(aComplexType, maSchemaBase))
-            ProcessAttribute(aAttribute);
-
-        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.
-            maStartState.SetIsAccepting();
-            maStateContext.RemoveState(maEndState);
-        }
-
-        for (final INode aChild : aComplexType.GetChildren())
-            ProcessType(aChild, maBaseState, maStartState, maEndState);
-
-        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(),
-            maStartState.GetFullname(),
-            maEndState.GetFullname(),
-            aElement.GetTypeName().GetStateName());
-
-        final Transition aTransition = new Transition(
-            maStartState,
-            maEndState,
-            aElement.GetElementName(),
-            aElement.GetTypeName().GetStateName());
-        maStartState.AddTransition(aTransition);
-    }
-
-
-
-
-    @Override
-    public void Visit (final ElementReference aReference)
-    {
-        assert(aReference.GetChildCount() == 0);
-
-        AddComment("Element reference to %s", aReference.GetReferencedElementName());
-
-        final Element aElement = aReference.GetReferencedElement(maSchemaBase);
-        if (aElement == null)
-            throw new RuntimeException("can't find referenced element "+aReference.GetReferencedElementName());
-        StartBlock();
-        ProcessType(aElement, maBaseState, maStartState, maEndState);
-        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());
-
-        final Vector<INode> aNodes = aExtension.GetTypeNodes(maSchemaBase);
-
-        StartBlock();
-        int nStateIndex = 0;
-        State aCurrentState = maStateContext.CreateState(maBaseState, "E"+nStateIndex++);
-        AddEpsilonTransition(maStartState, aCurrentState);
-        for (final INode aChild : aNodes)
-        {
-            final State aNextState = maStateContext.CreateState(maBaseState, "E"+nStateIndex++);
-            ProcessType(aChild, aCurrentState, aCurrentState, aNextState);
-            aCurrentState = aNextState;
-        }
-        AddEpsilonTransition(aCurrentState, maEndState);
-        EndBlock();
-    }
-
-
-
-
-    @Override
-    public void Visit (final Group aGroup)
-    {
-        assert(aGroup.GetChildCount() == 1);
-
-        AddComment("Group %s", aGroup.GetName());
-
-        StartBlock();
-        final State aGroupBaseState = maStateContext.CreateState(maBaseState, "G");
-        ProcessType(
-            aGroup.GetOnlyChild(),
-            aGroupBaseState,
-            maStartState,
-            maEndState);
-        EndBlock();
-    }
-
-
-
-
-    @Override
-    public void Visit (final GroupReference aReference)
-    {
-        AddComment("Group reference to %s", aReference.GetReferencedGroupName());
-        final Group aGroup = aReference.GetReferencedGroup(maSchemaBase);
-        if (aGroup == null)
-            throw new RuntimeException("can't find referenced group "+aReference.GetReferencedGroupName());
-        StartBlock();
-        ProcessType(aGroup, maBaseState, maStartState, maEndState);
-        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());
-        StartBlock();
-
-        final INode aChild = aOccurrence.GetChildren().iterator().next();
-
-        int nIndex = 0;
-        State aCurrentState = maStateContext.CreateState(maBaseState, "O"+nIndex++);
-        AddEpsilonTransition(maStartState, 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(maStartState, maEndState);
-        }
-        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(maBaseState, "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(maBaseState, "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, maEndState);
-        }
-        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, maEndState);
-                }
-
-                // i-1 -> i
-                final State aNextState = maStateContext.CreateState(maBaseState, "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, maEndState);
-        }
-        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.");
-
-        StartBlock();
-        int nStateIndex = 0;
-        State aCurrentState = maStateContext.CreateState(maBaseState, "S"+nStateIndex++);
-        AddEpsilonTransition(maStartState, aCurrentState);
-        for (final INode aChild : aSequence.GetChildren())
-        {
-            final State aNextState = maStateContext.CreateState(maBaseState, "S"+nStateIndex++);
-            ProcessType(aChild, aCurrentState, aCurrentState, aNextState);
-            aCurrentState = aNextState;
-        }
-        AddEpsilonTransition(aCurrentState, maEndState);
-        EndBlock();
-    }
-
-
-
-
-    @Override
-    public void Visit (final SimpleContent aSimpleContent)
-    {
-        AddComment("SimpleContent.");
-    }
-
-
-
-
-    @Override
-    public void Default (final INode aNode)
-    {
-        throw new RuntimeException("can not handle "+aNode.toString());
-    }
-
-
-
-
-    private void ProcessType (
-        final INode aNode,
-        final State aBaseState,
-        final State aStartState,
-        final State aEndState)
-    {
-        aNode.AcceptVisitor(
-            new ValidatingCreatorVisitor(
-                maAttributes,
-                maStateContext,
-                maSchemaBase,
-                maLog,
-                msLogIndentation,
-                aBaseState,
-                aStartState,
-                aEndState));
-    }
-
-
-
-
-    private void ProcessAttribute (
-        final Attribute aAttribute)
-    {
-        Vector<Attribute> aAttributes = maAttributes.get(maStartState);
-        if (aAttributes == null)
-        {
-            aAttributes = new Vector<>();
-            maAttributes.put(maStartState, aAttributes);
-        }
-        aAttributes.add(aAttribute);
-
-        if (maLog != null)
-            maLog.printf("%sattribute %s\n", msLogIndentation, aAttribute.toString());
-    }
-
-
-
-
-    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 void AddSkipTransition (
-        final State aState,
-        final SkipData aSkipData)
-    {
-        aState.AddSkipData(aSkipData);
-
-        if (maLog != null)
-        {
-            maLog.printf("%sskip state %s\n",
-                msLogIndentation,
-                aState.GetFullname());
-        }
-    }
-
-
-
-
-    private void AddComment (
-        final String sFormat,
-        final Object ... aArgumentList)
-    {
-        if (maLog != null)
-        {
-            maLog.print(msLogIndentation);
-            maLog.print("// ");
-            maLog.printf(sFormat, aArgumentList);
-            maLog.print("\n");
-        }
-    }
-
-
-
-
-    private void StartBlock ()
-    {
-        if (maLog != null)
-            msLogIndentation += "    ";
-    }
-
-
-
-
-    private void EndBlock ()
-    {
-        if (maLog != null)
-            msLogIndentation = msLogIndentation.substring(4);
-    }
-
-
-
-
-    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

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list