/*******************************************************************************
* 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.List;
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.mapping.relational.AggregateFieldDescription;
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.internal.helper.DatabaseField;
import org.eclipse.persistence.mappings.foundation.AbstractTransformationMapping;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping;
public final class MWMethodBasedTransformer
extends MWTransformer
{
// **************** Variables *********************************************
private MWMethodHandle methodHandle;
public final static String METHOD_PROPERTY = "method";
// **************** Constructors ******************************************
/** Default constructor - for TopLink use only */
private MWMethodBasedTransformer() {
super();
}
public MWMethodBasedTransformer(Parent parent, MWMethod method) {
super(parent);
this.setMethod(method);
}
/** Used for backward compatibility only */
MWMethodBasedTransformer(Parent parent, MWMethodHandle methodHandle) {
super(parent);
this.methodHandle = methodHandle.setScrubber(this.buildMethodScrubber());
}
// **************** Initialization ****************************************
protected void initialize(Node parent) {
super.initialize(parent);
this.methodHandle = new MWMethodHandle(this, this.buildMethodScrubber());
}
// **************** 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) {
MWMethodBasedTransformer.this.setMethod(null);
}
public String toString() {
return "MWMethodBasedTransformer.buildMethodScrubber()";
}
};
}
// **************** Method ************************************************
public MWMethod getMethod() {
return this.methodHandle.getMethod();
}
public void setMethod(MWMethod newMethod) {
MWMethod oldMethod = this.getMethod();
this.methodHandle.setMethod(newMethod);
if (this.attributeValueHasChanged(oldMethod, newMethod)) {
this.firePropertyChanged(METHOD_PROPERTY, oldMethod, newMethod);
this.firePropertyChanged(TRANSFORMER_PROPERTY, oldMethod, newMethod);
this.getProject().recalculateAggregatePathsToColumn(this.parentDescriptor());
}
}
// **************** Aggregate Support *************************************
public String fieldNameForRuntime() {
return "METHOD_TRANSFORMER " + ((getMethod() == null) ? null : getMethod().getName());
}
public AggregateFieldDescription fullFieldDescription() {
return getDescriptionForMethodSignature(getMethod());
}
private AggregateFieldDescription getDescriptionForMethodSignature(MWMethod method) {
final String signature = (method == null) ? null : method.signature();
return new AggregateFieldDescription() {
public String getMessageKey() {
return "AGGREGATE_FIELD_DESCRIPTION_FOR_METHOD_BASED_TRANSFORMER";
}
public Object[] getMessageArguments() {
return new Object[] {signature};
}
};
}
public boolean fieldIsWritten() {
return true;
}
// **************** UI support *********************************************
public String transformerDisplayString() {
MWMethod method = this.getMethod();
return (method == null) ? null : method.shortSignature();
}
// **************** Problems *********************************************
public void addAttributeTransformerProblemsForMapping(List newProblems, MWTransformationMapping mapping) {
// transformer method must be specified
if (this.getMethod() == null) {
newProblems.add(buildProblem(ProblemConstants.MAPPING_ATTRIBUTE_TRANSFORMER_METHOD_MISSING));
}
else {
// method must have correct signature
if (! this.getMethod().isCandidateAttributeTransformerMethod()) {
newProblems.add(buildProblem(ProblemConstants.MAPPING_ATTRIBUTE_TRANSFORMER_METHOD_INVALID,
this.getMethod().signature()));
}
// method must be visible to descriptor class
if (! CollectionTools.contains(mapping.getParentDescriptor().getMWClass().allMethods(), this.getMethod())) {
newProblems.add(buildProblem(ProblemConstants.MAPPING_ATTRIBUTE_TRANSFORMER_METHOD_NOT_VISIBLE,
this.getMethod().signature()));
}
}
}
public void addFieldTransformerProblemsForAssociation(List newProblems, MWFieldTransformerAssociation association) {
// transformer method must be specified
if (this.getMethod() == null) {
newProblems.add(buildProblem(ProblemConstants.MAPPING_FIELD_TRANSFORMER_METHOD_MISSING,
association.fieldName()));
}
else {
// method must have correct signature
if (! this.getMethod().isCandidateFieldTransformerMethod()) {
newProblems.add(buildProblem(ProblemConstants.MAPPING_FIELD_TRANSFORMER_METHOD_INVALID,
this.getMethod().signature(),
association.fieldName()));
}
// method must be visible to descriptor class
if (! CollectionTools.contains(association.getMapping().getParentDescriptor().getMWClass().allMethods(), this.getMethod())) {
newProblems.add(buildProblem(ProblemConstants.MAPPING_FIELD_TRANSFORMER_METHOD_NOT_VISIBLE,
this.getMethod().signature(),
association.fieldName()));
}
}
}
// **************** Runtime conversion ************************************
public void setRuntimeAttributeTransformer(AbstractTransformationMapping mapping) {
if (this.getMethod() != null) {
mapping.setAttributeTransformation(this.getMethod().getName());
}
}
public void addRuntimeFieldTransformer(AbstractTransformationMapping mapping, DatabaseField runtimeField) {
if (this.getMethod() != null) {
mapping.addFieldTransformation(runtimeField, this.getMethod().getName());
}
}
// **************** Misc. *************************************************
public void toString(StringBuffer sb) {
this.getMethod().toString(sb);
}
// **************** TopLink Methods ***************************************
public static XMLDescriptor buildDescriptor() {
XMLDescriptor descriptor = new XMLDescriptor();
descriptor.setJavaClass(MWMethodBasedTransformer.class);
descriptor.getInheritancePolicy().setParentClass(MWTransformer.class);
XMLCompositeObjectMapping methodHandleMapping = new XMLCompositeObjectMapping();
methodHandleMapping.setAttributeName("methodHandle");
methodHandleMapping.setGetMethodName("getMethodHandleForTopLink");
methodHandleMapping.setSetMethodName("setMethodHandleForTopLink");
methodHandleMapping.setReferenceClass(MWMethodHandle.class);
methodHandleMapping.setXPath("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 methodHandle) {
NodeReferenceScrubber scrubber = this.buildMethodScrubber();
this.methodHandle = ((methodHandle == null) ? new MWMethodHandle(this, scrubber) : methodHandle.setScrubber(scrubber));
}
}