blob: 6b8ad63ca25be53c47fd0e108c9c2fc3c25a7440 [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.sdo.helper;
import commonj.sdo.Property;
import commonj.sdo.Type;
import commonj.sdo.helper.HelperContext;
import java.io.StringWriter;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.xml.namespace.QName;
import org.eclipse.persistence.sdo.SDOConstants;
import org.eclipse.persistence.sdo.SDOProperty;
import org.eclipse.persistence.sdo.SDOType;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.oxm.Namespace;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.internal.oxm.schema.SchemaModelProject;
import org.eclipse.persistence.internal.oxm.schema.model.*;
import org.eclipse.persistence.oxm.XMLConstants;
import org.eclipse.persistence.oxm.XMLContext;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLLogin;
import org.eclipse.persistence.oxm.XMLMarshaller;
import org.eclipse.persistence.oxm.platform.DOMPlatform;
import org.eclipse.persistence.sessions.Project;
/**
* <p><b>Purpose</b> SDOSchemaGenerator generates an XSD (returned as a String)
* from a list of SDO Type objects. Populates an org.eclipse.persistence.internal.oxm.schema.model.Schema
* object and makes use of org.eclipse.persistence.internal.oxm.schema.SchemaModelProject to marshal
* the Schema Object to XML.
* @see commonj.sdo.helper.XSDHelper
*/
public class SDOSchemaGenerator {
private Map<String, String> namespaceToSchemaLocation;
private SchemaLocationResolver schemaLocationResolver;
private List allTypes;
private Schema generatedSchema;
// hold the context containing all helpers so that we can preserve inter-helper relationships
private HelperContext aHelperContext;
public SDOSchemaGenerator(HelperContext aContext) {
aHelperContext = aContext;
}
/**
* <p>Method to generate an XSD. Note the following:<ul>
* <li> All types must have same URI
* <li> Referenced types in same URI will also be generated in schema
* <li> Includes will never be generated
* <li> Imports will be generated for referenced types in other URIs
* </ul>
* @param types The list of commonj.sdo.Type objects to generate the XSD from
* @param aSchemaLocationResolver implementation of the org.eclipse.persistence.sdo.helper.SchemaLocationResolver interface
* used for getting the value of the schemaLocation attribute of generated imports and includes
* @return String The generated XSD.
*/
public String generate(List types, SchemaLocationResolver aSchemaLocationResolver) {
schemaLocationResolver = aSchemaLocationResolver;
if ((types == null) || (types.size() == 0)) {
throw new IllegalArgumentException("No Schema was generated from null or empty list of types.");
}
String uri = null;
Type firstType = (Type)types.get(0);
uri = firstType.getURI();
allTypes = types;
generateSchema(uri, types);
//Now we have a built schema model
Project p = new SchemaModelProject();
Vector<Namespace> generatedNamespaces = generatedSchema.getNamespaceResolver().getNamespaces();
XMLDescriptor desc = ((XMLDescriptor)p.getDescriptor(Schema.class));
for (int i = 0; i < generatedNamespaces.size(); i++) {
Namespace next = generatedNamespaces.get(i);
desc.getNamespaceResolver().put(next.getPrefix(), next.getNamespaceURI());
if (next.getNamespaceURI().equals(SDOConstants.SDO_URL) || next.getNamespaceURI().equals(SDOConstants.SDOXML_URL) || next.getNamespaceURI().equals(SDOConstants.SDOJAVA_URL)) {
if (!importExists(generatedSchema.getImports(), next.getNamespaceURI())) {
Import theImport = new Import();
theImport.setNamespace(next.getNamespaceURI());
String schemaLocation = "classpath:/xml/";
String customLocation = null;
if (next.getNamespaceURI().equals(SDOConstants.SDO_URL)) {
if(schemaLocationResolver != null) {
customLocation = schemaLocationResolver.resolveSchemaLocation(firstType, SDOConstants.SDO_BOOLEAN);
}
if(customLocation != null) {
schemaLocation = customLocation;
} else {
schemaLocation += "sdoModel.xsd";
}
} else if (next.getNamespaceURI().equals(SDOConstants.SDOXML_URL)) {
if(schemaLocationResolver != null) {
customLocation = schemaLocationResolver.resolveSchemaLocation(firstType, new SDOType(SDOConstants.SDOXML_URL, "XMLInfo"));
}
if(customLocation != null) {
schemaLocation = customLocation;
} else {
schemaLocation += "sdoXML.xsd";
}
} else if (next.getNamespaceURI().equals(SDOConstants.SDOJAVA_URL)) {
if(schemaLocationResolver != null) {
customLocation = schemaLocationResolver.resolveSchemaLocation(firstType, SDOConstants.SDO_BOOLEANOBJECT);
}
if(customLocation != null) {
schemaLocation = customLocation;
} else {
schemaLocation += "sdoJava.xsd";
}
}
theImport.setSchemaLocation(schemaLocation);
generatedSchema.getImports().add(theImport);
}
}
}
XMLLogin login = new XMLLogin();
login.setDatasourcePlatform(new DOMPlatform());
p.setDatasourceLogin(login);
XMLContext context = new XMLContext(p);
XMLMarshaller marshaller = context.createMarshaller();
StringWriter generatedSchemaWriter = new StringWriter();
marshaller.marshal(generatedSchema, generatedSchemaWriter);
return generatedSchemaWriter.toString();
}
/**
* <p>Method to generate an XSD. Note the following:<ul>
* <li> All types must have same URI
* <li> Referenced types in same URI will also be generated in schema
* <li> Includes will never be generated
* <li> Imports will be generated for referenced types in other URIs
* </ul>
* @param types The list of commonj.sdo.Type objects to generate the XSD from
* @param aNamespaceToSchemaLocation map of namespaces to schemaLocations
* used for getting the value of the schemaLocation attribute of generated imports and includes
* @return String The generated XSD.
*/
public String generate(List types, Map<String, String> aNamespaceToSchemaLocation) {
if ((types == null) || (types.size() == 0)) {
throw new IllegalArgumentException("No Schema was generated from null or empty list of types.");
}
String uri = null;
namespaceToSchemaLocation = aNamespaceToSchemaLocation;
Type firstType = (Type)types.get(0);
if (firstType == null) {
throw new IllegalArgumentException("No Schema was generated from a list of types containing null elements");
} else {
uri = firstType.getURI();
}
allTypes = types;
generateSchema(uri, types);
//Now we have a built schema model
Project p = new SchemaModelProject();
Vector<Namespace> namespaces = generatedSchema.getNamespaceResolver().getNamespaces();
for (int i = 0; i < namespaces.size(); i++) {
Namespace next = namespaces.get(i);
((XMLDescriptor)p.getDescriptor(Schema.class)).getNamespaceResolver().put(next.getPrefix(), next.getNamespaceURI());
}
XMLLogin login = new XMLLogin();
login.setDatasourcePlatform(new DOMPlatform());
p.setDatasourceLogin(login);
XMLContext context = new XMLContext(p);
XMLMarshaller marshaller = context.createMarshaller();
StringWriter generatedSchemaWriter = new StringWriter();
marshaller.marshal(generatedSchema, generatedSchemaWriter);
return generatedSchemaWriter.toString();
}
private void generateSchema(String uri, List typesWithSameUri) {
generatedSchema = new Schema();
generatedSchema.setTargetNamespace(uri);
generatedSchema.setDefaultNamespace(uri);
generatedSchema.setAttributeFormDefault(false);
generatedSchema.setElementFormDefault(true);
String javaPackage = null;
for (int i = 0; i < typesWithSameUri.size(); i++) {
SDOType nextType = (SDOType)typesWithSameUri.get(i);
if (nextType.isSubType()) {
//A schema can not be generated because the following type has more than 1 base type + type
}
if (!nextType.isDataType()) {
String fullName = nextType.getInstanceClassName();
if (fullName != null) {
String nextPackage = null;
int lastDot = fullName.lastIndexOf('.');
if (lastDot != -1) {
nextPackage = fullName.substring(0, lastDot);
}
if (nextPackage != null) {
javaPackage = nextPackage;
}
}
}
if (nextType.isDataType()) {
//generate simple type
SimpleType generatedType = generateSimpleType(nextType);
generatedSchema.addTopLevelSimpleTypes(generatedType);
} else {
//generate complex type
ComplexType generatedType = generateComplexType(nextType);
generatedSchema.addTopLevelComplexTypes(generatedType);
//generate global element for the complex type generated above
Element element = buildElementForComplexType(generatedSchema, generatedType);
if (element != null) {
generatedSchema.addTopLevelElement(element);
}
}
}
if (javaPackage != null) {
getPrefixForURI(SDOConstants.SDOJAVA_URL);
generatedSchema.getAttributesMap().put(SDOConstants.SDOJAVA_PACKAGE_QNAME, javaPackage);
}
}
private SimpleType generateSimpleType(Type type) {
SDOType sdoType = (SDOType) type;
SimpleType simpleType = new SimpleType();
String xsdLocalName = sdoType.getXsdLocalName();
if (xsdLocalName != null) {
simpleType.setName(xsdLocalName);
} else {
simpleType.setName(sdoType.getName());
}
if ((sdoType.getAppInfoElements() != null) && (sdoType.getAppInfoElements().size() > 0)) {
Annotation annotation = new Annotation();
annotation.setAppInfo(sdoType.getAppInfoElements());
simpleType.setAnnotation(annotation);
}
if ((xsdLocalName != null) && !(xsdLocalName.equals(sdoType.getName()))) {
String sdoXmlPrefix = getPrefixForURI(SDOConstants.SDOXML_URL);
QName qname = new QName(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_NAME, sdoXmlPrefix);
simpleType.getAttributesMap().put(qname, sdoType.getName());
}
if ((sdoType.getAliasNames() != null) && (sdoType.getAliasNames().size() > 0)) {
String sdoXmlPrefix = getPrefixForURI(SDOConstants.SDOXML_URL);
String aliasNamesString = buildAliasNameString(sdoType.getAliasNames());
QName qname = new QName(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_ALIASNAME, sdoXmlPrefix);
simpleType.getAttributesMap().put(qname, aliasNamesString);
}
Object value = sdoType.get(SDOConstants.JAVA_CLASS_PROPERTY);
if (value instanceof String) {
String sdoJavaPrefix = getPrefixForURI(SDOConstants.SDOJAVA_URL);
QName qname = new QName(SDOConstants.SDOJAVA_URL, SDOConstants.SDOJAVA_INSTANCECLASS, sdoJavaPrefix);
simpleType.getAttributesMap().put(qname, (String) value);
}
SDOType baseType = null;
if (sdoType.isSubType()) {
baseType = (SDOType) sdoType.getBaseTypes().get(0);
}
if (baseType != null) {
Restriction restriction = new Restriction();
addTypeToListIfNeeded(sdoType, baseType);
QName schemaType = ((SDOTypeHelper)aHelperContext.getTypeHelper()).getXSDTypeFromSDOType(baseType);
if (schemaType != null) {
String prefix = getPrefixStringForURI(schemaType.getNamespaceURI());
restriction.setBaseType(prefix + schemaType.getLocalPart());
} else {
String prefix = getPrefixStringForURI(baseType.getURI());
restriction.setBaseType(prefix + baseType.getName());
}
simpleType.setRestriction(restriction);
}
return simpleType;
}
private ComplexType generateComplexType(Type type) {
SDOType sdoType = (SDOType) type;
ComplexType complexType = new ComplexType();
String xsdLocalName = sdoType.getXsdLocalName();
if (xsdLocalName != null) {
complexType.setName(xsdLocalName);
} else {
complexType.setName(sdoType.getName());
}
if ((xsdLocalName != null) && !(xsdLocalName.equals(sdoType.getName()))) {
String sdoXmlPrefix = getPrefixForURI(SDOConstants.SDOXML_URL);
QName qname = new QName(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_NAME, sdoXmlPrefix);
complexType.getAttributesMap().put(qname, sdoType.getName());
}
complexType.setAbstractValue(sdoType.isAbstract());
if ((sdoType.getAppInfoElements() != null) && (sdoType.getAppInfoElements().size() > 0)) {
Annotation annotation = new Annotation();
annotation.setAppInfo(sdoType.getAppInfoElements());
complexType.setAnnotation(annotation);
}
if ((sdoType.getAliasNames() != null) && (sdoType.getAliasNames().size() > 0)) {
String sdoXmlPrefix = getPrefixForURI(SDOConstants.SDOXML_URL);
String aliasNamesString = buildAliasNameString(sdoType.getAliasNames());
QName qname = new QName(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_ALIASNAME, sdoXmlPrefix);
complexType.getAttributesMap().put(qname, aliasNamesString);
}
complexType.setMixed(sdoType.isSequenced());
Type baseType = null;
if (sdoType.isSubType()) {
baseType = (Type)sdoType.getBaseTypes().get(0);
//baseName = base.getName();
//String baseURI = ((Type)type.getBaseTypes().get(0)).getURI();
//if (baseURI != type.getURI()) {
//need to add something to track referenced uris for includes/imports
//}
}
if (baseType != null) {
addTypeToListIfNeeded(sdoType, baseType);
Extension extension = new Extension();
QName schemaType = ((SDOTypeHelper)aHelperContext.getTypeHelper()).getXSDTypeFromSDOType(baseType);
//fixed below for bug5893546
if (schemaType != null) {
extension.setBaseType(getPrefixStringForURI(schemaType.getNamespaceURI()) + schemaType.getLocalPart());
} else if ((baseType.getURI() == null) || (baseType.getURI().equalsIgnoreCase(generatedSchema.getTargetNamespace()))) {
extension.setBaseType(baseType.getName());
} else {
extension.setBaseType(getPrefixStringForURI(baseType.getURI()) + baseType.getName());
}
buildElementsAndAttributes(extension, sdoType);
ComplexContent complexContent = new ComplexContent();
complexContent.setExtension(extension);
complexType.setComplexContent(complexContent);
return complexType;
}
buildElementsAndAttributes(complexType, sdoType);
return complexType;
}
private void buildElementsAndAttributes(Object owner, Type type) {
List properties = type.getDeclaredProperties();
NestedParticle nestedParticle = null;
if ((properties == null) || (properties.size() == 0)) {
if (type.isOpen()) {
nestedParticle = new Sequence();
} else {
return;
}
} else {
if (type.isSequenced()) {
nestedParticle = new Choice();
nestedParticle.setMaxOccurs(Occurs.UNBOUNDED);
} else {
nestedParticle = new Sequence();
}
}
for (int i = 0; i < properties.size(); i++) {
Property nextProperty = (Property)properties.get(i);
if (aHelperContext.getXSDHelper().isElement(nextProperty)) {
Element elem = buildElement(nextProperty, nestedParticle);
nestedParticle.addElement(elem);
} else if (aHelperContext.getXSDHelper().isAttribute(nextProperty)) {
Attribute attr = buildAttribute(nextProperty);
if (owner instanceof ComplexType) {
((ComplexType)owner).getOrderedAttributes().add(attr);
} else if (owner instanceof Extension) {
((Extension)owner).getOrderedAttributes().add(attr);
}
}
}
if (type.isOpen()) {
Any any = new Any();
any.setProcessContents(AnyAttribute.LAX);
any.setMaxOccurs(Occurs.UNBOUNDED);
nestedParticle.addAny(any);
AnyAttribute anyAttribute = new AnyAttribute();
anyAttribute.setProcessContents(AnyAttribute.LAX);
if (owner instanceof ComplexType) {
((ComplexType)owner).setAnyAttribute(anyAttribute);
}
}
if (!nestedParticle.isEmpty()) {
if (owner instanceof ComplexType) {
((ComplexType)owner).setTypeDefParticle((TypeDefParticle)nestedParticle);
//baseType.getAttributes().add(attr);
} else if (owner instanceof Extension) {
((Extension)owner).setTypeDefParticle((TypeDefParticle)nestedParticle);
}
}
}
private void addSimpleComponentAnnotations(SimpleComponent sc, Property property, boolean element) {
SDOProperty sdoProperty = (SDOProperty) property;
if (sdoProperty.isReadOnly()) {
String sdoXmlPrefix = getPrefixForURI(SDOConstants.SDOXML_URL);
QName qname = new QName(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_READONLY, sdoXmlPrefix);
sc.getAttributesMap().put(qname, "true");
}
if (sdoProperty.hasAliasNames()) {
String sdoXmlPrefix = getPrefixForURI(SDOConstants.SDOXML_URL);
String aliasNamesString = buildAliasNameString(sdoProperty.getAliasNames());
QName qname = new QName(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_ALIASNAME, sdoXmlPrefix);
sc.getAttributesMap().put(qname, aliasNamesString);
}
String xsdLocalName = sdoProperty.getXsdLocalName();
if ((xsdLocalName != null) && !(xsdLocalName.equals(sdoProperty.getName()))) {
String sdoXmlPrefix = getPrefixForURI(SDOConstants.SDOXML_URL);
QName qname = new QName(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_NAME, sdoXmlPrefix);
sc.getAttributesMap().put(qname, sdoProperty.getName());
}
if ((element && !sdoProperty.isContainment() && !sdoProperty.getType().isDataType()) || (!element && !sdoProperty.getType().isDataType())) {
String sdoXmlPrefix = getPrefixForURI(SDOConstants.SDOXML_URL);
String uri = sdoProperty.getType().getURI();
String value = sdoProperty.getType().getName();
if (uri != null) {
String typePrefix = getPrefixForURI(uri);
if (typePrefix != null) {
value = typePrefix + ":" + value;
}
}
QName qname = new QName(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_PROPERTYTYPE, sdoXmlPrefix);
sc.getAttributesMap().put(qname, value);
}
if (sdoProperty.getOpposite() != null) {
String value = sdoProperty.getOpposite().getName();
String sdoXmlPrefix = getPrefixForURI(SDOConstants.SDOXML_URL);
QName qname = new QName(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_OPPOSITEPROPERTY, sdoXmlPrefix);
sc.getAttributesMap().put(qname, value);
}
Property xmlDataTypeProperty = aHelperContext.getTypeHelper().getOpenContentProperty(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_DATATYPE);
Type dataType = (Type) sdoProperty.get(xmlDataTypeProperty);
if (dataType == null) {
dataType = getAutomaticDataTypeForType(sdoProperty.getType());
}
if (dataType != null && !shouldSuppressDataType(sdoProperty, dataType)) {
String sdoXmlPrefix = getPrefixForURI(SDOConstants.SDOXML_URL);
QName qname = new QName(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_DATATYPE, sdoXmlPrefix);
String dataTypeString = dataType.getName();
if (dataType.getURI() != null) {
String dataTypePrefix = getPrefixForURI(dataType.getURI());
if (dataTypePrefix != null) {
dataTypeString = dataTypePrefix + ":" + dataTypeString;
}
}
sc.getAttributesMap().put(qname, dataTypeString);
}
if (element) {
String mimeType = (String) sdoProperty.get(SDOConstants.MIME_TYPE_PROPERTY);
if (mimeType != null) {
String prefix = getPrefixForURI(SDOConstants.MIMETYPE_URL);
QName qname = new QName(SDOConstants.XML_MIME_TYPE_QNAME.getNamespaceURI(), SDOConstants.XML_MIME_TYPE_QNAME.getLocalPart(), prefix);
sc.getAttributesMap().put(qname, mimeType);
} else {
mimeType = (String) sdoProperty.get(SDOConstants.MIME_TYPE_PROPERTY_PROPERTY);
if (mimeType != null) {
String prefix = getPrefixForURI(SDOConstants.ORACLE_SDO_URL);
QName qname = new QName(SDOConstants.XML_MIME_TYPE_PROPERTY_QNAME.getNamespaceURI(), SDOConstants.XML_MIME_TYPE_PROPERTY_QNAME.getLocalPart(), prefix);
sc.getAttributesMap().put(qname, mimeType);
}
}
}
}
private boolean shouldSuppressDataType(SDOProperty prop, Type dataType){
if(prop.isNullable()){
SDOType type = prop.getType();
if(dataType == SDOConstants.SDO_BOOLEANOBJECT && (type == SDOConstants.SDO_BOOLEAN || type == SDOConstants.SDO_BOOLEANOBJECT )){
return true;
}
if(dataType == SDOConstants.SDO_BYTEOBJECT && (type == SDOConstants.SDO_BYTE || type == SDOConstants.SDO_BYTEOBJECT )){
return true;
}
if(dataType == SDOConstants.SDO_CHARACTEROBJECT && (type == SDOConstants.SDO_CHARACTER || type == SDOConstants.SDO_CHARACTEROBJECT )){
return true;
}
if(dataType == SDOConstants.SDO_DOUBLEOBJECT && (type == SDOConstants.SDO_DOUBLE || type == SDOConstants.SDO_DOUBLEOBJECT )){
return true;
}
if(dataType == SDOConstants.SDO_FLOATOBJECT && (type == SDOConstants.SDO_FLOAT || type == SDOConstants.SDO_FLOATOBJECT )){
return true;
}
if(dataType == SDOConstants.SDO_INTOBJECT && (type == SDOConstants.SDO_INT || type == SDOConstants.SDO_INTOBJECT )){
return true;
}
if(dataType == SDOConstants.SDO_LONGOBJECT && (type == SDOConstants.SDO_LONG || type == SDOConstants.SDO_LONGOBJECT )){
return true;
}
if(dataType == SDOConstants.SDO_SHORTOBJECT && (type == SDOConstants.SDO_SHORT || type == SDOConstants.SDO_SHORTOBJECT )){
return true;
}
}
return false;
}
private String buildAliasNameString(List<String> aliasNames) {
StringBuilder aliasNamesStringBuilder = new StringBuilder();
for (int i = 0, size = aliasNames.size(); i < size; i++) {
aliasNamesStringBuilder.append(aliasNames.get(i));
if (i < (size - 1)) {
aliasNamesStringBuilder.append(' ');
}
}
return aliasNamesStringBuilder.toString();
}
private Element buildElement(Property property, NestedParticle nestedParticle) {
SDOProperty sdoProperty = (SDOProperty) property;
Element elem = new Element();
String xsdLocalName = sdoProperty.getXsdLocalName();
if (xsdLocalName != null) {
elem.setName(xsdLocalName);
} else {
elem.setName(sdoProperty.getName());
}
elem.setMinOccurs(Occurs.ZERO);
elem.setNillable(sdoProperty.isNullable());
if ((sdoProperty.getAppInfoElements() != null) && (sdoProperty.getAppInfoElements().size() > 0)) {
Annotation annotation = new Annotation();
annotation.setAppInfo(sdoProperty.getAppInfoElements());
elem.setAnnotation(annotation);
}
// process default values that are defined in the schema (not via primitive numeric Object wrapped pseudo defaults)
if (sdoProperty.isDefaultSet()) {
if (!sdoProperty.isMany() && sdoProperty.getType().isDataType()) {
XMLConversionManager xmlConversionManager = ((SDOXMLHelper)aHelperContext.getXMLHelper()).getXmlConversionManager();
elem.setDefaultValue(xmlConversionManager.convertObject(sdoProperty.getDefault(), ClassConstants.STRING, sdoProperty.getXsdType()));
}
}
addSimpleComponentAnnotations(elem, sdoProperty, true);
/*
When containment is true, then DataObjects of that Type will appear as nested elements in an XML document.
When containment is false and the property's type is a DataObject, a URI reference
to the element containing the DataObject is used and an sdo:propertyType
declaration records the target type. Values in XML documents will be of the form
"#xpath" where the xpath is an SDO DataObject XPath subset. It is typical to
customize the declaration to IDREF if the target element has an attribute with type
customized to ID.
[TYPE.NAME] is the type of the element. If property.type.dataType is true,
[TYPE.NAME] is the name of the XSD built in SimpleType corresponding to
property.type, where the prefix is for the xsd namespace. Otherwise,
[TYPE.NAME] is property.type.name where the tns: prefix is determined by the
namespace declaration for the Type's URI.
*/
Type schemaSDOType = null;
QName schemaType = sdoProperty.getXsdType();
if (schemaType != null) {
schemaSDOType = aHelperContext.getTypeHelper().getType(schemaType.getNamespaceURI(), schemaType.getLocalPart());
if ((sdoProperty.getType() == SDOConstants.SDO_STRING) && (schemaSDOType != SDOConstants.SDO_STRING)) {
String sdoXmlPrefix = getPrefixForURI(SDOConstants.SDOXML_URL);
QName qname = new QName(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_STRING_NAME, sdoXmlPrefix);
elem.getAttributesMap().put(qname, "true");
}
}
if (!sdoProperty.isContainment() && !sdoProperty.getType().isDataType()) {
schemaType = SDOConstants.ANY_URI_QNAME;
}
Type propertyType = sdoProperty.getType();
if (propertyType != null) {
if (sdoProperty.getContainingType() != null) {
addTypeToListIfNeeded(sdoProperty.getContainingType(), propertyType);
}
if (schemaType == null) {
schemaType = ((SDOTypeHelper)aHelperContext.getTypeHelper()).getXSDTypeFromSDOType(propertyType);
}
//get url for prefix in namespace resolver and map sure it is added to the schema if necessary
if (schemaType != null) {
elem.setType(getPrefixStringForURI(schemaType.getNamespaceURI()) + schemaType.getLocalPart());
if (schemaSDOType != null) {
addTypeToListIfNeeded(sdoProperty.getContainingType(), schemaSDOType);
}
} else if ((propertyType.getURI() == null) || (propertyType.getURI().equalsIgnoreCase(generatedSchema.getTargetNamespace()))) {
String xsdTypeLocalName = ((SDOType)propertyType).getXsdLocalName();
if (xsdTypeLocalName != null) {
elem.setType(xsdTypeLocalName);
} else {
elem.setType(propertyType.getName());
}
} else {
String nameString = null;
String xsdTypeLocalName = ((SDOType)propertyType).getXsdLocalName();
if (xsdTypeLocalName != null) {
nameString = xsdTypeLocalName;
} else {
nameString = propertyType.getName();
}
elem.setType(getPrefixStringForURI(propertyType.getURI()) + nameString);
}
} else {
elem.setType("anyURI");
}
if (sdoProperty.isMany()) {
elem.setMaxOccurs(Occurs.UNBOUNDED);
} else if (nestedParticle.getMaxOccurs() == Occurs.UNBOUNDED) {
//this means property.isMany==false and the owning sequence of choice is unbounded Jira SDO-3
String sdoXmlPrefix = getPrefixForURI(SDOConstants.SDOXML_URL);
QName qname = new QName(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_MANY, sdoXmlPrefix);
elem.getAttributesMap().put(qname, "false");
}
return elem;
}
private Attribute buildAttribute(Property property) {
Attribute attr = new Attribute();
String xsdLocalName = ((SDOProperty)property).getXsdLocalName();
if (xsdLocalName != null) {
attr.setName(xsdLocalName);
} else {
attr.setName(property.getName());
}
if ((((SDOProperty)property).getAppInfoElements() != null) && (((SDOProperty)property).getAppInfoElements().size() > 0)) {
Annotation annotation = new Annotation();
annotation.setAppInfo(((SDOProperty)property).getAppInfoElements());
attr.setAnnotation(annotation);
}
// process default values that are defined in the schema (not via primitive numeric Object wrapped pseudo defaults)
if (((SDOProperty)property).isDefaultSet()) {
if (!property.isMany() && property.getType().isDataType()) {
XMLConversionManager xmlConversionManager = ((SDOXMLHelper)aHelperContext.getXMLHelper()).getXmlConversionManager();
attr.setDefaultValue(xmlConversionManager.convertObject(property.getDefault(), ClassConstants.STRING, ((SDOProperty)property).getXsdType()));
}
}
addSimpleComponentAnnotations(attr, property, false);
Type propertyType = property.getType();
QName schemaType = ((SDOProperty)property).getXsdType();
if (schemaType != null) {
Type schemaSDOType = aHelperContext.getTypeHelper().getType(schemaType.getNamespaceURI(), schemaType.getLocalPart());
if ((property.getType() == SDOConstants.SDO_STRING) && (schemaSDOType != SDOConstants.SDO_STRING)) {
String sdoXmlPrefix = getPrefixForURI(SDOConstants.SDOXML_URL);
QName qname = new QName(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_STRING_NAME, sdoXmlPrefix);
attr.getAttributesMap().put(qname, "true");
}
}
if (!property.getType().isDataType()) {
schemaType = SDOConstants.ANY_URI_QNAME;
}
if (propertyType != null) {
if (property.getContainingType() != null) {
addTypeToListIfNeeded(property.getContainingType(), propertyType);
}
if (schemaType == null) {
schemaType = ((SDOTypeHelper)aHelperContext.getTypeHelper()).getXSDTypeFromSDOType(propertyType);
}
if (schemaType != null) {
attr.setType(getPrefixStringForURI(schemaType.getNamespaceURI()) + schemaType.getLocalPart());
} else if ((propertyType.getURI() == null) || (propertyType.getURI().equalsIgnoreCase(generatedSchema.getTargetNamespace()))) {
String xsdTypeLocalName = ((SDOType)propertyType).getXsdLocalName();
if (xsdTypeLocalName != null) {
attr.setType(xsdTypeLocalName);
} else {
attr.setType(propertyType.getName());
}
} else {
String nameString = null;
String xsdTypeLocalName = ((SDOType)propertyType).getXsdLocalName();
if (xsdTypeLocalName != null) {
nameString = xsdTypeLocalName;
} else {
nameString = propertyType.getName();
}
attr.setType(getPrefixStringForURI(propertyType.getURI()) + nameString);
}
//get url for prefix in namespace resolver and map sure it is added to the schema if necessary
/*
if (schemaType != null) {
attr.setType(getPrefixStringForURI(schemaType.getNamespaceURI()) + schemaType.getLocalPart());
} else {
attr.setType(propertyType.getName());
}*/
}
return attr;
}
private void addTypeToListIfNeeded(Type sourceType, Type targetType) {
if ((targetType.getURI() != null) && !targetType.getURI().equals(SDOConstants.SDO_URL) && !targetType.getURI().equals(SDOConstants.SDOJAVA_URL) && !targetType.getURI().equals(SDOConstants.SDOXML_URL)) {
boolean alreadyGenerated = allTypes.contains(targetType);
String schemaLocation = null;
if (namespaceToSchemaLocation != null) {
schemaLocation = namespaceToSchemaLocation.get(targetType.getURI());
if (targetType.getURI().equals(generatedSchema.getTargetNamespace())) {
if (!alreadyGenerated) {
allTypes.add(targetType);
}
} else {
if(!importExists(generatedSchema.getImports(), schemaLocation)){
Import theImport = new Import();
theImport.setSchemaLocation(schemaLocation);
theImport.setNamespace(targetType.getURI());
generatedSchema.getImports().add(theImport);
}
}
} else if (schemaLocationResolver != null) {
schemaLocation = schemaLocationResolver.resolveSchemaLocation(sourceType, targetType);
if (schemaLocation != null) {
if (targetType.getURI().equals(generatedSchema.getTargetNamespace())) {
if(!importExists(generatedSchema.getIncludes(), schemaLocation)){
Include include = new Include();
include.setSchemaLocation(schemaLocation);
generatedSchema.getIncludes().add(include);
// 20060713 remove type from List of types when adding an include
allTypes.remove(targetType);
}
} else {
if(!importExists(generatedSchema.getImports(), schemaLocation)){
Import theImport = new Import();
theImport.setSchemaLocation(schemaLocation);
theImport.setNamespace(targetType.getURI());
generatedSchema.getImports().add(theImport);
}
}
} else {
if (!alreadyGenerated) {
//we can #1 add to list of allTypes or #2 make an appropriate include
if (targetType.getURI().equals(generatedSchema.getTargetNamespace())) {
allTypes.add(targetType);
}
}
}
} else {
if (!alreadyGenerated) {
//we can #1 add to list of allTypes or #2 make an appropriate include
if (targetType.getURI().equals(generatedSchema.getTargetNamespace())) {
allTypes.add(targetType);
}
}
}
}
}
private Element buildElementForComplexType(Schema schema, ComplexType type) {
Element elem = new Element();
String name = type.getName();
if (name == null) {
return null;
}
String lowerName = Character.toLowerCase(name.charAt(0)) + name.substring(1, name.length());
Element exists = schema.getTopLevelElements().get(lowerName);
if (exists != null) {
elem.setName(name);
} else {
elem.setName(lowerName);
}
elem.setType(type.getName());
return elem;
}
private String getPrefixStringForURI(String uri) {
if(null == uri || SDOConstants.EMPTY_STRING.equals(uri)) {
return SDOConstants.EMPTY_STRING;
}
String prefix = getPrefixForURI(uri);
if (prefix == null) {
return SDOConstants.EMPTY_STRING;
} else {
return prefix + ":";
}
}
private String getPrefixForURI(String uri) {
String prefix = null;
if (uri.equals(generatedSchema.getTargetNamespace())) {
return null;
} else if (uri.equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
return XMLConstants.SCHEMA_PREFIX;
} else if (uri.equals(SDOConstants.SDO_URL)) {
prefix = generatedSchema.getNamespaceResolver().resolveNamespaceURI(uri);
if (prefix == null) {
prefix = generatedSchema.getNamespaceResolver().generatePrefix(SDOConstants.SDO_PREFIX);
generatedSchema.getNamespaceResolver().put(prefix, uri);
}
} else if (uri.equals(SDOConstants.SDOJAVA_URL)) {
prefix = generatedSchema.getNamespaceResolver().resolveNamespaceURI(uri);
if (prefix == null) {
prefix = generatedSchema.getNamespaceResolver().generatePrefix(SDOConstants.SDOJAVA_PREFIX);
generatedSchema.getNamespaceResolver().put(prefix, uri);
}
} else if (uri.equals(SDOConstants.SDOXML_URL)) {
prefix = generatedSchema.getNamespaceResolver().resolveNamespaceURI(uri);
if (prefix == null) {
prefix = generatedSchema.getNamespaceResolver().generatePrefix(SDOConstants.SDOXML_PREFIX);
generatedSchema.getNamespaceResolver().put(prefix, uri);
}
}
if (prefix == null) {
prefix = generatedSchema.getNamespaceResolver().resolveNamespaceURI(uri);
}
if (prefix != null) {
return prefix;
} else {
String generatedPrefix = generatedSchema.getNamespaceResolver().generatePrefix();
generatedSchema.getNamespaceResolver().put(generatedPrefix, uri);
return generatedPrefix;
}
}
private Type getAutomaticDataTypeForType(Type theType) {
// Section 10.1 of the spec
//For the SDO Java Types, the corresponding base SDO Type is used. For the SDO Java
// Types, and for SDO Date, an sdo:dataType annotation is generated on the XML attribute
// or element referring to the SDO Type.
if (theType == SDOConstants.SDO_BOOLEANOBJECT) {
return SDOConstants.SDO_BOOLEANOBJECT;
} else if (theType == SDOConstants.SDO_BYTEOBJECT) {
return SDOConstants.SDO_BYTEOBJECT;
} else if (theType == SDOConstants.SDO_CHARACTEROBJECT) {
return SDOConstants.SDO_CHARACTEROBJECT;
} else if (theType == SDOConstants.SDO_DOUBLEOBJECT) {
return SDOConstants.SDO_DOUBLEOBJECT;
} else if (theType == SDOConstants.SDO_INTOBJECT) {
return SDOConstants.SDO_INTOBJECT;
} else if (theType == SDOConstants.SDO_FLOATOBJECT) {
return SDOConstants.SDO_FLOATOBJECT;
} else if (theType == SDOConstants.SDO_LONGOBJECT) {
return SDOConstants.SDO_LONGOBJECT;
} else if (theType == SDOConstants.SDO_SHORTOBJECT) {
return SDOConstants.SDO_SHORTOBJECT;
} else if (theType == SDOConstants.SDO_DATE) {
return SDOConstants.SDO_DATE;
} else if (theType == SDOConstants.SDO_DATETIME) {
return SDOConstants.SDO_DATETIME;
}
return null;
}
private boolean importExists(java.util.List imports, String schemaName){
for(int i=0;i < imports.size();i++){
//Cast to the parent class, since this could be an Include or an Import
Include nextImport = (Include)imports.get(i);
if(nextImport.getSchemaLocation() != null && nextImport.getSchemaLocation().equals(schemaName)){
return true;
}
}
return false;
}
}