org.eclipse.persistence.eis.EISDescriptor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction f2b9fc5
/*
* Copyright (c) 1998, 2020 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
// 14/05/2012-2.4 Guy Pelletier
// - 376603: Provide for table per tenant support for multitenant applications
package org.eclipse.persistence.eis;
import java.util.List;
import java.util.Vector;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.DescriptorQueryManager;
import org.eclipse.persistence.descriptors.InheritancePolicy;
import org.eclipse.persistence.eis.mappings.EISCompositeCollectionMapping;
import org.eclipse.persistence.eis.mappings.EISCompositeDirectCollectionMapping;
import org.eclipse.persistence.eis.mappings.EISCompositeObjectMapping;
import org.eclipse.persistence.eis.mappings.EISDirectMapping;
import org.eclipse.persistence.eis.mappings.EISOneToManyMapping;
import org.eclipse.persistence.eis.mappings.EISOneToOneMapping;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.internal.databaseaccess.DatasourceCall;
import org.eclipse.persistence.internal.databaseaccess.DatasourcePlatform;
import org.eclipse.persistence.internal.expressions.SQLStatement;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.oxm.QNameInheritancePolicy;
import org.eclipse.persistence.internal.oxm.XMLObjectBuilder;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.AggregateMapping;
import org.eclipse.persistence.mappings.CollectionMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.queries.DatabaseQuery;
/**
*
* An EISDescriptor
defines the mapping from a JCA data
* structure to a Java object. There are two types of EIS descriptors:
*
* - Root - indicates to the EclipseLink runtime that the EIS descriptor's
* reference class is a parent class: no other class will reference it by way of
* a composite object mapping or composite collection mapping. For an EIS root
* descriptor, EIS interactions can be defined to invoke methods on an EIS
*
- Composite - indicates to the EclipseLink runtime that the EIS descriptor's
* reference class may be referenced by a composite object mapping or composite
* collection mapping
*
*
* @see org.eclipse.persistence.eis.interactions.EISInteraction
* @see org.eclipse.persistence.eis.mappings.EISMapping
*
* @author James
* @since OracleAS TopLink 10g (10.0.3)
*/
public class EISDescriptor extends ClassDescriptor {
/** Define the type of data the descriptor maps to. */
protected String dataFormat;
/** Define the valid data formats that the descriptor can map to. */
public static final String MAPPED = "mapped";
public static final String INDEXED = "indexed";
public static final String XML = "xml";
/** Allow namespaces to be specified for XML type descriptors. */
protected NamespaceResolver namespaceResolver;
/**
* Default constructor.
*/
public EISDescriptor() {
super();
this.shouldOrderMappings = false;
this.dataFormat = XML;
}
@Override
protected void validateMappingType(DatabaseMapping mapping) {
if (!(mapping.isEISMapping())) {
throw DescriptorException.invalidMappingType(mapping);
}
}
/**
* PUBLIC:
* Specify the data type name for the class of objects the descriptor maps.
* This may be the XML schema complex type name, or the JCA record name for the type being mapped.
*/
public void setDataTypeName(String dataTypeName) throws DescriptorException {
this.setTableName(dataTypeName);
}
/**
* PUBLIC:
* Return the XML namespace resolver.
* XML type EIS descriptor can use a namespace resolver to support XML schema namespaces.
*/
public NamespaceResolver getNamespaceResolver() {
return namespaceResolver;
}
/**
* PUBLIC:
* The inheritance policy is used to define how a descriptor takes part in inheritance.
* All inheritance properties for both child and parent classes is configured in inheritance policy.
* Caution must be used in using this method as it lazy initializes an inheritance policy.
* Calling this on a descriptor that does not use inheritance will cause problems, #hasInheritance() must always first be called.
*/
@Override
public InheritancePolicy getInheritancePolicy() {
if (inheritancePolicy == null) {
if(isXMLFormat()) {
// Lazy initialize to conserve space in non-inherited classes.
setInheritancePolicy(new org.eclipse.persistence.internal.oxm.QNameInheritancePolicy(this));
} else {
setInheritancePolicy(new InheritancePolicy(this));
}
}
return inheritancePolicy;
}
/**
* PUBLIC:
* Set the XML namespace resolver.
* XML type EIS descriptor can use a namespace resolver to support XML schema namespaces.
*/
public void setNamespaceResolver(NamespaceResolver namespaceResolver) {
this.namespaceResolver = namespaceResolver;
}
/**
* INTERNAL:
* Avoid SDK initialization.
*/
@Override
public void setQueryManager(DescriptorQueryManager queryManager) {
this.queryManager = queryManager;
if (queryManager != null) {
queryManager.setDescriptor(this);
}
}
/**
* INTERNAL:
* Configure the object builder for the correct dataFormat.
*/
@Override
public void preInitialize(AbstractSession session) {
// Must not initialize if already done.
if (isInitialized(PREINITIALIZED)) {
return;
}
if (isXMLFormat()) {
setObjectBuilder(new XMLObjectBuilder(this));
if(this.hasInheritance()) {
((QNameInheritancePolicy)getInheritancePolicy()).setNamespaceResolver(this.namespaceResolver);
}
}
// initializeQueryManager();
super.preInitialize(session);
}
/**
* INTERNAL:
* Initialize the query manager specific to the descriptor type.
* Allow the platform to initialize the CRUD queries to defaults.
*/
@Override
public void initialize(DescriptorQueryManager queryManager, AbstractSession session) {
((DatasourcePlatform)session.getDatasourcePlatform()).initializeDefaultQueries(queryManager, session);
super.initialize(queryManager, session);
}
public boolean isXMLFormat() {
return this.dataFormat.equals(XML);
}
public boolean isMappedFormat() {
return this.dataFormat.equals(MAPPED);
}
public boolean isIndexedFormat() {
return this.dataFormat.equals(INDEXED);
}
/**
* PUBLIC:
* Return the data format that the descriptor maps to.
*/
public String getDataFormat() {
return dataFormat;
}
/**
* PUBLIC:
* Specify the data type name for the class of objects the descriptor maps.
* This may be the XML schema complex type name, or the JCA record name for the type being mapped.
*/
public String getDataTypeName() throws DescriptorException {
return this.getTableName();
}
/**
* PUBLIC:
* Configure the data format that the descriptor maps to.
*/
public void setDataFormat(String dataFormat) {
this.dataFormat = dataFormat;
}
/**
* PUBLIC:
* Configure the data format to use mapped records.
*/
public void useMappedRecordFormat() {
setDataFormat(MAPPED);
}
/**
* PUBLIC:
* Configure the data format to use indexed records.
*/
public void useIndexedRecordFormat() {
setDataFormat(INDEXED);
}
/**
* PUBLIC:
* Configure the data format to use xml records.
*/
public void useXMLRecordFormat() {
setDataFormat(XML);
}
/**
* INTERNAL:
* Build the nested row.
*/
@Override
public AbstractRecord buildNestedRowFromFieldValue(Object fieldValue) {
if (fieldValue instanceof AbstractRecord) {
return (AbstractRecord)fieldValue;
}
// BUG#2667762 if the tag was empty this could be a string of whitespace.
if (!(fieldValue instanceof List)) {
return getObjectBuilder().createRecord(0, null);
}
List nestedRows = (List)fieldValue;
if (nestedRows.isEmpty()) {
return getObjectBuilder().createRecord(0, null);
} else {
// BUG#2667762 if the tag was empty this could be a string of whitespace.
if (!(nestedRows.get(0) instanceof AbstractRecord)) {
return getObjectBuilder().createRecord(0, null);
}
return (AbstractRecord)nestedRows.get(0);
}
}
/**
* INTERNAL:
* Build the nested rows.
*/
@Override
public Vector buildNestedRowsFromFieldValue(Object fieldValue, AbstractSession session) {
if (!isXMLFormat()) {
if (!(fieldValue instanceof List)) {
return new Vector();
}
return new Vector((List)fieldValue);
}
// BUG#2667762 if the tag was empty this could be a string of whitespace.
if (!(fieldValue instanceof Vector)) {
return new Vector(0);
}
return (Vector)fieldValue;
}
/**
* INTERNAL:
* Extract the direct values from the specified field value.
* Return them in a vector.
* The field value could be a vector or could be a text value if only a single value.
*/
@Override
public Vector buildDirectValuesFromFieldValue(Object fieldValue) {
if (!(fieldValue instanceof Vector)) {
Vector fieldValues = new Vector(1);
fieldValues.add(fieldValue);
return fieldValues;
}
return (Vector)fieldValue;
}
/**
* INTERNAL:
* Build the appropriate field value for the specified
* set of direct values.
* The database better be expecting a Vector.
*/
@Override
public Object buildFieldValueFromDirectValues(Vector directValues, String elementDataTypeName, AbstractSession session) {
return directValues;
}
/**
* INTERNAL:
* Build and return the field value from the specified nested database row.
*/
@Override
public Object buildFieldValueFromNestedRow(AbstractRecord nestedRow, AbstractSession session) throws DatabaseException {
Vector nestedRows = new Vector(1);
nestedRows.add(nestedRow);
return this.buildFieldValueFromNestedRows(nestedRows, "", session);
}
/**
* INTERNAL:
* Build and return the appropriate field value for the specified
* set of nested rows.
*/
@Override
public Object buildFieldValueFromNestedRows(Vector nestedRows, String structureName, AbstractSession session) throws DatabaseException {
return nestedRows;
}
/**
* INTERNAL:
* XML type descriptors should use XMLFields.
*/
@Override
public DatabaseField buildField(String fieldName) {
if (isXMLFormat()) {
XMLField xmlField = new XMLField(fieldName);
xmlField.setNamespaceResolver(this.getNamespaceResolver());
xmlField.initialize();
return xmlField;
} else {
return super.buildField(fieldName);
}
}
/**
* INTERNAL:
* If the field is an XMLField then set the namespace resolver from the descriptor.
* This allows the resolver to only be set in the descriptor.
*/
@Override
public DatabaseField buildField(DatabaseField field) {
if (isXMLFormat()) {
if(!(field instanceof XMLField)) {
String xPath = field.getName();
// Moxy requires /text on elements.
if ((xPath.indexOf('@') == -1) && (xPath.indexOf("/text()") == -1)) {
xPath = xPath + "/text()";
}
field = new XMLField(xPath);
}
((XMLField)field).setNamespaceResolver(getNamespaceResolver());
((XMLField)field).initialize();
}
return super.buildField(field);
}
/**
* Return a new direct/basic mapping for this type of descriptor.
*/
@Override
public AbstractDirectMapping newDirectMapping() {
return new EISDirectMapping();
}
/**
* Return a new aggregate/embedded mapping for this type of descriptor.
*/
@Override
public AggregateMapping newAggregateMapping() {
return new EISCompositeObjectMapping();
}
/**
* Return a new aggregate collection/element collection mapping for this type of descriptor.
*/
@Override
public DatabaseMapping newAggregateCollectionMapping() {
return new EISCompositeCollectionMapping();
}
/**
* Return a new direct collection/element collection mapping for this type of descriptor.
*/
@Override
public DatabaseMapping newDirectCollectionMapping() {
return new EISCompositeDirectCollectionMapping();
}
/**
* Return a new one to one mapping for this type of descriptor.
*/
@Override
public ObjectReferenceMapping newOneToOneMapping() {
return new EISOneToOneMapping();
}
/**
* Return a new many to one mapping for this type of descriptor.
*/
@Override
public ObjectReferenceMapping newManyToOneMapping() {
return new EISOneToOneMapping();
}
/**
* Return a new one to many mapping for this type of descriptor.
*/
@Override
public CollectionMapping newOneToManyMapping() {
return new EISOneToManyMapping();
}
/**
* Return a new one to many mapping for this type of descriptor.
*/
@Override
public CollectionMapping newUnidirectionalOneToManyMapping() {
return new EISOneToManyMapping();
}
/**
* Return a new one to many mapping for this type of descriptor.
*/
@Override
public CollectionMapping newManyToManyMapping() {
return new EISOneToManyMapping();
}
/**
* PUBLIC: Add a direct mapping to the receiver. The new mapping specifies
* that an instance variable of the class of objects which the receiver
* describes maps in the default manner for its type to the indicated
* database field.
*
* @param attributeName
* instanceVariableName is the name of an instance variable of
* the class which the receiver describes.
* @param fieldName
* fieldName is the name of the xml element or attribute which
* corresponds with the designated instance variable.
* @return The newly created DatabaseMapping is returned.
*/
@Override
public DatabaseMapping addDirectMapping(String attributeName, String fieldName) {
EISDirectMapping mapping = new EISDirectMapping();
mapping.setAttributeName(attributeName);
if (isXMLFormat()) {
mapping.setXPath(fieldName);
} else {
mapping.setFieldName(fieldName);
}
return addMapping(mapping);
}
/**
* PUBLIC:
* Add a direct to node mapping to the receiver. The new mapping specifies that
* a variable accessed by the get and set methods of the class of objects which
* the receiver describes maps in the default manner for its type to the indicated
* database field.
*/
@Override
public DatabaseMapping addDirectMapping(String attributeName, String getMethodName, String setMethodName, String fieldName) {
EISDirectMapping mapping = new EISDirectMapping();
mapping.setAttributeName(attributeName);
mapping.setSetMethodName(setMethodName);
mapping.setGetMethodName(getMethodName);
if (isXMLFormat()) {
mapping.setXPath(fieldName);
} else {
mapping.setFieldName(fieldName);
}
return addMapping(mapping);
}
/**
* PUBLIC:
* Specify the primary key field.
* This should be called for each field that make up the primary key.
* For EIS XML Descriptors use the addPrimaryKeyField(DatabaseField) API
* and supply an org.eclipse.persistence.oxm.XMLField parameter instead of using this method
*/
@Override
public void addPrimaryKeyFieldName(String fieldName) {
if (isXMLFormat()) {
addPrimaryKeyField(new XMLField(fieldName));
} else {
super.addPrimaryKeyFieldName(fieldName);
}
}
/**
* PUBLIC:
* Set the sequence number field name.
* This is the field in the descriptors table that needs its value to be generated.
* This is normally the primary key field of the descriptor.
* For EIS XML Descriptors use the setSequenceNumberFieldName(DatabaseField) API
* and supply an org.eclipse.persistence.oxm.XMLField parameter instead of using this method
*/
@Override
public void setSequenceNumberFieldName(String fieldName) {
super.setSequenceNumberFieldName(fieldName);
}
/**
* INTERNAL:
* Override this method to throw an exception. SQL should not be generated for
* EIS Calls.
*/
@Override
public DatasourceCall buildCallFromStatement(SQLStatement statement, DatabaseQuery query, AbstractSession session) {
return ((EISPlatform)session.getDatasourcePlatform()).buildCallFromStatement(statement, query, session);
}
@Override
public void initialize(AbstractSession session) throws DescriptorException {
if (isXMLFormat()) {
for(int x = 0, primaryKeyFieldsSize = this.primaryKeyFields.size(); x