diff options
author | Armin Le Grand <alg@apache.org> | 2014-07-14 19:09:11 +0000 |
---|---|---|
committer | Armin Le Grand <alg@apache.org> | 2014-07-14 19:09:11 +0000 |
commit | 3c1d4742e649fe9c8aed8c2817fe3e1f3364f298 (patch) | |
tree | e0c6e02c89aa9227726c9469da1001b3e29c41df /ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/StateMachine.java | |
parent | c5c31e2aeaedbdf76e1f38d3c385e34f5ed875ca (diff) |
Resync to trunk, windows non-pro buildaoo/aw080
Diffstat (limited to 'ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/StateMachine.java')
-rw-r--r-- | ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/StateMachine.java | 330 |
1 files changed, 330 insertions, 0 deletions
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 new file mode 100644 index 000000000000..39ff4dfd8137 --- /dev/null +++ b/ooxml/source/framework/JavaOOXMLParser/src/org/apache/openoffice/ooxml/parser/StateMachine.java @@ -0,0 +1,330 @@ +/************************************************************** +* +* 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.parser; + +import java.io.File; +import java.util.Stack; +import java.util.Vector; + +import javax.xml.stream.Location; + +import org.apache.openoffice.ooxml.parser.action.ActionManager; +import org.apache.openoffice.ooxml.parser.action.ActionTrigger; +import org.apache.openoffice.ooxml.parser.action.IAction; +import org.apache.openoffice.ooxml.parser.attribute.AttributeManager; +import org.apache.openoffice.ooxml.parser.attribute.AttributeProvider; +import org.apache.openoffice.ooxml.parser.attribute.AttributeValues; +import org.apache.openoffice.ooxml.parser.type.SimpleTypeManager; + +/** The state machine is initialized at creation from the data tables + * created previously by a stack automaton. + */ +public class StateMachine +{ + public StateMachine ( + final File aParseTableFile, + final Vector<String> aErrorsAndWarnings) + { + 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")); + 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")); + maAttributeValueMap = new NameMap(aReader.GetSection("attribute-value")); + maAcceptingStates = new AcceptingStateTable(aReader.GetSection("accepting-state")); + maSimpleTypeManager = new SimpleTypeManager( + aReader.GetSection("simple-type"), + maAttributeValueMap); + maAttributeManager = new AttributeManager( + aReader.GetSection("attribute"), + maNamespaceMap, + maNameMap, + maStateNameMap, + maSimpleTypeManager, + aErrorsAndWarnings); + 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); + maErrorsAndWarnings = aErrorsAndWarnings; + + if (Log.Dbg != null) + { + Log.Dbg.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()); + Log.Dbg.printf("starting in state _start_ (%d)\n", mnCurrentStateId); + } + } + + + + + public boolean ProcessStartElement ( + final String sNamespaceURI, + final String sElementName, + final Location aStartLocation, + final Location aEndLocation, + final AttributeProvider aAttributes) + { + boolean bResult = false; + + try + { + 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", + aNamespaceDescriptor.Prefix, + sElementName, + aNamespaceDescriptor.Id, + nElementNameId, + aStartLocation.getLineNumber(), + aStartLocation.getColumnNumber()); + + final Transition aTransition = maTransitions.GetTransition( + mnCurrentStateId, + aNamespaceDescriptor.Id, + nElementNameId); + if (aTransition == null) + { + final String sText = String.format( + "can not find transition for state %s(%d) and element %s:%s(%d:%d) at L%dC%d\n", + maStateNameMap.GetNameForId(mnCurrentStateId), + mnCurrentStateId, + aNamespaceDescriptor.Prefix, + maNameMap.GetNameForId(nElementNameId), + aNamespaceDescriptor.Id, + nElementNameId, + aStartLocation.getLineNumber(), + aStartLocation.getColumnNumber()); + Log.Err.printf(sText); + if (Log.Dbg != null) + Log.Dbg.printf(sText); + } + else + { + 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"); + } + + // 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); + + // e) and run all actions that are bound to the the current start tag. + ExecuteActions( + mnCurrentStateId, + maCurrentElementContext, + ActionTrigger.ElementStart, + null, + aStartLocation, + aEndLocation); + + bResult = true; + } + } + catch (RuntimeException aException) + { + Log.Err.printf("error at line %d and column %d\n", + aStartLocation.getLineNumber(), + aStartLocation.getColumnNumber()); + throw aException; + } + return bResult; + } + + + + + public void ProcessEndElement ( + final String sNamespaceURI, + final String sElementName, + final Location aStartLocation, + final Location aEndLocation) + { + if ( ! maAcceptingStates.Contains(mnCurrentStateId) + && mnCurrentStateId!=-1) + { + 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 NamespaceMap.NamespaceDescriptor aDescriptor = maNamespaceMap.GetDescriptorForURI(sNamespaceURI); + + // 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, + aStartLocation, + aEndLocation); + + if (Log.Dbg != null) + { + Log.Dbg.DecreaseIndentation(); + Log.Dbg.printf("/%s:%s L%d%d\n", + aDescriptor.Prefix, + sElementName, + aStartLocation.getLineNumber(), + aStartLocation.getColumnNumber()); + Log.Dbg.printf(" %s(%d) <- %s(%d)\n", + maStateNameMap.GetNameForId(nPreviousStateId), + nPreviousStateId, + maStateNameMap.GetNameForId(mnCurrentStateId), + mnCurrentStateId); + } + } + + + + + public void ProcessCharacters ( + final String sText, + final Location aStartLocation, + final Location aEndLocation) + { + if (Log.Dbg != null) + Log.Dbg.printf("text [%s]\n", sText.replace("\n", "\\n")); + + ExecuteActions( + mnCurrentStateId, + maCurrentElementContext, + ActionTrigger.Text, + sText, + aStartLocation, + aEndLocation); + + } + + + + + public boolean IsInSkipState () + { + return maSkipStates.Contains(mnCurrentStateId); + } + + + + + public ActionManager GetActionManager () + { + return maActionManager; + } + + + + + private void ExecuteActions ( + final int nStateId, + final ElementContext aElementContext, + final ActionTrigger eTrigger, + final String sText, + final Location aStartLocation, + final Location aEndLocation) + { + final Iterable<IAction> aActions = maActionManager.GetActions(nStateId, eTrigger); + if (aActions != null) + for (final IAction aAction : aActions) + aAction.Run(eTrigger, aElementContext, sText, aStartLocation, aEndLocation); + } + + + + + private final NamespaceMap maNamespaceMap; + private final NameMap maNameMap; + private final NameMap maStateNameMap; + private final TransitionTable maTransitions; + private final SimpleTypeManager maSimpleTypeManager; + private final AttributeManager maAttributeManager; + private final NameMap maAttributeValueMap; + 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; + private final Vector<String> maErrorsAndWarnings; +} |