/*******************************************************************************
* 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.descriptor;
import java.util.List;
import org.eclipse.persistence.tools.workbench.mappingsmodel.MWModel;
import org.eclipse.persistence.tools.workbench.mappingsmodel.ProblemConstants;
import org.eclipse.persistence.tools.workbench.mappingsmodel.handles.MWClassHandle;
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.meta.MWClass;
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWMethod;
import org.eclipse.persistence.tools.workbench.utility.CollectionTools;
import org.eclipse.persistence.tools.workbench.utility.node.Node;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.mappings.OneToOneMapping;
import org.eclipse.persistence.mappings.converters.ObjectTypeConverter;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping;
import org.eclipse.persistence.oxm.mappings.XMLDirectMapping;
public final class MWDescriptorInstantiationPolicy extends MWAbstractDescriptorPolicy {
private volatile String policyType;
public static final String POLICY_TYPE_PROPERTY = "policyType";
// Instantiation Policy types
public final static String DEFAULT_CONSTRUCTOR = "Default constructor";
public final static String METHOD = "Method";
public final static String FACTORY = "Factory";
private MWClassHandle factoryTypeHandle;
public static final String FACTORY_TYPE_PROPERTY = "factoryType";
private MWMethodHandle useMethodHandle;
public static final String USE_METHOD_PROPERTY = "useMethod";
private MWMethodHandle factoryMethodHandle;
public static final String FACTORY_METHOD_PROPERTY = "factoryMethod";
private MWMethodHandle instantiationMethodHandle;
public static final String INSTANTIATION_METHOD_PROPERTY = "instantiationMethod";
// ********** constructors **********
private MWDescriptorInstantiationPolicy() {
// for TopLink use only
super();
}
MWDescriptorInstantiationPolicy(MWMappingDescriptor descriptor) {
super(descriptor);
}
// ********** initialization **********
protected void initialize(Node parent) {
super.initialize(parent);
this.policyType = DEFAULT_CONSTRUCTOR;
this.factoryTypeHandle = new MWClassHandle(this, this.buildFactoryTypeScrubber());
this.useMethodHandle = new MWMethodHandle(this, this.buildUseMethodScrubber());
this.factoryMethodHandle = new MWMethodHandle(this, this.buildFactoryMethodScrubber());
this.instantiationMethodHandle = new MWMethodHandle(this, this.buildInstantiationMethodScrubber());
}
// ********** accessors **********
public MWMethod getFactoryMethod() {
return this.factoryMethodHandle.getMethod();
}
public void setFactoryMethod(MWMethod factoryMethod) {
Object old = this.getFactoryMethod();
this.factoryMethodHandle.setMethod(factoryMethod);
this.firePropertyChanged(FACTORY_METHOD_PROPERTY, old, factoryMethod);
}
public MWClass getFactoryType() {
return this.factoryTypeHandle.getType();
}
public void setFactoryType(MWClass factoryType) {
Object old = this.factoryTypeHandle.getType();
this.factoryTypeHandle.setType(factoryType);
this.firePropertyChanged(FACTORY_TYPE_PROPERTY, old, factoryType);
}
public MWMethod getInstantiationMethod() {
return this.instantiationMethodHandle.getMethod();
}
public void setInstantiationMethod(MWMethod instantiationMethod) {
Object old = this.getInstantiationMethod();
this.instantiationMethodHandle.setMethod(instantiationMethod);
this.firePropertyChanged(INSTANTIATION_METHOD_PROPERTY, old, instantiationMethod);
}
public MWMethod getUseMethod() {
return this.useMethodHandle.getMethod();
}
public void setUseMethod(MWMethod useMethod) {
Object old = this.getUseMethod();
this.useMethodHandle.setMethod(useMethod);
this.firePropertyChanged(USE_METHOD_PROPERTY, old, useMethod);
}
public String getPolicyType() {
return this.policyType;
}
public void setPolicyType(String policyType) {
Object old = this.policyType;
this.policyType = policyType;
this.firePropertyChanged(POLICY_TYPE_PROPERTY, old, policyType);
}
// ********** behavior **********
public boolean checkUseMethodLegitimacy() {
return CollectionTools.contains(this.getOwningDescriptor().getMWClass().allMethods(), this.getUseMethod());
}
public boolean checkFactoryInstantiationMethodLegitimacy() {
return CollectionTools.contains(this.getFactoryType().allMethods(), this.getInstantiationMethod());
}
public boolean checkFactoryMethodLegitimacy() {
return CollectionTools.contains(this.getFactoryType().allMethods(), this.getFactoryMethod());
}
public void toString(StringBuffer sb) {
sb.append(this.getPolicyType());
}
// ********** containment hierarchy **********
protected void addChildrenTo(List children) {
super.addChildrenTo(children);
children.add(this.useMethodHandle);
children.add(this.factoryMethodHandle);
children.add(this.instantiationMethodHandle);
children.add(this.factoryTypeHandle);
}
private NodeReferenceScrubber buildUseMethodScrubber() {
return new NodeReferenceScrubber() {
public void nodeReferenceRemoved(Node node, MWHandle handle) {
MWDescriptorInstantiationPolicy.this.setUseMethod(null);
}
public String toString() {
return "MWDescriptorInstantiationPolicy.buildUseMethodScrubber()";
}
};
}
private NodeReferenceScrubber buildFactoryMethodScrubber() {
return new NodeReferenceScrubber() {
public void nodeReferenceRemoved(Node node, MWHandle handle) {
MWDescriptorInstantiationPolicy.this.setFactoryMethod(null);
}
public String toString() {
return "MWDescriptorInstantiationPolicy.buildFactoryMethodScrubber()";
}
};
}
private NodeReferenceScrubber buildInstantiationMethodScrubber() {
return new NodeReferenceScrubber() {
public void nodeReferenceRemoved(Node node, MWHandle handle) {
MWDescriptorInstantiationPolicy.this.setInstantiationMethod(null);
}
public String toString() {
return "MWDescriptorInstantiationPolicy.buildInstantiationMethodScrubber()";
}
};
}
private NodeReferenceScrubber buildFactoryTypeScrubber() {
return new NodeReferenceScrubber() {
public void nodeReferenceRemoved(Node node, MWHandle handle) {
MWDescriptorInstantiationPolicy.this.setFactoryType(null);
}
public String toString() {
return "MWDescriptorInstantiationPolicy.buildFactoryTypeScrubber()";
}
};
}
// ********** run-time **********
public void adjustRuntimeDescriptor(ClassDescriptor runtimeDescriptor) {
String policyType = getPolicyType();
if (policyType == MWDescriptorInstantiationPolicy.DEFAULT_CONSTRUCTOR) {
runtimeDescriptor.useDefaultConstructorInstantiationPolicy();
}
else if (policyType == MWDescriptorInstantiationPolicy.METHOD) {
MWMethod instantiationMethod = getUseMethod();
if (instantiationMethod != null) {
runtimeDescriptor.useMethodInstantiationPolicy(instantiationMethod.getName());
}
}
else if (policyType == MWDescriptorInstantiationPolicy.FACTORY) {
// at least the factory class and an instantiation method must be selected
MWClass factoryType = getFactoryType();
if (factoryType == null) {
return;
}
MWMethod instantiationMethod = getInstantiationMethod();
if (instantiationMethod == null) {
return;
}
String factoryClassName = factoryType.getName();
MWMethod factoryMethod = getFactoryMethod();
if (factoryMethod == null) {
runtimeDescriptor.useFactoryInstantiationPolicy(factoryClassName, instantiationMethod.getName());
} else {
runtimeDescriptor.useFactoryInstantiationPolicy(factoryClassName, instantiationMethod.getName(), factoryMethod.getName());
}
} else {
throw new IllegalStateException(policyType);
}
}
// ********** MWAbstractDescriptorPolicy implementation **********
public MWDescriptorPolicy getPersistedPolicy() {
return this;
}
public boolean isActive() {
return true;
}
// ********** problems **********
protected void addProblemsTo(List problems) {
super.addProblemsTo(problems);
this.checkDefaultConstructor(problems);
this.checkInstantiationMethod(problems);
this.checkFactoryMethod(problems);
this.checkFactoryInstantiationMethod(problems);
}
private void checkDefaultConstructor(List newProblems) {
if (this.getPolicyType() == MWDescriptorInstantiationPolicy.DEFAULT_CONSTRUCTOR) {
if ( ! this.getOwningDescriptor().getMWClass().hasAccessibleZeroArgumentConstructor()) {
newProblems.add(this.buildProblem(ProblemConstants.DESCRIPTOR_INSTANTIATION_NO_ZERO_ARG_CONSTRUCTOR));
}
}
}
private void checkInstantiationMethod(List newProblems) {
if (this.getPolicyType() == MWDescriptorInstantiationPolicy.METHOD) {
if (this.getUseMethod() == null) {
newProblems.add(this.buildProblem(ProblemConstants.DESCRIPTOR_INSTANTIATION_USE_METHOD));
} else {
if ( ! this.checkUseMethodLegitimacy()) {
newProblems.add(this.buildProblem(ProblemConstants.DESCRIPTOR_INSTANTIATION_INSTANTIATION_METHOD_NOT_VISIBLE));
}
else if ( ! this.getUseMethod().isCandidateInstantiationMethod()) {
newProblems.add(this.buildProblem(ProblemConstants.DESCRIPTOR_INSTANTIATION_INSTANTIATION_METHOD_NOT_VALID));
}
}
}
}
private void checkFactoryMethod(List newProblems) {
if (this.getPolicyType() == MWDescriptorInstantiationPolicy.FACTORY) {
if ((this.getFactoryMethod() != null) && (this.getFactoryType() != null)) {
if ( ! this.checkFactoryMethodLegitimacy()) {
newProblems.add(this.buildProblem(ProblemConstants.DESCRIPTOR_INSTANTIATION_FACTORY_METHOD_NOT_VISIBLE));
}
else if ( ! this.getFactoryMethod().isCandidateFactoryMethod()) {
newProblems.add(this.buildProblem(ProblemConstants.DESCRIPTOR_INSTANTIATION_FACTORY_METHOD_NOT_VALID));
}
}
}
}
private void checkFactoryInstantiationMethod(List newProblems) {
if (this.getPolicyType() == MWDescriptorInstantiationPolicy.FACTORY) {
if (this.getInstantiationMethod() == null) {
newProblems.add(this.buildProblem(ProblemConstants.DESCRIPTOR_INSTANTIATION_USE_FACTORY));
} else {
if (this.getFactoryType() != null) {
if ( ! this.checkFactoryInstantiationMethodLegitimacy()) {
newProblems.add(this.buildProblem(ProblemConstants.DESCRIPTOR_INSTANTIATION_FACTORY_INSTANTIATION_METHOD_NOT_VISIBLE));
}
else if ( ! this.getInstantiationMethod().isCandidateFactoryInstantiationMethodFor(this.getFactoryType())) {
newProblems.add(this.buildProblem(ProblemConstants.DESCRIPTOR_INSTANTIATION_FACTORY_INSTANTIATION_METHOD_NOT_VALID));
}
}
}
}
}
// ********** TopLink methods **********
public static XMLDescriptor buildDescriptor() {
XMLDescriptor descriptor = new XMLDescriptor();
descriptor.setJavaClass(MWDescriptorInstantiationPolicy.class);
ObjectTypeConverter policyTypeConverter = new ObjectTypeConverter();
policyTypeConverter.addConversionValue(
MWDescriptorInstantiationPolicy.DEFAULT_CONSTRUCTOR,
MWDescriptorInstantiationPolicy.DEFAULT_CONSTRUCTOR);
policyTypeConverter.addConversionValue(
MWDescriptorInstantiationPolicy.FACTORY,
MWDescriptorInstantiationPolicy.FACTORY);
policyTypeConverter.addConversionValue(
MWDescriptorInstantiationPolicy.METHOD,
MWDescriptorInstantiationPolicy.METHOD);
XMLDirectMapping policyTypeMapping = new XMLDirectMapping();
policyTypeMapping.setAttributeName("policyType");
policyTypeMapping.setXPath("policy-type/text()");
/*policyTypeMapping.setNullValue(MWDescriptorInstantiationPolicy.DEFAULT_CONSTRUCTOR);*/
policyTypeMapping.setConverter(policyTypeConverter);
descriptor.addMapping(policyTypeMapping);
XMLCompositeObjectMapping factoryTypeHandleMapping = new XMLCompositeObjectMapping();
factoryTypeHandleMapping.setAttributeName("factoryTypeHandle");
factoryTypeHandleMapping.setSetMethodName("setFactoryTypeHandleForTopLink");
factoryTypeHandleMapping.setGetMethodName("getFactoryTypeHandleForTopLink");
factoryTypeHandleMapping.setReferenceClass(MWClassHandle.class);
factoryTypeHandleMapping.setXPath("factory-type-handle");
descriptor.addMapping(factoryTypeHandleMapping);
XMLCompositeObjectMapping useMethodHandleMapping = new XMLCompositeObjectMapping();
useMethodHandleMapping.setAttributeName("useMethodHandle");
useMethodHandleMapping.setSetMethodName("setUseMethodHandleForTopLink");
useMethodHandleMapping.setGetMethodName("getUseMethodHandleForTopLink");
useMethodHandleMapping.setReferenceClass(MWMethodHandle.class);
useMethodHandleMapping.setXPath("use-method-handle");
descriptor.addMapping(useMethodHandleMapping);
XMLCompositeObjectMapping factoryMethodHandleMapping = new XMLCompositeObjectMapping();
factoryMethodHandleMapping.setAttributeName("factoryMethodHandle");
factoryMethodHandleMapping.setSetMethodName("setFactoryMethodHandleForTopLink");
factoryMethodHandleMapping.setGetMethodName("getFactoryMethodHandleForTopLink");
factoryMethodHandleMapping.setReferenceClass(MWMethodHandle.class);
factoryMethodHandleMapping.setXPath("factory-method-handle");
descriptor.addMapping(factoryMethodHandleMapping);
XMLCompositeObjectMapping instantiationMethodHandleMapping = new XMLCompositeObjectMapping();
instantiationMethodHandleMapping.setAttributeName("instantiationMethodHandle");
instantiationMethodHandleMapping.setSetMethodName("setInstantiationMethodHandleForTopLink");
instantiationMethodHandleMapping.setGetMethodName("getInstantiationMethodHandleForTopLink");
instantiationMethodHandleMapping.setReferenceClass(MWMethodHandle.class);
instantiationMethodHandleMapping.setXPath("isntantiation-method-handle");
descriptor.addMapping(instantiationMethodHandleMapping);
return descriptor;
}
/**
* check for null
*/
private MWClassHandle getFactoryTypeHandleForTopLink() {
return (this.factoryTypeHandle.getType() == null) ? null : this.factoryTypeHandle;
}
private void setFactoryTypeHandleForTopLink(MWClassHandle handle) {
NodeReferenceScrubber scrubber = this.buildFactoryTypeScrubber();
this.factoryTypeHandle = ((handle == null) ? new MWClassHandle(this, scrubber) : handle.setScrubber(scrubber));
}
/**
* check for null
*/
private MWMethodHandle getUseMethodHandleForTopLink() {
return (this.useMethodHandle.getMethod() == null) ? null : this.useMethodHandle;
}
private void setUseMethodHandleForTopLink(MWMethodHandle handle) {
NodeReferenceScrubber scrubber = this.buildUseMethodScrubber();
this.useMethodHandle = ((handle == null) ? new MWMethodHandle(this, scrubber) : handle.setScrubber(scrubber));
}
/**
* check for null
*/
private MWMethodHandle getFactoryMethodHandleForTopLink() {
return (this.factoryMethodHandle.getMethod() == null) ? null : this.factoryMethodHandle;
}
private void setFactoryMethodHandleForTopLink(MWMethodHandle handle) {
NodeReferenceScrubber scrubber = this.buildFactoryMethodScrubber();
this.factoryMethodHandle = ((handle == null) ? new MWMethodHandle(this, scrubber) : handle.setScrubber(scrubber));
}
/**
* check for null
*/
private MWMethodHandle getInstantiationMethodHandleForTopLink() {
return (this.instantiationMethodHandle.getMethod() == null) ? null : this.instantiationMethodHandle;
}
private void setInstantiationMethodHandleForTopLink(MWMethodHandle handle) {
NodeReferenceScrubber scrubber = this.buildInstantiationMethodScrubber();
this.instantiationMethodHandle = ((handle == null) ? new MWMethodHandle(this, scrubber) : handle.setScrubber(scrubber));
}
}