SchemaVisitor {
{{
private String[] nsPrefixes;
private Stack elementStack, attributeStack, typeStack;
private Stack attrCountStack;
private boolean redefineMode;
private GlobalAttrGroup currentAttrGroup;
private String errors = "";
}}
before Schema
{{
elementStack = new Stack();
attributeStack = new Stack();
typeStack = new Stack();
attrCountStack = new Stack();
redefineMode = false;
currentAttrGroup = null;
nsPrefixes = host.get_attrs().getAllAttributeNames("xmlns", null);
// Make a dummy registration of the names "allGrpPart", "choice" and
// "seq" so that they become unavailable as unique names, and the unique
// names used will start from allGrpPart_1, etc.
Utils.registerName("TYPE", "allGrpPart");
Utils.registerName("TYPE", "choice");
Utils.registerName("TYPE", "seq");
}}
before IncludeSchema
{{
String xsdIncludeFileName =
host.get_attrs().getAttributeValue(null, "schemaLocation");
if (xsdIncludeFileName.equals(""))
{
errors = errors + "\n" +
"No schemaLocation specified in Include element";
return;
}
try {
Schema.readDefinition(xsdIncludeFileName, def);
}
catch (Exception e) {
errors = errors + "\n" +
"Error in processing included schema-definition (" +
e.getMessage() + ")";
}
}}
before ImportSchema
{{
String xsdImportFileName =
host.get_attrs().getAttributeValue(null, "schemaLocation");
if (xsdImportFileName.equals(""))
{
errors = errors + "\n" +
"No schemaLocation specified in Import element";
return;
}
try {
Schema.readDefinition(xsdImportFileName, def);
}
catch (Exception e) {
errors = errors + "\n" +
"Error in processing imported schema-definition (" +
e.getMessage() + ")";
}
}}
before RedefineSchema
{{
String xsdRedefineFileName =
host.get_attrs().getAttributeValue(null, "schemaLocation");
if (xsdRedefineFileName.equals(""))
{
errors = errors + "\n" +
"No schemaLocation specified in Redefine element";
return;
}
try {
Schema.readDefinition(xsdRedefineFileName, def);
redefineMode = true;
}
catch (Exception e) {
errors = errors + "\n" +
"Error in processing redefined schema-definition (" +
e.getMessage() + ")";
}
}}
after RedefineSchema
{{
redefineMode = false;
}}
before Element
{{
String name, type;
// If it's a reference to another element, then lookup its type
name = host.get_attrs().getAttributeValue(null, "ref");
if (!name.equals("")) // it's a reference
{
type = getTypeOfElement(removeNSPrefix(name));
if (type.equals("")) // which is not expected to be true
{
errors = errors + "\n" +
"Global element " + name +
" not defined before its reference";
type = "Unknown";
}
}
else // it's a new element definition
{
name = host.get_attrs().getAttributeValue(null, "name");
type = host.get_attrs().getAttributeValue(null, "type");
if (!type.equals(""))
type = resolveXMLTypeName(type);
else
type = Utils.getUniqueName("TYPE", name + "Type");
}
Boolean nillable_flag = null;
String nillable_flag_attr =
host.get_attrs().getAttributeValue(null, "nillable");
if (nillable_flag_attr.equalsIgnoreCase("true"))
nillable_flag = new Boolean(true);
// 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())
{
Utils.registerName("ELEMENT", name);
DataElement newElement = new DataElement();
newElement.set_name(name);
newElement.set_type(type);
newElement.set_nillable_flag(nillable_flag);
// A global element may also be declared as "abstract"
String abstract_ind =
host.get_attrs().getAttributeValue(null, "abstract");
if (abstract_ind.equalsIgnoreCase("true"))
newElement.set_abstract_ind(new Boolean(true));
def.get_global_elements().put(name, newElement);
if (def.get_root_element() == null)
def.set_root_element(newElement);
elementStack.push(newElement);
}
else
{
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
ElementClassPart newClassPart = new ElementClassPart();
newClassPart.set_name(name);
newClassPart.set_type(type);
newClassPart.set_nillable_flag(nillable_flag);
Constraint cons = new Constraint();
cons.min_occurs = 1; cons.max_occurs = 1;
String occurrence;
occurrence = host.get_attrs().getAttributeValue(null, "minOccurs");
if (!occurrence.equals(""))
cons.min_occurs = Integer.parseInt(occurrence);
occurrence = host.get_attrs().getAttributeValue(null, "maxOccurs");
if (occurrence.equals("unbounded"))
cons.max_occurs = Integer.MAX_VALUE; // represents unbounded
else if (!occurrence.equals(""))
cons.max_occurs = Integer.parseInt(occurrence);
cons.fixed_value =
host.get_attrs().getAttributeValue(null, "fixed");
cons.default_value =
host.get_attrs().getAttributeValue(null, "default");
if ((cons.min_occurs == 0) && (cons.default_value.equals("")))
cons.default_value = cons.fixed_value;
if (cons.fixed_value.equals(""))
cons.fixed_value = null;
if (cons.default_value.equals(""))
cons.default_value = null;
// If the element is within an "All" group, then forcibly set the
// min and max-occurs attributes to 0 and 1, respectively
if (currentClass.get_category().equals("ALL-GROUP"))
{
cons.min_occurs = 0;
cons.max_occurs = 1;
}
// 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 = Utils.convertToObjectType(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(SubclassSpec_List.parse(""));
listUnitClass.set_attr_parts(AttrClassPart_List.parse(""));
listUnitClass.set_element_parts(ElementClassPart_List.parse(""));
Constraint listCons = new Constraint();
listCons.min_occurs = cons.min_occurs;
listCons.max_occurs = cons.max_occurs;
cons.min_occurs = 1; cons.max_occurs = 1;
newClassPart.set_constraint(cons);
addElementToClass(listUnitClass, newClassPart);
// Before adding the list unit class to the list of types, check
// if there already exists another listUnitClass exactly
// matching this definition
if (! matchingClassExists(listUnitClass))
{
listUnitName = Utils.getUniqueName("TYPE", listUnitName);
listUnitClass.set_name(listUnitName);
Utils.registerName("TYPE", listUnitName);
def.get_types().addElement(listUnitClass);
}
ElementClassPart listClassPart = new ElementClassPart();
listClassPart.set_name(listUnitName);
listClassPart.set_type(listUnitName);
listClassPart.set_constraint(listCons);
addElementToClass(currentClass, listClassPart);
}
else // not a list part
{
newClassPart.set_constraint(cons);
addElementToClass(currentClass, newClassPart);
}
elementStack.push(newClassPart);
}
}}
after Element
{{
elementStack.pop();
}}
before Attribute
{{
String name, type;
// If it's a reference to another attribute, then lookup its type
name = host.get_attrs().getAttributeValue(null, "ref");
if (!name.equals("")) // it's a reference
{
type = getTypeOfAttribute(removeNSPrefix(name));
if (type.equals("")) // which is not expected to be true
{
errors = errors + "\n" +
"Global attribute " + name +
" not defined before its reference";
type = "Unknown";
}
}
else // it's a new attribute definition
{
name = host.get_attrs().getAttributeValue(null, "name");
type = host.get_attrs().getAttributeValue(null, "type");
if (!type.equals(""))
type = resolveXMLTypeName(type);
else
type = Utils.getUniqueName("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 or
// the current attribute-group definition
if (elementStack.empty() && typeStack.empty() &&
(currentAttrGroup == null))
{
Utils.registerName("ATTRIBUTE", name);
DataElement newAttribute = new DataElement();
newAttribute.set_name(name);
newAttribute.set_type(type);
def.get_global_attributes().put(name, newAttribute);
attributeStack.push(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;
cons.fixed_value = ""; cons.default_value = "";
String occurrence;
occurrence = host.get_attrs().getAttributeValue(null, "use");
if (occurrence.equals("prohibited"))
cons.max_occurs = 0;
else if (occurrence.equals("required"))
{
cons.min_occurs = 1;
cons.fixed_value =
host.get_attrs().getAttributeValue(null, "fixed");
}
else if (occurrence.equals("fixed"))
{
cons.fixed_value =
host.get_attrs().getAttributeValue(null, "fixed");
cons.default_value = cons.fixed_value;
}
else if (occurrence.equals("default"))
cons.default_value =
host.get_attrs().getAttributeValue(null, "default");
if (cons.fixed_value.equals(""))
cons.fixed_value = null;
if (cons.default_value.equals(""))
cons.default_value = null;
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 = Utils.convertToObjectType(type);
newClassPart.set_type(type);
}
if (currentAttrGroup != null)
currentAttrGroup.get_attributes().addElement(newClassPart);
else
{
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass != null) // which should always be true
currentClass.get_attr_parts().addElement(newClassPart);
if (! ((cons.min_occurs == 0) && (cons.max_occurs == 0)))
{
int attrCount = ((Integer) attrCountStack.pop()).intValue();
attrCountStack.push(new Integer(attrCount+1));
}
}
attributeStack.push(newClassPart);
}
}}
after Attribute
{{
attributeStack.pop();
}}
before AttributeGroup
{{
// If it's a reference to an already defined attrGroup, then copy the
// attributes belonging to the group into the current entity (which can
// be another attribute group or a complexType)
String name = host.get_attrs().getAttributeValue(null, "ref");
if (! name.equals("")) // it's a reference
{
name = removeNSPrefix(name);
GlobalAttrGroup refGroup =
(GlobalAttrGroup) def.get_global_attribute_groups().get(name);
if (refGroup == null) // which is not expected to be true
{
errors = errors + "\n" +
"Attribute group " + name +
" not defined before its reference";
return;
}
else
{
DataClass currentClass;
if (currentAttrGroup != null) // the ref. is from another group
currentClass = null;
else // the ref. is from a complexType definition
{
currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
}
for (Enumeration attrs = refGroup.get_attributes().elements();
attrs.hasMoreElements(); )
{
AttrClassPart attr = (AttrClassPart) attrs.nextElement();
if (currentAttrGroup != null)
currentAttrGroup.get_attributes().addElement(attr);
else
{
currentClass.get_attr_parts().addElement(attr);
if (! ((attr.get_constraint().min_occurs == 0) &&
(attr.get_constraint().max_occurs == 0)))
{
int attrCount = ((Integer) attrCountStack.pop()).intValue();
attrCountStack.push(new Integer(attrCount+1));
}
}
}
}
}
else // it's a new attribute-group definition
{
name = host.get_attrs().getAttributeValue(null, "name");
// If this is under the "redefine" element and it's re-defining an
// existing attribute-group with the same name, then make it the
// current attribute-group and remove the previously defined
// attributes under it
GlobalAttrGroup prevDef =
(GlobalAttrGroup) def.get_global_attribute_groups().get(name);
if (redefineMode && (prevDef != null))
currentAttrGroup = prevDef;
else
{
currentAttrGroup = new GlobalAttrGroup();
currentAttrGroup.set_name(name);
def.get_global_attribute_groups().put(name, currentAttrGroup);
}
currentAttrGroup.set_attributes(AttrClassPart_List.parse(""));
}
}}
after AttributeGroup
{{
currentAttrGroup = null;
}}
before ElementGroup
{{
// If it's a reference to an already defined group, then create an
// element class part with the same name as the group and with the type
// set to the class representing the group
String name = host.get_attrs().getAttributeValue(null, "ref");
if (! name.equals("")) // it's a reference
{
name = removeNSPrefix(name);
String groupClassName = (String) def.get_global_groups().get(name);
if (groupClassName == null) // which is not expected to be true
{
errors = errors + "\n" +
"Group " + name + " not defined before its reference";
return;
}
else
{
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
ElementClassPart newClassPart = new ElementClassPart();
newClassPart.set_name(name);
newClassPart.set_type(groupClassName);
Constraint cons = new Constraint();
cons.min_occurs = 1; cons.max_occurs = 1;
String occurrence;
occurrence = host.get_attrs().getAttributeValue(null, "minOccurs");
if (!occurrence.equals(""))
cons.min_occurs = Integer.parseInt(occurrence);
occurrence = host.get_attrs().getAttributeValue(null, "maxOccurs");
if (occurrence.equals("unbounded"))
cons.max_occurs = Integer.MAX_VALUE; // represents unbounded
else if (!occurrence.equals(""))
cons.max_occurs = Integer.parseInt(occurrence);
cons.group_part_flag = new Boolean(true);
newClassPart.set_constraint(cons);
addElementToClass(currentClass, newClassPart);
}
}
else // it's a new group definition
{
name = host.get_attrs().getAttributeValue(null, "name");
String groupClassName;
DataClass groupClass = null;
// If this is under the "redefine" element and it's re-defining an
// existing element-group with the same name, then use the
// previously created class to represent the group-elements
if (redefineMode)
{
String prevGroupClassName =
(String) def.get_global_groups().get(name);
if (prevGroupClassName != null)
{
for (Enumeration elems = def.get_types().elements();
elems.hasMoreElements(); )
{
DataClass c = (DataClass) elems.nextElement();
if (c.get_name().equals(prevGroupClassName))
{
groupClass = c;
groupClassName = c.get_name();
break;
}
}
}
}
if (groupClass == null)
{
groupClassName = Utils.getUniqueName("TYPE", name + "Group");
Utils.registerName("TYPE", groupClassName);
def.get_global_groups().put(name, groupClassName);
groupClass = new DataClass();
groupClass.set_name(groupClassName);
groupClass.set_category("GROUP");
groupClass.set_abstract_ind(false);
groupClass.set_subclasses(SubclassSpec_List.parse(""));
def.get_types().addElement(groupClass);
}
groupClass.set_attr_parts(AttrClassPart_List.parse(""));
groupClass.set_element_parts(ElementClassPart_List.parse(""));
typeStack.push(groupClass);
attrCountStack.push(new Integer(0));
}
}}
after ElementGroup
{{
// If it was a new group definition, then pop the dataclass representing
// it from the typeStack
if (host.get_attrs().getAttributeValue(null, "ref").equals(""))
{
typeStack.pop();
attrCountStack.pop();
}
}}
before AllGroup
{{
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
// Convert the "all" group to a DataClass, and add an element class-
// part (of that type) to the current class to hold the place of the
// ""all"" group
String groupClassName =
Utils.getUniqueName("TYPE", currentClass.get_name() + "AllGrp");
Utils.registerName("TYPE", groupClassName);
// First, add an element-class-part to the current class that will
// hold the place of this group
ElementClassPart newClassPart = new ElementClassPart();
newClassPart.set_name(groupClassName);
newClassPart.set_type(groupClassName);
Constraint cons = new Constraint();
cons.min_occurs = 0; cons.max_occurs = Integer.MAX_VALUE;
cons.group_part_flag = new Boolean(true);
cons.all_group_flag = new Boolean(true);
newClassPart.set_constraint(cons);
addElementToClass(currentClass, newClassPart);
// And, create a dataclass to represent the group
DataClass groupClass = new DataClass();
groupClass.set_name(groupClassName);
groupClass.set_category("ALL-GROUP");
groupClass.set_abstract_ind(true);
groupClass.set_subclasses(SubclassSpec_List.parse(""));
groupClass.set_attr_parts(AttrClassPart_List.parse(""));
groupClass.set_element_parts(ElementClassPart_List.parse(""));
def.get_types().addElement(groupClass);
typeStack.push(groupClass);
attrCountStack.push(new Integer(0));
}}
after AllGroup
{{
// Pop the dataclass representing the all-group from the typeStack
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass != null) // which should always be true
{
typeStack.pop();
attrCountStack.pop();
}
}}
before ChoiceGroup
{{
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which is not expected to be true
return;
// Convert the choice group to a DataClass, and add an element class-
// part (of that type) to the current class to hold the place of the
// "Choice" group
String groupClassName =
Utils.getUniqueName("TYPE", currentClass.get_name() + "Choice");
Utils.registerName("TYPE", groupClassName);
// First, add an element-class-part to the current class that will
// hold the place of this group
ElementClassPart newClassPart = new ElementClassPart();
newClassPart.set_name(groupClassName);
newClassPart.set_type(groupClassName);
Constraint cons = new Constraint();
cons.min_occurs = 1; cons.max_occurs = 1;
String occurrence;
occurrence = host.get_attrs().getAttributeValue(null, "minOccurs");
if (!occurrence.equals(""))
cons.min_occurs = Integer.parseInt(occurrence);
occurrence = host.get_attrs().getAttributeValue(null, "maxOccurs");
if (occurrence.equals("unbounded"))
cons.max_occurs = Integer.MAX_VALUE; // represents unbounded
else if (!occurrence.equals(""))
cons.max_occurs = Integer.parseInt(occurrence);
cons.group_part_flag = new Boolean(true);
newClassPart.set_constraint(cons);
addElementToClass(currentClass, newClassPart);
// And, create a dataclass to represent the group
DataClass groupClass = new DataClass();
groupClass.set_name(groupClassName);
groupClass.set_category("CHOICE-GROUP");
groupClass.set_abstract_ind(true);
groupClass.set_subclasses(SubclassSpec_List.parse(""));
groupClass.set_attr_parts(AttrClassPart_List.parse(""));
groupClass.set_element_parts(ElementClassPart_List.parse(""));
def.get_types().addElement(groupClass);
typeStack.push(groupClass);
attrCountStack.push(new Integer(0));
}}
after ChoiceGroup
{{
// Pop the dataclass representing the choice-group from the typeStack
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass != null) // which should always be true
{
typeStack.pop();
attrCountStack.pop();
}
}}
before SequenceGroup
{{
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which is not expected to be true
return;
// If this group is defined under another "Choice" group or if it is
// defined to be a list part, then it is converted to a DataClass, and
// an element-class-part (of that type) is added to the current class to
// hold the place of the "Sequence" group
Constraint cons = new Constraint();
cons.min_occurs = 1; cons.max_occurs = 1;
String occurrence;
occurrence = host.get_attrs().getAttributeValue(null, "minOccurs");
if (!occurrence.equals(""))
cons.min_occurs = Integer.parseInt(occurrence);
occurrence = host.get_attrs().getAttributeValue(null, "maxOccurs");
if (occurrence.equals("unbounded"))
cons.max_occurs = Integer.MAX_VALUE; // represents unbounded
else if (!occurrence.equals(""))
cons.max_occurs = Integer.parseInt(occurrence);
if (((currentClass.get_category().equals("CHOICE-GROUP"))) ||
(cons.max_occurs > 1))
{
String groupClassName = Utils.getUniqueName("TYPE", "seq");
Utils.registerName("TYPE", groupClassName);
// First, add an element-class-part to the current class that will
// hold the place of this group
ElementClassPart newClassPart = new ElementClassPart();
newClassPart.set_name(groupClassName);
newClassPart.set_type(groupClassName);
cons.group_part_flag = new Boolean(true);
newClassPart.set_constraint(cons);
addElementToClass(currentClass, newClassPart);
// Now, create a dataclass to represent the group
DataClass groupClass = new DataClass();
groupClass.set_name(groupClassName);
groupClass.set_category("SEQ-GROUP");
groupClass.set_abstract_ind(false);
groupClass.set_subclasses(SubclassSpec_List.parse(""));
groupClass.set_attr_parts(AttrClassPart_List.parse(""));
groupClass.set_element_parts(ElementClassPart_List.parse(""));
def.get_types().addElement(groupClass);
typeStack.push(groupClass);
attrCountStack.push(new Integer(0));
}
}}
after SequenceGroup
{{
// If this group was converted to a class, then pop the dataclass
// representing it from the typeStack
DataClass currentClass = (DataClass) typeStack.peek();
if ((currentClass != null) &&
(currentClass.get_category().equals("SEQ-GROUP")))
{
typeStack.pop();
attrCountStack.pop();
}
}}
before TypeDef
{{
// If this is a global type, then it must have a name, otherwise it's
// anonymous and name it after the enclosing attribute or element
String name;
DataClass newType = null;
if (! attributeStack.empty())
name = ((DataItem) attributeStack.peek()).get_type();
else if (! elementStack.empty())
name = ((DataItem) elementStack.peek()).get_type();
else // if (elementStack.empty())
{
name = host.get_attrs().getAttributeValue(null, "name");
// If this is under the "redefine" element then the existing type
// defintion with that name has to be replaced by the new definition
if (redefineMode)
{
for (Enumeration elems = def.get_types().elements();
elems.hasMoreElements(); )
{
DataClass c = (DataClass) elems.nextElement();
if (c.get_name().equals(name))
{
newType = c;
break;
}
}
}
}
Utils.registerName("TYPE", name);
if (newType == null)
{
newType = new DataClass();
newType.set_name(name);
newType.set_category("");
newType.set_abstract_ind(false);
newType.set_subclasses(SubclassSpec_List.parse(""));
newType.set_attr_parts(AttrClassPart_List.parse(""));
newType.set_element_parts(ElementClassPart_List.parse(""));
def.get_types().addElement(newType);
}
typeStack.push(newType);
attrCountStack.push(new Integer(0));
}}
after TypeDef
{{
typeStack.pop();
attrCountStack.pop();
}}
before ComplexType
{{
DataClass currentType = (DataClass) typeStack.peek();
currentType.set_category("COMPLEX");
String abstract_ind =
host.get_attrs().getAttributeValue(null, "abstract");
currentType.set_abstract_ind(
Boolean.valueOf(abstract_ind).booleanValue());
// If this type has "mixed" content, then add a "filler" part as the
// first element
String mixed_flag = host.get_attrs().getAttributeValue(null, "mixed");
if (mixed_flag.equalsIgnoreCase("true"))
{
currentType.set_mixed_content_ind(new Boolean(mixed_flag));
// Make a dummy registration to reserve the name "filler"
Utils.registerName(currentType.get_name(), "ELEMENT", "filler");
String fillerName =
Utils.getUniqueName(currentType.get_name(), "ELEMENT",
"filler");
Utils.registerName(currentType.get_name(), "ELEMENT", fillerName);
ElementClassPart fillerPart = new ElementClassPart();
fillerPart.set_name(fillerName);
fillerPart.set_type("String");
fillerPart.set_filler_flag(new Boolean(true));
Constraint cons = new Constraint();
cons.min_occurs = 0; cons.max_occurs = 1;
fillerPart.set_constraint(cons);
currentType.get_element_parts().addElement(fillerPart);
}
}}
before SimpleType
{{
((DataClass) typeStack.peek()).set_category("SIMPLE");
}}
before TypeDerivation
{{
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
String baseType = removeNSPrefix(
host.get_attrs().getAttributeValue(null, "base"));
// If this is under the "redefine" element and it's deriving from the
// existing type with the same name, then nothing needs to be done here
if (redefineMode && baseType.equals(currentClass.get_name()))
return;
// Also if it's deriving from "anyType", then nothing needs to be done
if (baseType.equals("anyType"))
return;
if (Utils.isBuiltInXMLType(baseType))
{
baseType = resolveXMLTypeName(baseType);
ElementClassPart newClassPart = new ElementClassPart();
newClassPart.set_name("value");
newClassPart.set_type(baseType);
Constraint cons = new Constraint();
cons.min_occurs = 1; cons.max_occurs = 1;
newClassPart.set_constraint(cons);
addElementToClass(currentClass, newClassPart);
}
else if (! baseType.equals("anyType"))
{
DataClass baseClass = findDataClass(baseType);
if (baseClass == null) // which is not expected to be true
{
errors = errors + "\n" +
"Base type " + baseType +
" not defined before its reference";
return;
}
currentClass.set_superclass(baseType);
currentClass.set_superclass_abstract_ind(
new Boolean(baseClass.get_abstract_ind()));
}
}}
before Extension
{{
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
String baseType = removeNSPrefix(
host.get_attrs().getAttributeValue(null, "base"));
// If this is under the "redefine" element and it's extending the
// existing type with the same name, then nothing needs to be done here
// because the "base" class-parts are already part of the current class
if (redefineMode && baseType.equals(currentClass.get_name()))
return;
// Also if it's extending "anyType", then nothing needs to be done
if (baseType.equals("anyType"))
return;
if (!Utils.isBuiltInXMLType(baseType))
{
DataClass baseClass = findDataClass(baseType);
if (baseClass == null) // which is not expected to be true
return;
// Copy all parts (attributes and elements) from the base class
// into the derived class - to create a flattened structure
for (Enumeration attrs = baseClass.get_attr_parts().elements();
attrs.hasMoreElements(); )
{
AttrClassPart a = (AttrClassPart) attrs.nextElement();
currentClass.get_attr_parts().addElement(a);
if (! ((a.get_constraint().min_occurs == 0) &&
(a.get_constraint().max_occurs == 0)))
{
int attrCount = ((Integer) attrCountStack.pop()).intValue();
attrCountStack.push(new Integer(attrCount+1));
}
}
for (Enumeration elems = baseClass.get_element_parts().elements();
elems.hasMoreElements(); )
{
ElementClassPart e = (ElementClassPart) elems.nextElement();
addElementToClass(currentClass, e);
}
}
}}
before Restriction
{{
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
String baseType = removeNSPrefix(
host.get_attrs().getAttributeValue(null, "base"));
// If it's restriction "anyType", then nothing needs to be done
if (baseType.equals("anyType"))
return;
// If this is under the "redefine" element and it's restricting the
// existing type with the same name, then the "base" class-parts are
// already part of the current class. So, for restriction of a simple
// type, noting should be done here; but for restriction of a complex
// type, the class-parts have to be removed (because they will all be
// specified again).
if (!Utils.isBuiltInXMLType(baseType))
{
DataClass baseClass;
if (redefineMode && baseType.equals(currentClass.get_name()))
baseClass = currentClass;
else
{
baseClass = findDataClass(baseType);
if (baseClass == null) // which is not expected to be true
return;
}
if (baseClass.get_category().equals("SIMPLE"))
{
if (redefineMode && (baseClass == currentClass))
return;
// Copy all parts (attributes and elements) from the base class
// into the derived class - to create a flattened structure
for (Enumeration attrs = baseClass.get_attr_parts().elements();
attrs.hasMoreElements(); )
{
AttrClassPart a = (AttrClassPart) attrs.nextElement();
currentClass.get_attr_parts().addElement(a);
if (! ((a.get_constraint().min_occurs == 0) &&
(a.get_constraint().max_occurs == 0)))
{
int attrCount = ((Integer) attrCountStack.pop()).intValue();
attrCountStack.push(new Integer(attrCount+1));
}
}
for (Enumeration elems = baseClass.get_element_parts().elements();
elems.hasMoreElements(); )
{
ElementClassPart e = (ElementClassPart) elems.nextElement();
addElementToClass(currentClass, e);
}
}
else // it's a restriction of a complexType
{
if (redefineMode && (baseClass == currentClass))
{
currentClass.set_attr_parts(AttrClassPart_List.parse(""));
currentClass.set_element_parts(ElementClassPart_List.parse(""));
}
}
}
}}
after TypeDerivation
{{
// Add this class to the list of subclasses for the base class (if any)
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
String baseType = removeNSPrefix(
host.get_attrs().getAttributeValue(null, "base"));
// If this is under the "redefine" element and it's extending the
// existing type with the same name, then nothing needs to be done here
// because the "base" and current classes are the same
if (redefineMode && baseType.equals(currentClass.get_name()))
return;
// Also if it's deriving from "anyType", then nothing needs to be done
if (baseType.equals("anyType"))
return;
if (!Utils.isBuiltInXMLType(baseType))
{
DataClass baseClass = findDataClass(baseType);
if (baseClass == null) // which is not expected to be true
return;
// If the superclass is abstract, compute the lookahead needed to
// correctly identify the current concrete class for parsing and
// include that in the subclass list for the superclass;
// otherwise just use the classname
int lookaheadCount = 0;
if ((currentClass.get_superclass_abstract_ind() != null) &&
(currentClass.get_superclass_abstract_ind().booleanValue()))
{
lookaheadCount =
(((Integer) attrCountStack.peek()).intValue()+1) * 3;
}
baseClass.get_subclasses().addElement(
new SubclassSpec(currentClass.get_name(), lookaheadCount));
}
}}
// Constraining facets are defined only for simpleTypes; so just pick the
// first (which also happens to be the only) element, and update its
// constraint with the respective value in each case
before EnumerationSpec
{{
String value = host.get_attrs().getAttributeValue(null, "value");
if (value.equals(""))
return;
value = "" + value + "";
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
Constraint cons = null;
for (Enumeration elems = currentClass.get_element_parts().elements();
elems.hasMoreElements(); )
{
ElementClassPart e = (ElementClassPart) elems.nextElement();
cons = e.get_constraint();
break;
}
if (cons != null)
{
if (cons.get_enum_values() == null)
cons.set_enum_values(value);
else
cons.set_enum_values(cons.get_enum_values() + value);
}
}}
before LengthSpec
{{
String value = host.get_attrs().getAttributeValue(null, "value");
if (value.equals(""))
return;
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
Constraint cons = null;
for (Enumeration elems = currentClass.get_element_parts().elements();
elems.hasMoreElements(); )
{
ElementClassPart e = (ElementClassPart) elems.nextElement();
cons = e.get_constraint();
break;
}
if (cons != null)
cons.set_length(new Integer(value));
}}
before MaxLength
{{
String value = host.get_attrs().getAttributeValue(null, "value");
if (value.equals(""))
return;
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
Constraint cons = null;
for (Enumeration elems = currentClass.get_element_parts().elements();
elems.hasMoreElements(); )
{
ElementClassPart e = (ElementClassPart) elems.nextElement();
cons = e.get_constraint();
break;
}
if (cons != null)
cons.set_max_length(new Integer(value));
}}
before MinLength
{{
String value = host.get_attrs().getAttributeValue(null, "value");
if (value.equals(""))
return;
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
Constraint cons = null;
for (Enumeration elems = currentClass.get_element_parts().elements();
elems.hasMoreElements(); )
{
ElementClassPart e = (ElementClassPart) elems.nextElement();
cons = e.get_constraint();
break;
}
if (cons != null)
cons.set_min_length(new Integer(value));
}}
before MaxExclusive
{{
String value = host.get_attrs().getAttributeValue(null, "value");
if (value.equals(""))
return;
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
Constraint cons = null;
for (Enumeration elems = currentClass.get_element_parts().elements();
elems.hasMoreElements(); )
{
ElementClassPart e = (ElementClassPart) elems.nextElement();
cons = e.get_constraint();
break;
}
if (cons != null)
{
cons.set_max_value(value);
cons.set_max_included(new Boolean(false));
}
}}
before MaxInclusive
{{
String value = host.get_attrs().getAttributeValue(null, "value");
if (value.equals(""))
return;
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
Constraint cons = null;
for (Enumeration elems = currentClass.get_element_parts().elements();
elems.hasMoreElements(); )
{
ElementClassPart e = (ElementClassPart) elems.nextElement();
cons = e.get_constraint();
break;
}
if (cons != null)
{
cons.set_max_value(value);
cons.set_max_included(new Boolean(true));
}
}}
before MinExclusive
{{
String value = host.get_attrs().getAttributeValue(null, "value");
if (value.equals(""))
return;
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
Constraint cons = null;
for (Enumeration elems = currentClass.get_element_parts().elements();
elems.hasMoreElements(); )
{
ElementClassPart e = (ElementClassPart) elems.nextElement();
cons = e.get_constraint();
break;
}
if (cons != null)
{
cons.set_min_value(value);
cons.set_min_included(new Boolean(false));
}
}}
before MinInclusive
{{
String value = host.get_attrs().getAttributeValue(null, "value");
if (value.equals(""))
return;
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
Constraint cons = null;
for (Enumeration elems = currentClass.get_element_parts().elements();
elems.hasMoreElements(); )
{
ElementClassPart e = (ElementClassPart) elems.nextElement();
cons = e.get_constraint();
break;
}
if (cons != null)
{
cons.set_min_value(value);
cons.set_min_included(new Boolean(true));
}
}}
before Pattern
{{
String value = host.get_attrs().getAttributeValue(null, "value");
if (value.equals(""))
return;
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
Constraint cons = null;
for (Enumeration elems = currentClass.get_element_parts().elements();
elems.hasMoreElements(); )
{
ElementClassPart e = (ElementClassPart) elems.nextElement();
cons = e.get_constraint();
break;
}
if (cons != null)
cons.set_pattern(value);
}}
before TotalDigits
{{
String value = host.get_attrs().getAttributeValue(null, "value");
if (value.equals(""))
return;
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
Constraint cons = null;
for (Enumeration elems = currentClass.get_element_parts().elements();
elems.hasMoreElements(); )
{
ElementClassPart e = (ElementClassPart) elems.nextElement();
cons = e.get_constraint();
break;
}
if (cons != null)
cons.set_total_digits(new Integer(value));
}}
before FractionDigits
{{
String value = host.get_attrs().getAttributeValue(null, "value");
if (value.equals(""))
return;
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
Constraint cons = null;
for (Enumeration elems = currentClass.get_element_parts().elements();
elems.hasMoreElements(); )
{
ElementClassPart e = (ElementClassPart) elems.nextElement();
cons = e.get_constraint();
break;
}
if (cons != null)
cons.set_fraction_digits(new Integer(value));
}}
before Whitespace
{{
String value = host.get_attrs().getAttributeValue(null, "value");
if (value.equals(""))
return;
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
Constraint cons = null;
for (Enumeration elems = currentClass.get_element_parts().elements();
elems.hasMoreElements(); )
{
ElementClassPart e = (ElementClassPart) elems.nextElement();
cons = e.get_constraint();
break;
}
if (cons != null)
cons.set_whitespace(value);
}}
before ListVariety
{{
DataClass currentClass = (DataClass) typeStack.peek();
if (currentClass == null) // which should never be true
return;
String unitType = host.get_attrs().getAttributeValue(null, "itemType");
if (!unitType.equals(""))
unitType = Utils.convertToObjectType(resolveXMLTypeName(unitType));
else
unitType = currentClass.get_name() + "Item";
ElementClassPart newClassPart = new ElementClassPart();
newClassPart.set_name("value");
newClassPart.set_type(unitType);
Constraint cons = new Constraint();
cons.min_occurs = 0; cons.max_occurs = Integer.MAX_VALUE;
newClassPart.set_constraint(cons);
addElementToClass(currentClass, newClassPart);
elementStack.push(newClassPart);
}}
after ListVariety
{{
elementStack.pop();
}}
before UnionVariety
{{
// NOT IMPLEMENTED
}}
public String getErrors()
{{
return errors;
}}
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)
{{
Utils.TypeInfo typeinfo =
Utils.resolveXMLTypeName(removeNSPrefix(XMLType));
if ((typeinfo.category == Utils.BUILT_IN_NON_JAVA_TYPE) &&
(!def.get_types().contains(typeinfo.classDef)))
{
def.get_types().addElement(typeinfo.classDef);
}
if ((typeinfo.listUnitClassDef != null) &&
(!def.get_types().contains(typeinfo.listUnitClassDef)))
{
def.get_types().addElement(typeinfo.listUnitClassDef);
}
return typeinfo.typeName;
}}
private DataClass findDataClass(String className)
{{
for (Enumeration elems = def.get_types().elements();
elems.hasMoreElements(); )
{
DataClass c = (DataClass) elems.nextElement();
if (c.get_name().equals(className))
return c;
}
return null;
}}
private void addElementToClass(DataClass currentClass,
ElementClassPart classPart)
{{
if (currentClass != null)
{
if (((currentClass.get_category().equals("CHOICE-GROUP"))) ||
(currentClass.get_category().equals("ALL-GROUP")))
{
String groupClassName;
if ((currentClass.get_category().equals("CHOICE-GROUP")))
groupClassName = Utils.getUniqueName("TYPE", "choice");
else // it's an "ALL-GROUP"
groupClassName = Utils.getUniqueName("TYPE", "allGrpPart");
Utils.registerName("TYPE", groupClassName);
// Create a dataclass (as a sub-class of the current class) to
// contain the "choice" or "all" element
currentClass.get_subclasses().addElement(
new SubclassSpec(groupClassName, 0));
DataClass groupClass = new DataClass();
groupClass.set_name(groupClassName);
groupClass.set_category("GROUP");
groupClass.set_abstract_ind(false);
groupClass.set_superclass(currentClass.get_name());
groupClass.set_superclass_abstract_ind(
new Boolean(currentClass.get_abstract_ind()));
groupClass.set_subclasses(SubclassSpec_List.parse(""));
groupClass.set_attr_parts(AttrClassPart_List.parse(""));
groupClass.set_element_parts(ElementClassPart_List.parse(""));
// Add the group-part element to this class, instead of directly
// adding it to the current class
classPart.get_constraint().min_occurs = 1;
classPart.get_constraint().max_occurs = 1;
groupClass.get_element_parts().addElement(classPart);
def.get_types().addElement(groupClass);
}
else
{
currentClass.get_element_parts().addElement(classPart);
// If this class-part belongs to a complexType with "mixed"
// content, then add a "filler" part after this part
if ((currentClass.get_mixed_content_ind() != null) &&
(currentClass.get_mixed_content_ind().booleanValue()))
{
String fillerName =
Utils.getUniqueName(currentClass.get_name(), "ELEMENT",
"filler");
Utils.registerName(currentClass.get_name(), "ELEMENT",
fillerName);
ElementClassPart fillerPart = new ElementClassPart();
fillerPart.set_name(fillerName);
fillerPart.set_type("String");
fillerPart.set_filler_flag(new Boolean(true));
Constraint cons = new Constraint();
cons.min_occurs = 0; cons.max_occurs = 1;
fillerPart.set_constraint(cons);
currentClass.get_element_parts().addElement(fillerPart);
}
}
}
}}
private boolean matchingClassExists(DataClass newClass)
{{
DataClass oldClass = null;
// first check, if another class with this name exists at all
for (Enumeration elems = def.get_types().elements();
elems.hasMoreElements(); )
{
DataClass c = (DataClass) elems.nextElement();
if (c.get_name().equals(newClass.get_name()))
{
oldClass = c;
break;
}
}
if (oldClass == null)
return false;
// Check if the category matches
if (! oldClass.get_category().equals(newClass.get_category()))
return false;
Vector oldClassParts;
Vector newClassParts;
// Check if the attribute-definitions match
oldClassParts = new Vector();
for (Enumeration elems = oldClass.get_attr_parts().elements();
elems.hasMoreElements(); )
{
oldClassParts.add((AttrClassPart) elems.nextElement());
}
newClassParts = new Vector();
for (Enumeration elems = newClass.get_attr_parts().elements();
elems.hasMoreElements(); )
{
newClassParts.add((AttrClassPart) elems.nextElement());
}
if (oldClassParts.size() != newClassParts.size())
return false;
for (int i = 0; i < oldClassParts.size(); i++)
{
AttrClassPart oldC, newC;
oldC = (AttrClassPart) oldClassParts.get(i);
newC = (AttrClassPart) newClassParts.get(i);
if ((! oldC.get_name().equals(newC.get_name())) ||
(! oldC.get_type().equals(newC.get_type())))
return false;
}
// Check if the element-definitions match
oldClassParts = new Vector();
for (Enumeration elems = oldClass.get_element_parts().elements();
elems.hasMoreElements(); )
{
oldClassParts.add((ElementClassPart) elems.nextElement());
}
newClassParts = new Vector();
for (Enumeration elems = newClass.get_element_parts().elements();
elems.hasMoreElements(); )
{
newClassParts.add((ElementClassPart) elems.nextElement());
}
if (oldClassParts.size() != newClassParts.size())
return false;
for (int i = 0; i < oldClassParts.size(); i++)
{
ElementClassPart oldC, newC;
oldC = (ElementClassPart) oldClassParts.get(i);
newC = (ElementClassPart) newClassParts.get(i);
if ((! oldC.get_name().equals(newC.get_name())) ||
(! oldC.get_type().equals(newC.get_type())))
return false;
}
return true;
}}
}
TypeDef {
public abstract AttrValue_List get_attrs();
}
TypeDerivation {
public abstract AttrValue_List get_attrs();
}