blob: 0e7a7ae13de55448dd470030d1fa3eaed371c960 [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 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:
// Andrei Ilitchev (Oracle), March 7, 2008
// - New file introduced for bug 211300.
// 05/16/2008-1.0M8 Guy Pelletier
// - 218084: Implement metadata merging functionality between mapping files
// 02/06/2009-2.0 Guy Pelletier
// - 248293: JPA 2.0 Element Collections (part 2)
// 03/27/2009-2.0 Guy Pelletier
// - 241413: JPA 2.0 Add EclipseLink support for Map type attributes
// 04/27/2010-2.1 Guy Pelletier
// - 309856: MappedSuperclasses from XML are not being initialized properly
// 03/24/2011-2.3 Guy Pelletier
// - 337323: Multi-tenant with shared schema support (part 1)
// 11/19/2012-2.5 Guy Pelletier
// - 389090: JPA 2.1 DDL Generation Support (foreign key metadata support)
package org.eclipse.persistence.internal.jpa.metadata.accessors.mappings;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.persistence.annotations.ReadTransformer;
import org.eclipse.persistence.annotations.WriteTransformer;
import org.eclipse.persistence.annotations.WriteTransformers;
import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.ClassAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAccessibleObject;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAnnotatedElement;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAnnotation;
import org.eclipse.persistence.internal.jpa.metadata.transformers.ReadTransformerMetadata;
import org.eclipse.persistence.internal.jpa.metadata.transformers.WriteTransformerMetadata;
import org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappings;
import org.eclipse.persistence.mappings.TransformationMapping;
/**
* INTERNAL:
* TransformationAccessor. Transformation annotation may or may not be present
* on the accessible object.
*
* Key notes:
* - any metadata mapped from XML to this class must be compared in the
* equals method.
* - any metadata mapped from XML to this class must be handled in the merge
* method. (merging is done at the accessor/mapping level)
* - any metadata mapped from XML to this class must be initialized in the
* initXMLObject method.
* - methods should be preserved in alphabetical order.
*
* @author Andrei Ilitchev
* @since EclipseLink 1.0
*/
public class TransformationAccessor extends BasicAccessor {
private ReadTransformerMetadata m_readTransformer;
private List<WriteTransformerMetadata> m_writeTransformers = new ArrayList<WriteTransformerMetadata>();
/**
* INTERNAL:
*/
public TransformationAccessor() {
super("<transformation>");
}
/**
* INTERNAL:
*/
public TransformationAccessor(MetadataAnnotation transformation, MetadataAnnotatedElement annotatedElement, ClassAccessor classAccessor) {
super(transformation, annotatedElement, classAccessor);
if (transformation != null) {
setFetch(transformation.getAttributeString("fetch"));
setOptional(transformation.getAttributeBooleanDefaultTrue("optional"));
}
if (isAnnotationPresent(ReadTransformer.class)) {
m_readTransformer = new ReadTransformerMetadata(getAnnotation(ReadTransformer.class), this);
}
// Set the write transformers if specified.
// Process all the write transformers first.
if (isAnnotationPresent(WriteTransformers.class)) {
for (Object transformer : getAnnotation(WriteTransformers.class).getAttributeArray("value")) {
m_writeTransformers.add(new WriteTransformerMetadata((MetadataAnnotation) transformer, this));
}
}
// Process the single write transformer second.
if (isAnnotationPresent(WriteTransformer.class)) {
m_writeTransformers.add(new WriteTransformerMetadata(getAnnotation(WriteTransformer.class), this));
}
// TODO: ReturningPolicy
}
/**
* INTERNAL:
*/
@Override
public boolean equals(Object objectToCompare) {
if (super.equals(objectToCompare) && objectToCompare instanceof TransformationAccessor) {
TransformationAccessor transformationAccessor = (TransformationAccessor) objectToCompare;
if (! valuesMatch(m_readTransformer, transformationAccessor.getReadTransformer())) {
return false;
}
return valuesMatch(m_writeTransformers, transformationAccessor.getWriteTransformers());
}
return false;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (m_readTransformer != null ? m_readTransformer.hashCode() : 0);
result = 31 * result + (m_writeTransformers != null ? m_writeTransformers.hashCode() : 0);
return result;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public ReadTransformerMetadata getReadTransformer() {
return m_readTransformer;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public List<WriteTransformerMetadata> getWriteTransformers() {
return m_writeTransformers;
}
/**
* INTERNAL:
*/
@Override
public void initXMLObject(MetadataAccessibleObject accessibleObject, XMLEntityMappings entityMappings) {
super.initXMLObject(accessibleObject, entityMappings);
// Init the ORMetadata objects.
initXMLObject(m_readTransformer, accessibleObject);
// Init the list of ORMetadata objects.
initXMLObjects(m_writeTransformers, accessibleObject);
}
/**
* INTERNAL:
* Process a transformation accessor. Creates a TransformationMapping and
* adds it to descriptor.
*/
@Override
public void process() {
TransformationMapping mapping = new TransformationMapping();
setMapping(mapping);
mapping.setAttributeName(getAttributeName());
mapping.setIsOptional(isOptional());
mapping.setIsLazy(usesIndirection());
if (getMutable() != null) {
mapping.setIsMutable(getMutable());
}
// Will check for PROPERTY access.
setAccessorMethods(mapping);
if (m_readTransformer != null) {
m_readTransformer.process(mapping, getAnnotatedElementName());
}
if (m_writeTransformers.isEmpty()) {
mapping.setIsReadOnly(true);
} else {
if (m_writeTransformers.size() == 1) {
// If only one WriteTransformer specified then if column name
// is not specified attribute name will be used as a column
// name.
if (! m_writeTransformers.get(0).hasFieldName()) {
m_writeTransformers.get(0).setFieldName(getAttributeName());
}
}
for (WriteTransformerMetadata writeTransformer : m_writeTransformers) {
writeTransformer.process(mapping, getAnnotatedElementName());
}
}
// TODO: ReturningPolicy
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setReadTransformer(ReadTransformerMetadata readTransformer) {
m_readTransformer = readTransformer;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setWriteTransformers(List<WriteTransformerMetadata> writeTransformers) {
m_writeTransformers = writeTransformers;
}
}