SchemaVisitor {
{{
private String[] nsPrefixes;
private Stack elementStack, typeStack;
}}
public void start()
{{
elementStack = new Stack();
typeStack = new Stack();
}}
public void before(Schema host)
{{
nsPrefixes = host.get_attrs().getAllAttributeNames("xmlns", null);
}}
public void after(Schema host)
{{
}}
public void before(Element host)
{{
String name, type;
// If it's a reference to another element, then it needs special
// processing
name = host.get_attrs().getAttributeValue(null, "ref");
if (!name.equals(""))
type = getTypeOfElement(name);
else
{
name = host.get_attrs().getAttributeValue(null, "name");
type = host.get_attrs().getAttributeValue(null, "type");
if (!type.equals(""))
type = resolveXMLTypeName(type);
else
type = name + "Type";
}
// If this element is directly under the "schema" element, add it as a
// global element.
// Otherwise it must be a "part" under the current type definition
if (elementStack.empty() && typeStack.empty())
{
DataElement newElement = new DataElement();
newElement.set_name(name);
newElement.set_type(type);
def.get_global_elements().put(name, newElement);
if (def.get_root_element() == null)
def.set_root_element(newElement);
elementStack.push(newElement);
}
else
{
ElementClassPart newClassPart = new ElementClassPart();
newClassPart.set_name(name);
newClassPart.set_type(type);
Constraint cons = new Constraint();
cons.min_occurs = 1; cons.max_occurs = 1;
String facet;
facet = host.get_attrs().getAttributeValue(null, "minOccurs");
if (!facet.equals(""))
cons.min_occurs = Integer.parseInt(facet);
facet = host.get_attrs().getAttributeValue(null, "maxOccurs");
if (facet.equals("unbounded"))
cons.max_occurs = Integer.MAX_VALUE; // represents unbounded
else if (!facet.equals(""))
cons.max_occurs = Integer.parseInt(facet);
// If the part is optional or a list, then make sure that the type
// used is not a primitive data type
if ((cons.min_occurs != 1) || (cons.max_occurs != 1))
{
type = Lookup.useObjectType(type);
newClassPart.set_type(type);
}
// If it's going to be a list, we need to add an intermediate
// list container class
if (cons.max_occurs > 1)
{
// The current element will contain a list of the intermediate
// class and all the constraining facets defined on the part
// will be transferred to the part of the intermediate list unit
//
// e.g. if the schema has:
//
//
//
//
// ...
//
//
//
//
//
//
//
//
// then the resulting classes in the CD will be:
// Store = " Cities "" ...
// Cities = ">" List(CityListUnit).
// CityListUnit = " City "".
//
// & the check for max. 20 items will be defined in CityListUnit
//
// From the example, the current element here is "city"
String listUnitName = name + "ListUnit";
DataClass listUnitClass = new DataClass();
listUnitClass.set_name(listUnitName);
listUnitClass.set_category("LISTUNIT");
listUnitClass.set_abstract_ind(false);
listUnitClass.set_subclasses(String_List.parse(""));
listUnitClass.set_attr_parts(AttrClassPart_List.parse(""));
listUnitClass.set_element_parts(ElementClassPart_List.parse(""));
listUnitClass.set_part_constraints(GroupConstraint_List.parse(""));
def.get_types().addElement(listUnitClass);
ElementClassPart listClassPart = new ElementClassPart();
listClassPart.set_name(listUnitName);
listClassPart.set_type(listUnitName);
Constraint listCons = new Constraint();
listCons.min_occurs = cons.min_occurs;
listCons.max_occurs = cons.max_occurs;
listClassPart.set_constraint(listCons);
cons.min_occurs = 1; cons.max_occurs = 1;
newClassPart.set_constraint(cons);
listUnitClass.get_element_parts().addElement(newClassPart);
DataClass currentType = (DataClass) typeStack.peek();
if (currentType != null) // which should always be true
currentType.get_element_parts().addElement(listClassPart);
}
else // not a list part
{
newClassPart.set_constraint(cons);
DataClass currentType = (DataClass) typeStack.peek();
if (currentType != null) // which should always be true
currentType.get_element_parts().addElement(newClassPart);
}
elementStack.push(newClassPart);
}
}}
public void after(Element host)
{{
elementStack.pop();
}}
public void before(Attribute host)
{{
String name, type;
// If it's a reference to another attribute, then it needs special
// processing
name = host.get_attrs().getAttributeValue(null, "ref");
if (!name.equals(""))
type = getTypeOfAttribute(name);
else
{
name = host.get_attrs().getAttributeValue(null, "name");
type = host.get_attrs().getAttributeValue(null, "type");
if (!type.equals(""))
type = resolveXMLTypeName(type);
else
type = name + "Type";
}
// If this attribute is directly under the "schema" element, add it as a
// global attribute.
// Otherwise it must be a "part" under the current type definition
if (elementStack.empty() && typeStack.empty())
{
DataElement newAttribute = new DataElement();
newAttribute.set_name(name);
newAttribute.set_type(type);
def.get_global_attributes().put(name, newAttribute);
}
else
{
AttrClassPart newClassPart = new AttrClassPart();
newClassPart.set_name(name);
newClassPart.set_type(type);
Constraint cons = new Constraint();
cons.min_occurs = 0; cons.max_occurs = 1;
String facet;
facet = host.get_attrs().getAttributeValue(null, "minOccurs");
if (!facet.equals(""))
cons.min_occurs = Integer.parseInt(facet);
facet = host.get_attrs().getAttributeValue(null, "maxOccurs");
if (facet.equals("unbounded"))
cons.max_occurs = Integer.MAX_VALUE; // represents unbounded
else if (!facet.equals(""))
cons.max_occurs = Integer.parseInt(facet);
newClassPart.set_constraint(cons);
// If the part is optional or a list, then make sure that the type
// used is not a primitive data type
if ((cons.min_occurs != 1) || (cons.max_occurs != 1))
{
type = Lookup.useObjectType(type);
newClassPart.set_type(type);
}
DataClass currentType = (DataClass) typeStack.peek();
if (currentType != null) // which should always be true
currentType.get_attr_parts().addElement(newClassPart);
}
}}
public void before(AttributeGroup host)
{{
}}
public void before(ElementGroup host)
{{
}}
public void before(TypeDef host)
{{
// If this is a global type, then it must have a name, otherwise it's
// anonymous and name it after the enclosing element
String name;
if (elementStack.empty())
name = host.get_attrs().getAttributeValue(null, "name");
else
name = ((DataItem) elementStack.peek()).get_type();
DataClass newType = new DataClass();
newType.set_name(name);
newType.set_category("");
newType.set_abstract_ind(false);
newType.set_subclasses(String_List.parse(""));
newType.set_attr_parts(AttrClassPart_List.parse(""));
newType.set_element_parts(ElementClassPart_List.parse(""));
newType.set_part_constraints(GroupConstraint_List.parse(""));
def.get_types().addElement(newType);
typeStack.push(newType);
}}
public void after(TypeDef host)
{{
typeStack.pop();
}}
public void before(ComplexType host)
{{
((DataClass) typeStack.peek()).set_category("COMPLEX");
}}
public void after(ComplexType host)
{{
}}
public void before(SimpleType host)
{{
((DataClass) typeStack.peek()).set_category("SIMPLE");
}}
public void after(SimpleType host)
{{
}}
public String[] getNamespacePrefix()
{{
return nsPrefixes;
}}
private String getTypeOfElement(String name)
{{
DataElement element = (DataElement) def.get_global_elements().get(name);
if (element != null)
return element.get_type();
return "";
}}
private String getTypeOfAttribute(String name)
{{
DataElement element = (DataElement) def.get_global_attributes().get(name);
if (element != null)
return element.get_type();
return "";
}}
private String removeNSPrefix(String itemName)
{{
return itemName.substring(itemName.indexOf(':')+1, itemName.length());
}}
private String resolveXMLTypeName(String XMLType)
{{
Lookup.TypeInfo typeinfo =
Lookup.resolveXMLTypeName(removeNSPrefix(XMLType));
if ((typeinfo.category == Lookup.BUILT_IN_NON_JAVA_TYPE) &&
(!def.get_types().contains(typeinfo.classDef)))
{
def.get_types().addElement(typeinfo.classDef);
}
return typeinfo.typeName;
}}
}
TypeDef {
public abstract AttrValue_List get_attrs();
}