[Libreoffice-commits] core.git: Branch 'aoo/trunk' - ooxml/source
Andre Fischer
af at apache.org
Thu Jun 12 05:07:30 PDT 2014
ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ActionDescriptor.java | 93 +++
ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ActionIterator.java | 97 +++
ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ActionManager.java | 142 ++++
ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ActionTrigger.java | 10
ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeManager.java | 8
ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeValues.java | 49 +
ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ElementContext.java | 65 ++
ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/IAction.java | 27
ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/NameMap.java | 17
ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/OOXMLParser.java | 287 +++-------
ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/Parser.java | 203 +++++++
ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/StateMachine.java | 138 +++-
12 files changed, 905 insertions(+), 231 deletions(-)
New commits:
commit 038e3ce8001ba3dc821f921fda731c8d49e68858
Author: Andre Fischer <af at apache.org>
Date: Thu Jun 12 11:01:20 2014 +0000
125035: Added support for actions to the experimental Java parser.
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ActionDescriptor.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ActionDescriptor.java
new file mode 100644
index 0000000..fe3bae7
--- /dev/null
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ActionDescriptor.java
@@ -0,0 +1,93 @@
+package org.apache.openoffice.ooxml.parser;
+
+import java.util.Vector;
+
+/** Container of all actions that are associated with a single state.
+ */
+public class ActionDescriptor
+{
+ public ActionDescriptor (
+ final int nStateId,
+ final String sName)
+ {
+ msStateName = sName;
+
+ maElementStartActions = null;
+ maElementEndActions = null;
+ maTextActions = null;
+ }
+
+
+
+
+ public void AddAction (
+ final IAction aAction,
+ final ActionTrigger eTrigger)
+ {
+ GetActionsForTrigger(eTrigger, true).add(aAction);
+ }
+
+
+
+
+ public Iterable<IAction> GetActions (
+ final ActionTrigger eTrigger)
+ {
+ return GetActionsForTrigger(eTrigger, false);
+ }
+
+
+
+
+ @Override
+ public String toString ()
+ {
+ return "actions for state "+msStateName;
+ }
+
+
+
+
+ private Vector<IAction> GetActionsForTrigger (
+ final ActionTrigger eTrigger,
+ final boolean bCreateWhenMissing)
+ {
+ Vector<IAction> aActions = null;
+ switch(eTrigger)
+ {
+ case ElementStart:
+ aActions = maElementStartActions;
+ if (bCreateWhenMissing && aActions==null)
+ {
+ aActions = new Vector<>();
+ maElementStartActions = aActions;
+ }
+ break;
+ case ElementEnd:
+ aActions = maElementEndActions;
+ if (bCreateWhenMissing && aActions==null)
+ {
+ aActions = new Vector<>();
+ maElementEndActions = aActions;
+ }
+ break;
+ case Text:
+ aActions = maTextActions;
+ if (bCreateWhenMissing && aActions==null)
+ {
+ aActions = new Vector<>();
+ maTextActions = aActions;
+ }
+ break;
+ }
+ return aActions;
+ }
+
+
+
+
+ private final String msStateName;
+ private Vector<IAction> maElementStartActions;
+ private Vector<IAction> maElementEndActions;
+ private Vector<IAction> maTextActions;
+}
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ActionIterator.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ActionIterator.java
new file mode 100644
index 0000000..0b6307f
--- /dev/null
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ActionIterator.java
@@ -0,0 +1,97 @@
+package org.apache.openoffice.ooxml.parser;
+
+import java.util.Iterator;
+
+/** Iterate over two sources of actions, both given as an Iterable<IAction>
+ * object that can be null.
+*/
+public class ActionIterator implements Iterable<IAction>
+{
+ public ActionIterator (
+ final Iterable<IAction> aOneStateActions,
+ final Iterable<IAction> aAllStateActions)
+ {
+ maOneStateActions = aOneStateActions;
+ maAllStateActions = aAllStateActions;
+ }
+
+
+
+
+ @Override public Iterator<IAction> iterator()
+ {
+ return new Iterator<IAction>()
+ {
+ Iterator<IAction> maIterator = null;
+ int mnPhase = 0;
+
+ @Override
+ public boolean hasNext()
+ {
+ while(true)
+ {
+ if (mnPhase == 2)
+ return false;
+ else if (mnPhase == 0)
+ {
+ if (maIterator == null)
+ if (maOneStateActions == null)
+ {
+ mnPhase = 1;
+ continue;
+ }
+ else
+ maIterator = maOneStateActions.iterator();
+ if (maIterator.hasNext())
+ return true;
+ else
+ {
+ maIterator = null;
+ mnPhase = 1;
+ }
+ }
+ else if (mnPhase == 1)
+ {
+ if (maIterator == null)
+ if (maAllStateActions == null)
+ {
+ mnPhase = 2;
+ return false;
+ }
+ else
+ maIterator = maAllStateActions.iterator();
+ if (maIterator.hasNext())
+ return true;
+ else
+ {
+ mnPhase = 2;
+ }
+ }
+ }
+ }
+
+
+
+
+ @Override
+ public IAction next()
+ {
+ return maIterator.next();
+ }
+
+
+
+
+ @Override
+ public void remove()
+ {
+ }
+ };
+ }
+
+
+
+
+ private final Iterable<IAction> maOneStateActions;
+ private final Iterable<IAction> maAllStateActions;
+}
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ActionManager.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ActionManager.java
new file mode 100644
index 0000000..4acd8ab
--- /dev/null
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ActionManager.java
@@ -0,0 +1,142 @@
+package org.apache.openoffice.ooxml.parser;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/** Manage actions that are bound to states and XML events.
+ */
+public class ActionManager
+{
+ ActionManager (
+ final NameMap aStateNameToIdMap)
+ {
+ maStateNameToIdMap = aStateNameToIdMap;
+ maAllStatesActions = new ActionDescriptor(0,"*");
+ maStateToActionsMap = new HashMap<>();
+ }
+
+
+
+
+ /** Add an action for an element start.
+ * @param sStateSelector
+ * The element is specified via a state name. This allows one element
+ * that leads to different complex types to have different actions,
+ * depending on the complex type.
+ * The selector value can be a full state name (including the namespace
+ * prefix and CT prefix, e.g. w06_CT_Table) or a regular expression
+ * (e.g. .*_CT_Table to match w06_CT_Table and w12_CT_Table).
+ * The action is bound to all matching states.
+ * @param aAction
+ * The action to call on entering any of the states that match the
+ * selector.
+ */
+ public void AddElementStartAction (
+ final String sStateSelector,
+ final IAction aAction)
+ {
+ AddAction(sStateSelector, aAction, ActionTrigger.ElementStart);
+ }
+
+
+
+
+ /** Add an action for an element end.
+ * @see AddElementStartAction.
+ */
+ public void AddElementEndAction (
+ final String sStateSelector,
+ final IAction aAction)
+ {
+ AddAction(sStateSelector, aAction, ActionTrigger.ElementEnd);
+ }
+
+
+
+
+ /** Add an action for XML text events.
+ * @see AddElementStartAction.
+ */
+ public void AddTextAction (
+ final String sStateSelector,
+ final IAction aAction)
+ {
+ AddAction(sStateSelector, aAction, ActionTrigger.Text);
+ }
+
+
+
+
+ /** Return an iterable object that gives access to all actions
+ * bound to the given state and trigger.
+ * Return value can be null when there are no actions bound to the state
+ * and trigger.
+ */
+ public Iterable<IAction> GetActions (
+ final int nStateId,
+ final ActionTrigger eTrigger)
+ {
+ final ActionDescriptor aOneStateActionsDescriptor = maStateToActionsMap.get(nStateId);
+ final Iterable<IAction> aOneStateActions = aOneStateActionsDescriptor!=null
+ ? aOneStateActionsDescriptor.GetActions(eTrigger)
+ : null;
+ final Iterable<IAction> aAllStateActions = maAllStatesActions.GetActions(eTrigger);
+
+ if (aOneStateActions == null)
+ return aAllStateActions;
+ else if (aAllStateActions == null)
+ return aOneStateActions;
+ else
+ return new ActionIterator(aOneStateActions, aAllStateActions);
+ }
+
+
+
+
+ private void AddAction (
+ final String sStateSelector,
+ final IAction aAction,
+ final ActionTrigger eTrigger)
+ {
+ if (sStateSelector.equals("*"))
+ {
+ // Simple optimization when an action is defined for all states.
+ maAllStatesActions.AddAction(aAction, eTrigger);
+ }
+ else if (sStateSelector.contains("*") || sStateSelector.contains("?"))
+ {
+ // The state selector contains wildcards. We have to iterate over
+ // all state names to find the matching ones.
+ for (final int nStateId : maStateNameToIdMap.GetMatchingStateIds(sStateSelector))
+ {
+ GetActionDescriptor(nStateId).AddAction(aAction, eTrigger);
+ }
+ }
+ else
+ {
+ final int nStateId = maStateNameToIdMap.GetIdForName(sStateSelector);
+ GetActionDescriptor(nStateId).AddAction(aAction, eTrigger);
+ }
+ }
+
+
+
+
+ private ActionDescriptor GetActionDescriptor (final int nStateId)
+ {
+ ActionDescriptor aDescriptor = maStateToActionsMap.get(nStateId);
+ if (aDescriptor == null)
+ {
+ aDescriptor = new ActionDescriptor(nStateId, maStateNameToIdMap.GetNameForId(nStateId));
+ maStateToActionsMap.put(nStateId, aDescriptor);
+ }
+ return aDescriptor;
+ }
+
+
+
+
+ private final NameMap maStateNameToIdMap;
+ private final ActionDescriptor maAllStatesActions;
+ private final Map<Integer,ActionDescriptor> maStateToActionsMap;
+}
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ActionTrigger.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ActionTrigger.java
new file mode 100644
index 0000000..26c9759
--- /dev/null
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ActionTrigger.java
@@ -0,0 +1,10 @@
+package org.apache.openoffice.ooxml.parser;
+
+/** An enumeration of all supported action triggers.
+ */
+public enum ActionTrigger
+{
+ ElementStart,
+ ElementEnd,
+ Text
+}
\ No newline at end of file
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 c8034d4..877ad2b 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
@@ -89,10 +89,12 @@ public class AttributeManager
/** For the state with id nStateId, match the attributes from the document
* with the attribute specifications of that state.
*/
- public void ParseAttributes (
+ public AttributeValues ParseAttributes (
final int nStateId,
final AttributeProvider aDocumentAttributes)
{
+ final AttributeValues aValues = new AttributeValues();
+
final Map<Integer,AttributeDescriptor> aAttributesPerState = maStateIdToAttributesMap.get(nStateId);
if (aAttributesPerState == null)
{
@@ -120,6 +122,8 @@ public class AttributeManager
aEntry[2],
aAttributesPerState);
aUsedAttributes.add(aAttributeDescriptor);
+ aValues.AddAttribute(aAttributeDescriptor, aEntry[2]);
+
if (Log.Dbg != null)
{
if (aAttributeDescriptor == null)
@@ -147,6 +151,8 @@ public class AttributeManager
}
}
}
+
+ return aValues;
}
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeValues.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeValues.java
new file mode 100644
index 0000000..0d21486
--- /dev/null
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/AttributeValues.java
@@ -0,0 +1,49 @@
+
+package org.apache.openoffice.ooxml.parser;
+
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+/** Container of attribute values of an opening tag.
+ */
+public class AttributeValues
+{
+ AttributeValues ()
+ {
+ maAttributes = new TreeMap<>();
+ }
+
+
+
+
+ public void AddAttribute (
+ final AttributeDescriptor aAttributeDescriptor,
+ final String sValue)
+ {
+ maAttributes.put(
+ aAttributeDescriptor.GetName(),
+ sValue);
+ }
+
+
+
+
+ public Iterable<Entry<String,Object>> GetAttributes ()
+ {
+ return maAttributes.entrySet();
+ }
+
+
+
+
+ public int GetAttributeCount ()
+ {
+ return maAttributes.size();
+ }
+
+
+
+
+ private Map<String,Object> maAttributes;
+}
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ElementContext.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ElementContext.java
new file mode 100644
index 0000000..04da341
--- /dev/null
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/ElementContext.java
@@ -0,0 +1,65 @@
+package org.apache.openoffice.ooxml.parser;
+
+/** Context that has the same life time (by default) as the element it represents.
+ * Gives access to the attribute values and the parent context.
+ */
+public class ElementContext
+{
+ ElementContext (
+ final String sElementName,
+ final String sTypeName,
+ final boolean bIsSkipping,
+ final AttributeValues aValues,
+ final ElementContext aParentContext)
+ {
+ msElementName = sElementName;
+ msTypeName = sTypeName;
+ mbIsSkipping = bIsSkipping;
+ maAttributeValues = aValues;
+ maParentContext = aParentContext;
+ }
+
+
+
+
+ public String GetElementName ()
+ {
+ return msElementName;
+ }
+
+
+
+
+ public String GetTypeName ()
+ {
+ return msTypeName;
+ }
+
+
+
+
+ public AttributeValues GetAttributes ()
+ {
+ return maAttributeValues;
+ }
+
+
+
+
+ /** Return the context of the parent element.
+ * Can be null when there is no parent element.
+ */
+ public ElementContext GetParentContext ()
+ {
+ return maParentContext;
+ }
+
+
+
+
+ private final String msElementName;
+ private final String msTypeName;
+ private final boolean mbIsSkipping;
+ private final AttributeValues maAttributeValues;
+ private final ElementContext maParentContext;
+}
diff --git a/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/IAction.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/IAction.java
new file mode 100644
index 0000000..61c5a04
--- /dev/null
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/IAction.java
@@ -0,0 +1,27 @@
+package org.apache.openoffice.ooxml.parser;
+
+import javax.xml.stream.Location;
+
+/** Interface for actions that are bound to states and triggered by XML events.
+ */
+public interface IAction
+{
+ /** Callback for a single XML event.
+ * @param eTrigger
+ * Equivalent to the XML event type.
+ * @param aContext
+ * The context of the element that was just entered (element start),
+ * is about to be left (element end) or is currently active (all other
+ * events).
+ * @param sText
+ * Contains text for ActionTrigger.Text. Is null for all other
+ * triggers.
+ * @param aLocation
+ * The location in the source file that triggered the XML event.
+ */
+ void Run (
+ final ActionTrigger eTrigger,
+ final ElementContext aContext,
+ final String sText,
+ final Location aLocation);
+}
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 fe4424d..f15d3f6 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
@@ -23,6 +23,7 @@ package org.apache.openoffice.ooxml.parser;
import java.util.HashMap;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Vector;
public class NameMap
@@ -78,6 +79,22 @@ public class NameMap
+ /** Return the ids of all states whose names match the given pattern.
+ */
+ public Vector<Integer> GetMatchingStateIds (final String sPattern)
+ {
+ final Vector<Integer> aStateIds = new Vector<>();
+ for (final Entry<String,Integer> aEntry : maNameToIdMap.entrySet())
+ {
+ if (aEntry.getKey().matches(sPattern))
+ aStateIds.add(aEntry.getValue());
+ }
+ return aStateIds;
+ }
+
+
+
+
private final Map<String,Integer> maNameToIdMap;
private final Vector<String> maIdToNameMap;
}
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 398ff58..e8df037 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
@@ -24,12 +24,13 @@ package org.apache.openoffice.ooxml.parser;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.Location;
/** This OOXML parser is based on the output of the schema parser.
* It exists to debug the schema parser and as illustration and preparation of
@@ -39,6 +40,10 @@ import javax.xml.stream.XMLStreamReader;
*/
public class OOXMLParser
{
+ class ActionContext
+ {
+ public Map<String,Integer> TypeCounts = new TreeMap<>();
+ }
/** The parser is called with two arguments:
* - A path to where the parser tables with the states and transitions can
* be found.
@@ -63,23 +68,40 @@ public class OOXMLParser
System.out.printf("writing no log data\n");
}
+ new OOXMLParser(aArgumentList[0], aArgumentList[1]);
+ }
+
+
+
+ private OOXMLParser (
+ final String sParseTableFilename,
+ final String sInputFilename)
+ {
long nStartTime = System.currentTimeMillis();
- final StateMachine aMachine = new StateMachine(new File(aArgumentList[0]));
- final InputStream aIn = GetInputStream(aArgumentList[1]);
- final XMLStreamReader aReader = GetStreamReader(aIn, aArgumentList[1]);
+ final StateMachine aMachine = new StateMachine(new File(sParseTableFilename));
+ final InputStream aIn = GetInputStream(sInputFilename);
long nEndTime = System.currentTimeMillis();
+
+ final ActionContext aActionContext = new ActionContext();
+ AddSomeActions(aMachine.GetActionManager(), aActionContext);
+
System.out.printf("initialzed parser in %fs\n", (nEndTime-nStartTime)/1000.0);
try
{
- if (aReader != null)
+ nStartTime = System.currentTimeMillis();
+ final Parser aParser = new Parser(aMachine, aIn);
+ aParser.Parse();
+ final int nElementCount = aParser.GetElementCount();
+ nEndTime = System.currentTimeMillis();
+ System.out.printf("parsed %d elements in %fs\n",
+ nElementCount,
+ (nEndTime-nStartTime)/1000.0);
+
+ System.out.printf("%d different elements found:\n", aActionContext.TypeCounts.size());
+ for (final Entry<String, Integer> aEntry : aActionContext.TypeCounts.entrySet())
{
- nStartTime = System.currentTimeMillis();
- final int nElementCount = Parse(aReader, aMachine);
- nEndTime = System.currentTimeMillis();
- System.out.printf("parsed %d elements in %fs\n",
- nElementCount,
- (nEndTime-nStartTime)/1000.0);
+ System.out.printf("%-32s : %6d\n", aEntry.getKey(), aEntry.getValue());
}
}
catch (final Exception aException)
@@ -91,6 +113,71 @@ public class OOXMLParser
+ private static void AddSomeActions (
+ final ActionManager aActionManager,
+ final ActionContext aActionContext)
+ {
+ aActionManager.AddElementStartAction(
+ "*",
+ new IAction()
+ {
+ @Override public void Run(
+ final ActionTrigger eTrigger,
+ final ElementContext aContext,
+ final String sText,
+ final Location aLocation)
+ {
+ Integer nValue = aActionContext.TypeCounts.get(aContext.GetTypeName());
+ if (nValue == null)
+ nValue = 1;
+ else
+ ++nValue;
+ aActionContext.TypeCounts.put(aContext.GetTypeName(), nValue);
+ }
+ }
+ );
+ aActionManager.AddElementStartAction(
+ ".*CT_Shd",
+ new IAction()
+ {
+ @Override public void Run(
+ final ActionTrigger eTrigger,
+ final ElementContext aContext,
+ final String sText,
+ final Location aLocation)
+ {
+ System.out.printf("processing %s of element %s at position %d\n",
+ eTrigger,
+ aContext.GetElementName(),
+ aLocation.getCharacterOffset());
+
+ if (aContext.GetAttributes().GetAttributeCount() == 0)
+ System.out.printf(" no attributes\n");
+ else
+ for (final Entry<String,Object> aAttribute : aContext.GetAttributes().GetAttributes())
+ System.out.printf(" %s -> %s\n", aAttribute.getKey(), aAttribute.getValue());
+ }
+ }
+ );
+ aActionManager.AddTextAction(
+ ".*CT_Text",
+ new IAction()
+ {
+ @Override public void Run(
+ final ActionTrigger eTrigger,
+ final ElementContext aContext,
+ final String sText,
+ final Location aLocation)
+ {
+ System.out.printf("%s text \"%s\"\n", aContext.GetTypeName(), sText.replace("\n", "\\n"));
+ }
+ }
+ );
+ }
+
+
+
+
private static InputStream GetInputStream (final String sInputName)
{
final InputStream aIn;
@@ -126,178 +213,4 @@ public class OOXMLParser
}
return aIn;
}
-
-
-
-
- private static XMLStreamReader GetStreamReader (
- final InputStream aIn,
- final String sDescription)
- {
- if (aIn == null)
- return null;
-
- try
- {
- final XMLInputFactory aFactory = (XMLInputFactory)XMLInputFactory.newInstance();
- aFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
- aFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
- aFactory.setProperty(XMLInputFactory.IS_COALESCING, false);
-
- return (XMLStreamReader)aFactory.createXMLStreamReader(
- sDescription,
- aIn);
- }
- catch (final Exception aException)
- {
- aException.printStackTrace();
- return null;
- }
- }
-
-
-
-
- private static int Parse (
- final XMLStreamReader aReader,
- final StateMachine aMachine)
- {
- int nElementCount = 0;
- try
- {
- final AttributeProvider aAttributeProvider = new AttributeProvider(aReader);
- while (aReader.hasNext())
- {
- final int nCode = aReader.next();
- switch(nCode)
- {
- case XMLStreamReader.START_ELEMENT:
- ++nElementCount;
- if (aMachine.IsInSkipState())
- {
- if (Log.Dbg != null)
- Log.Dbg.printf("is skip state -> starting to skip\n");
- nElementCount += Skip(aReader);
- }
- else if ( ! aMachine.ProcessStartElement(
- aReader.getNamespaceURI(),
- aReader.getLocalName(),
- aReader.getLocation(),
- aAttributeProvider))
- {
- if (Log.Dbg != null)
- Log.Dbg.printf("starting to skip to recover from error\n");
- nElementCount += Skip(aReader);
- }
- break;
-
- case XMLStreamReader.END_ELEMENT:
- aMachine.ProcessEndElement(
- aReader.getNamespaceURI(),
- aReader.getLocalName(),
- aReader.getLocation());
- break;
-
- case XMLStreamReader.CHARACTERS:
- final String sText = aReader.getText();
- if (Log.Dbg != null)
- Log.Dbg.printf("text [%s]\n", sText.replace("\n", "\\n"));
- aMachine.ProcessCharacters(sText);
- break;
-
- case XMLStreamReader.END_DOCUMENT:
- Log.Std.printf("--- end of document ---\n");
- break;
-
- default:
- Log.Err.printf("can't handle XML event of type %d\n", nCode);
- }
- }
-
- aReader.close();
- }
- catch (final XMLStreamException aException)
- {
- aException.printStackTrace();
- }
-
- return nElementCount;
- }
-
-
-
-
- private static int Skip (final XMLStreamReader aReader)
- {
- 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.
- int nRelativeDepth = 1;
- int nElementCount = 0;
- try
- {
- while (aReader.hasNext())
- {
- final int nCode = aReader.next();
- switch (nCode)
- {
- case XMLStreamReader.START_ELEMENT:
- ++nRelativeDepth;
- ++nElementCount;
- if (Log.Dbg != null)
- {
- Log.Dbg.printf("skipping start element %s\n", aReader.getLocalName());
- Log.Dbg.IncreaseIndentation();
- }
- break;
-
- case XMLStreamReader.END_ELEMENT:
- --nRelativeDepth;
- if (Log.Dbg != null)
- Log.Dbg.DecreaseIndentation();
- if (nRelativeDepth <= 0)
- {
- if (Log.Dbg != null)
- Log.Dbg.printf("leaving skip mode on %s\n", aReader.getLocalName());
- return nElementCount;
- }
- break;
-
- case XMLStreamReader.END_DOCUMENT:
- throw new RuntimeException("saw end of document while skipping elements\n");
-
- case XMLStreamReader.CHARACTERS:
- SkipText(aReader.getText());
- break;
-
- default:
- if (Log.Dbg != null)
- Log.Dbg.printf("%s\n", nCode);
- break;
- }
- }
- }
- catch (final XMLStreamException aException)
- {
- aException.printStackTrace();
- }
- return nElementCount;
- }
-
-
-
-
- private static void SkipText (final String sText)
- {
- 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/Parser.java b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/Parser.java
new file mode 100644
index 0000000..cd0883d
--- /dev/null
+++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/Parser.java
@@ -0,0 +1,203 @@
+package org.apache.openoffice.ooxml.parser;
+
+import java.io.InputStream;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+/** This is the actual parser (where OOXMLParser is the front end that handles
+ * parameters given to the main method).
+ */
+public class Parser
+{
+ public Parser (
+ final StateMachine aMachine,
+ final InputStream aIn)
+ {
+ maMachine = aMachine;
+ maReader = GetStreamReader(aIn, "input");
+ mnElementCount = 0;
+ }
+
+
+
+
+ void Parse ()
+ {
+ try
+ {
+ final AttributeProvider aAttributeProvider = new AttributeProvider(maReader);
+ while (maReader.hasNext())
+ {
+ final int nCode = maReader.next();
+ switch(nCode)
+ {
+ case XMLStreamReader.START_ELEMENT:
+ ++mnElementCount;
+ if (maMachine.IsInSkipState())
+ {
+ if (Log.Dbg != null)
+ Log.Dbg.printf("is skip state -> starting to skip\n");
+ Skip();
+ }
+ else if ( ! maMachine.ProcessStartElement(
+ maReader.getNamespaceURI(),
+ maReader.getLocalName(),
+ maReader.getLocation(),
+ aAttributeProvider))
+ {
+ if (Log.Dbg != null)
+ Log.Dbg.printf("starting to skip to recover from error\n");
+ Skip();
+ }
+ break;
+
+ case XMLStreamReader.END_ELEMENT:
+ maMachine.ProcessEndElement(
+ maReader.getNamespaceURI(),
+ maReader.getLocalName(),
+ maReader.getLocation());
+ break;
+
+ case XMLStreamReader.CHARACTERS:
+ maMachine.ProcessCharacters(
+ maReader.getText(),
+ maReader.getLocation());
+ break;
+
+ case XMLStreamReader.END_DOCUMENT:
+ Log.Std.printf("--- end of document ---\n");
+ break;
+
+ default:
+ Log.Err.printf("can't handle XML event of type %d\n", nCode);
+ }
+ }
+
+ maReader.close();
+ }
+ catch (final XMLStreamException aException)
+ {
+ aException.printStackTrace();
+ }
+ }
+
+
+
+
+ public int GetElementCount ()
+ {
+ return mnElementCount;
+ }
+
+
+
+
+ private void Skip ()
+ {
+ if (Log.Dbg != null)
+ {
+ Log.Dbg.printf("starting to skip on %s at L%dC%d\n",
+ maReader.getLocalName(),
+ maReader.getLocation().getLineNumber(),
+ maReader.getLocation().getColumnNumber());
+ Log.Dbg.IncreaseIndentation();
+ }
+
+ // We are called when processing a start element. This means that we are
+ // already at relative depth 1.
+ int nRelativeDepth = 1;
+ try
+ {
+ while (maReader.hasNext())
+ {
+ final int nCode = maReader.next();
+ switch (nCode)
+ {
+ case XMLStreamReader.START_ELEMENT:
+ ++nRelativeDepth;
+ ++mnElementCount;
+ if (Log.Dbg != null)
+ {
+ Log.Dbg.printf("skipping start element %s\n", maReader.getLocalName());
+ Log.Dbg.IncreaseIndentation();
+ }
+ break;
+
+ case XMLStreamReader.END_ELEMENT:
+ --nRelativeDepth;
+ if (Log.Dbg != null)
+ Log.Dbg.DecreaseIndentation();
+ if (nRelativeDepth <= 0)
+ {
+ if (Log.Dbg != null)
+ Log.Dbg.printf("leaving skip mode on %s\n", maReader.getLocalName());
+ return;
+ }
+ break;
+
+ case XMLStreamReader.END_DOCUMENT:
+ throw new RuntimeException("saw end of document while skipping elements\n");
+
+ case XMLStreamReader.CHARACTERS:
+ SkipText(maReader.getText());
+ break;
+
+ default:
+ if (Log.Dbg != null)
+ Log.Dbg.printf("%s\n", nCode);
+ break;
+ }
+ }
+ }
+ catch (final XMLStreamException aException)
+ {
+ aException.printStackTrace();
+ }
+ }
+
+
+
+
+ private void SkipText (final String sText)
+ {
+ if (Log.Dbg != null)
+ Log.Dbg.printf("skipping text [%s]\n", sText.replace("\n", "\\n"));
+ }
+
+
+
+
+ private XMLStreamReader GetStreamReader (
+ final InputStream aIn,
+ final String sDescription)
+ {
+ if (aIn == null)
+ return null;
+
+ try
+ {
+ final XMLInputFactory aFactory = (XMLInputFactory)XMLInputFactory.newInstance();
+ aFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
+ aFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
+ aFactory.setProperty(XMLInputFactory.IS_COALESCING, false);
+
+ return (XMLStreamReader)aFactory.createXMLStreamReader(
+ sDescription,
+ aIn);
+ }
+ catch (final Exception aException)
+ {
+ aException.printStackTrace();
+ return null;
+ }
+ }
+
+
+
+
+ private final XMLStreamReader maReader;
+ private final StateMachine maMachine;
+ private int mnElementCount;
+}
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 6b19977..c851b2c 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
@@ -47,20 +47,21 @@ public class StateMachine
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<>();
+ maElementContextStack = new Stack<>();
+ maActionManager = new ActionManager(maStateNameMap);
+
+ 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());
if (Log.Dbg != null)
Log.Dbg.printf("starting in state _start_ (%d)\n", mnCurrentStateId);
@@ -79,20 +80,20 @@ public class StateMachine
try
{
- final NamespaceMap.NamespaceDescriptor aDescriptor = maNamespaceMap.GetDescriptorForURI(sNamespaceURI);
+ final NamespaceMap.NamespaceDescriptor aNamespaceDescriptor = 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,
+ aNamespaceDescriptor.Prefix,
sElementName,
- aDescriptor.Id,
+ aNamespaceDescriptor.Id,
nElementNameId,
aLocation.getLineNumber(),
aLocation.getColumnNumber());
final Transition aTransition = maTransitions.GetTransition(
mnCurrentStateId,
- aDescriptor.Id,
+ aNamespaceDescriptor.Id,
nElementNameId);
if (aTransition == null)
{
@@ -100,7 +101,7 @@ public class StateMachine
"can not find transition for state %s(%d) and element %s(%d:%d) at L%dC%d\n",
maStateNameMap.GetNameForId(mnCurrentStateId),
mnCurrentStateId,
- aDescriptor.Id,
+ aNamespaceDescriptor.Id,
maNameMap.GetNameForId(nElementNameId),
nElementNameId,
aLocation.getLineNumber(),
@@ -123,10 +124,42 @@ public class StateMachine
Log.Dbg.printf("\n");
}
- final int nOldState = mnCurrentStateId;
- SetCurrentState(aTransition.GetEndStateId());
+ // Follow the transition to its end state but first process its
+ // content. We do that by
+
+ if (Log.Dbg != null)
+ Log.Dbg.IncreaseIndentation();
+
+ // a) pushing the end state to the state stack so that on the
+ // end tag that corresponds to the current start tag it will become the current state.
+ maStateStack.push(aTransition.GetEndStateId());
+
+ // b) entering the state that corresponds to start tag that
+ // we are currently processing.
+ mnCurrentStateId = aTransition.GetActionId();
+
+ // c) Prepare the attributes and store them in the new element context.
+ final AttributeValues aAttributeValues = maAttributeManager.ParseAttributes(
+ mnCurrentStateId,
+ aAttributes);
+
+ // d) creating a new ElementContext for the element that just starts.
+ maElementContextStack.push(maCurrentElementContext);
+ final ElementContext aPreviousElementContext = maCurrentElementContext;
+ maCurrentElementContext = new ElementContext(
+ sElementName,
+ maStateNameMap.GetNameForId(aTransition.GetActionId()),
+ false,
+ aAttributeValues,
+ aPreviousElementContext);
- ExecuteActions(aTransition, aAttributes, nOldState, mnCurrentStateId);
+ // e) and run all actions that are bound to the the current start tag.
+ ExecuteActions(
+ mnCurrentStateId,
+ maCurrentElementContext,
+ ActionTrigger.ElementStart,
+ null,
+ aLocation);
bResult = true;
}
@@ -161,8 +194,22 @@ public class StateMachine
final NamespaceMap.NamespaceDescriptor aDescriptor = maNamespaceMap.GetDescriptorForURI(sNamespaceURI);
- final int nOldStateId = mnCurrentStateId;
- SetCurrentState(maStateStack.pop());
+ // Leave the current element.
+
+ final int nPreviousStateId = mnCurrentStateId;
+ mnCurrentStateId = maStateStack.pop();
+ if (mnCurrentStateId == mnEndStateId)
+ mnCurrentStateId = mnStartStateId;
+
+ final ElementContext aPreviousElementContext = maCurrentElementContext;
+ maCurrentElementContext = maElementContextStack.pop();
+
+ ExecuteActions(
+ nPreviousStateId,
+ aPreviousElementContext,
+ ActionTrigger.ElementEnd,
+ null,
+ aLocation);
if (Log.Dbg != null)
{
@@ -173,8 +220,8 @@ public class StateMachine
aLocation.getLineNumber(),
aLocation.getColumnNumber());
Log.Dbg.printf(" %s(%d) <- %s(%d)\n",
- maStateNameMap.GetNameForId(nOldStateId),
- nOldStateId,
+ maStateNameMap.GetNameForId(nPreviousStateId),
+ nPreviousStateId,
maStateNameMap.GetNameForId(mnCurrentStateId),
mnCurrentStateId);
}
@@ -184,8 +231,19 @@ public class StateMachine
public void ProcessCharacters (
- final String sText)
+ final String sText,
+ final Location aLocation)
{
+ if (Log.Dbg != null)
+ Log.Dbg.printf("text [%s]\n", sText.replace("\n", "\\n"));
+
+ ExecuteActions(
+ mnCurrentStateId,
+ maCurrentElementContext,
+ ActionTrigger.Text,
+ sText,
+ aLocation);
+
}
@@ -199,34 +257,25 @@ public class StateMachine
- private void SetCurrentState (final int nState)
+ public ActionManager GetActionManager ()
{
- if (mnCurrentStateId != nState)
- {
- if (nState == mnEndStateId)
- mnCurrentStateId = mnStartStateId;
- else
- mnCurrentStateId = nState;
- }
+ return maActionManager;
}
private void ExecuteActions (
- final Transition aTransition,
- final AttributeProvider aAttributes,
- final int nOldState,
- final int nNewState)
+ final int nStateId,
+ final ElementContext aElementContext,
+ final ActionTrigger eTrigger,
+ final String sText,
+ final Location aLocation)
{
- maStateStack.push(mnCurrentStateId);
- if (Log.Dbg != null)
- Log.Dbg.IncreaseIndentation();
- final int nActionId = aTransition.GetActionId();
- SetCurrentState(nActionId);
- maAttributeManager.ParseAttributes(
- nActionId,
- aAttributes);
+ final Iterable<IAction> aActions = maActionManager.GetActions(nStateId, eTrigger);
+ if (aActions != null)
+ for (final IAction aAction : aActions)
+ aAction.Run(eTrigger, aElementContext, sText, aLocation);
}
@@ -239,8 +288,11 @@ public class StateMachine
private final AttributeManager maAttributeManager;
private int mnCurrentStateId;
private Stack<Integer> maStateStack;
+ private ElementContext maCurrentElementContext;
+ private Stack<ElementContext> maElementContextStack;
private final int mnStartStateId;
private final int mnEndStateId;
private SkipStateTable maSkipStates;
private AcceptingStateTable maAcceptingStates;
+ private final ActionManager maActionManager;
}
More information about the Libreoffice-commits
mailing list