blob: 5fec411ef87ec1e06f4b17b2841ad1108158ac6d [file] [log] [blame]
/**************************************************************
*
* 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.schema.model.optimize;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import org.apache.openoffice.ooxml.schema.iterator.AttributeNodeIterator;
import org.apache.openoffice.ooxml.schema.iterator.DereferencingNodeIterator;
import org.apache.openoffice.ooxml.schema.model.base.INode;
import org.apache.openoffice.ooxml.schema.model.base.INodeVisitor;
import org.apache.openoffice.ooxml.schema.model.base.Node;
import org.apache.openoffice.ooxml.schema.model.base.NodeType;
import org.apache.openoffice.ooxml.schema.model.base.QualifiedName;
import org.apache.openoffice.ooxml.schema.model.complex.Element;
import org.apache.openoffice.ooxml.schema.model.schema.SchemaBase;
/** Optimize the given schema base by creating a new one and adding only those
* complex types, simple types, groups, attributes and attribute groups, that
* are really used, i.e. used by one of the top level elements or by a type or
* group that is in use.
*/
public class SchemaOptimizer
{
public SchemaOptimizer (
final SchemaBase aOriginalSchemaBase)
{
maOriginalSchemaBase = aOriginalSchemaBase;
maOptimizedSchemaBase = new SchemaBase();
maTodoList = new LinkedList<>();
maProcessedTypes = new HashSet<>();
}
public SchemaBase Run ()
{
// Seed the work list with the top-level elements.
for (final Element aElement : maOriginalSchemaBase.TopLevelElements.GetUnsorted())
{
maOptimizedSchemaBase.TopLevelElements.Add(aElement);
RequestType(aElement.GetTypeName());
}
final INodeVisitor aCopyVisitor = new CopyVisitor(
maOriginalSchemaBase,
maOptimizedSchemaBase);
final INodeVisitor aRequestVisitor = new RequestVisitor(
maOriginalSchemaBase,
this);
while ( ! maTodoList.isEmpty())
{
final INode aNode = maTodoList.poll();
// Iterate over all child nodes and attributes.
for (final INode aChild : new DereferencingNodeIterator(aNode, maOriginalSchemaBase, true))
{
aChild.AcceptVisitor(aCopyVisitor);
aChild.AcceptVisitor(aRequestVisitor);
for (final INode aAttribute : aChild.GetAttributes())
aAttribute.AcceptVisitor(aCopyVisitor);
for (final INode aAttribute : new AttributeNodeIterator(aChild, maOriginalSchemaBase))
aAttribute.AcceptVisitor(aRequestVisitor);
}
// Request used namespaces.
final QualifiedName aName = aNode.GetName();
if (aName != null)
maOptimizedSchemaBase.Namespaces.ProvideNamespace(aName.GetNamespaceURI(), aName.GetNamespacePrefix());
}
/*
System.out.printf("%d original attributes\n", maOriginalSchemaBase.Attributes.GetCount());
for (final Attribute aAttribute : maOriginalSchemaBase.Attributes.GetUnsorted())
System.out.printf("%s\n", aAttribute);
System.out.printf("%d optimized attributes\n", maOptimizedSchemaBase.Attributes.GetCount());
for (final Attribute aAttribute : maOptimizedSchemaBase.Attributes.GetUnsorted())
System.out.printf("%s\n", aAttribute);
*/
return maOptimizedSchemaBase;
}
void RequestType (final QualifiedName aName)
{
final Node aNode = maOriginalSchemaBase.GetTypeForName(aName);
if (aNode == null)
throw new RuntimeException("there is no type named '"+aName+"' in the schema");
else
RequestType(aNode);
}
void RequestType (final INode aNode)
{
if (aNode.GetNodeType() == NodeType.SimpleTypeReference)
System.out.println(aNode);
if ( ! maProcessedTypes.contains(aNode))
{
maProcessedTypes.add(aNode);
maTodoList.add(aNode);
}
}
private final SchemaBase maOriginalSchemaBase;
private final SchemaBase maOptimizedSchemaBase;
private final Queue<INode> maTodoList;
private final Set<INode> maProcessedTypes;
}