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