blob: b2cceb0d4408d72686302ea5b3b02eda1f2caf64 [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;
import commonj.sdo.DataObject;
import commonj.sdo.Property;
import commonj.sdo.Type;
import commonj.sdo.helper.HelperContext;
import commonj.sdo.impl.HelperProvider;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import org.eclipse.persistence.sdo.helper.SDOClassLoader;
import org.eclipse.persistence.sdo.helper.SDOHelperContext;
import org.eclipse.persistence.sdo.helper.SDOTypeHelper;
import org.eclipse.persistence.sdo.helper.SDOXMLHelper;
import org.eclipse.persistence.sdo.helper.SDOXSDHelper;
import org.eclipse.persistence.sdo.helper.extension.SDOUtil;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.SDOException;
import org.eclipse.persistence.internal.descriptors.InstantiationPolicy;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.oxm.Namespace;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLConstants;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.mappings.XMLAnyAttributeMapping;
import org.eclipse.persistence.oxm.mappings.XMLAnyCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLDirectMapping;
import org.eclipse.persistence.oxm.schema.XMLSchemaClassPathReference;
import org.eclipse.persistence.oxm.schema.XMLSchemaReference;
public class SDOType implements Type, Serializable {
private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
private QName qName;
private boolean open;// if this Type is open
private boolean isAbstract;// if this is an abstract Type
protected boolean isDataType;// if this is a dataType
private List baseTypes;// a list of this Type's base Types (added for now waitting for final decision)
private List declaredProperties;// a list of Properties defined by this Type.(Optional, leave it for now)
private transient Map declaredPropertiesMap;
private List aliasNames;
private boolean xsd;
private boolean xsdList;
private String xsdLocalName;
private QName xsdType;
protected transient XMLDescriptor xmlDescriptor;
private Map propertyValues;
private SDOProperty changeSummaryProperty;
private List allProperties;
private SDOProperty[] allPropertiesArr;
private List subTypes;
private boolean finalized;
private Class javaClass;
private String javaClassName;
private String javaImplClassName;
protected Class javaImplClass;
private List<SDOProperty> nonFinalizedReferencingProps;
private List nonFinalizedMappingURIs;
/** hold a wrapper object for primitive numeric defaults */
private Object pseudoDefault;
// hold the context containing all helpers so that we can preserve inter-helper relationships
protected HelperContext aHelperContext;
private List appInfoElements;
private Map appInfoMap;
/** Open Content setOpen constants */
private static final String ANY_MAPPING_ATTRIBUTE_NAME = "openContentProperties";
private static final String ANY_MAPPING_GET_METHOD_NAME = "_getOpenContentPropertiesWithXMLRoots";
private static final String ANY_MAPPING_SET_METHOD_NAME = "_setOpenContentPropertiesWithXMLRoots";
private static final String SDO_REF_MAPPING_ATTRIBUTE_NAME = "sdoRef";
public SDOType(HelperContext helperContext) {
this((SDOTypeHelper)helperContext.getTypeHelper());
}
public SDOType(SDOTypeHelper sdoTypeHelper) {
this(sdoTypeHelper, new XMLDescriptor());
xmlDescriptor.setLazilyInitialized(true);
}
protected SDOType(SDOTypeHelper sdoTypeHelper, XMLDescriptor xmlDescriptor) {
this.xmlDescriptor = xmlDescriptor;
if(null != sdoTypeHelper) {
aHelperContext = sdoTypeHelper.getHelperContext();
if(null != xmlDescriptor) {
this.xmlDescriptor.setNamespaceResolver(sdoTypeHelper.getNamespaceResolver());
}
}
}
/**
* INTERNAL:
* Build up a Type with given name and uri and a default static HelperContext.
* Use {@link #SDOType(String, String, org.eclipse.persistence.sdo.helper.SDOTypeHelper)} instead
* @param uri the URI of this type
* @param type_name the unique of this Type
*/
public SDOType(String uri, String type_name) {
// JIRA129 - default to static global context - Do Not use this convenience constructor outside of JUnit testing
this(uri, type_name, (SDOTypeHelper) HelperProvider.getDefaultContext().getTypeHelper());
}
/**
* Build up a Type with given name and uri
* @param uri the URI of this type
* @param name the unique of this Type
* @param sdoTypeHelper the current HelperContext
*/
public SDOType(String uri, String name, SDOTypeHelper sdoTypeHelper) {
this(sdoTypeHelper);
if(null != uri) {
uri = uri.intern();
}
if(null != name) {
name = name.intern();
}
this.qName = new QName(uri, name);
}
protected SDOType(String uri, String name, SDOTypeHelper sdoTypeHelper, XMLDescriptor xmlDescriptor) {
this(sdoTypeHelper, xmlDescriptor);
if(null != uri) {
uri = uri.intern();
}
if(null != name) {
name = name.intern();
}
this.qName = new QName(uri, name);
}
public QName getQName() {
return qName;
}
public void setQName(QName qName) {
this.qName = qName;
}
@Override
public String getName() {
return qName.getLocalPart();
}
@Override
public String getURI() {
String uri = qName.getNamespaceURI();
if("".equals(uri)) {
return null;
} else {
return uri;
}
}
@Override
public Class getInstanceClass() {
if ((javaClass == null) && (javaClassName != null)) {
try {
SDOClassLoader loader = ((SDOXMLHelper)aHelperContext.getXMLHelper()).getLoader();
Class<?> clazz = loader.getParent().loadClass(javaClassName);
if(isValidInstanceClass(clazz)) {
javaClass = clazz;
} else {
javaClass = getClass();
}
} catch (ClassNotFoundException e) {
javaClass = getClass();
} catch (SecurityException e) {
throw SDOException.classNotFound(e, getURI(), getName());
}
}
if(javaClass == getClass()) {
return null;
}
return javaClass;
}
/**
* Verify that the class is a valid instance class.
*/
private boolean isValidInstanceClass(Class clazz) {
if(isDataType) {
return true;
}
if(!clazz.isInterface()) {
return false;
}
return !isStrictTypeCheckingEnabled() || hasClassGetterForEachProperty(clazz);
}
/**
* Checks that the given class has getter for each property of this type.
*
* @param clazz class to be checked
* @return {@code true} if given class has getter for each property
*/
private boolean hasClassGetterForEachProperty(Class clazz) {
for(Object object: this.getDeclaredProperties()) {
SDOProperty sdoProperty = (SDOProperty) object;
SDOType sdoPropertyType = sdoProperty.getType();
if(!sdoPropertyType.isChangeSummaryType()) {
String javaType = SDOUtil.getJavaTypeForProperty(sdoProperty);
try {
// Verify get method
String getMethodName = SDOUtil.getMethodName(sdoProperty.getName(), javaType);
PrivilegedAccessHelper.getPublicMethod(clazz, getMethodName, EMPTY_CLASS_ARRAY, false);
} catch(NoSuchMethodException e) {
//if the method isn't found and the type is boolean try looking for a "get" method instead of an "is" method
if(sdoPropertyType == SDOConstants.SDO_BOOLEAN || sdoPropertyType == SDOConstants.SDO_BOOLEANOBJECT ){
try{
String booleanGetterMethodName = SDOUtil.getBooleanGetMethodName(sdoProperty.getName(), javaType);
PrivilegedAccessHelper.getPublicMethod(clazz, booleanGetterMethodName, EMPTY_CLASS_ARRAY, false);
} catch(NoSuchMethodException e2) {
return false;
}
}else{
return false;
}
}
}
}
return true;
}
/**
* Indicates whether to check instance class strictly.
*
* @return boolean
*/
private boolean isStrictTypeCheckingEnabled() {
final HelperContext helperContext = getHelperContext();
if (helperContext instanceof SDOHelperContext) {
return ((SDOHelperContext)helperContext).isStrictTypeCheckingEnabled();
}
return true;
}
@Override
public boolean isInstance(Object object) {
if ((!isDataType()) && (object instanceof DataObject)) {
Type doType = ((DataObject)object).getType();
if (doType != null) {
return doType.equals(this);
}
}
//this check is taken from page 77 of the spec
Class instanceClass = getInstanceClass();
if (instanceClass != null) {
return instanceClass.isInstance(object);
}
return false;
}
@Override
public List getProperties() {
if (allProperties == null) {
allProperties = new ArrayList();
}
return allProperties;
}
@Override
public SDOProperty getProperty(String propertyName) {
SDOProperty queriedProperty = (SDOProperty)getDeclaredPropertiesMap().get(propertyName);
if (null == queriedProperty && isSubType()) {
for (int i = 0; i < getBaseTypes().size(); i++) {
queriedProperty = ((SDOType)getBaseTypes().get(i)).getProperty(propertyName);
if (queriedProperty != null) {
break;
}
}
}
return queriedProperty;
}
@Override
public boolean isDataType() {
return isDataType;
}
@Override
public boolean isOpen() {
return open;
}
@Override
public boolean isSequenced() {
return xmlDescriptor.isSequencedObject();
}
@Override
public boolean isAbstract() {
return isAbstract;
}
@Override
public List getBaseTypes() {
if (baseTypes == null) {
baseTypes = new ArrayList();
}
return baseTypes;
}
/**
* INTERNAL:
* Provide a means to determine if this type has base types without causing the base types property to be initialized.
*/
public boolean isSubType() {
return !(null == baseTypes || baseTypes.isEmpty());
}
@Override
public List getDeclaredProperties() {
if (declaredProperties == null) {
declaredProperties = new ArrayList();
}
return declaredProperties;
}
@Override
public List getAliasNames() {
if (aliasNames == null) {
aliasNames = new ArrayList();
}
return aliasNames;
}
/**
* INTERNAL:
* Assign a unique string to a type, which belongs to same uri, among types.
* @param name a unique string representing a type.
*/
public void addAliasName(String name) {
getAliasNames().add(name);
QName qname = new QName(getURI(), name);
((SDOTypeHelper)aHelperContext.getTypeHelper()).getTypesHashMap().put(qname, this);
}
/**
* INTERNAL:
* Assign a list of alias names to a type, which are unique in URI.
* @param names a unique string representing a type.
*/
public void setAliasNames(List names) {
for (int i = 0; i < names.size(); i++) {
addAliasName((String)names.get(i));
}
}
/**
* INTERNAL:
* Make this Type an opened Type to allow open content by assigning true value
* or a Type not to accept any additional properties by assigning false value,
* {@link #isOpen()}.
* @param bOpen boolean value implying if this Type is open
*/
public void setOpen(boolean bOpen) {
if (isDataType() && bOpen) {
throw SDOException.typeCannotBeOpenAndDataType(getURI(), getName());
}
if (open != bOpen) {
open = bOpen;
if (open) {
if (isSubType()) {
Type baseType = (Type)getBaseTypes().get(0);
if (!baseType.isOpen()) {
addOpenMappings();
}
} else {
addOpenMappings();
}
if(isBaseType()) {
for (int i = 0; i < getSubTypes().size(); i++) {
SDOType nextSubType = (SDOType)getSubTypes().get(i);
nextSubType.setOpen(bOpen);
}
}
}
}
}
private void addOpenMappings() {
XMLAnyCollectionMapping anyMapping = new XMLAnyCollectionMapping();
anyMapping.setAttributeName(ANY_MAPPING_ATTRIBUTE_NAME);
anyMapping.setGetMethodName(ANY_MAPPING_GET_METHOD_NAME);
anyMapping.setSetMethodName(ANY_MAPPING_SET_METHOD_NAME);
anyMapping.setUseXMLRoot(true);
getXmlDescriptor().addMapping(anyMapping);
XMLAnyAttributeMapping anyAttrMapping = new XMLAnyAttributeMapping();
anyAttrMapping.setAttributeName("openContentPropertiesAttributes");
anyAttrMapping.setGetMethodName("_getOpenContentPropertiesAttributesMap");
anyAttrMapping.setSetMethodName("_setOpenContentPropertiesAttributesMap");
getXmlDescriptor().addMapping(anyAttrMapping);
}
/**
* INTERNAL:
* Change this Type's abstract setting. If it is true, this Type can't be instantiated and typically serve as base Type.
* @param makeAbstract boolean value implying if this Type is abstract.
*/
public void setAbstract(boolean makeAbstract) {
isAbstract = makeAbstract;
}
/**
* INTERNAL:
* If set as true, this Type specifies Sequenced DataObjects.
* @param sequenced boolean value implying if this type is sequenced.
*/
public void setSequenced(boolean sequenced) {
xmlDescriptor.setSequencedObject(sequenced);
}
public void setMixed(boolean isMixed) {
String textAttribute = "text";
XMLDirectMapping textMapping = (XMLDirectMapping) xmlDescriptor.getMappingForAttributeName(textAttribute);
if (isMixed) {
if (null == textMapping) {
textMapping = new XMLDirectMapping();
textMapping.setAttributeName(textAttribute);
textMapping.setXPath("text()");
xmlDescriptor.addMapping(textMapping);
}
} else {
xmlDescriptor.removeMappingForAttributeName(textAttribute);
}
}
/**
* INTERNAL:
* Set this Type to a simple Type by passing in boolean value true. Otherwise,
* If boolean value is passed in, instances of this type implement DataObject.
* @param datatype boolean value implying if it is a simple Type
*/
public void setDataType(boolean datatype) {
if (datatype && isOpen()) {
throw SDOException.typeCannotBeOpenAndDataType(getURI(), getName());
}
isDataType = datatype;
if (datatype) {
setFinalized(true);
}
}
/**
* INTERNAL:
* Set a list of Types as This Type's base Types.
* @param bTypes a list types to become this Type's base Type.
*/
public void setBaseTypes(List bTypes) {
if (bTypes != null) {
for (int i = 0; i < bTypes.size(); i++) {
addBaseType((SDOType)bTypes.get(i));
}
} else {
baseTypes = null;
}
}
/**
* INTERNAL:
* @param type a type to become this Type's base Type.
*/
public void addBaseType(SDOType type) {
if (!this.getBaseTypes().contains(type)) {
getBaseTypes().add(type);
updateSubtypes(type);
if(!(type.isDataType() && (type.getQName().getNamespaceURI() == SDOConstants.SDO_URL || type.getQName().getNamespaceURI() == SDOConstants.SDOJAVA_URL))) {
type.getSubTypes().add(this);
}
if (type.isOpen() && this.isOpen()) {
//don't want any mappings on this descriptor
DatabaseMapping anyCollectionMapping = getXmlDescriptor().getMappingForAttributeName(ANY_MAPPING_ATTRIBUTE_NAME);
getXmlDescriptor().getMappings().remove(anyCollectionMapping);
DatabaseMapping anyAttrMapping = getXmlDescriptor().getMappingForAttributeName("openContentPropertiesAttributes");
getXmlDescriptor().getMappings().remove(anyAttrMapping);
}
//int increaseBy = type.getProperties().size();
//increaseIndices(increaseBy);
}
}
private void updateSubtypes(Type baseType) {
getProperties().addAll(0, baseType.getProperties());
if(isBaseType()) {
for (int i = 0; i < getSubTypes().size(); i++) {
SDOType nextSubType = (SDOType)getSubTypes().get(i);
nextSubType.updateSubtypes(baseType);
}
}
}
/**
* INTERNAL:
* Sets the Java class that this type represents.
* @param aClass the Java class that this type represents.
*/
public void setInstanceClass(Class aClass) {
javaClass = aClass;
if (javaClass != null) {
javaClassName = javaClass.getName();
}
}
/**
* INTERNAL:
* Set if this property was declared in an XML schema.
* @param bXsd a boolean representing if this property was declared in an XML schema
*/
public void setXsd(boolean bXsd) {
xsd = bXsd;
}
/**
* INTERNAL:
* Returns if this property was declared in an XML schema. Defaults to false.
* @return if this property was declared in an XML schema
*/
public boolean isXsd() {
return xsd;
}
/**
* INTERNAL:
* Set the local name of this property.
* @param xsdLocalNameString a String representing the local name of this property if it was declared in an XML schema
*/
public void setXsdLocalName(String xsdLocalNameString) {
xsdLocalName = xsdLocalNameString;
}
/**
* INTERNAL:
* Returns the local name of the Property.
* @return the local name of the property.
*/
public String getXsdLocalName() {
return xsdLocalName;
}
/**
* INTERNAL:
* @param property
*/
public void addDeclaredProperty(Property property) {
addDeclaredProperty((SDOProperty)property);
}
/**
* INTERNAL:
* @param property
*/
public void addDeclaredProperty(SDOProperty property) {
int end = getDeclaredProperties().size();
addDeclaredProperty(property, end);
}
/**
* INTERNAL:
* @param property
*/
public void addDeclaredProperty(Property property, int index) {
addDeclaredProperty((SDOProperty)property, index);
}
/**
* INTERNAL:
* @param property
*/
public void addDeclaredProperty(SDOProperty property, int index) {
if (!getDeclaredPropertiesMap().containsKey(property.getName())) {
int currentSize = getDeclaredProperties().size();
int allSize = getProperties().size();
int insertPlace = allSize - currentSize + index;
//updateSubTypesProps
if(isBaseType()) {
for (int i = 0; i < getSubTypes().size(); i++) {
SDOType nextSubType = (SDOType)getSubTypes().get(i);
nextSubType.updateIndices(insertPlace, property);
}
}
getDeclaredProperties().add(index, property);
getProperties().add(insertPlace, property);
property.setContainingType(this);
getDeclaredPropertiesMap().put(property.getName(), property);
if (property.hasAliasNames()) {
for (int j = 0; j < property.getAliasNames().size(); j++) {
getDeclaredPropertiesMap().put(property.getAliasNames().get(j), property);
}
}
if ((property.getType() != null) && (property.getType().isChangeSummaryType())) {
changeSummaryProperty = property;
}
}
}
/**
* INTERNAL:
*/
public void removeDeclaredProperties(Property p) {
getDeclaredProperties().remove(p);
getDeclaredPropertiesMap().remove(p.getName());
getProperties().remove(p);
}
/**
* INTERNAL:
*/
public Map getDeclaredPropertiesMap() {
if (null == declaredPropertiesMap) {
declaredPropertiesMap = new HashMap();
}
return declaredPropertiesMap;
}
/**
* INTERNAL:
* Sets the name of the Java class that this type represents.
* @param instanceClassName the Java class that this type represents.
*/
public void setInstanceClassName(String instanceClassName) {
javaClassName = instanceClassName;
javaClass = null;
}
/**
* INTERNAL:
* Returns the Java class name that this type represents.
* @return the Java class name.
*/
public String getInstanceClassName() {
if ((javaClassName == null) && (javaClass != null)) {
javaClassName = javaClass.getName();
}
return javaClassName;
}
/**
* INTERNAL:
* Set if this type is an xsd:list in the schema
* @param anXsdList a boolean representing if this type represents an xsd:list in the schema
*/
public void setXsdList(boolean anXsdList) {
xsdList = anXsdList;
}
/**
* INTERNAL:
* Indicates if this Type is an xsd:list in the schema
* @return true if this Type represents an xsd:list in the schema
*/
public boolean isXsdList() {
return xsdList;
}
/**
* INTERNAL:
* Set the XMLDescriptor on this Type
* @param anXMLDescriptor
*/
public void setXmlDescriptor(XMLDescriptor anXMLDescriptor) {
xmlDescriptor = anXMLDescriptor;
}
public XMLDescriptor getXmlDescriptor() {
return xmlDescriptor;
}
/**
* INTERNAL:
* Get the XMLDescriptor associated with this Type or generate a new one.
*/
public void initializeNamespaces(List namespaceResolvers) {
if (!isDataType()) {
NamespaceResolver nr = new NamespaceResolver();
// copy namespaces between resolvers for well known and SDO namespaces
if (namespaceResolvers != null) {
for (int i = 0; i < namespaceResolvers.size(); i++) {
NamespaceResolver nextNR = (NamespaceResolver)namespaceResolvers.get(i);
if (nextNR != null) {
for (int j = 0, size = nextNR.getNamespaces().size(); j < size; j++) {
Namespace nextNamespace = nextNR.getNamespaces().get(j);
if ((!nextNamespace.getPrefix().equals(javax.xml.XMLConstants.XMLNS_ATTRIBUTE)) && (!nextNamespace.getNamespaceURI().equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI)) &&
(!nextNamespace.getNamespaceURI().equals(SDOConstants.SDOJAVA_URL)) && (!nextNamespace.getNamespaceURI().equals(SDOConstants.SDOXML_URL)) &&
(!nextNamespace.getNamespaceURI().equals(SDOConstants.SDO_URL))) {
String newPrefix = ((SDOTypeHelper)aHelperContext.getTypeHelper()).addNamespace(nextNamespace.getPrefix(), nextNamespace.getNamespaceURI());
nr.put(newPrefix, nextNamespace.getNamespaceURI());
}
}
}
}
}
xmlDescriptor.setNamespaceResolver(nr);
if (getURI() != null) {
String prefix = ((SDOTypeHelper)aHelperContext.getTypeHelper()).getPrefix(getURI());
xmlDescriptor.getNamespaceResolver().put(prefix, getURI());
}
xmlDescriptor.getNamespaceResolver().put(XMLConstants.SCHEMA_INSTANCE_PREFIX, javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
}
}
/**
* INTERNAL:
* Convenience method that sets up class indicator and @sdoRef
* attribute.
*
* @param xdesc
* @param pCls
*/
private void addClassIndicator(XMLDescriptor xdesc, Class pCls, boolean isInheritanceRoot) {
XMLField field = (XMLField)getXmlDescriptor().buildField("@xsi:type");
field.initialize();
xdesc.getInheritancePolicy().setClassIndicatorField(field);
String parentIndicator = getName();
String parentPrefix = xdesc.getNamespaceResolver().resolveNamespaceURI(getURI());
if (parentPrefix != null) {
parentIndicator = parentPrefix + SDOConstants.SDO_XPATH_NS_SEPARATOR_FRAGMENT + parentIndicator;
}
xdesc.getInheritancePolicy().addClassIndicator(pCls, parentIndicator);
// only add the @sdoRef attribute if necessary
if (xdesc.getMappingForAttributeName(SDO_REF_MAPPING_ATTRIBUTE_NAME) == null) {
String sdoPrefix = ((SDOTypeHelper)aHelperContext.getTypeHelper()).getPrefix(SDOConstants.SDO_URL);
XMLDirectMapping sdoRefMapping = new XMLDirectMapping();
sdoRefMapping.setAttributeName(SDO_REF_MAPPING_ATTRIBUTE_NAME);
XMLField xmlField = new XMLField("@" + sdoPrefix + SDOConstants.SDO_XPATH_NS_SEPARATOR_FRAGMENT + SDOConstants.CHANGESUMMARY_REF);
xmlField.getXPathFragment().setNamespaceURI(SDOConstants.SDO_URL);
xmlField.getLastXPathFragment().setNamespaceURI(SDOConstants.SDO_URL);
sdoRefMapping.setField(xmlField);
xdesc.addMapping(sdoRefMapping);
}
}
public void setupInheritance(SDOType parentType) {
if (parentType == null) {
// root of inheritance
addClassIndicator(getXmlDescriptor(), getImplClass(), true);
} else {
if ((parentType.getURI() != null) && (!parentType.getURI().equals(SDOConstants.SDO_URL))) {
// set parent descriptor indicator if necessary
if (!parentType.getXmlDescriptor().hasInheritance()) {
addClassIndicator(parentType.getXmlDescriptor(), parentType.getImplClass(), false);
}
XMLDescriptor parentDescriptor = (XMLDescriptor)parentType.getXmlDescriptor().getInheritancePolicy().getRootParentDescriptor();
NamespaceResolver parentNR = parentDescriptor.getNonNullNamespaceResolver();
if (parentNR != null) {
for (int i = 0; i < parentNR.getNamespaces().size(); i++) {
Namespace nextNamespace = parentNR.getNamespaces().get(i);
if ((!nextNamespace.getPrefix().equals(javax.xml.XMLConstants.XMLNS_ATTRIBUTE)) && (!nextNamespace.getNamespaceURI().equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI)) &&
(!nextNamespace.getNamespaceURI().equals(SDOConstants.SDOJAVA_URL)) && (!nextNamespace.getNamespaceURI().equals(SDOConstants.SDOXML_URL)) &&
(!nextNamespace.getNamespaceURI().equals(SDOConstants.SDO_URL))) {
getXmlDescriptor().getNonNullNamespaceResolver().put(nextNamespace.getPrefix(), nextNamespace.getNamespaceURI());
}
}
}
if (getInstanceClassName() != null) {
String indicator = getName();
String prefix = parentDescriptor.getNamespaceResolver().resolveNamespaceURI(getURI());
if (prefix == null) {
prefix = getXmlDescriptor().getNamespaceResolver().resolveNamespaceURI(getURI());
if (prefix != null) {
parentDescriptor.getNamespaceResolver().put(prefix, getURI());
}
}
if (prefix != null) {
indicator = prefix + SDOConstants.SDO_XPATH_NS_SEPARATOR_FRAGMENT + indicator;
}
Class implClass = getImplClass();
parentDescriptor.getInheritancePolicy().addClassIndicator(implClass, indicator);
parentDescriptor.getInheritancePolicy().setShouldReadSubclasses(true);
Class parentClass = parentType.getImplClass();
getXmlDescriptor().getInheritancePolicy().setParentClass(parentClass);
getXmlDescriptor().getInheritancePolicy().setParentDescriptor(parentType.getXmlDescriptor());
parentType.getXmlDescriptor().getNamespaceResolver().put(XMLConstants.SCHEMA_INSTANCE_PREFIX, javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
getXmlDescriptor().getNamespaceResolver().put(XMLConstants.SCHEMA_INSTANCE_PREFIX, javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
}
}
}
// now setup inheritance for any subtypes
if(isBaseType()) {
for (int i = 0; i < subTypes.size(); i++) {
SDOType nextSubType = (SDOType)subTypes.get(i);
if (!nextSubType.isDataType() && nextSubType.isSubType()) {
nextSubType.setupInheritance(this);
}
}
}
}
/**
* INTERNAL:
* For this Type generate classes
* @param packageName
* @param namespaceResolvers
*/
public void preInitialize(String packageName, List namespaceResolvers) {
String instanceClassName = getInstanceClassName();
if (null == instanceClassName) {
if (null == packageName) {
String uri = getURI();
if (null == uri) {
packageName = SDOUtil.getDefaultPackageName() + SDOConstants.JAVA_PACKAGE_NAME_SEPARATOR;
} else {
packageName = SDOUtil.getPackageNameFromURI(uri) + SDOConstants.JAVA_PACKAGE_NAME_SEPARATOR;
}
}
// Verify and fix any Class name that does not conform to conventions
// run the class name through the JAXB mangler
String mangledClassName = SDOUtil.className(getName(), false, true, true);
// we will not fix any type collision at this time as a result of class renaming
// write fully qualified java class name
StringBuffer fullClassName = new StringBuffer(packageName);
fullClassName.append(mangledClassName);
setInstanceClassName(fullClassName.toString());
}
AbstractSessionLog.getLog().log(AbstractSessionLog.FINER,//
"sdo_type_generation_processing_type", //
new Object[] { Helper.getShortClassName(getClass()), getInstanceClassName() });
initializeNamespaces(namespaceResolvers);
getXmlDescriptor().setJavaClassName(getImplClassName());
// See SDOResolvable enhancement
String schemaContext = getName();
if (getXmlDescriptor().getNamespaceResolver() != null) {
String prefix = getXmlDescriptor().getNamespaceResolver().resolveNamespaceURI(getURI());
if ((prefix != null) && !prefix.equals(SDOConstants.EMPTY_STRING)) {
schemaContext = prefix + SDOConstants.SDO_XPATH_NS_SEPARATOR_FRAGMENT + schemaContext;
}
}
String schemaContextWithSlash = SDOConstants.SDO_XPATH_SEPARATOR_FRAGMENT + schemaContext;
XMLSchemaReference schemaRef = new XMLSchemaClassPathReference();
schemaRef.setSchemaContext(schemaContextWithSlash);
schemaRef.setType(XMLSchemaReference.COMPLEX_TYPE);
getXmlDescriptor().setSchemaReference(schemaRef);
}
/**
* INTERNAL:
*/
public void postInitialize() {
String idPropName = (String)get(SDOConstants.ID_PROPERTY);
if (idPropName != null) {
SDOProperty idProp = getProperty(idPropName);
if (idProp != null) {
String targetxpath = idProp.getQualifiedXPath(getURI(), true);
getXmlDescriptor().addPrimaryKeyFieldName(targetxpath);
}
}
setFinalized(true);
if(null != nonFinalizedReferencingProps) {
for (int i = 0; i < nonFinalizedReferencingProps.size(); i++) {
SDOProperty nextProp = nonFinalizedReferencingProps.get(i);
String nextURI = (String)getNonFinalizedMappingURIs().get(i);
nextProp.buildMapping(nextURI, nextProp.getIndexInType());
}
nonFinalizedReferencingProps = null;
nonFinalizedMappingURIs = null;
}
// set @sdoRef attribute mapping for complex types that are not involved in inheritance
if (!isDataType() && !isSubType() && !isBaseType()) {
String sdoPrefix = ((SDOTypeHelper)aHelperContext.getTypeHelper()).getPrefix(SDOConstants.SDO_URL);
XMLDirectMapping sdoRefMapping = new XMLDirectMapping();
sdoRefMapping.setAttributeName(SDO_REF_MAPPING_ATTRIBUTE_NAME);
XMLField xmlField = new XMLField("@" + sdoPrefix + SDOConstants.SDO_XPATH_NS_SEPARATOR_FRAGMENT + SDOConstants.CHANGESUMMARY_REF);
xmlField.getXPathFragment().setNamespaceURI(SDOConstants.SDO_URL);
xmlField.getLastXPathFragment().setNamespaceURI(SDOConstants.SDO_URL);
sdoRefMapping.setField(xmlField);
xmlDescriptor.addMapping(sdoRefMapping);
}
if(!isDataType()) {
getImplClass();
if(!isAbstract() && !isWrapperType()) {
TypeInstantiationPolicy tip = new TypeInstantiationPolicy(this);
this.xmlDescriptor.setInstantiationPolicy(tip);
}
}
}
/**
* INTERNAL:
*/
public void setImplClassName(String implClassName) {
javaImplClassName = implClassName;
javaImplClass = null;
}
/**
* INTERNAL:
*/
public String getImplClassName() {
if ((javaImplClassName == null) && (javaClassName != null)) {
javaImplClassName = javaClassName + SDOConstants.SDO_IMPL_NAME;
}
return javaImplClassName;
}
/**
* INTERNAL:
*/
public Class getImplClass() {
if ((javaImplClass == null) && (getImplClassName() != null)) {
try {
SDOClassLoader loader = ((SDOXMLHelper)aHelperContext.getXMLHelper()).getLoader();
javaImplClass = loader.loadClass(getImplClassName(), this);
xmlDescriptor.setJavaClass(javaImplClass);
} catch (ClassNotFoundException e) {
throw SDOException.classNotFound(e, getURI(), getName());
} catch (SecurityException e) {
throw SDOException.classNotFound(e, getURI(), getName());
}
}
return javaImplClass;
}
@Override
public Object get(Property property) {
if(null == propertyValues) {
return null;
}
return propertyValues.get(property);
}
@Override
public List getInstanceProperties() {
if(null == propertyValues) {
return Collections.EMPTY_LIST;
}
return new ArrayList(getPropertyValues().keySet());
}
/**
* INTERNAL:
*/
public void setPropertyValues(Map properties) {
this.propertyValues = properties;
}
/**
* INTERNAL:
*/
public Map getPropertyValues() {
if (propertyValues == null) {
propertyValues = new HashMap();
}
return propertyValues;
}
/**
* INTERNAL:
*
* @param property
* @param value
*/
public void setInstanceProperty(Property property, Object value) {
if (property.equals(SDOConstants.JAVA_CLASS_PROPERTY) && value instanceof String) {
setInstanceClassName((String)value);
}
getPropertyValues().put(property, value);
}
/**
* INTERNAL:
*/
public SDOProperty getChangeSummaryProperty() {
return changeSummaryProperty;
}
/**
* INTERNAL:
*/
public SDOProperty[] getPropertiesArray() {
if ((allPropertiesArr == null) || (allPropertiesArr.length != getProperties().size())) {
List l = getProperties();
int s = (l == null) ? 0 : l.size();
if (s > 0) {
allPropertiesArr = (SDOProperty[])l.toArray(new SDOProperty[s]);
} else {
// initialize an empty array
allPropertiesArr = new SDOProperty[0];
}
}
return allPropertiesArr;
}
/**
* INTERNAL:
*/
public void setSubTypes(List subTypesList) {
subTypes = subTypesList;
}
/**
* INTERNAL:
*/
public List getSubTypes() {
if (subTypes == null) {
subTypes = new ArrayList();
}
return subTypes;
}
/**
* INTERNAL:
* Provide a means to determine if this type has sub types without causing the sub types property to be initialized.
*/
public boolean isBaseType() {
return !(null == subTypes || subTypes.isEmpty());
}
private void updateIndices(int insertPosition, Property property) {
int declaredSize = getDeclaredProperties().size();
SDOProperty nextProp = null;
for (int i = 0; i < declaredSize; i++) {
nextProp = (SDOProperty)getDeclaredProperties().get(i);
nextProp.incrementIndexInType();
}
getProperties().add(insertPosition, property);
if(isBaseType()) {
int subTypesSize = getSubTypes().size();
SDOType nextSubType = null;
for (int i = 0; i < subTypesSize; i++) {
nextSubType = (SDOType)getSubTypes().get(i);
nextSubType.updateIndices(insertPosition, property);
}
}
}
/**
* INTERNAL:
*/
public void setXsdType(QName xsdTypeQName) {
xsdType = xsdTypeQName;
}
/**
* INTERNAL:
*/
public QName getXsdType() {
return xsdType;
}
/**
* INTERNAL:
*/
public void setFinalized(boolean bFinalized) {
finalized = bFinalized;
}
/**
* INTERNAL:
*/
public boolean isFinalized() {
return finalized;
}
/**
* INTERNAL:
*/
public void setNonFinalizedReferencingProps(List nonFinalizedReferencingProps) {
this.nonFinalizedReferencingProps = nonFinalizedReferencingProps;
}
/**
* INTERNAL:
*/
public List getNonFinalizedReferencingProps() {
if (nonFinalizedReferencingProps == null) {
nonFinalizedReferencingProps = new ArrayList();
}
return nonFinalizedReferencingProps;
}
/**
* INTERNAL:
*/
public void setNonFinalizedMappingURIs(List nonFinalizedMappingURIsList) {
nonFinalizedMappingURIs = nonFinalizedMappingURIsList;
}
/**
* INTERNAL:
*/
public List getNonFinalizedMappingURIs() {
if (nonFinalizedMappingURIs == null) {
nonFinalizedMappingURIs = new ArrayList();
}
return nonFinalizedMappingURIs;
}
/**
* INTERNAL:
*/
public void setAppInfoElements(List appInfoElementsList) {
appInfoElements = appInfoElementsList;
}
/**
* INTERNAL:
*/
public List getAppInfoElements() {
return appInfoElements;
}
/**
* INTERNAL:
*/
public Map getAppInfoMap() {
if (appInfoMap == null) {
appInfoMap = ((SDOXSDHelper)aHelperContext.getXSDHelper()).buildAppInfoMap(appInfoElements);
}
return appInfoMap;
}
/**
* INTERNAL:
* Return the wrapped initial value for the primitive numeric (when not defined)
* See p.45 of Java Spec 4th edition.
* See p.85 Sect 9.3 of the SDO Spec.
* @return aDefault Object (primitive numerics) or null (DataObjects, String, Lists)
*/
public Object getPseudoDefault() {
return pseudoDefault;
}
/**
* INTERNAL:
* Set an Object wrapper around primitive numeric types
* @param anObject
*/
public void setPseudoDefault(Object anObject) {
pseudoDefault = anObject;
}
/**
* Return the HelperContext object associated with this type.
* For example, the typeHelper associated with the returned HelperContext would contain this type
*/
public HelperContext getHelperContext(){
return aHelperContext;
}
public boolean isChangeSummaryType() {
return false;
}
public boolean isDataObjectType() {
return false;
}
public boolean isTypeType() {
return false;
}
public boolean isOpenSequencedType() {
return false;
}
public boolean isWrapperType() {
return false;
}
public static class TypeInstantiationPolicy extends InstantiationPolicy {
SDOType sdoType;
public TypeInstantiationPolicy(SDOType type) {
sdoType = type;
}
@Override
public Object buildNewInstance() throws DescriptorException {
return sdoType.getHelperContext().getDataFactory().create(sdoType);
}
}
}