blob: 4d1c3b7cd8a9d528d1339585d3db89384f371779 [file] [log] [blame]
/*
* Copyright (c) 1998, 2020 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:
// Oracle - initial API and implementation from Oracle TopLink
// 05/16/2008-1.0M8 Guy Pelletier
// - 218084: Implement metadata merging functionality between mapping files
// 06/09/2009-2.0 Guy Pelletier
// - 249037: JPA 2.0 persisting list item index
// 09/03/2010-2.2 Guy Pelletier
// - 317286: DB column lenght not in sync between @Column and @JoinColumn
// 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.columns;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.jpa.metadata.accessors.MetadataAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAnnotation;
/**
* INTERNAL:
* Object to process JPA relational type colummns into EclipseLink database fields.
*
* Key notes:
* - any metadata mapped from XML to this class must be compared in the
* equals method.
* - when loading from annotations, the constructor accepts the metadata
* accessor this metadata was loaded from. Used it to look up any
* 'companion' annotation needed for processing.
* - methods should be preserved in alphabetical order.
*
* @author Guy Pelletier
* @since EclipseLink 1.2
*/
public abstract class RelationalColumnMetadata extends MetadataColumn {
// NOTE: The foreign key metadata is currently not mapped in the join-column
// XML element, rather it is mapped as a separate element in a sequence with
// it. Therefore, this element is only populated through annotation
// processing right now, BUT this should be made available from our
// eclipselink-orm.xml and therefore maintaining a better annotation/xml
// mirror which was unfortunately not followed with JPA 2.1.
private ForeignKeyMetadata m_foreignKey;
private String m_referencedColumnName;
/**
* INTERNAL:
* Used for annotation loading.
*/
public RelationalColumnMetadata(MetadataAnnotation relationalColumn, MetadataAccessor accessor) {
super(relationalColumn, accessor);
if (relationalColumn != null) {
m_referencedColumnName = (relationalColumn.getAttributeString("referencedColumnName"));
// Also allow EIS/NoSQL synonym referencedFieldName
if (m_referencedColumnName == null) {
m_referencedColumnName = (relationalColumn.getAttributeString("referencedFieldName"));
}
// Set a foreign key if one if specified in the annotation.
if (relationalColumn.hasAttribute("foreignKey")) {
m_foreignKey = new ForeignKeyMetadata(relationalColumn.getAttributeAnnotation("foreignKey"), accessor);
}
}
}
/**
* INTERNAL:
* Used for XML loading.
*/
protected RelationalColumnMetadata(String xmlElement) {
super(xmlElement);
}
/**
* INTERNAL:
*/
@Override
public boolean equals(Object objectToCompare) {
if (super.equals(objectToCompare) && objectToCompare instanceof RelationalColumnMetadata) {
RelationalColumnMetadata relationalColumn = (RelationalColumnMetadata) objectToCompare;
if (! valuesMatch(m_foreignKey, relationalColumn.getForeignKey())) {
return false;
}
return valuesMatch(m_referencedColumnName, relationalColumn.getReferencedColumnName());
}
return false;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (m_foreignKey != null ? m_foreignKey.hashCode() : 0);
result = 31 * result + (m_referencedColumnName != null ? m_referencedColumnName.hashCode() : 0);
return result;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public ForeignKeyMetadata getForeignKey() {
return m_foreignKey;
}
/**
* INTERNAL:
*/
protected DatabaseField getForeignKeyField() {
return super.getDatabaseField();
}
/**
* INTERNAL:
* By calling this method we will return the foreign key field with the
* extra metadata from the primary key field that can not be applied to a
* referenced column.
*/
public DatabaseField getForeignKeyField(DatabaseField primaryKeyField) {
// Initialize the DatabaseField with values and defaults.
DatabaseField fkField = getForeignKeyField();
// Primary key field is null in variable one to one case.
if (primaryKeyField != null) {
fkField.setLength(primaryKeyField.getLength());
fkField.setPrecision(primaryKeyField.getPrecision());
fkField.setScale(primaryKeyField.getScale());
}
return fkField;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public String getReferencedColumnName() {
return m_referencedColumnName;
}
/**
* INTERNAL:
* Return true if a foreign key has been defined on this column.
*/
public boolean hasForeignKey() {
return m_foreignKey != null;
}
/**
* INTERNAL:
*/
public boolean isForeignKeyFieldNotSpecified() {
return getName() == null || getName().equals("");
}
/**
* INTERNAL:
*/
public boolean isPrimaryKeyFieldNotSpecified() {
return m_referencedColumnName == null || m_referencedColumnName.equals("");
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setForeignKey(ForeignKeyMetadata foreignKey) {
m_foreignKey = foreignKey;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setReferencedColumnName(String referencedColumnName) {
m_referencedColumnName = referencedColumnName;
}
}