1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements.  See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership.  The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License.  You may obtain a copy of the License at
10 *
11 *   http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied.  See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21 
22 package org.apache.openoffice.ooxml.schema.automaton;
23 
24 import java.io.File;
25 import java.util.Vector;
26 
27 import org.apache.openoffice.ooxml.schema.iterator.DereferencingNodeIterator;
28 import org.apache.openoffice.ooxml.schema.model.base.INode;
29 import org.apache.openoffice.ooxml.schema.model.base.NodeType;
30 import org.apache.openoffice.ooxml.schema.model.complex.Any;
31 import org.apache.openoffice.ooxml.schema.model.complex.ComplexType;
32 import org.apache.openoffice.ooxml.schema.model.complex.Element;
33 import org.apache.openoffice.ooxml.schema.model.schema.Schema;
34 import org.apache.openoffice.ooxml.schema.model.schema.SchemaBase;
35 
36 /** Create a set of stack automatons for a given set of schemas.
37  *  Creates one automaton for each complex type and one for the top level elements.
38  *
39  *  Input files but are not validated to conform to the schemas.
40  */
41 public class NonValidatingCreator
42     extends CreatorBase
43 {
NonValidatingCreator( final SchemaBase aSchemaBase, final File aLogFile)44     public NonValidatingCreator (
45         final SchemaBase aSchemaBase,
46         final File aLogFile)
47     {
48         super(aSchemaBase, aLogFile);
49     }
50 
51 
52 
53 
Create( final Iterable<Schema> aTopLevelSchemas)54     public FiniteAutomatonContainer Create (
55         final Iterable<Schema> aTopLevelSchemas)
56     {
57         final FiniteAutomatonContainer aAutomatons = new FiniteAutomatonContainer(maStateContainer);
58 
59         // Create a single automaton for all top level elements.
60         aAutomatons.AddAutomaton(
61             null,
62             CreateForTopLevelElements(aTopLevelSchemas));
63 
64         // Create one automaton for each complex type.
65         for (final ComplexType aComplexType : maSchemaBase.ComplexTypes.GetSorted())
66             aAutomatons.AddAutomaton(
67                 aComplexType.GetName(),
68                 CreateForComplexType(aComplexType));
69 
70         // Create one automaton for each simple type that is referenced by an element.
71         for (final INode aSimpleType : maElementSimpleTypes)
72             aAutomatons.AddAutomaton(
73                 aSimpleType.GetName(),
74                 CreateForSimpleType(aSimpleType));
75 
76         maLog.Close();
77 
78         return aAutomatons;
79     }
80 
81 
82 
83 
CreateForTopLevelElements( final Iterable<Schema> aTopLevelSchemas)84     private FiniteAutomaton CreateForTopLevelElements (
85         final Iterable<Schema> aTopLevelSchemas)
86     {
87         maLog.AddComment("top level elements");
88         maLog.StartBlock();
89         final String sTypeName = "<top-level>";
90         final StateContext aStateContext = new StateContext(
91             maStateContainer,
92             sTypeName);
93         final State aStartState = aStateContext.GetStartState();
94         final State aEndState = aStateContext.CreateEndState();
95 
96         // top level elements
97         for (final Schema aSchema : aTopLevelSchemas)
98         {
99             maLog.AddComment("schema %s", aSchema.GetShortName());
100             maLog.StartBlock();
101             for (final Element aElement : aSchema.TopLevelElements.GetSorted())
102             {
103                 maLog.AddComment("Element: on '%s' go from %s to %s via %s",
104                     aElement.GetElementName().GetDisplayName(),
105                     aStartState.GetFullname(),
106                     aEndState.GetFullname(),
107                     aElement.GetTypeName().GetStateName());
108 
109                 aStateContext.GetStartState().AddTransition(
110                     new Transition(
111                         aStartState,
112                         aEndState,
113                         aElement.GetElementName(),
114                         aElement.GetTypeName().GetStateName()));
115             }
116             maLog.EndBlock();
117         }
118         maLog.EndBlock();
119 
120         return new FiniteAutomaton(aStateContext, null, null);
121     }
122 
123 
124 
125 
CreateForComplexType(final ComplexType aComplexType)126     private FiniteAutomaton CreateForComplexType (final ComplexType aComplexType)
127     {
128         maLog.printf("\n");
129         maLog.AddComment ("Complex Type %s defined in %s.",
130             aComplexType.GetName().GetDisplayName(),
131             aComplexType.GetLocation());
132         maLog.StartBlock();
133 
134         final StateContext aStateContext = new StateContext(
135             maStateContainer,
136             aComplexType.GetName().GetStateName());
137 
138         for (final Element aElement : CollectElements(aComplexType))
139         {
140             maLog.AddComment("Element: on '%s' go from %s to %s via %s",
141                 aElement.GetElementName().GetDisplayName(),
142                 aStateContext.GetStartState().GetFullname(),
143                 aStateContext.GetStartState().GetFullname(),
144                 aElement.GetTypeName().GetStateName());
145 
146             aStateContext.GetStartState().AddTransition(
147                 new Transition(
148                     aStateContext.GetStartState(),
149                     aStateContext.GetStartState(),
150                     aElement.GetElementName(),
151                     aElement.GetTypeName().GetStateName()));
152 
153             // For elements whose type is a simple type we have to remember that
154             // simple type for later (and then create an NFA for it.)
155             final INode aSimpleType = maSchemaBase.GetSimpleTypeForName(
156                 aElement.GetTypeName());
157             if (aSimpleType != null)
158                 maElementSimpleTypes.add(aSimpleType);
159         }
160 
161         for (final Any aAny : CollectAnys(aComplexType))
162         {
163             AddSkipTransition(
164                 aStateContext.GetStartState(),
165                 new SkipData(
166                     aAny.GetProcessContentsFlag(),
167                     aAny.GetNamespaces()));
168         }
169 
170         // Collect all attributes.
171         maAttributes = new Vector<>();
172         for (final INode aNode : new DereferencingNodeIterator(aComplexType, maSchemaBase, true))
173             ProcessAttributes(aNode);
174 
175         aStateContext.GetStartState().SetIsAccepting();
176 
177         maLog.EndBlock();
178 
179         return new FiniteAutomaton(aStateContext, maAttributes, aComplexType.GetLocation());
180     }
181 
182 
183 
184 
185     /** Collect all elements inside the type tree that is rooted in the given
186      *  complex type.
187      */
CollectElements(final ComplexType aType)188     private Vector<Element> CollectElements (final ComplexType aType)
189     {
190         final Vector<Element> aElements = new Vector<>();
191         for (final INode aNode : new DereferencingNodeIterator(aType, maSchemaBase, false))
192         {
193             if (aNode.GetNodeType() == NodeType.Element)
194                 aElements.add((Element)aNode);
195         }
196         return aElements;
197     }
198 
199 
200 
201 
CollectAnys(final ComplexType aType)202     private Vector<Any> CollectAnys (final ComplexType aType)
203     {
204         final Vector<Any> aAnys = new Vector<>();
205         for (final INode aNode : new DereferencingNodeIterator(aType, maSchemaBase, false))
206         {
207             if (aNode.GetNodeType() == NodeType.Any)
208                 aAnys.add((Any)aNode);
209         }
210         return aAnys;
211     }
212 }
213