blob: 91e628874d904ac21e838d30b09ca928d9fe087f [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.netbeans.modules.xml.axi.impl;
import java.util.List;
import org.netbeans.modules.xml.axi.AXIComponent;
import org.netbeans.modules.xml.axi.AXIDocument;
import org.netbeans.modules.xml.axi.ContentModel;
import org.netbeans.modules.xml.axi.SchemaReference;
import org.netbeans.modules.xml.schema.model.*;
import org.netbeans.modules.xml.xam.dom.NamedComponentReference;
/**
* Creates and populates children for a parent AXIComponent.
* Parent AXIComponent must first construct a AXIModelBuilder and then
* call its populateChildren method to populate the list of children.
*
* This is a visitor, which visits each node in the schema model tree
* to construct the AXI model.
*
* @author Samaresh (Samaresh.Panda@Sun.Com)
*/
public class AXIModelBuilder extends AbstractModelBuilder {
/**
* Creates a new instance of AXIModelBuilder
*/
public AXIModelBuilder(AXIComponent parent) {
super((AXIModelImpl)parent.getModel());
this.parent = parent;
}
/**
* Populates the children list for the specified schema component.
* @param schemaComponent the component, for which, children and attribute
* lists are to be populated.
* @param visitChildren in general, this should be true, except when this is
* being called for an Element's type. Purely to keep the type tree in the sharedPool.
* @children children to be populated.
* @attributes attributes to be populated.
*/
public void populateChildren(SchemaComponent schemaComponent,
boolean visitChildren, List<AXIComponent> children) {
this.children = children;
//For an Element's type (if global), we want to visit the
//type so that it gets stored in the shared pool.
if(!visitChildren) {
schemaComponent.accept(this);
return;
}
//visit all children
for(SchemaComponent child : schemaComponent.getChildren()) {
child.accept(this);
}
}
/**
* Visit Schema.
*/
public void visit(Schema schema) {
}
/**
* Visit AnyElement.
*/
public void visit(org.netbeans.modules.xml.schema.model.AnyElement schemaComponent) {
AXIComponent child = getAXIComponent(schemaComponent, false);
addChild(child);
}
/**
* Visit AnyAttribute.
*/
public void visit(AnyAttribute schemaComponent) {
AXIComponent child = getAXIComponent(schemaComponent, false);
addChild(child);
}
/**
* Visit GlobalElement.
*/
public void visit(GlobalElement component) {
AXIComponent child = getAXIComponent(component, true);
addChild(child);
}
/**
* Visit LocalElement.
*/
public void visit(LocalElement component) {
AXIComponent child = getAXIComponent(component, false);
addChild(child);
}
/**
* Visit ElementReference.
*/
public void visit(ElementReference component) {
AXIComponent child = getAXIComponent(component, false);
addChild(child);
}
/**
* Visit GlobalAttribute.
*/
public void visit(GlobalAttribute component) {
AXIComponent child = getAXIComponent(component, true);
addChild(child);
}
/**
* Visit LocalAttribute.
*/
public void visit(LocalAttribute component) {
AXIComponent child = getAXIComponent(component, false);
addChild(child);
}
/**
* Visit AttributeReference.
*/
public void visit(AttributeReference component) {
AXIComponent child = getAXIComponent(component, false);
addChild(child);
}
/**
* Visit Sequence.
*/
public void visit(Sequence component) {
AXIComponent child = getAXIComponent(component, false);
addChild(child);
}
/**
* Visit Choice.
*/
public void visit(Choice component) {
AXIComponent child = getAXIComponent(component, false);
addChild(child);
}
/**
* Visit All.
*/
public void visit(All component) {
AXIComponent child = getAXIComponent(component, false);
addChild(child);
}
/**
* Visit GlobalGroup.
*/
public void visit(GlobalGroup component) {
AXIComponent child = getAXIComponent(component, true);
addChild(child);
}
/**
* Visit GroupReference.
*/
public void visit(GroupReference component) {
NamedComponentReference ref = component.getRef();
if(ref == null)
return;
SchemaComponent sc = model.getReferenceableSchemaComponent(ref);
if(sc == null)
return;
AXIComponent child = getAXIComponent(sc, true);
addChild(child);
}
/**
* Visit GlobalAttributeGroup.
*/
public void visit(GlobalAttributeGroup component) {
AXIComponent child = getAXIComponent(component, true);
addChild(child);
}
/**
* Visit AttributeGroupReference.
*/
public void visit(AttributeGroupReference component) {
NamedComponentReference ref = component.getGroup();
if(ref == null)
return;
SchemaComponent sc = model.getReferenceableSchemaComponent(ref);
if(sc == null)
return;
AXIComponent child = getAXIComponent(sc, true);
addChild(child);
}
/**
* Visit GlobalComplexType.
*/
public void visit(GlobalComplexType component) {
AXIComponent child = getAXIComponent(component, true);
addChild(child);
}
/**
* Visit LocalComplexType.
*/
public void visit(LocalComplexType component) {
visitChildren(component);
}
/**
* Visit ComplexContent.
*/
public void visit(ComplexContent component) {
visitChildren(component);
}
/**
* Visit SimpleContent.
*/
public void visit(SimpleContent component) {
visitChildren(component);
}
/**
* Visit ComplexExtension.
*/
public void visit(SimpleExtension component) {
NamedComponentReference ref = component.getBase();
if(ref != null) {
SchemaComponent type = model.getReferenceableSchemaComponent(ref);
if(type != null) {
AXIComponent child = getAXIComponent(type, true);
addChild(child);
}
}
visitChildren(component);
}
/**
* Visit ComplexExtension.
*/
public void visit(ComplexExtension component) {
NamedComponentReference ref = component.getBase();
if(ref != null) {
SchemaComponent type = model.getReferenceableSchemaComponent(ref);
if(type != null) {
AXIComponent child = getAXIComponent(type, true);
addChild(child);
}
}
visitChildren(component);
}
@Override
public void visit(Include include) {
SchemaReference ref = model.getComponentFactory().createSchemaReference(include);
addChild(ref);
visitChildren(include);
}
@Override
public void visit(Import im) {
SchemaReference ref = model.getComponentFactory().createSchemaReference(im);
addChild(ref);
visitChildren(im);
}
/**
* Returns an AXIComponent if one exists or creates one.
*
* When this method gets called with a global component, it looks up the model
* and returns the global AXI component, unless the parent is AXIDocument.
*
* For local components, it always creates one.
*/
private AXIComponent getAXIComponent(final SchemaComponent schemaComponent, boolean isGlobal) {
//when parent is schema or for non-global components,
//always create one.
if(parent instanceof AXIDocument || !isGlobal) {
return new AXIComponentCreator(getModel()).
createNew(schemaComponent);
}
if(!getModel().fromSameSchemaModel(schemaComponent)) {
return getModel().lookupFromOtherModel(schemaComponent);
}
return getModel().lookup(schemaComponent);
}
/**
* Adds the new component to the children list.
*/
private void addChild(AXIComponent child) {
if(child == null)
return;
if(parent instanceof AXIDocument) {
children.add(child);
((AXIDocumentImpl)parent).addToCache(child);
return;
}
if(child instanceof ContentModel) {
Util.addProxyChildren(parent, child, children);
return;
}
children.add(child);
}
////////////////////////////////////////////////////////////////////
////////////////////////// member variables ////////////////////////
////////////////////////////////////////////////////////////////////
/**
* Parent AXIComponent for whom, children are being populated.
*/
private AXIComponent parent;
/**
* Ref to the original children list being passed by the caller.
*/
private List<AXIComponent> children;
}