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