blob: 2392213edf0d07376e5935f725e209b3403213e0 [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.io.IOException;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Map.Entry;
import org.netbeans.modules.xml.axi.datatype.CustomDatatype;
import org.netbeans.modules.xml.schema.model.*;
import org.netbeans.modules.xml.xam.dom.NamedComponentReference;
import org.netbeans.modules.xml.axi.*;
import org.netbeans.modules.xml.axi.AXIDocument;
import org.netbeans.modules.xml.axi.AXIModel;
import org.netbeans.modules.xml.axi.AXIModelFactory;
import org.netbeans.modules.xml.axi.AXIType;
import org.netbeans.modules.xml.axi.AbstractAttribute;
import org.netbeans.modules.xml.axi.AbstractElement;
import org.netbeans.modules.xml.axi.Attribute;
import org.netbeans.modules.xml.axi.Compositor;
import org.netbeans.modules.xml.axi.ContentModel;
import org.netbeans.modules.xml.axi.Element;
import org.netbeans.modules.xml.axi.SchemaGenerator;
import org.netbeans.modules.xml.axi.SchemaGenerator.PrimitiveCart;
import org.netbeans.modules.xml.axi.SchemaGenerator.UniqueId;
import org.netbeans.modules.xml.axi.datatype.Datatype;
import org.netbeans.modules.xml.axi.visitor.AXINonCyclicVisitor;
/**
*
* @author Ayub Khan
*/
public abstract class DefaultSchemaGenerator extends SchemaGenerator {
protected AXIModel am;
protected SchemaModel sm;
protected SchemaGenerator.UniqueId id;
protected SchemaGenerator.PrimitiveCart pc;
java.util.List<AXIComponent> path = new ArrayList<AXIComponent>();
protected SchemaComponent sc;
protected SchemaComponent scParent;
protected SchemaComponent datatypeParent;
protected SortedMap<Integer, java.util.List<Object>> fixNamesMap = null;
protected java.util.List<SchemaComponent> createGlobals = null;
protected HashMap<SchemaComponent, SchemaComponent> refMap = null;
protected HashMap<Class, HashMap<String, SchemaComponent>> namesMap = null;
protected java.util.List<Element> elementReuseList = null;
protected SchemaGeneratorHelper sgh;
private int fgeCount;
public static final int commitRange = Integer.getInteger("schematools.axi.adp", 0);
/**
* Creates a new instance of DefaultSchemaGenerator
*/
public DefaultSchemaGenerator(SchemaGenerator.Mode mode) {
super(mode);
id = createUniqueId();
pc = createPrimitiveCart();
fixNamesMap = new TreeMap<Integer, java.util.List<Object>>();
createGlobals = new ArrayList<SchemaComponent>();
refMap = new HashMap<SchemaComponent, SchemaComponent>();
namesMap = new HashMap<Class, HashMap<String, SchemaComponent>>();
elementReuseList = new ArrayList<Element>();
fgeCount = 0;
}
public void updateSchema(SchemaModel sm) throws IOException {
assert getMode() == SchemaGenerator.Mode.UPDATE;
sgh = new UpdateHelper();
sgh.execute(sm);
}
public void transformSchema(SchemaModel sm) throws IOException {
assert getMode() == SchemaGenerator.Mode.TRANSFORM;
sgh = new TransformHelper();
sgh.execute(sm);
}
public void visit(Element element) {
if(getMode() != SchemaGenerator.Mode.TRANSFORM && element instanceof ElementRef)
prepareElementRef((ElementRef)element);
else
prepareLocalElement(element);
}
public void visit(Attribute attribute) {
if(getMode() != SchemaGenerator.Mode.TRANSFORM && attribute instanceof AttributeRef)
prepareAttributeRef((AttributeRef)attribute);
else
prepareLocalAttribute(attribute);
}
public void visit(AXIType type) {
if(type instanceof Datatype)
((Datatype)type).accept(this);
}
public void visit(Datatype d) {
SchemaGeneratorUtil.createInlineSimpleType(d, sm, this.datatypeParent, pc);
}
public void visit(ContentModel cm) {
if(scParent instanceof Schema) {
GlobalComplexType gct = SchemaGeneratorUtil.createGlobalComplexType(sm);
assert gct != null;
gct.setName(cm.getName());
SchemaGeneratorUtil.populateContentModel(gct, cm);
if(getMode() != SchemaGenerator.Mode.TRANSFORM) {
cm.setPeer(gct);
int index = cm.getIndex(false);
SchemaGeneratorUtil.addChildComponent(sm, sm.getSchema(), gct, index);
} else
scParent = gct;
scParent = gct;
for(AXIComponent child: cm.getChildren()) {
child.accept(this);
}
}
}
public void visit(Compositor compositor) {
int index = -1;
if(getMode() != SchemaGenerator.Mode.TRANSFORM)
index = compositor.getIndex(false);
switch(compositor.getType()) {
case SEQUENCE: {
Sequence seq = null;
if(scParent instanceof ComplexType) {
if(scParent instanceof LocalComplexType) {
LocalComplexType lct = (LocalComplexType) scParent;
if(lct.getDefinition() != null) {
ComplexTypeDefinition ctd = lct.getDefinition();
if(ctd instanceof SimpleContent) {
transformToComplexContent(compositor, ctd);
seq = SchemaGeneratorUtil.createSequence(sm, lct);
} else
seq = SchemaGeneratorUtil.createSequence(sm, ctd, index);
} else
seq = SchemaGeneratorUtil.createSequence(sm,
(LocalComplexType) scParent);
} else if(scParent instanceof GlobalComplexType) {
GlobalComplexType gct = (GlobalComplexType) scParent;
if(gct.getDefinition() != null) {
ComplexTypeDefinition ctd = gct.getDefinition();
if(ctd instanceof SimpleContent) {
transformToComplexContent(compositor, ctd);
seq = SchemaGeneratorUtil.createSequence(sm, gct);
} else
seq = SchemaGeneratorUtil.createSequence(sm, ctd, index);
} else
seq = SchemaGeneratorUtil.createSequence(sm,
(GlobalComplexType) scParent);
}
} else if(scParent instanceof ComplexContentDefinition) {
ComplexContentDefinition ccd = (ComplexContentDefinition) scParent;
if(ccd instanceof ComplexContentRestriction &&
((ComplexContentRestriction)ccd).getDefinition() != null)
seq = SchemaGeneratorUtil.createSequence(sm,
((ComplexContentRestriction)ccd).getDefinition(), index);
//TODO
// else if(ccd instanceof ComplexExtension &&
// ((ComplexExtension)ccd).getLocalDefinition() != null)
// seq = ((ComplexExtension)ccd).getLocalDefinition();
else
seq = SchemaGeneratorUtil.createSequence(sm,
(ComplexContentDefinition) scParent);
} else if(scParent instanceof Sequence) {
seq = SchemaGeneratorUtil.createSequence(sm, (Sequence)scParent, index);
} else if(scParent instanceof Choice) {
seq = SchemaGeneratorUtil.createSequence(sm, (Choice)scParent, index);
}
SchemaGeneratorUtil.populateCompositor(seq, compositor);
if(getMode() != SchemaGenerator.Mode.TRANSFORM)
compositor.setPeer(seq);
else
scParent = seq;
}
break;
case CHOICE: {
Choice c = null;
if(scParent instanceof ComplexType) {
if(scParent instanceof LocalComplexType) {
LocalComplexType lct = (LocalComplexType) scParent;
if(lct.getDefinition() != null) {
ComplexTypeDefinition ctd = lct.getDefinition();
if(ctd instanceof SimpleContent) {
transformToComplexContent(compositor, ctd);
c = SchemaGeneratorUtil.createChoice(sm, lct);
} else
c = SchemaGeneratorUtil.createChoice(sm, ctd, index);
} else
c = SchemaGeneratorUtil.createChoice(sm,
(LocalComplexType) scParent);
}
if(scParent instanceof GlobalComplexType) {
GlobalComplexType gct = (GlobalComplexType) scParent;
if(gct.getDefinition() != null) {
ComplexTypeDefinition ctd = gct.getDefinition();
if(ctd instanceof SimpleContent) {
transformToComplexContent(compositor, ctd);
c = SchemaGeneratorUtil.createChoice(sm, gct);
} else
c = SchemaGeneratorUtil.createChoice(sm, ctd, index);
}
else
c = SchemaGeneratorUtil.createChoice(sm,
(GlobalComplexType) scParent);
}
} else if(scParent instanceof ComplexContentDefinition) {
ComplexContentDefinition ccd = (ComplexContentDefinition) scParent;
if(ccd instanceof ComplexContentRestriction &&
((ComplexContentRestriction)ccd).getDefinition() != null)
c = SchemaGeneratorUtil.createChoice(sm,
((ComplexContentRestriction)ccd).getDefinition(), index);
//TODO
// else if(ccd instanceof ComplexExtension &&
// ((ComplexExtension)ccd).getLocalDefinition() != null)
// seq = ((ComplexExtension)ccd).getLocalDefinition();
else
c = SchemaGeneratorUtil.createChoice(sm,
(ComplexContentDefinition) scParent);
} else if(scParent instanceof Choice) {
c = SchemaGeneratorUtil.createChoice(sm, (Choice)scParent, index);
} else if(scParent instanceof Sequence) {
c = SchemaGeneratorUtil.createChoice(sm, (Sequence)scParent, index);
}
SchemaGeneratorUtil.populateCompositor(c, compositor);
if(getMode() != SchemaGenerator.Mode.TRANSFORM)
compositor.setPeer(c);
else
scParent = c;
}
break;
case ALL: {
All a = null;
if(scParent instanceof ComplexType) {
a = SchemaGeneratorUtil.createAll(sm, (ComplexType) scParent);
} else if(scParent instanceof ComplexContentDefinition) {
ComplexContentDefinition ccd = (ComplexContentDefinition) scParent;
if(ccd instanceof ComplexContentRestriction &&
((ComplexContentRestriction)ccd).getDefinition() != null)
a = (All)
((ComplexContentRestriction)ccd).getDefinition();
//TODO
// else if(ccd instanceof ComplexExtension &&
// ((ComplexExtension)ccd).getLocalDefinition() != null)
// seq = ((ComplexExtension)ccd).getLocalDefinition();
else
a = SchemaGeneratorUtil.createAll(sm,
(ComplexContentDefinition) scParent);
}
SchemaGeneratorUtil.populateCompositor(a, compositor);
if(getMode() != SchemaGenerator.Mode.TRANSFORM)
compositor.setPeer(a);
else
scParent = a;
}
break;
default: assert false;
}
}
private ComplexType transformToComplexContent(Compositor compositor, final ComplexTypeDefinition ctd) {
AXIComponent parent = compositor.getParent();
ComplexType lct = null;
if(ctd instanceof SimpleContent) {
lct = (ComplexType) ctd.getParent();
if(ctd.getChildren().get(0) instanceof SimpleExtension) {
NamedComponentReference base = ((SimpleExtension)ctd.getChildren().get(0)).getBase();
if(base != null && base.get() instanceof GlobalSimpleType) {
SimpleContent sc1 = (SimpleContent) ctd;
copyAttribute(parent, lct, sc1);
copyAttribute(parent, lct, sc1.getLocalDefinition());
}
}
}
return lct;
}
private void copyAttribute(AXIComponent parent, final LocalAttributeContainer lac,
final SchemaComponent scd) {
for(SchemaComponent sc: scd.getChildren()) {
if(sc instanceof org.netbeans.modules.xml.schema.model.Attribute) {
LocalAttribute la = (LocalAttribute)((org.netbeans.modules.xml.schema.model.Attribute)sc).copy(lac);
lac.addLocalAttribute(la);
for(AXIComponent child : parent.getChildren()) {
if(child.getPeer() == sc) {
child.setPeer(la);
}
}
}
}
}
public void visit(AXIComponent c) {
throw new IllegalArgumentException("No action taken on this component: "+
c.toString());
}
protected abstract SchemaGenerator.Pattern getSchemaDesignPattern();
////////////////////////////////////////////////////////////////////
////////////////////////// helper methods ////////////////////////
////////////////////////////////////////////////////////////////////
protected void prepareGlobalElement(Element element) {
GlobalElement e = null;
ElementReference eref = null;
int index = -1;
if(getMode() != SchemaGenerator.Mode.TRANSFORM)
index = element.getIndex(false);
if(scParent instanceof Schema) {
e = createGlobalElement(element);
sgh.addElement(e, index);
prepareFixGlobalElementNames(element, (GlobalElement) e, null);
} else if(scParent instanceof ComplexTypeDefinition) {
String seed = element.getName();
boolean found = false;
if(SchemaGeneratorUtil.isSimpleElement(element) ||
SchemaGeneratorUtil.hasProxyChild(element)) {
HashMap<String, SchemaComponent> map =
namesMap.get(GlobalElement.class);
if(map != null && map.get(seed) != null) {
GlobalElement ge1 = (GlobalElement) map.get(seed);
GlobalElement ge2 = SchemaGeneratorUtil.createGlobalElement(sm);
ge2.setName(element.getName());
SchemaGeneratorUtil.populateElement(ge2, element);
this.datatypeParent = ge2;
if(element.getType() instanceof Datatype)
element.getType().accept(this);
else if(element.getType() instanceof ContentModel)
SchemaGeneratorUtil.setType(ge2,
(GlobalComplexType) ((ContentModel)element.
getType()).getPeer());
if(SchemaGeneratorUtil.isIdentical(ge1, ge2)) {
found = true;
e = ge1;
if(!elementReuseList.contains(element))
elementReuseList.add(element);
}
}
}
if(!found) {
e = createGlobalElement(element);
sgh.addElement(e, -1);
}
eref = SchemaGeneratorUtil.createElementReference(sm, scParent, e, index);
addRef(eref, e);
prepareFixGlobalElementNames(element, e, eref);
}
assert e != null;
sc = e;
//set block, final, fixed, default, form etc
SchemaGeneratorUtil.populateElement(e, element);
if(eref != null)
SchemaGeneratorUtil.populateElement(eref, element);
this.datatypeParent = e;
if(element.getType() instanceof Datatype)
element.getType().accept(this);
setPeer(element, e, eref);
}
protected void prepareElementRef(ElementRef element) {
int index = element.getIndex();
org.netbeans.modules.xml.schema.model.ElementReference eRef =
SchemaGeneratorUtil.createElementReference(sm, (ComplexTypeDefinition) scParent,
(GlobalElement)element.getReferent().getPeer(), index);
setPeer(element, null, eRef);
}
protected void prepareLocalElement(Element element) {
org.netbeans.modules.xml.schema.model.Element e = null;
int index = -1;
if(getMode() != SchemaGenerator.Mode.TRANSFORM)
index = element.getIndex(false);
if(scParent instanceof Schema) {
e = createGlobalElement(element);
sgh.addElement((GlobalElement) e, index);
prepareFixGlobalElementNames(element, (GlobalElement) e, null);
} else if(scParent instanceof ComplexTypeDefinition) {
e = SchemaGeneratorUtil.createLocalElement(sm,
(ComplexTypeDefinition) scParent, element.getName(), index);
}
assert e != null;
sc = e;
//set block, final, fixed, default, form etc
SchemaGeneratorUtil.populateElement(e, element);
this.datatypeParent = e;
if(element.getType() instanceof Datatype)
element.getType().accept(this);
setPeer(element, e, null);
}
protected void prepareAttributeRef(AttributeRef attribute) {
int index = attribute.getIndex();
org.netbeans.modules.xml.schema.model.AttributeReference aRef =
SchemaGeneratorUtil.createAttributeReference(sm, scParent,
(GlobalAttribute)attribute.getReferent().getPeer(), index);
setPeer(attribute, null, aRef);
}
protected void prepareLocalAttribute(Attribute attribute) {
assert scParent != null;
int index = -1;
if(getMode() != SchemaGenerator.Mode.TRANSFORM)
index = attribute.getIndex();
LocalAttribute attr = null;
if(scParent instanceof ComplexType &&
((ComplexType)scParent).getDefinition() instanceof ComplexTypeDefinition) {
if(((ComplexType)scParent).getDefinition() instanceof SimpleContent) {
SimpleContentDefinition def = ((SimpleContent)((ComplexType)scParent).
getDefinition()).getLocalDefinition();
if(def instanceof SimpleContentRestriction)
attr = SchemaGeneratorUtil.createLocalAttribute(sm, attribute.getName(),
(SimpleContentRestriction)def, index);
else if(def instanceof Extension)
attr = SchemaGeneratorUtil.createLocalAttribute(sm, attribute.getName(),
(Extension)def, index);
}
else if(((ComplexType)scParent).getDefinition() instanceof ComplexContent) {
ComplexContentDefinition def = ((ComplexContent)((ComplexType)scParent).
getDefinition()).getLocalDefinition();
if(def instanceof ComplexContentRestriction)
attr = SchemaGeneratorUtil.createLocalAttribute(sm, attribute.getName(),
(ComplexContentRestriction)def, index);
else if(def instanceof Extension)
attr = SchemaGeneratorUtil.createLocalAttribute(sm, attribute.getName(),
(Extension)def, index);
}
else {
attr = SchemaGeneratorUtil.createLocalAttribute(sm, attribute.getName(),
scParent, index);
}
} else
attr = SchemaGeneratorUtil.createLocalAttribute(sm, attribute.getName(),
scParent, index);
assert attr != null;
//set fixed, default, form, use etc
SchemaGeneratorUtil.populateAttribute(attr, attribute);
this.datatypeParent = attr;
if(attribute.getType() instanceof Datatype)
attribute.getType().accept(this);
if(getMode() != SchemaGenerator.Mode.TRANSFORM)
attribute.setPeer(attr);
}
protected GlobalElement createGlobalElement(final Element element) {
GlobalElement ge = SchemaGeneratorUtil.createGlobalElement(sm);
String eName = findUniqueGlobalName(
GlobalElement.class, ge, element.getName());
ge.setName(eName);
return ge;
}
protected GlobalComplexType createGlobalComplexType(final String seed) {
GlobalComplexType gct;
gct = (GlobalComplexType)
SchemaGeneratorUtil.createGlobalComplexType(sm);
String typeName = findUniqueGlobalName(
GlobalComplexType.class, gct, seed);
gct.setName(typeName);
return gct;
}
public void createGlobalSimpleType(
final Datatype d, final SchemaModel sm, final SchemaComponent sc,
final SchemaGenerator.UniqueId id, SchemaGenerator.PrimitiveCart pc) {
if(d != null) {
NamedComponentReference<GlobalSimpleType> ref =null;
if(SchemaGeneratorUtil.isPrimitiveType(d)) {
ref = SchemaGeneratorUtil.createPrimitiveType(d, sc, pc);
} else {
GlobalSimpleType gst;
gst = SchemaGeneratorUtil.createGlobalSimpleType(sm);
String typeName = d.getName();
typeName = findUniqueGlobalName(
GlobalSimpleType.class, gst,
"New"+typeName.substring(0, 1).toUpperCase()+
typeName.substring(1)+"Type"+String.valueOf(id.nextId()));
gst.setName(typeName);
sgh.addSimpleType(gst, -1);
if(d instanceof CustomDatatype)
SchemaGeneratorUtil.populateSimpleType(
((CustomDatatype)d).getBase(), sm, gst, pc);
else
SchemaGeneratorUtil.populateSimpleType(d, sm, gst, pc);
ref = sc.createReferenceTo(gst, GlobalSimpleType.class);
}
SchemaGeneratorUtil.setSimpleType(sc, ref);
}
}
protected GlobalType createPeerGlobalComplexType(Element element) {
org.netbeans.modules.xml.schema.model.Element e =
(org.netbeans.modules.xml.schema.model.Element) element.getPeer();
if(e instanceof ElementReference)
e = (GlobalElement) getRef(e);
GlobalComplexType gct = createGlobalComplexType(element.getName()+"Type");
assert gct != null;
sgh.addComplexType(gct, -1);
SchemaGeneratorUtil.setType(e, gct);
return gct;
}
protected void prepareFixGlobalElementNames(final Element element, final GlobalElement e,
final ElementReference eref) {
java.util.List<Object> scs = new ArrayList<Object>();
scs.add(element);
scs.add(e);
scs.add(eref);
fixNamesMap.put(Integer.valueOf(fgeCount++), scs);
}
protected void fixGlobalElementNames() {
//clear unique names map
namesMap.clear();
//create buckets
HashMap<GlobalElement, java.util.List<ElementReference>> erefMap = new
HashMap<GlobalElement, java.util.List<ElementReference>>();
for (Entry<Integer,java.util.List<Object>> e : fixNamesMap.entrySet()) {
java.util.List<Object> scs = e.getValue();
if(scs != null && scs.size() > 1) {
GlobalElement ge = (GlobalElement) scs.get(1);
ElementReference eref = (ElementReference) scs.get(2);
java.util.List<ElementReference> erefs = erefMap.get(ge);
if(erefs == null) {
erefs = new ArrayList<ElementReference>();
erefMap.put(ge, erefs);
}
if(eref != null && !erefs.contains(eref))
erefs.add(eref);
}
}
int count = 0;
Iterator it = erefMap.keySet().iterator();
while(it.hasNext()) {
if(commitRange > 0 && (count++)%commitRange==0) {
sm.endTransaction();
sm.startTransaction();
}
GlobalElement ge = (GlobalElement) it.next();
java.util.List<ElementReference> erefs = erefMap.get(ge);
String name = findUniqueGlobalName(
GlobalElement.class, ge, ge.getName());
ge.setName(name);
for(ElementReference eref:erefs)
eref.setRef(eref.createReferenceTo(ge, GlobalElement.class));
}
erefMap.clear();
erefMap = null;
fixNamesMap.clear();
}
<T extends NameableSchemaComponent>String
findUniqueGlobalName(Class<T> type, NameableSchemaComponent c,
final String seed) {
return sgh.findUniqueGlobalName(type, c, seed);
}
protected SchemaComponent getParent(final AXIComponent axiparent)
throws IllegalArgumentException {
return sgh.getParent(axiparent);
}
protected void setPeer(final Element element,
final org.netbeans.modules.xml.schema.model.Element e,
final ElementReference eref) {
sgh.setPeer(element, e, eref);
}
protected void setPeer(final Attribute attribute,
final org.netbeans.modules.xml.schema.model.Attribute a,
final AttributeReference aRef) {
sgh.setPeer(attribute, a, aRef);
}
private UniqueId createUniqueId() {
return new UniqueId() {
private int lastId = -1;
public int nextId() {
return ++lastId;
}
};
}
private PrimitiveCart createPrimitiveCart() {
return new PrimitiveCart() {
private Map<SchemaComponent, Datatype> pc = new HashMap<SchemaComponent, Datatype>();
private Map<String, GlobalSimpleType> ptypes = new HashMap<String, GlobalSimpleType>();
private GlobalSimpleType def = null;
public void add(Datatype d, SchemaComponent referer) {
pc.put(referer, d);
}
public Set<Map.Entry<SchemaComponent, Datatype>> getEntries() {
return pc.entrySet();
}
public GlobalSimpleType getDefaultPrimitive() {
if(def==null) {
def = getPrimitiveType("string");//NoI18n
}
return def;
}
public GlobalSimpleType getPrimitiveType(String typeName) {
if(ptypes.isEmpty()) {
SchemaModel primitiveModel = SchemaModelFactory.getDefault().getPrimitiveTypesModel();
Collection<GlobalSimpleType> primitives = primitiveModel.getSchema().getSimpleTypes();
for(GlobalSimpleType ptype: primitives){
ptypes.put(ptype.getName(), ptype);
}
}
return ptypes.get(typeName);
}
};
}
protected void addRef(SchemaComponent referer, SchemaComponent ref) {
sgh.addRef(referer, ref);
}
protected SchemaComponent getRef(SchemaComponent referer) {
return sgh.getRef(referer);
}
protected void addToGlobal(SchemaComponent sc) {
createGlobals.add(sc);
}
private void fixPrimitiveTypes() {
for(Map.Entry<SchemaComponent, Datatype> e: pc.getEntries()) {
Datatype d = (Datatype) e.getValue();
SchemaComponent referer = (SchemaComponent) e.getKey();
String typeName = d.getName();
if(d instanceof CustomDatatype)
typeName = ((CustomDatatype)d).getBase().getName();
GlobalSimpleType gst = pc.getPrimitiveType(typeName);
NamedComponentReference<GlobalSimpleType> ref =
referer.createReferenceTo(gst, GlobalSimpleType.class);
SchemaGeneratorUtil.setSimpleType(referer, ref);
}
}
protected void clear() {
path.clear();
path = null;
createGlobals.clear();
createGlobals = null;
fixNamesMap.clear();
fixNamesMap = null;
refMap.clear();
refMap = null;
namesMap.clear();
namesMap = null;
}
interface SchemaGeneratorHelper {
public void execute(SchemaModel sm) throws IOException;
public SchemaComponent getParent(final AXIComponent axiparent)
throws IllegalArgumentException;
/*
* finds unique name from a bucket of global components
*/
public <T extends NameableSchemaComponent>String
findUniqueGlobalName(Class<T> type, NameableSchemaComponent c,
final String seed);
public void setPeer(final Element element,
final org.netbeans.modules.xml.schema.model.Element e,
final ElementReference eref);
public void setPeer(final Attribute attribute,
final org.netbeans.modules.xml.schema.model.Attribute a,
final AttributeReference aRef);
public void addRef(SchemaComponent referer, SchemaComponent ref);
public SchemaComponent getRef(SchemaComponent referer);
public void addElement(GlobalElement ge, int index);
public void addComplexType(GlobalComplexType gct, int index);
public void addSimpleType(GlobalSimpleType gst, int index);
}
class UpdateHelper implements SchemaGeneratorHelper {
UpdateHelper() {
}
public void execute(SchemaModel sm) throws IOException {
DefaultSchemaGenerator.this.sm = sm;
DefaultSchemaGenerator.this.am =
AXIModelFactory.getDefault().getModel(sm);
SchemaUpdate su = SchemaGeneratorUtil.getSchemaUpdate(am);
Collection<SchemaUpdate.UpdateUnit> us = su.getUpdateUnits();
try {
((AXIModelImpl)am).disableAutoSync();
sm.startTransaction();
for(SchemaUpdate.UpdateUnit u:us) {
AXIComponent source = u.getSource();
if(source.getModel() != am) //skip mutating other model
continue;
SchemaUpdate.UpdateUnit.Type type = u.getType();
if(type == SchemaUpdate.UpdateUnit.Type.CHILD_ADDED)
addSchemaComponent(source, u);
else if(type == SchemaUpdate.UpdateUnit.Type.CHILD_DELETED)
SchemaGeneratorUtil.removeSchemaComponent(source, u, sm);
else if(type == SchemaUpdate.UpdateUnit.Type.CHILD_MODIFIED)
SchemaGeneratorUtil.modifySchemaComponent(source, u, sm, pc);
}
// addAllGlobals();
} finally {
clear();
sm.endTransaction();
((AXIModelImpl)am).enableAutoSync();
}
}
protected void addSchemaComponent(AXIComponent source,
SchemaUpdate.UpdateUnit u) {
assert u.getNewValue() != null;
scParent = DefaultSchemaGenerator.this.getParent(
((AXIComponent)u.getNewValue()).getParent());
assert scParent != null;
((AXIComponent)u.getNewValue()).accept(DefaultSchemaGenerator.this);
}
public <T extends NameableSchemaComponent>String
findUniqueGlobalName(Class<T> type, NameableSchemaComponent c,
final String seed) {
return SchemaGeneratorUtil.findUniqueGlobalName(type, seed, sm);
}
public SchemaComponent getParent(final AXIComponent axiparent)
throws IllegalArgumentException {
SchemaComponent scParent = null;
if(axiparent instanceof AXIDocument)
scParent = sm.getSchema();
else if(axiparent instanceof Element){
SchemaComponent e = axiparent.getPeer();
if(e instanceof ElementReference)
e = getRef(axiparent.getPeer());
assert e != null;
SchemaComponent lct = SchemaGeneratorUtil.getLocalComplexType(e);
if(lct == null) {
lct = SchemaGeneratorUtil.getGlobalComplexType(e);
if(lct == null) {
if((e instanceof GlobalElement && ((GlobalElement)e).getType() != null &&
((GlobalElement)e).getType().get() instanceof GlobalSimpleType) ||
(e instanceof LocalElement && ((LocalElement)e).getType() != null &&
((LocalElement)e).getType().get() instanceof GlobalSimpleType)) {
SimpleContent newsc = sm.getFactory().createSimpleContent();
SimpleExtension se = sm.getFactory().createSimpleExtension();
newsc.setLocalDefinition(se);
GlobalType gst = null;
if(e instanceof GlobalElement)
gst = ((GlobalElement)e).getType().get();
else if(e instanceof LocalElement)
gst = ((LocalElement)e).getType().get();
if(gst != null)
se.setBase(se.createReferenceTo(gst, GlobalType.class));
lct = SchemaGeneratorUtil.createLocalComplexType(sm, e);
((LocalComplexType)lct).setDefinition(newsc);
} else
lct = SchemaGeneratorUtil.createLocalComplexType(sm, e);
}
}
assert lct != null;
scParent = lct;
} else if(axiparent instanceof ContentModel){
scParent = axiparent.getPeer();
} else if(axiparent instanceof Compositor){
scParent = axiparent.getPeer();
}
return scParent;
}
public void setPeer(final Element element,
final org.netbeans.modules.xml.schema.model.Element e,
final ElementReference eref) {
if(eref != null)
element.setPeer(eref);
else
element.setPeer(e);
}
public void setPeer(final Attribute attribute,
final org.netbeans.modules.xml.schema.model.Attribute a,
final AttributeReference aRef) {
if(aRef != null)
attribute.setPeer(aRef);
else
attribute.setPeer(a);
}
public void addElement(GlobalElement ge, int index) {
if(index != -1)
SchemaGeneratorUtil.addChildComponent(sm, sm.getSchema(), ge, index);
else
sm.getSchema().addElement((GlobalElement) ge);
}
public void addComplexType(GlobalComplexType gct, int index) {
if(index != -1)
SchemaGeneratorUtil.addChildComponent(sm, sm.getSchema(), gct, index);
else
sm.getSchema().addComplexType(gct);
}
public void addSimpleType(GlobalSimpleType gst, int index) {
if(index != -1)
SchemaGeneratorUtil.addChildComponent(sm, sm.getSchema(), gst, index);
else
sm.getSchema().addSimpleType(gst);
}
public void addRef(SchemaComponent referer, SchemaComponent ref) {
}
public SchemaComponent getRef(SchemaComponent referer) {
if(referer instanceof ElementReference)
return ((ElementReference)referer).getRef().get();
else if(referer instanceof org.netbeans.modules.xml.schema.model.Element)
if(referer instanceof GlobalElement &&
((GlobalElement)referer).getType() != null &&
((GlobalElement)referer).getType().get() instanceof GlobalComplexType)
return ((GlobalElement)referer).getType().get();
else if(referer instanceof LocalElement &&
((LocalElement)referer).getType() != null &&
((LocalElement)referer).getType().get() instanceof GlobalComplexType)
return ((LocalElement)referer).getType().get();
return null;
}
protected void clear() {
DefaultSchemaGenerator.this.clear();
}
}
class TransformHelper implements SchemaGeneratorHelper {
TransformHelper() {
}
public void execute(SchemaModel sm) throws IOException {
DefaultSchemaGenerator.this.sm = sm;
DefaultSchemaGenerator.this.am = AXIModelFactory.getDefault().getModel(sm);
Schema schema = sm.getSchema();
assert schema != null;
try {
HashMap<Class, Map<String, SchemaComponent>> allGlobals =
new HashMap<Class, Map<String, SchemaComponent>>();
java.util.List<Element> lrges = preTransform(schema, allGlobals);
((AXIModelImpl)am).disableAutoSync();
sm.startTransaction();
for(Element element : lrges) {
java.util.List<AXIComponent> pathFromRoot = new ArrayList<AXIComponent>();
pathFromRoot.add(element);
transformChildren(element, schema, pathFromRoot);
}
postTransform(schema, allGlobals);
} finally {
clear();
try {
sm.endTransaction();
}
finally {
((AXIModelImpl)am).enableAutoSync();
am.sync();
}
}
}
public SchemaComponent getParent(final AXIComponent axiparent)
throws IllegalArgumentException {
throw new IllegalArgumentException("should not call this api during transform");
}
protected void transformChildren(AXIComponent component,
SchemaComponent parent, java.util.List<AXIComponent> pathFromRoot) {
//skip transforming components from other model
if(!SchemaGeneratorUtil.fromSameSchemaModel(component.getPeer(), sm))
return;
assert parent != null;
DefaultSchemaGenerator.this.scParent = parent;
component.accept(DefaultSchemaGenerator.this);
if(elementReuseList.contains(component))
return;
SchemaComponent cc = DefaultSchemaGenerator.this.sc;
//check for cycle
if(component instanceof Element) {
Element orig = (Element)component;
if(orig.isReference()) {
orig = SchemaGeneratorUtil.findOriginalElement(orig);
}
if(path.size() > 0 && path.contains(orig))
return;
path.add(orig);
}
try {
if(component.getChildren().size() > 0) {
parent = scParent;
}
assert parent != null;
if(component instanceof AbstractElement) {
for(AbstractAttribute attr :
((AbstractElement)component).getAttributes()) {
//skip transforming components from other model
if(!SchemaGeneratorUtil.fromSameSchemaModel(attr.getPeer(), sm))
continue;
DefaultSchemaGenerator.this.scParent = parent;
attr.accept(DefaultSchemaGenerator.this);
}
}
for(AXIComponent child: component.getChildren()) {
if(!(child instanceof AbstractAttribute)) {
if(pathFromRoot.contains(child.getOriginal()))
continue;
pathFromRoot.add(child.getOriginal());
transformChildren(child, parent, pathFromRoot);
}
}
} finally {
if(component instanceof Element)
path.remove(path.size()-1);
}
}
protected java.util.List<Element> preTransform(Schema schema,
Map<Class, Map<String, SchemaComponent>> allGlobals) {
java.util.List<Element> lrges =
SchemaGeneratorUtil.findMasterGlobalElements(
DefaultSchemaGenerator.this.am);
//Now expand the AXI tree deep for some global elements from the list
AXINonCyclicVisitor visitor = new AXINonCyclicVisitor(am);
visitor.expand(lrges);
//All saved globals
SortedMap<String, SchemaComponent> ggmap =
new TreeMap<String, SchemaComponent>();
allGlobals.put(GlobalGroup.class, ggmap);
for(GlobalGroup ag:schema.getGroups())
ggmap.put(ag.getName(), ag);
SortedMap<String, SchemaComponent> gctmap =
new TreeMap<String, SchemaComponent>();
allGlobals.put(GlobalComplexType.class, gctmap);
for(GlobalComplexType gct:schema.getComplexTypes())
gctmap.put(gct.getName(), gct);
SortedMap<String, SchemaComponent> gagmap =
new TreeMap<String, SchemaComponent>();
allGlobals.put(GlobalAttributeGroup.class, gagmap);
for(GlobalAttributeGroup ag:schema.getAttributeGroups())
gagmap.put(ag.getName(), ag);
SortedMap<String, SchemaComponent> gstmap =
new TreeMap<String, SchemaComponent>();
allGlobals.put(GlobalSimpleType.class, gstmap);
for(GlobalType gst:schema.getSimpleTypes())
gstmap.put(gst.getName(), gst);
SortedMap<String, SchemaComponent> gemap =
new TreeMap<String, SchemaComponent>();
allGlobals.put(GlobalElement.class, gemap);
for(GlobalElement ge:schema.getElements())
gemap.put(ge.getName(), ge);
SortedMap<String, SchemaComponent> gamap =
new TreeMap<String, SchemaComponent>();
allGlobals.put(GlobalAttribute.class, gamap);
for(GlobalAttribute ga:schema.getAttributes())
gamap.put(ga.getName(), ga);
return lrges;
}
protected void postTransform(Schema schema,
HashMap<Class, Map<String, SchemaComponent>> allGlobals) {
//remove previous global elements, complextypes etc.,
removeAllGlobals(schema, allGlobals);
//add new elements, complextypes etc.,
addAllGlobals(schema, createGlobals);
//fix global element names, make them unique
fixGlobalElementNames();
//fix primitive types
fixPrimitiveTypes();
}
//remove all previous global components
private void removeAllGlobals(final Schema schema,
final HashMap<Class, Map<String, SchemaComponent>> allGlobals) {
//remove all global simpleType
removeGlobalSchemaComponent(GlobalSimpleType.class, allGlobals, schema);
//remove all global attribute
removeGlobalSchemaComponent(GlobalAttribute.class, allGlobals, schema);
//remove all global attribute group
removeGlobalSchemaComponent(GlobalAttributeGroup.class, allGlobals, schema);
//remove all global complexType
removeGlobalSchemaComponent(GlobalComplexType.class, allGlobals, schema);
//remove all global group
removeGlobalSchemaComponent(GlobalGroup.class, allGlobals, schema);
//remove all global element
removeGlobalSchemaComponent(GlobalElement.class, allGlobals, schema);
}
private void removeGlobalSchemaComponent(final Class type,
final HashMap<Class, Map<String, SchemaComponent>> allGlobals,
final Schema schema) {
Map<String, SchemaComponent> gmap = allGlobals.get(type);
if(gmap == null) return;
int count = 0;
for (Map.Entry entry : gmap.entrySet()) {
SchemaComponent sc = (SchemaComponent) entry.getValue();
commitTransaction(count);
if(sc instanceof GlobalSimpleType)
schema.removeSimpleType((GlobalSimpleType) sc);
else if(sc instanceof GlobalAttribute)
schema.removeAttribute((GlobalAttribute) sc);
else if(sc instanceof GlobalAttributeGroup)
schema.removeAttributeGroup((GlobalAttributeGroup) sc);
else if(sc instanceof GlobalComplexType)
schema.removeComplexType((GlobalComplexType) sc);
else if(sc instanceof GlobalGroup)
schema.removeGroup((GlobalGroup) sc);
else if(sc instanceof GlobalElement)
schema.removeElement((GlobalElement) sc);
}
}
private void commitTransaction(int count) {
if(commitRange > 0 && (count++)%commitRange==0) {
sm.endTransaction();
sm.startTransaction();
}
}
/*
* finds unique name from a bucket of global components
*/
public <T extends NameableSchemaComponent>String
findUniqueGlobalName(Class<T> type, NameableSchemaComponent c,
final String seed) {
HashMap<String, SchemaComponent> map = namesMap.get(type);
if(map == null) {
map = new HashMap<String, SchemaComponent>();
namesMap.put(type, map);
}
int count = 0;
boolean found = true;
while(found) {
found = false;
SchemaComponent sc =
map.get(count>0?(seed + String.valueOf(count)):seed);
if(sc != null) {
count++;
found = true;
}
}
String uniqueName = count>0?(seed + String.valueOf(count)):seed;
map.put(uniqueName, c);
return uniqueName;
}
public void setPeer(final Element element,
final org.netbeans.modules.xml.schema.model.Element e,
final ElementReference eref) {
if(element.getChildren().size() > 0) {
SchemaComponent lct = SchemaGeneratorUtil.getLocalComplexType(e);
if(lct == null) {
//check type from another schema model
lct = SchemaGeneratorUtil.findTypeFromOtherModel(e, element, sm);
if(lct == null)
lct = SchemaGeneratorUtil.createLocalComplexType(sm, e);
assert lct != null;
scParent = lct;
}
} else
scParent = e;
}
public void setPeer(final Attribute attribute,
final org.netbeans.modules.xml.schema.model.Attribute a,
final AttributeReference aref) {
//FIXME
}
public void addElement(GlobalElement ge, int index) {
//ignore index for transform, always append to schema
addToGlobal(ge);
}
public void addComplexType(GlobalComplexType gct, int index) {
//ignore index for transform, always append to schema
addToGlobal(gct);
}
public void addSimpleType(GlobalSimpleType gst, int index) {
//ignore index for transform, always append to schema
addToGlobal(gst);
}
protected void addAllGlobals(final Schema schema,
java.util.List<SchemaComponent> createGlobals) {
for(int i=0;i<createGlobals.size();i++) {
SchemaComponent sc = createGlobals.get(i);
if(commitRange > 0 && i%commitRange==0) {
sm.endTransaction();
sm.startTransaction();
}
if(sc instanceof GlobalElement)
sm.getSchema().addElement((GlobalElement) sc);
else if(sc instanceof GlobalComplexType)
sm.getSchema().addComplexType((GlobalComplexType) sc);
if(sc instanceof GlobalSimpleType)
sm.getSchema().addSimpleType((GlobalSimpleType) sc);
else if(sc instanceof GlobalGroup)
sm.getSchema().addGroup((GlobalGroup) sc);
else if(sc instanceof GlobalAttributeGroup)
sm.getSchema().addAttributeGroup(
(GlobalAttributeGroup) sc);
}
}
public void addRef(SchemaComponent referer, SchemaComponent ref) {
refMap.put(referer, ref);
}
public SchemaComponent getRef(SchemaComponent referer) {
return refMap.get(referer);
}
protected void clear() {
DefaultSchemaGenerator.this.clear();
}
}
}