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.model.optimize; 23 24 import java.util.HashSet; 25 import java.util.LinkedList; 26 import java.util.Queue; 27 import java.util.Set; 28 29 import org.apache.openoffice.ooxml.schema.iterator.AttributeNodeIterator; 30 import org.apache.openoffice.ooxml.schema.iterator.DereferencingNodeIterator; 31 import org.apache.openoffice.ooxml.schema.model.base.INode; 32 import org.apache.openoffice.ooxml.schema.model.base.INodeVisitor; 33 import org.apache.openoffice.ooxml.schema.model.base.Node; 34 import org.apache.openoffice.ooxml.schema.model.base.NodeType; 35 import org.apache.openoffice.ooxml.schema.model.base.QualifiedName; 36 import org.apache.openoffice.ooxml.schema.model.complex.Element; 37 import org.apache.openoffice.ooxml.schema.model.schema.SchemaBase; 38 39 /** Optimize the given schema base by creating a new one and adding only those 40 * complex types, simple types, groups, attributes and attribute groups, that 41 * are really used, i.e. used by one of the top level elements or by a type or 42 * group that is in use. 43 */ 44 public class SchemaOptimizer 45 { SchemaOptimizer( final SchemaBase aOriginalSchemaBase)46 public SchemaOptimizer ( 47 final SchemaBase aOriginalSchemaBase) 48 { 49 maOriginalSchemaBase = aOriginalSchemaBase; 50 maOptimizedSchemaBase = new SchemaBase(); 51 maTodoList = new LinkedList<>(); 52 maProcessedTypes = new HashSet<>(); 53 } 54 55 56 57 Run()58 public SchemaBase Run () 59 { 60 // Seed the work list with the top-level elements. 61 for (final Element aElement : maOriginalSchemaBase.TopLevelElements.GetUnsorted()) 62 { 63 maOptimizedSchemaBase.TopLevelElements.Add(aElement); 64 RequestType(aElement.GetTypeName()); 65 } 66 67 final INodeVisitor aCopyVisitor = new CopyVisitor( 68 maOriginalSchemaBase, 69 maOptimizedSchemaBase); 70 final INodeVisitor aRequestVisitor = new RequestVisitor( 71 maOriginalSchemaBase, 72 this); 73 74 while ( ! maTodoList.isEmpty()) 75 { 76 final INode aNode = maTodoList.poll(); 77 78 // Iterate over all child nodes and attributes. 79 for (final INode aChild : new DereferencingNodeIterator(aNode, maOriginalSchemaBase, true)) 80 { 81 aChild.AcceptVisitor(aCopyVisitor); 82 aChild.AcceptVisitor(aRequestVisitor); 83 for (final INode aAttribute : aChild.GetAttributes()) 84 aAttribute.AcceptVisitor(aCopyVisitor); 85 for (final INode aAttribute : new AttributeNodeIterator(aChild, maOriginalSchemaBase)) 86 aAttribute.AcceptVisitor(aRequestVisitor); 87 } 88 89 // Request used namespaces. 90 final QualifiedName aName = aNode.GetName(); 91 if (aName != null) 92 maOptimizedSchemaBase.Namespaces.ProvideNamespace(aName.GetNamespaceURI(), aName.GetNamespacePrefix()); 93 } 94 95 /* 96 System.out.printf("%d original attributes\n", maOriginalSchemaBase.Attributes.GetCount()); 97 for (final Attribute aAttribute : maOriginalSchemaBase.Attributes.GetUnsorted()) 98 System.out.printf("%s\n", aAttribute); 99 System.out.printf("%d optimized attributes\n", maOptimizedSchemaBase.Attributes.GetCount()); 100 for (final Attribute aAttribute : maOptimizedSchemaBase.Attributes.GetUnsorted()) 101 System.out.printf("%s\n", aAttribute); 102 */ 103 104 return maOptimizedSchemaBase; 105 } 106 107 108 109 RequestType(final QualifiedName aName)110 void RequestType (final QualifiedName aName) 111 { 112 final Node aNode = maOriginalSchemaBase.GetTypeForName(aName); 113 if (aNode == null) 114 throw new RuntimeException("there is no type named '"+aName+"' in the schema"); 115 else 116 RequestType(aNode); 117 } 118 119 120 121 RequestType(final INode aNode)122 void RequestType (final INode aNode) 123 { 124 if (aNode.GetNodeType() == NodeType.SimpleTypeReference) 125 System.out.println(aNode); 126 if ( ! maProcessedTypes.contains(aNode)) 127 { 128 maProcessedTypes.add(aNode); 129 maTodoList.add(aNode); 130 } 131 } 132 133 134 135 136 private final SchemaBase maOriginalSchemaBase; 137 private final SchemaBase maOptimizedSchemaBase; 138 private final Queue<INode> maTodoList; 139 private final Set<INode> maProcessedTypes; 140 } 141