/*******************************************************************************
* 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.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.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.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 MWDescriptorCopyPolicy extends MWAbstractDescriptorPolicy {
private MWMethodHandle methodHandle;
private volatile String policyType;
public final static String COPY_POLICY_PROPERTY = "copyPolicy";
public final static String CLONE = "clone";
public final static String INSTANTIATION_POLICY = "instantiation";
public final static String CONSTRUCTOR = "constructor"; // keep
public final static String CONSTRUCTOR_PROPERTY = CONSTRUCTOR;
public final static String COPY_POLICY_TYPE_PROPERTY = "copyPolicyType";
// around for backward compatibility
public final static String COPY_METHOD_PROPERTY = "copyMethod";
// ********** constructors **********
private MWDescriptorCopyPolicy() {
// for TopLink use only
super();
}
public MWDescriptorCopyPolicy(MWMappingDescriptor descriptor) {
super(descriptor);
}
// ********** initialization **********
protected void initialize(Node parent) {
super.initialize(parent);
this.methodHandle = new MWMethodHandle(this, this.buildMethodScrubber());
this.policyType = INSTANTIATION_POLICY;
}
// ********** accessors **********
public MWMethod getMethod() {
return this.methodHandle.getMethod();
}
public void setMethod(MWMethod newMethod) {
MWMethod oldMethod = this.methodHandle.getMethod();
this.methodHandle.setMethod(newMethod);
firePropertyChanged(COPY_METHOD_PROPERTY, oldMethod, newMethod);
}
public String getPolicyType() {
return this.policyType;
}
public void setPolicyType(String policyType) {
String oldValue = this.policyType;
this.policyType = policyType;
firePropertyChanged(COPY_POLICY_TYPE_PROPERTY, oldValue, this.policyType);
}
// ********** containment hierarchy **********
protected void addChildrenTo(List children) {
super.addChildrenTo(children);
children.add(this.methodHandle);
}
private NodeReferenceScrubber buildMethodScrubber() {
return new NodeReferenceScrubber() {
public void nodeReferenceRemoved(Node node, MWHandle handle) {
MWDescriptorCopyPolicy.this.setMethod(null);
}
public String toString() {
return "MWDescriptorCopyPolicy.buildMethodScrubber()";
}
};
}
// ********** MWAbstractDescriptorPolicy implementation **********
public MWDescriptorPolicy getPersistedPolicy() {
return this;
}
public boolean isActive() {
return true;
}
// ********** runtime conversion **********
public void adjustRuntimeDescriptor(ClassDescriptor runtimeDescriptor) {
if (this.policyType == MWDescriptorCopyPolicy.INSTANTIATION_POLICY) {
runtimeDescriptor.useInstantiationCopyPolicy();
} else if (this.policyType == MWDescriptorCopyPolicy.CLONE) {
MWMethod method = getMethod();
if (method != null) {
runtimeDescriptor.useCloneCopyPolicy(method.getName());
}
}
}
// ********** problems **********
protected void addProblemsTo(List problems) {
super.addProblemsTo(problems);
this.checkCloneCopyPolicy(problems);
}
private void checkCloneCopyPolicy(List newProblems) {
if (this.getPolicyType() == CLONE) {
if (this.getMethod() == null) {
newProblems.add(this.buildProblem(ProblemConstants.DESCRIPTOR_COPYING_NO_METHOD_SPECIFIED));
} else {
if ( ! this.checkIfMethodIsInOwningClass()) {
newProblems.add(this.buildProblem(ProblemConstants.DESCRIPTOR_COPYING_METHOD_NOT_VISIBLE));
}
else if ( ! this.getMethod().isCandidateCloneMethod()) {
newProblems.add(buildProblem(ProblemConstants.DESCRIPTOR_COPYING_METHOD_NOT_VALID));
}
}
}
}
public boolean checkIfMethodIsInOwningClass() {
return CollectionTools.contains(getOwningDescriptor().getMWClass().allMethods(), getMethod());
}
// ********** printing **********
public void toString(StringBuffer sb) {
sb.append(this.getPolicyType());
sb.append(", method=");
sb.append(this.getMethod());
}
// ********** TopLink methods **********
public static XMLDescriptor buildDescriptor() {
// Same as 5.0 for now
XMLDescriptor descriptor = new XMLDescriptor();
descriptor.setJavaClass(MWDescriptorCopyPolicy.class);
// use an object type mapping so we can preserve object identity
ObjectTypeConverter policyTypeConverter = new ObjectTypeConverter();
policyTypeConverter.addConversionValue(
MWDescriptorCopyPolicy.INSTANTIATION_POLICY,
MWDescriptorCopyPolicy.INSTANTIATION_POLICY);
policyTypeConverter.addConversionValue(
MWDescriptorCopyPolicy.CLONE,
MWDescriptorCopyPolicy.CLONE);
// convert the old "constructor" values to "instantiation"
policyTypeConverter
.setDefaultAttributeValue(MWDescriptorCopyPolicy.INSTANTIATION_POLICY);
XMLDirectMapping policyTypeMapping = new XMLDirectMapping();
policyTypeMapping.setAttributeName("policyType");
policyTypeMapping.setXPath("policy-type/text()");
policyTypeMapping.setNullValue(MWDescriptorCopyPolicy.INSTANTIATION_POLICY);
policyTypeMapping.setConverter(policyTypeConverter);
descriptor.addMapping(policyTypeMapping);
XMLCompositeObjectMapping methodHandleMapping = new XMLCompositeObjectMapping();
methodHandleMapping.setAttributeName("methodHandle");
methodHandleMapping.setGetMethodName("getMethodHandleForTopLink");
methodHandleMapping.setSetMethodName("setMethodHandleForTopLink");
methodHandleMapping.setReferenceClass(MWMethodHandle.class);
methodHandleMapping.setXPath("copy-policy-method-handle");
descriptor.addMapping(methodHandleMapping);
return descriptor;
}
/**
* check for null
*/
private MWMethodHandle getMethodHandleForTopLink() {
return (this.methodHandle.getMethod() == null) ? null : this.methodHandle;
}
private void setMethodHandleForTopLink(MWMethodHandle handle) {
NodeReferenceScrubber scrubber = this.buildMethodScrubber();
this.methodHandle = ((handle == null) ? new MWMethodHandle(this, scrubber) : handle.setScrubber(scrubber));
}
}