/*******************************************************************************
* Copyright (c) 1998, 2015 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 v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.workbench.mappingsmodel.mapping;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.persistence.tools.workbench.mappingsmodel.MWDataField;
import org.eclipse.persistence.tools.workbench.mappingsmodel.MWModel;
import org.eclipse.persistence.tools.workbench.mappingsmodel.MWQueryKey;
import org.eclipse.persistence.tools.workbench.mappingsmodel.ProblemConstants;
import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.MWLockingPolicy;
import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.MWMappingDescriptor;
import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.relational.MWInterfaceDescriptor;
import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.xml.MWEisDescriptor;
import org.eclipse.persistence.tools.workbench.mappingsmodel.handles.MWAttributeHandle;
import org.eclipse.persistence.tools.workbench.mappingsmodel.handles.MWHandle;
import org.eclipse.persistence.tools.workbench.mappingsmodel.handles.MWMethodHandle;
import org.eclipse.persistence.tools.workbench.mappingsmodel.handles.MWHandle.NodeReferenceScrubber;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWAbstractTableReferenceMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWAggregateMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWCollectionMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWDirectToFieldMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWDirectToXmlTypeMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWManyToManyMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWOneToManyMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWOneToOneMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWRelationalDirectCollectionMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWRelationalDirectContainerMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWRelationalDirectMapMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWRelationalDirectMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWRelationalMappingFactory;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWRelationalTransformationMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWVariableOneToOneMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWAbstractAnyMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWAbstractCompositeMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWAnyAttributeMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWAnyCollectionMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWAnyObjectMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWCompositeCollectionMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWCompositeObjectMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWEisMappingFactory;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWEisOneToManyMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWEisOneToOneMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWEisReferenceMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWOXMappingFactory;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWXmlCollectionReferenceMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWXmlDirectCollectionMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWXmlDirectMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWXmlFragmentCollectionMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWXmlFragmentMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWXmlMappingFactory;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWXmlObjectReferenceMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWXmlTransformationMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.xml.MWXpathedMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWClass;
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWClassAttribute;
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWClassCodeGenPolicy;
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWMethod;
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWMethodCodeGenPolicy;
import org.eclipse.persistence.tools.workbench.mappingsmodel.query.MWQueryable;
import org.eclipse.persistence.tools.workbench.utility.filters.Filter;
import org.eclipse.persistence.tools.workbench.utility.iterators.CompositeIterator;
import org.eclipse.persistence.tools.workbench.utility.iterators.TransformationIterator;
import org.eclipse.persistence.tools.workbench.utility.node.Node;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.descriptors.InheritancePolicy;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping;
import org.eclipse.persistence.oxm.mappings.XMLDirectMapping;
/**
* Discussion of morphing mappings:<ol>
*
* <li> Any subclass can be sent one of the asMW___Mapping() methods.
* The default implementation is defined here. They are overridden where
* appropriate - when no transmogrification is needed and the mapping simply
* returns itself.
*
* <li> Each concrete subclass must override the method initializeOn(MWMapping newMapping)
* and call the appropriate initializeFromMW___Mapping(MW___Mapping oldMapping).
* [This is call double-dispatching.]
* We could have overloaded the same method name (e.g. initializeFrom(MW___Mapping oldMapping))
* but the resulting confusion is not worth it. "Upcasting" just makes this really fuzzy....
*
* <il> If necessary, each subclass (concrete and abstract) should override
* the initializeFromMW___Mapping(MW___Mapping oldMapping) method. This override
* should first call super.initializeFromMW___Mapping(MW___Mapping oldMapping); then
* it should initialize only the properties that are defined by it that have
* corresponding properties in the oldMapping.
*
* </ol>
*/
public abstract class MWMapping extends MWModel implements MWQueryable {
private MWAttributeHandle attributeHandle;
public final static String ATTRIBUTE_PROPERTY = "attribute";
private volatile String name;
public final static String NAME_PROPERTY = "name";
private volatile boolean inherited;
public final static String INHERITED_PROPERTY= "inherited";
private volatile boolean readOnly;
public final static String READ_ONLY_PROPERTY= "readOnly";
private volatile boolean usesMethodAccessing;
public final static String USES_METHOD_ACCESSING_PROPERTY = "usesMethodAccessing";
private MWMethodHandle getMethodHandle;
public final static String GET_METHOD_PROPERTY = "getMethod";
private MWMethodHandle setMethodHandle;
public final static String SET_METHOD_PROPERTY = "setMethod";
// used for backward compatibility
protected Map legacyValuesMap;
// ********** constructors **********
/** Default constructor - for TopLink use only */
protected MWMapping() {
super();
}
protected MWMapping(MWMappingDescriptor parent, MWClassAttribute attribute, String name) {
super(parent);
initialize(attribute, name);
}
// **************** Initialization ***************
/**
* initialize transient state
*/
protected void initialize() {
super.initialize();
this.legacyValuesMap = new HashMap();
}
/**
* initialize persistent state
*/
protected void initialize(Node parent) {
super.initialize(parent);
this.attributeHandle = new MWAttributeHandle(this, this.buildAttributeScrubber());
this.getMethodHandle = new MWMethodHandle(this, this.buildGetMethodScrubber());
this.setMethodHandle = new MWMethodHandle(this, this.buildSetMethodScrubber());
}
protected void initialize(MWClassAttribute attribute, String mappingName) {
this.attributeHandle.setAttribute(attribute);
if (getProject().getDefaultsPolicy().isMethodAccessing()) {
this.setUsesMethodAccessing(true);
}
this.name = mappingName;
}
// **************** Accessors ***************
public MWClassAttribute getInstanceVariable() {
return this.attributeHandle.getAttribute();
}
public void setInstanceVariable(MWClassAttribute newValue) {
Object oldValue = getInstanceVariable();
this.attributeHandle.setAttribute(newValue);
firePropertyChanged(ATTRIBUTE_PROPERTY, oldValue, newValue);
}
public String getName(){
return this.name;
}
public void setName(String name) {
Object old = this.name;
this.name = name;
this.firePropertyChanged(NAME_PROPERTY, old, name);
if (this.attributeValueHasChanged(old, name)) {
this.getProject().nodeRenamed(this);
}
}
public boolean isInherited() {
return this.inherited;
}
public void setInherited(boolean inherited) {
boolean old = this.inherited;
this.inherited = inherited;
this.firePropertyChanged(INHERITED_PROPERTY, old, inherited);
}
public boolean isReadOnly() {
return this.readOnly;
}
public void setReadOnly(boolean readOnly) {
boolean old = this.readOnly;
this.readOnly = readOnly;
this.firePropertyChanged(READ_ONLY_PROPERTY, old, readOnly);
}
public boolean usesMethodAccessing() {
return this.usesMethodAccessing;
}
public void setUsesMethodAccessing(boolean usesMethodAccessing) {
boolean old = this.usesMethodAccessing;
this.usesMethodAccessing = usesMethodAccessing;
if (old != usesMethodAccessing) {
this.firePropertyChanged(USES_METHOD_ACCESSING_PROPERTY, old, usesMethodAccessing);
if (usesMethodAccessing) {
if (this.getGetMethod() == null) {
this.setGetMethod((this.getInstanceVariable().getGetMethod() != null) ?
this.getInstanceVariable().getGetMethod()
:
this.getInstanceVariable().guessGetMethod()
);
}
if (this.getSetMethod() == null) {
this.setSetMethod((this.getInstanceVariable().getSetMethod() != null) ?
this.getInstanceVariable().getSetMethod()
:
this.getInstanceVariable().guessSetMethod()
);
}
} else {
this.setGetMethod(null);
this.setSetMethod(null);
}
}
}
public MWMethod getGetMethod() {
return this.getMethodHandle.getMethod();
}
public void setGetMethod(MWMethod getMethod) {
MWMethod old = this.getGetMethod();
this.getMethodHandle.setMethod(getMethod);
this.firePropertyChanged(GET_METHOD_PROPERTY, old, getMethod);
}
public Iterator candidateGetMethods() {
return new CompositeIterator(this.candidateGetMethodIterators());
}
private Iterator candidateGetMethodIterators() {
return new TransformationIterator(this.declaringClassesForCandidateAccessorMethods()) {
protected Object transform(Object next) {
return ((MWClass) next).candidateTopLinkGetMethods();
}
};
}
public MWMethod getSetMethod() {
return this.setMethodHandle.getMethod();
}
public void setSetMethod(MWMethod setMethod) {
MWMethod old = this.getSetMethod();
this.setMethodHandle.setMethod(setMethod);
this.firePropertyChanged(SET_METHOD_PROPERTY, old, setMethod);
}
public Iterator candidateSetMethods() {
return new CompositeIterator(this.candidateSetMethodIterators());
}
private Iterator candidateSetMethodIterators() {
return new TransformationIterator(this.declaringClassesForCandidateAccessorMethods()) {
protected Object transform(Object next) {
return ((MWClass) next).candidateTopLinkSetMethods();
}
};
}
private Iterator declaringClassesForCandidateAccessorMethods() {
return this.getParentDescriptor().getMWClass().lineageTo(this.getInstanceVariable().getDeclaringType());
}
/**
* Some mappings automatically have query keys associated with them.
* For example, a direct-to-field mapping called "firstName" has a
* query key named "firstName" that maps to the direct field
* in that mapping.
*
* If the mapping doesn't have an auto-generated query key, or if it
* is irrelevant for that type of mapping, this method returns null.
*/
public MWQueryKey getAutoGeneratedQueryKey() {
return null;
}
public boolean maintainsBidirectionalRelationship() {
return false;
}
public MWMapping getRelationshipPartnerMapping() {
return null;
}
public boolean isValidRelationshipPartner() {
return false;
}
public boolean isCollectionMapping(){
return false;
}
public boolean isOneToOneMapping(){
return false;
}
public boolean isReferenceMapping(){
return false;
}
public boolean isTableReferenceMapping(){
return false;
}
public void implementorsChangedFor(MWInterfaceDescriptor descriptor) {
//this is overridden by MWVariableOneToOneMapping
}
// ************ aggregate support ************
public final Iterator aggregateFieldNameGenerators() {
return buildAggregateFieldNameGenerators().iterator();
}
protected Collection buildAggregateFieldNameGenerators() {
return new ArrayList();
}
public void parentDescriptorMorphedToAggregate() {
// Method to be implemented by subclasses that need to do stuff like null out fields
// when they are morphed to aggregate. jbb
}
// **************** Containment hierarchy ***************
protected void addChildrenTo(List children) {
super.addChildrenTo(children);
children.add(this.attributeHandle);
children.add(this.getMethodHandle);
children.add(this.setMethodHandle);
}
private NodeReferenceScrubber buildAttributeScrubber() {
return new NodeReferenceScrubber() {
public void nodeReferenceRemoved(Node node, MWHandle handle) {
MWMapping.this.attributeRemoved();
}
public String toString() {
return "MWMapping.buildAttributeScrubber()";
}
};
}
void attributeRemoved() {
// we don't really need to clear the attribute;
// and some listeners would really appreciate it if we kept it around
// this.attributeHandle.setAttribute(null);
this.getParentDescriptor().removeMapping(this);
}
private NodeReferenceScrubber buildGetMethodScrubber() {
return new NodeReferenceScrubber() {
public void nodeReferenceRemoved(Node node, MWHandle handle) {
MWMapping.this.setGetMethod(null);
}
public String toString() {
return "MWMapping.buildGetMethodScrubber()";
}
};
}
private NodeReferenceScrubber buildSetMethodScrubber() {
return new NodeReferenceScrubber() {
public void nodeReferenceRemoved(Node node, MWHandle handle) {
MWMapping.this.setSetMethod(null);
}
public String toString() {
return "MWMapping.buildSetMethodScrubber()";
}
};
}
// **************** Convenience methods ***************
public MWMappingDescriptor getParentDescriptor() {
return (MWMappingDescriptor) this.getParent();
}
// ***************** Morphing ***************
private MWMappingFactory mappingFactory() {
return getParentDescriptor().mappingFactory();
}
/**
* IMPORTANT:
* See MWRMapping class comment concerning asBldr___Mapping() methods.
*/
public MWDirectMapping asMWDirectMapping() {
MWDirectMapping newMapping =
mappingFactory().createDirectMapping(getParentDescriptor(), getInstanceVariable(), getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping); // this will set the descriptor
return newMapping;
}
public MWXmlFragmentMapping asMWXmlFragmentMapping() {
MWXmlFragmentMapping newMapping =
((MWOXMappingFactory) this.mappingFactory()).createXmlFragmentMapping(this.getParentDescriptor(), this.getInstanceVariable(), this.getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping);
return newMapping;
}
public MWXmlFragmentCollectionMapping asMWXmlFragmentCollectionMapping() {
MWXmlFragmentCollectionMapping newMapping =
((MWOXMappingFactory) this.mappingFactory()).createXmlFragmentCollectionMapping(this.getParentDescriptor(), this.getInstanceVariable(), this.getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping);
return newMapping;
}
public MWXmlObjectReferenceMapping asMWXmlObjectReferenceMapping() {
MWXmlObjectReferenceMapping newMapping =
((MWOXMappingFactory) this.mappingFactory()).createXmlObjectReferenceMapping(this.getParentDescriptor(), this.getInstanceVariable(), this.getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping);
return newMapping;
}
public MWXmlCollectionReferenceMapping asMWXmlCollectionReferenceMapping() {
MWXmlCollectionReferenceMapping newMapping =
((MWOXMappingFactory) this.mappingFactory()).createXmlCollectionReferenceMapping(this.getParentDescriptor(), this.getInstanceVariable(), this.getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping);
return newMapping;
}
public MWDirectMapping asMWObjectTypeMapping() {
MWDirectMapping newMapping = asMWDirectMapping();
newMapping.setObjectTypeConverter();
return newMapping;
}
public MWDirectMapping asMWSerializedMapping() {
MWDirectMapping newMapping = asMWDirectMapping();
newMapping.setSerializedObjectConverter();
return newMapping;
}
public MWDirectMapping asMWTypeConversionMapping() {
MWDirectMapping newMapping = asMWDirectMapping();
newMapping.setTypeConversionConverter();
return newMapping;
}
public MWDirectToXmlTypeMapping asMWDirectToXmlTypeMapping() {
MWDirectToXmlTypeMapping newMapping =
((MWRelationalMappingFactory) mappingFactory()).createDirectToXmlTypeMapping(getParentDescriptor(), getInstanceVariable(), getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping); // this will set the descriptor
return newMapping;
}
public MWDirectCollectionMapping asMWDirectCollectionMapping() {
MWDirectCollectionMapping newMapping =
mappingFactory().createDirectCollectionMapping(getParentDescriptor(), getInstanceVariable(), getName());
this.initializeOn((MWMapping) newMapping);
newMapping.setChildBackpointers();
this.replaceWith((MWMapping) newMapping); // this will set the descriptor
return newMapping;
}
public MWDirectMapMapping asMWDirectMapMapping() {
MWDirectMapMapping newMapping =
mappingFactory().createDirectMapMapping(getParentDescriptor(), getInstanceVariable(), getName());
this.initializeOn((MWMapping) newMapping);
newMapping.setChildBackpointers();
this.replaceWith((MWMapping) newMapping); // this will set the descriptor
return newMapping;
}
public MWCompositeObjectMapping asMWCompositeObjectMapping() {
MWCompositeObjectMapping newMapping =
((MWXmlMappingFactory) mappingFactory()).createCompositeObjectMapping(getParentDescriptor(), getInstanceVariable(), getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping);
return newMapping;
}
public MWCompositeCollectionMapping asMWCompositeCollectionMapping() {
MWCompositeCollectionMapping newMapping =
((MWXmlMappingFactory) mappingFactory()).createCompositeCollectionMapping(getParentDescriptor(), getInstanceVariable(), getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping);
return newMapping;
}
public MWAnyObjectMapping asMWAnyObjectMapping() {
MWAnyObjectMapping newMapping =
((MWOXMappingFactory) this.mappingFactory()).createAnyObjectMapping(this.getParentDescriptor(), this.getInstanceVariable(), this.getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping);
return newMapping;
}
public MWAnyCollectionMapping asMWAnyCollectionMapping() {
MWAnyCollectionMapping newMapping =
((MWOXMappingFactory) this.mappingFactory()).createAnyCollectionMapping(this.getParentDescriptor(), this.getInstanceVariable(), this.getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping);
return newMapping;
}
public MWAnyAttributeMapping asMWAnyAttributeMapping() {
MWAnyAttributeMapping newMapping =
((MWOXMappingFactory) this.mappingFactory()).createAnyAttributeMapping(this.getParentDescriptor(), this.getInstanceVariable(), this.getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping);
return newMapping;
}
public MWVariableOneToOneMapping asMWVariableOneToOneMapping() {
MWVariableOneToOneMapping newMapping =
((MWRelationalMappingFactory) mappingFactory()).createVariableOneToOneMapping(getParentDescriptor(), getInstanceVariable(), getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping); // this will set the descriptor
return newMapping;
}
public MWTransformationMapping asMWTransformationMapping() {
MWTransformationMapping newMapping =
mappingFactory().createTransformationMapping(getParentDescriptor(), getInstanceVariable(), getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping); // this will set the descriptor
return newMapping;
}
public MWAggregateMapping asMWAggregateMapping() {
MWAggregateMapping newMapping =
((MWRelationalMappingFactory) mappingFactory()).createAggregateMapping(getParentDescriptor(), getInstanceVariable(), getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping); // this will set the descriptor
return newMapping;
}
public MWOneToOneMapping asMWOneToOneMapping() {
MWOneToOneMapping newMapping =
((MWRelationalMappingFactory) mappingFactory()).createOneToOneMapping(getParentDescriptor(), getInstanceVariable(), getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping); // this will set the descriptor
return newMapping;
}
public MWOneToManyMapping asMWOneToManyMapping() {
MWOneToManyMapping newMapping =
((MWRelationalMappingFactory) mappingFactory()).createOneToManyMapping(getParentDescriptor(), getInstanceVariable(), getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping); // this will set the descriptor
return newMapping;
}
public MWManyToManyMapping asMWManyToManyMapping() {
MWManyToManyMapping newMapping =
((MWRelationalMappingFactory) mappingFactory()).createManyToManyMapping(getParentDescriptor(), getInstanceVariable(), getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping); // this will set the descriptor
return newMapping;
}
public MWEisOneToManyMapping asMWEisOneToManyMapping() {
MWEisOneToManyMapping newMapping =
((MWEisMappingFactory) mappingFactory()).createEisOneToManyMapping((MWEisDescriptor) getParentDescriptor(), getInstanceVariable(), getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping); // this will set the descriptor
return newMapping;
}
public MWEisOneToOneMapping asMWEisOneToOneMapping() {
MWEisOneToOneMapping newMapping =
((MWEisMappingFactory) mappingFactory()).createEisOneToOneMapping((MWEisDescriptor) getParentDescriptor(), getInstanceVariable(), getName());
this.initializeOn(newMapping);
newMapping.setChildBackpointers();
this.replaceWith(newMapping); // this will set the descriptor
return newMapping;
}
/**
* IMPORTANT: See MWRMapping class comment.
* Subclasses should override this method to call the
* appropriate initializeFromMW___Mapping() method.
*/
protected abstract void initializeOn(MWMapping newMapping);
protected void replaceWith(MWMapping newMapping) {
this.getParentDescriptor().replaceMapping(this, newMapping);
}
/**
* IMPORTANT: See MWRMapping class comment concerning
* initializeFromMW___Mapping() methods.
*
* Note that these methods climb up the hierarchy tree.
*/
protected void initializeFromMWMapping(MWMapping oldMapping) {
this.setUsesMethodAccessing(oldMapping.usesMethodAccessing());
this.setGetMethod(oldMapping.getGetMethod());
this.setSetMethod(oldMapping.getSetMethod());
this.setInherited(oldMapping.isInherited());
this.setReadOnly(oldMapping.isReadOnly());
}
protected void initializeFromMWDirectMapping(MWDirectMapping oldMapping) {
this.initializeFromMWConverterMapping(oldMapping);
this.initializeFromMWMapping(oldMapping);
}
protected void initializeFromMWRelationalDirectMapping(MWRelationalDirectMapping oldMapping) {
this.initializeFromMWMapping(oldMapping);
}
public void initializeFromMWDirectToFieldMapping(MWDirectToFieldMapping oldMapping) {
this.initializeFromMWRelationalDirectMapping(oldMapping);
}
public void initializeFromMWDirectToXmlTypeMapping(MWDirectToXmlTypeMapping oldMapping) {
this.initializeFromMWDirectMapping(oldMapping);
}
public void initializeFromMWXmlDirectMapping(MWXmlDirectMapping oldMapping) {
this.initializeFromMWXpathedMapping(oldMapping);
this.initializeFromMWDirectMapping(oldMapping);
}
public void initializeFromMWXmlFragmentMapping(MWXmlFragmentMapping oldMapping) {
this.initializeFromMWXpathedMapping(oldMapping);
this.initializeFromMWDirectMapping(oldMapping);
}
public void initializeFromMWXmlFragmentCollectionMapping(MWXmlFragmentCollectionMapping oldMapping) {
this.initializeFromMWXpathedMapping(oldMapping);
this.initializeFromMWDirectCollectionMapping(oldMapping);
}
protected void initializeFromMWDirectCollectionMapping(MWDirectCollectionMapping oldMapping) {
this.initializeFromMWDirectContainerMapping((MWDirectContainerMapping) oldMapping);
}
public void initializeFromMWRelationalDirectMapMapping(MWRelationalDirectMapMapping oldMapping) {
this.initializeFromMWRelationalDirectContainerMapping(oldMapping);
this.initializeFromMWDirectMapMapping(oldMapping);
}
protected void initializeFromMWDirectMapMapping(MWDirectMapMapping oldMapping) {
this.initializeFromMWDirectContainerMapping((MWDirectContainerMapping) oldMapping);
}
protected void initializeFromMWDirectContainerMapping(MWDirectContainerMapping oldMapping) {
this.initializeFromMWConverterMapping(oldMapping);
this.initializeFromMWMapping(oldMapping);
}
public void initializeFromMWRelationalDirectCollectionMapping(MWRelationalDirectCollectionMapping oldMapping) {
this.initializeFromMWRelationalDirectContainerMapping(oldMapping);
this.initializeFromMWDirectCollectionMapping(oldMapping);
}
public void initializeFromMWRelationalDirectContainerMapping(MWRelationalDirectContainerMapping oldMapping) {
this.initializeFromMWIndirectableContainerMapping(oldMapping);
}
public void initializeFromMWXmlDirectCollectionMapping(MWXmlDirectCollectionMapping oldMapping) {
this.initializeFromMWXpathedMapping(oldMapping);
this.initializeFromMWDirectCollectionMapping(oldMapping);
}
protected void initializeFromMWAbstractAnyMapping(MWAbstractAnyMapping oldMapping) {
this.initializeFromMWXpathedMapping(oldMapping);
this.initializeFromMWMapping(oldMapping);
}
public void initializeFromMWAnyObjectMapping(MWAnyObjectMapping oldMapping) {
this.initializeFromMWAbstractAnyMapping(oldMapping);
}
public void initializeFromMWAnyCollectionMapping(MWAnyCollectionMapping oldMapping) {
this.initializeFromMWAbstractAnyMapping(oldMapping);
}
public void initializeFromMWAnyAttributeMapping(MWAnyAttributeMapping oldMapping) {
this.initializeFromMWAbstractAnyMapping(oldMapping);
}
protected void initializeFromMWAbstractCompositeMapping(MWAbstractCompositeMapping oldMapping) {
this.initializeFromMWReferenceObjectMapping(oldMapping);
this.initializeFromMWXpathedMapping(oldMapping);
this.initializeFromMWMapping(oldMapping);
}
public void initializeFromMWCompositeObjectMapping(MWCompositeObjectMapping oldMapping) {
this.initializeFromMWAbstractCompositeMapping(oldMapping);
}
public void initializeFromMWCompositeCollectionMapping(MWCompositeCollectionMapping oldMapping) {
this.initializeFromMWAbstractCompositeMapping(oldMapping);
}
public void initializeFromMWVariableOneToOneMapping(MWVariableOneToOneMapping oldMapping) {
this.initializeFromMWAbstractReferenceMapping(oldMapping);
}
protected void initializeFromMWAbstractReferenceMapping(MWAbstractReferenceMapping oldMapping) {
this.initializeFromMWIndirectableMapping(oldMapping);
this.initializeFromMWReferenceMapping(oldMapping);
this.initializeFromMWMapping(oldMapping);
}
protected void initializeFromMWAbstractTableReferenceMapping(MWAbstractTableReferenceMapping oldMapping) {
this.initializeFromMWAbstractReferenceMapping(oldMapping);
}
protected void initializeFromMWCollectionMapping(MWCollectionMapping oldMapping) {
this.initializeFromMWIndirectableContainerMapping(oldMapping);
this.initializeFromMWAbstractTableReferenceMapping(oldMapping);
}
public void initializeFromMWManyToManyMapping(MWManyToManyMapping oldMapping) {
this.initializeFromMWCollectionMapping(oldMapping);
}
public void initializeFromMWOneToManyMapping(MWOneToManyMapping oldMapping) {
this.initializeFromMWCollectionMapping(oldMapping);
}
public void initializeFromMWOneToOneMapping(MWOneToOneMapping oldMapping) {
this.initializeFromMWAbstractTableReferenceMapping(oldMapping);
}
protected void initializeFromMWEisReferenceMapping(MWEisReferenceMapping oldMapping) {
this.initializeFromMWAbstractReferenceMapping(oldMapping);
}
public void initializeFromMWEisOneToManyMapping(MWEisOneToManyMapping oldMapping) {
this.initializeFromMWIndirectableContainerMapping(oldMapping);
this.initializeFromMWEisReferenceMapping(oldMapping);
}
public void initializeFromMWEisOneToOneMapping(MWEisOneToOneMapping oldMapping) {
this.initializeFromMWEisReferenceMapping(oldMapping);
}
public void initializeFromMWAggregateMapping(MWAggregateMapping oldMapping) {
this.initializeFromMWReferenceObjectMapping(oldMapping);
this.initializeFromMWMapping(oldMapping);
}
public void initializeFromMWTransformationMapping(MWTransformationMapping oldMapping) {
this.initializeFromMWIndirectableMapping(oldMapping);
this.initializeFromMWMapping(oldMapping);
}
protected void initializeFromMWConverterMapping(MWConverterMapping oldMapping) {
// do nothing
}
protected void initializeFromMWIndirectableMapping(MWIndirectableMapping oldMapping) {
// do nothing
}
protected void initializeFromMWIndirectableContainerMapping(MWIndirectableContainerMapping oldMapping) {
this.initializeFromMWIndirectableMapping(oldMapping);
}
protected void initializeFromMWReferenceObjectMapping(MWReferenceObjectMapping oldMapping) {
// do nothing
}
protected void initializeFromMWReferenceMapping(MWReferenceMapping oldMapping) {
this.initializeFromMWReferenceObjectMapping(oldMapping);
}
public void initializeFromMWXmlCollectionReferenceMapping(MWXmlCollectionReferenceMapping oldMapping) {
}
public void initializeFromMWXmlObjectReferenceMapping(MWXmlObjectReferenceMapping oldMapping) {
}
protected void initializeFromMWXpathedMapping(MWXpathedMapping oldMapping) {
// do nothing
}
// ********** MWQueryable implementation **********
public boolean allowsChildren() {
return false;
}
public boolean allowsOuterJoin() {
return false;
}
public boolean isTraversableForBatchReadAttribute() {
return false;
}
public boolean isValidForBatchReadAttribute() {
return false;
}
public boolean isLeaf(Filter queryableFilter) {
return true;
}
public MWQueryable subQueryableElementAt(int index, Filter queryableFilter) {
throw new UnsupportedOperationException();
}
public List subQueryableElements(Filter queryableFilter) {
return Collections.EMPTY_LIST;
}
public boolean usesAnyOf() {
return false;
}
public boolean isTraversableForJoinedAttribute() {
return false;
}
public boolean isValidForJoinedAttribute() {
return false;
}
public boolean isTraversableForReadAllQueryOrderable() {
return false;
}
public boolean isValidForReadAllQueryOrderable() {
return false;
}
public boolean isTraversableForReportQueryAttribute() {
return false;
}
public boolean isValidForReportQueryAttribute() {
return false;
}
public boolean isTraversableForQueryExpression() {
return false;
}
public boolean isValidForQueryExpression() {
return false;
}
public String iconKey() {
throw new UnsupportedOperationException();
}
// **************** Source Code Generation ***************
/**
* Used for code gen.
* Default behavior is to defer to the instance variable,
* but some mappings (see MWOneToManyMapping)
* have particular additional information to impart.
*/
public MWMethodCodeGenPolicy accessorCodeGenPolicy(MWMethod accessor, MWClassCodeGenPolicy classCodeGenPolicy) {
return getInstanceVariable().accessorCodeGenPolicy(accessor, classCodeGenPolicy);
}
/**
* Used for code gen.
* Default behavior is to defer to the instance variable,
* but some mappings (see MWAggregateMapping, MWOneToOneMapping)
* have particular initial value requirements.
*/
public String initialValue(MWClassCodeGenPolicy classCodeGenPolicy) {
return getInstanceVariable().initialValueSourceCode(classCodeGenPolicy);
}
//************** Problem Handling ***************
protected void addProblemsTo(List currentProblems) {
super.addProblemsTo(currentProblems);
this.checkGetMethod(currentProblems);
this.checkSetMethod(currentProblems);
this.checkMethods(currentProblems);
this.checkWriteLockField(currentProblems);
this.checkMappableAttribute(currentProblems);
}
private void checkMappableAttribute(List currentProblems) {
if (this.getInstanceVariable() == null) {
return;
}
if (!this.getInstanceVariable().isMappable()) {
currentProblems.add(this.buildProblem(ProblemConstants.MAPPING_ATTRIBUTE_NO_LONGER_MAPPABLE));
}
}
private void checkGetMethod(List currentProblems) {
if (this.getGetMethod() == null){
return;
}
if (this.getGetMethod().methodParametersSize() != 0) {
currentProblems.add(this.buildProblem(ProblemConstants.MAPPING_INVALID_GET_METHOD));
}
}
private void checkSetMethod(List currentProblems) {
if (this.getSetMethod() == null){
return;
}
if (this.getSetMethod().methodParametersSize() != 1) {
currentProblems.add(this.buildProblem(ProblemConstants.MAPPING_INVALID_SET_METHOD));
}
}
private void checkMethods(List currentProblems) {
if ( ! this.usesMethodAccessing()) {
return;
}
if ((this.getGetMethod() == null) || (this.getSetMethod() == null)) {
currentProblems.add(this.buildProblem(ProblemConstants.MAPPING_METHOD_ACCESSORS_NOT_SPECIFIED));
}
}
private void checkWriteLockField(List currentProblems) {
// Pass if my referenced fields do not interfere with the write
// lock field (must be read only if referenced).
MWLockingPolicy policy = this.getParentDescriptor().getLockingPolicy();
Collection writtenFields = new ArrayList();
this.addWrittenFieldsTo(writtenFields);
for (Iterator stream = writtenFields.iterator(); stream.hasNext(); ) {
MWDataField field = (MWDataField) stream.next();
//CR #2098 If not stored in cache, read only is not required.
if ((field == policy.getVersionLockField()) && policy.shouldStoreVersionInCache()) {
if ( ! this.isReadOnly()) {
currentProblems.add(this.buildProblem(ProblemConstants.MAPPING_REFERENCE_WRITE_LOCK_FIELD_NOT_READ_ONLY));
}
}
}
}
/**
* Add all fields that are written by this mapping in this descriptor
*/
public abstract void addWrittenFieldsTo(Collection writtenFields);
// ************* Automap Support ****************
/**
* attempt to automap the mapping
*/
public void automap() {
// the default is to do nothing
}
public void addColumnlessDirectMappingTo(Collection columnlessDirectMappings) {
// the default is to do nothing
}
// ********** Runtime Conversion **********
public DatabaseMapping runtimeMapping() {
DatabaseMapping mapping = buildRuntimeMapping();
mapping.setAttributeName(this.getInstanceVariable().getName());
if (this.usesMethodAccessing()) {
if (getGetMethod() != null) {
mapping.setGetMethodName(this.getGetMethod().getName());
}
if (getSetMethod() != null) {
mapping.setSetMethodName(this.getSetMethod().getName());
}
}
mapping.setIsReadOnly(this.isReadOnly());
return mapping;
}
protected abstract DatabaseMapping buildRuntimeMapping();
// ********** display methods **********
/**
* add the attribute type, making it easier to map in the UI, e.g.
* attributeName : foo.bar.Type
*/
public String nameWithType() {
return (this.getInstanceVariable() != null) ?
this.getInstanceVariable().nameWithType()
:
this.getName();
}
/**
* add the attribute type, making it easier to map in the UI, e.g.
* attributeName : Type
*/
public String nameWithShortType() {
return (this.getInstanceVariable() != null) ?
this.getInstanceVariable().nameWithShortType()
:
this.getName();
}
public String displayString() {
return this.getName();
}
public void toString(StringBuffer sb) {
sb.append(this.getName());
}
// ********** TopLink methods **********
public static XMLDescriptor buildDescriptor() {
XMLDescriptor descriptor = new XMLDescriptor();
descriptor.setJavaClass(MWMapping.class);
org.eclipse.persistence.descriptors.InheritancePolicy ip = (org.eclipse.persistence.descriptors.InheritancePolicy)descriptor.getInheritancePolicy();
ip.setClassIndicatorFieldName("@type");
// *** relational mappings ***
ip.addClassIndicator(MWDirectToFieldMapping.class, "direct-to-field");
ip.addClassIndicator(MWDirectToXmlTypeMapping.class, "direct-to-xml-type");
ip.addClassIndicator(MWRelationalDirectCollectionMapping.class, "relational-direct-collection");
ip.addClassIndicator(MWManyToManyMapping.class, "many-to-many");
ip.addClassIndicator(MWOneToManyMapping.class, "one-to-many");
ip.addClassIndicator(MWOneToOneMapping.class, "one-to-one");
ip.addClassIndicator(MWVariableOneToOneMapping.class, "variable-one-to-one");
ip.addClassIndicator(MWRelationalTransformationMapping.class, "relational-transformation");
ip.addClassIndicator(MWAggregateMapping.class, "aggregate");
ip.addClassIndicator(MWRelationalDirectMapMapping.class, "relational-direct-map");
// *** xml mappings ***
ip.addClassIndicator(MWXmlDirectMapping.class, "xml-direct");
ip.addClassIndicator(MWXmlDirectCollectionMapping.class, "xml-direct-collection");
ip.addClassIndicator(MWAnyAttributeMapping.class, "any-attribute");
ip.addClassIndicator(MWAnyObjectMapping.class, "any-object");
ip.addClassIndicator(MWAnyCollectionMapping.class, "any-collection");
ip.addClassIndicator(MWCompositeObjectMapping.class, "composite-object");
ip.addClassIndicator(MWCompositeCollectionMapping.class, "composite-collection");
ip.addClassIndicator(MWXmlTransformationMapping.class, "xml-transformation");
ip.addClassIndicator(MWEisOneToOneMapping.class, "eis-one-to-one");
ip.addClassIndicator(MWEisOneToManyMapping.class, "eis-one-to-many");
ip.addClassIndicator(MWXmlFragmentMapping.class, "xml-fragment");
ip.addClassIndicator(MWXmlFragmentCollectionMapping.class, "xml-fragment-collection");
ip.addClassIndicator(MWXmlObjectReferenceMapping.class, "xml-object-reference");
ip.addClassIndicator(MWXmlCollectionReferenceMapping.class, "xml-collection-reference");
descriptor.addDirectMapping("name", "name/text()");
((XMLDirectMapping) descriptor.addDirectMapping("comment", "comment/text()")).setNullValue("");
((XMLDirectMapping) descriptor.addDirectMapping("inherited", "inherited/text()")).setNullValue(Boolean.FALSE);
((XMLDirectMapping) descriptor.addDirectMapping("readOnly", "read-only/text()")).setNullValue(Boolean.FALSE);
XMLCompositeObjectMapping attributeHandleMapping = new XMLCompositeObjectMapping();
attributeHandleMapping.setAttributeName("attributeHandle");
attributeHandleMapping.setReferenceClass(MWAttributeHandle.class);
attributeHandleMapping.setSetMethodName("setAttributeHandleForTopLink");
attributeHandleMapping.setGetMethodName("getAttributeHandleForTopLink");
attributeHandleMapping.setXPath("attribute-handle");
descriptor.addMapping(attributeHandleMapping);
((XMLDirectMapping) descriptor.addDirectMapping("usesMethodAccessing", "uses-method-accessing/text()")).setNullValue(Boolean.FALSE);
XMLCompositeObjectMapping getMethodHandleMapping = new XMLCompositeObjectMapping();
getMethodHandleMapping.setAttributeName("getMethodHandle");
getMethodHandleMapping.setSetMethodName("setGetMethodHandleForTopLink");
getMethodHandleMapping.setGetMethodName("getGetMethodHandleForTopLink");
getMethodHandleMapping.setReferenceClass(MWMethodHandle.class);
getMethodHandleMapping.setXPath("get-method-handle");
descriptor.addMapping(getMethodHandleMapping);
XMLCompositeObjectMapping setMethodHandleMapping = new XMLCompositeObjectMapping();
setMethodHandleMapping.setAttributeName("setMethodHandle");
setMethodHandleMapping.setSetMethodName("setSetMethodHandleForTopLink");
setMethodHandleMapping.setGetMethodName("getSetMethodHandleForTopLink");
setMethodHandleMapping.setReferenceClass(MWMethodHandle.class);
setMethodHandleMapping.setXPath("set-method-handle");
descriptor.addMapping(setMethodHandleMapping);
return descriptor;
}
/**
* check for null
*/
private MWAttributeHandle getAttributeHandleForTopLink() {
return (this.attributeHandle.getAttribute() == null) ? null : this.attributeHandle;
}
private void setAttributeHandleForTopLink(MWAttributeHandle attributeHandle) {
NodeReferenceScrubber scrubber = this.buildAttributeScrubber();
this.attributeHandle = ((attributeHandle == null) ? new MWAttributeHandle(this, scrubber) : attributeHandle.setScrubber(scrubber));
}
/**
* check for null
*/
private MWMethodHandle getGetMethodHandleForTopLink() {
return (this.getMethodHandle.getMethod() == null) ? null : this.getMethodHandle;
}
private void setGetMethodHandleForTopLink(MWMethodHandle getMethodHandle) {
NodeReferenceScrubber scrubber = this.buildGetMethodScrubber();
this.getMethodHandle = ((getMethodHandle == null) ? new MWMethodHandle(this, scrubber) : getMethodHandle.setScrubber(scrubber));
}
/**
* check for null
*/
private MWMethodHandle getSetMethodHandleForTopLink() {
return (this.setMethodHandle.getMethod() == null) ? null : this.setMethodHandle;
}
private void setSetMethodHandleForTopLink(MWMethodHandle setMethodHandle) {
NodeReferenceScrubber scrubber = this.buildSetMethodScrubber();
this.setMethodHandle = ((setMethodHandle == null) ? new MWMethodHandle(this, scrubber) : setMethodHandle.setScrubber(scrubber));
}
}