org.datanucleus.metadata.MetaDataMerger Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of datanucleus-core Show documentation
Show all versions of datanucleus-core Show documentation
DataNucleus Core provides the primary components of a heterogenous Java persistence solution.
It supports persistence API's being layered on top of the core functionality.
/**********************************************************************
Copyright (c) 2007 Andy Jefferson and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Contributors:
...
**********************************************************************/
package org.datanucleus.metadata;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.datanucleus.exceptions.NucleusException;
import org.datanucleus.exceptions.NucleusUserException;
import org.datanucleus.util.Localiser;
import org.datanucleus.util.NucleusLogger;
/**
* Convenience class to handle the merging of MetaData.
* This is used in the following situations
*
* - JDO : Merging ORM MetaData into JDO MetaData
* - JPA : Merging Annotations information into JPA MetaData
* - JDO : Merging Annotations information into JDO MetaData
*
*/
public class MetaDataMerger
{
/**
* Method to take a file JDO MetaData definition and merge in the ORM MetaData definition.
* If something is specified in the JDO MetaData and also in the ORM MetaData then the ORM MetaData takes precedence.
* @param primaryFmd The JDO Field definition (to be updated)
* @param ormFmd The ORM Field definition (to be merged into the JDO Field definition)
* @throws NucleusException if an error occurs while merging the ORM info
*/
public static void mergeFileORMData(FileMetaData primaryFmd, FileMetaData ormFmd)
{
if (ormFmd == null || primaryFmd == null)
{
return;
}
if (primaryFmd.isInitialised() || primaryFmd.isPopulated())
{
throw new NucleusException(Localiser.msg("MetaData.File.AlreadyPopulatedError",
primaryFmd.getFilename())).setFatal();
}
if (NucleusLogger.METADATA.isDebugEnabled())
{
NucleusLogger.METADATA.debug(Localiser.msg("044056", primaryFmd.getFilename()));
}
if (ormFmd.getCatalog() != null)
{
primaryFmd.setCatalog(ormFmd.getCatalog());
}
if (ormFmd.getSchema() != null)
{
primaryFmd.setSchema(ormFmd.getSchema());
}
}
/**
* Method to take a class JDO MetaData definition and merge in the ORM MetaData definition.
* If something is specified in the JDO MetaData and also in the ORM MetaData then the ORM MetaData takes precedence.
* This is tied pretty intrinsically to the AbstractClassMetaData class and so could have been included there.
* @param primaryCmd The JDO Class definition (to be updated)
* @param ormCmd The ORM Class definition (to be merged into the JDO Class definition)
* @param mmgr MetaData manager
* @throws NucleusException if an error occurs while merging the ORM info
*/
public static void mergeClassORMData(AbstractClassMetaData primaryCmd, AbstractClassMetaData ormCmd,
MetaDataManager mmgr)
{
if (ormCmd == null || primaryCmd == null)
{
return;
}
if (primaryCmd.isInitialised() || primaryCmd.isPopulated())
{
throw new NucleusException(Localiser.msg("044068", primaryCmd.name)).setFatal();
}
if (NucleusLogger.METADATA.isDebugEnabled())
{
NucleusLogger.METADATA.debug(Localiser.msg("044096", primaryCmd.getFullClassName()));
}
// Merge the attributes where they are set in the ORM
// A). Simple data
if (ormCmd.getCatalog() != null)
{
primaryCmd.catalog = ormCmd.getCatalog();
}
if (ormCmd.getSchema() != null)
{
primaryCmd.schema = ormCmd.getSchema();
}
if (ormCmd.getTable() != null)
{
primaryCmd.table = ormCmd.getTable();
}
if (ormCmd.detachable)
{
primaryCmd.detachable = true;
}
if (!ormCmd.requiresExtent)
{
primaryCmd.requiresExtent = false;
}
if (ormCmd.embeddedOnly)
{
primaryCmd.embeddedOnly = true;
}
// B). Object data. Assume that if it exists at all we copy it all
if (ormCmd.getPrimaryKeyMetaData() != null)
{
primaryCmd.setPrimaryKeyMetaData(ormCmd.getPrimaryKeyMetaData());
}
if (ormCmd.getInheritanceMetaData() != null)
{
// TODO Support merging bit by bit
primaryCmd.setInheritanceMetaData(ormCmd.getInheritanceMetaData());
}
if (ormCmd.getDatastoreIdentityMetaData() != null)
{
// TODO Support merging bit by bit
primaryCmd.setDatastoreIdentityMetaData(ormCmd.getDatastoreIdentityMetaData());
}
if (ormCmd.getVersionMetaData() != null)
{
VersionMetaData primVermd = primaryCmd.getVersionMetaData();
VersionMetaData ormVermd = ormCmd.getVersionMetaData();
if (primVermd != null)
{
// Merge bit by bit
if (ormVermd.getStrategy() != null)
{
primVermd.setStrategy(ormVermd.getStrategy());
}
if (ormVermd.getColumnName() != null)
{
primVermd.setColumnName(ormVermd.getColumnName());
}
if (ormVermd.getColumnMetaData() != null)
{
primVermd.setColumnMetaData(ormVermd.getColumnMetaData());
}
if (ormVermd.getIndexMetaData() != null)
{
primVermd.setIndexMetaData(ormVermd.getIndexMetaData());
}
}
else
{
// Just use ORM version metadata
primaryCmd.setVersionMetaData(ormVermd);
}
}
if (ormCmd.listeners != null)
{
if (primaryCmd.listeners == null)
{
primaryCmd.listeners = new ArrayList();
}
primaryCmd.listeners.addAll(ormCmd.listeners);
}
if (ormCmd.queries != null)
{
if (primaryCmd.queries == null)
{
primaryCmd.queries = new ArrayList();
}
else
{
primaryCmd.queries.clear();
}
primaryCmd.queries.addAll(ormCmd.queries);
}
if (ormCmd.joins != null)
{
primaryCmd.joins = null;
for (JoinMetaData joinmd : ormCmd.joins)
{
primaryCmd.addJoin(joinmd);
}
}
if (ormCmd.indexes != null)
{
primaryCmd.indexes = null;
for (IndexMetaData idxmd : ormCmd.indexes)
{
primaryCmd.addIndex(idxmd);
}
}
if (ormCmd.foreignKeys != null)
{
primaryCmd.foreignKeys = null;
for (ForeignKeyMetaData fkmd : ormCmd.foreignKeys)
{
primaryCmd.addForeignKey(fkmd);
}
}
if (ormCmd.uniqueConstraints != null)
{
primaryCmd.uniqueConstraints = null;
for (UniqueMetaData unimd : ormCmd.uniqueConstraints)
{
primaryCmd.addUniqueConstraint(unimd);
}
}
if (ormCmd.fetchGroups != null)
{
primaryCmd.fetchGroups = null;
for (FetchGroupMetaData fgmd : ormCmd.fetchGroups)
{
primaryCmd.addFetchGroup(fgmd);
}
}
if (ormCmd.unmappedColumns != null)
{
primaryCmd.unmappedColumns = null;
for (ColumnMetaData colmd : ormCmd.unmappedColumns)
{
primaryCmd.addUnmappedColumn(colmd);
}
}
// C). Add on any fields that weren't defined previously
for (int i=0;i ormExtensions = ormCmd.getExtensions();
if (ormExtensions != null)
{
primaryCmd.addExtensions(ormExtensions);
}
}
/**
* Method to take a field JDO MetaData definition and merge in the ORM MetaData definition.
* This is tied pretty intrinsically to the AbstractMemberMetaData class and so could have been included there.
* @param primaryFmd The JDO Field definition (to be updated)
* @param ormFmd The ORM Field definition (to be merged into the JDO Class definition)
* @throws NucleusException if an error occurs while merging the ORM info
*/
static void mergeMemberORMData(AbstractMemberMetaData primaryFmd, AbstractMemberMetaData ormFmd)
{
if (ormFmd == null || primaryFmd == null)
{
return;
}
if (primaryFmd.isInitialised() || primaryFmd.isPopulated())
{
throw new NucleusException(Localiser.msg("044107", primaryFmd.getClassName(), primaryFmd.getName())).setFatal();
}
if (ormFmd.persistenceModifier != null &&
ormFmd.persistenceModifier != FieldPersistenceModifier.DEFAULT &&
primaryFmd.persistenceModifier != ormFmd.persistenceModifier)
{
// Take the persistence-modifier from ORM since it is changed
primaryFmd.persistenceModifier = ormFmd.persistenceModifier;
}
if (ormFmd.className != null)
{
// If the ORM is an overriding field, make sure we have the (real) class name
primaryFmd.className = ormFmd.className;
}
if (ormFmd.containerMetaData != null)
{
primaryFmd.containerMetaData = ormFmd.containerMetaData;
primaryFmd.containerMetaData.parent = primaryFmd;
}
// Update our O/R mapping details
if (ormFmd.defaultFetchGroup != null)
{
primaryFmd.defaultFetchGroup = ormFmd.defaultFetchGroup;
}
/*if (Boolean.FALSE.equals(primaryFmd.primaryKey) && Boolean.TRUE.equals(ormFmd.primaryKey))
{
primaryFmd.primaryKey = Boolean.valueOf(ormFmd.isPrimaryKey());
}*/
if (ormFmd.getTable() != null)
{
primaryFmd.table = ormFmd.getTable();
}
if (ormFmd.getCatalog() != null)
{
primaryFmd.catalog = ormFmd.getCatalog();
}
if (ormFmd.getSchema() != null)
{
primaryFmd.schema = ormFmd.getSchema();
}
if (ormFmd.column != null)
{
primaryFmd.column = ormFmd.column;
}
if (ormFmd.dependent != null)
{
primaryFmd.dependent = ormFmd.dependent;
}
if (ormFmd.getMappedBy() != null)
{
primaryFmd.mappedBy = ormFmd.getMappedBy();
}
if (ormFmd.getValueStrategy() != null)
{
primaryFmd.valueStrategy = ormFmd.getValueStrategy();
}
if (ormFmd.getSequence() != null)
{
primaryFmd.sequence = ormFmd.getSequence();
}
if (ormFmd.indexed != null)
{
primaryFmd.indexed = ormFmd.indexed;
}
if (ormFmd.nullValue != NullValue.NONE)
{
primaryFmd.nullValue = ormFmd.nullValue;
}
if (ormFmd.getJoinMetaData() != null)
{
primaryFmd.setJoinMetaData(ormFmd.joinMetaData);
}
if (ormFmd.getEmbeddedMetaData() != null)
{
primaryFmd.setEmbeddedMetaData(ormFmd.embeddedMetaData);
}
if (ormFmd.getElementMetaData() != null)
{
primaryFmd.setElementMetaData(ormFmd.elementMetaData);
}
if (ormFmd.getKeyMetaData() != null)
{
primaryFmd.setKeyMetaData(ormFmd.keyMetaData);
}
if (ormFmd.getValueMetaData() != null)
{
primaryFmd.setValueMetaData(ormFmd.valueMetaData);
}
if (ormFmd.getOrderMetaData() != null)
{
primaryFmd.setOrderMetaData(ormFmd.orderMetaData);
}
if (ormFmd.getForeignKeyMetaData() != null)
{
primaryFmd.foreignKeyMetaData = ormFmd.getForeignKeyMetaData();
if (primaryFmd.foreignKeyMetaData != null)
{
primaryFmd.foreignKeyMetaData.parent = primaryFmd;
}
}
if (ormFmd.getIndexMetaData() != null)
{
primaryFmd.indexMetaData = ormFmd.getIndexMetaData();
if (primaryFmd.indexMetaData != null)
{
primaryFmd.indexMetaData.parent = primaryFmd;
}
}
if (ormFmd.getUniqueMetaData() != null)
{
primaryFmd.uniqueMetaData = ormFmd.getUniqueMetaData();
if (primaryFmd.uniqueMetaData != null)
{
primaryFmd.uniqueMetaData.parent = primaryFmd;
}
}
ColumnMetaData[] ormColumns = ormFmd.getColumnMetaData();
if (ormColumns != null)
{
primaryFmd.columns.clear();
for (int i = 0; i < ormColumns.length; i++)
{
primaryFmd.columns.add(ormColumns[i]);
}
}
// Add any extensions supplied in the ORM file
Map ormExtensions = ormFmd.getExtensions();
if (ormExtensions != null)
{
primaryFmd.addExtensions(ormExtensions);
}
}
/**
* Method to take a class XML metadata definition and merge in any Annotations metadata definition.
* If something is specified in the XML and also in the annotations then the XML takes precedence.
* This is tied pretty intrinsically to the AbstractClassMetaData class and so could have been included there.
* @param primaryCmd The XML metadata definition (to be updated)
* @param annotCmd The annotations metadata definition (to be merged into the XML definition)
* @param mmgr MetaData manager
* @throws NucleusException if an error occurs while merging the annotations info
*/
public static void mergeClassAnnotationsData(AbstractClassMetaData primaryCmd, AbstractClassMetaData annotCmd, MetaDataManager mmgr)
{
if (annotCmd == null || primaryCmd == null)
{
return;
}
if (primaryCmd.isInitialised() || primaryCmd.isPopulated())
{
throw new NucleusException(Localiser.msg("044068", primaryCmd.name)).setFatal();
}
if (NucleusLogger.METADATA.isDebugEnabled())
{
NucleusLogger.METADATA.debug(Localiser.msg("044095", primaryCmd.getFullClassName()));
}
// Merge any annotated information that is hanging off the package
PackageMetaData annotPmd = annotCmd.getPackageMetaData();
if (annotPmd.getSequences() != null)
{
// Register the sequences since the register process for the primaryCmd has passed
mmgr.registerSequencesForFile(annotCmd.getPackageMetaData().getFileMetaData());
SequenceMetaData[] seqmds = annotPmd.getSequences();
for (int i=0;i annotListeners = annotCmd.getListeners();
for (EventListenerMetaData elmd : annotListeners)
{
if (!elmd.getClassName().equals(primaryCmd.getFullClassName()))
{
// Add on listeners from annotations
primaryCmd.addListener(elmd);
}
}
}
}
if (annotCmd.excludeDefaultListeners != null && primaryCmd.excludeDefaultListeners == null)
{
primaryCmd.excludeDefaultListeners = annotCmd.excludeDefaultListeners;
}
if (annotCmd.excludeSuperClassListeners != null && primaryCmd.excludeSuperClassListeners == null)
{
primaryCmd.excludeSuperClassListeners = annotCmd.excludeSuperClassListeners;
}
if (primaryCmd.queries == null && annotCmd.queries != null)
{
for (QueryMetaData qmd : annotCmd.queries)
{
primaryCmd.addQuery(qmd);
}
}
if (primaryCmd.joins == null && annotCmd.joins != null)
{
for (JoinMetaData joinmd : annotCmd.joins)
{
primaryCmd.addJoin(joinmd);
}
}
if (primaryCmd.indexes == null && annotCmd.indexes != null)
{
for (IndexMetaData idxmd : annotCmd.indexes)
{
primaryCmd.addIndex(idxmd);
}
}
if (primaryCmd.foreignKeys == null && annotCmd.foreignKeys != null)
{
for (ForeignKeyMetaData fkmd : annotCmd.foreignKeys)
{
primaryCmd.addForeignKey(fkmd);
}
}
if (primaryCmd.uniqueConstraints == null && annotCmd.uniqueConstraints != null)
{
for (UniqueMetaData unimd : annotCmd.uniqueConstraints)
{
primaryCmd.addUniqueConstraint(unimd);
}
}
if (primaryCmd.fetchGroups == null && annotCmd.fetchGroups != null)
{
for (FetchGroupMetaData fgmd : annotCmd.fetchGroups)
{
primaryCmd.addFetchGroup(fgmd);
}
}
// C). Add on any fields that weren't defined previously
for (int i=0;i ormExtensions = annotCmd.getExtensions();
if (ormExtensions != null)
{
primaryCmd.addExtensions(ormExtensions);
}
}
/**
* Method to take a field/property XML metadata definition and merge in the Annotations metadata definition.
* This is tied pretty intrinsically to the AbstractMemberMetaData class and so could have been included there.
* @param primaryFmd The XML metadata Field definition (to be updated)
* @param annotFmd The Annotations metadata Field definition (to be merged into the XML definition)
* @throws NucleusException if an error occurs while merging the annotation info
*/
static void mergeMemberAnnotationsData(AbstractMemberMetaData primaryFmd, AbstractMemberMetaData annotFmd)
{
if (annotFmd == null || primaryFmd == null)
{
return;
}
if (primaryFmd.isInitialised() || primaryFmd.isPopulated())
{
throw new NucleusException(Localiser.msg("044107", primaryFmd.getClassName(), primaryFmd.getName())).setFatal();
}
if (primaryFmd.className == null && annotFmd.className != null)
{
// If the Annotation is an overriding field, make sure we have the (real) class name
primaryFmd.className = annotFmd.className;
}
if (primaryFmd.containerMetaData == null && annotFmd.containerMetaData != null)
{
primaryFmd.containerMetaData = annotFmd.containerMetaData;
primaryFmd.containerMetaData.parent = primaryFmd;
}
if (annotFmd.storeInLob)
{
primaryFmd.storeInLob = true;
}
if (annotFmd.persistenceModifier != FieldPersistenceModifier.DEFAULT &&
primaryFmd.persistenceModifier == FieldPersistenceModifier.DEFAULT)
{
primaryFmd.persistenceModifier = annotFmd.persistenceModifier;
}
if (annotFmd.defaultFetchGroup != null && primaryFmd.defaultFetchGroup == null)
{
primaryFmd.defaultFetchGroup = annotFmd.defaultFetchGroup;
}
if (annotFmd.primaryKey != null)
{
// "primary-key" will always have a value in XML so we just override if the annotation had it set
// This means that we don't allow overriding of the primary-key via XML
primaryFmd.primaryKey = annotFmd.primaryKey;
}
if (primaryFmd.table == null && annotFmd.table != null)
{
primaryFmd.table = annotFmd.table;
}
if (primaryFmd.catalog == null && annotFmd.catalog != null)
{
primaryFmd.catalog = annotFmd.catalog;
}
if (primaryFmd.schema == null && annotFmd.schema != null)
{
primaryFmd.schema = annotFmd.schema;
}
if (primaryFmd.column == null && annotFmd.column != null)
{
primaryFmd.column = annotFmd.column;
}
if (primaryFmd.dependent == null && annotFmd.dependent != null)
{
primaryFmd.dependent = annotFmd.dependent;
}
if (primaryFmd.mappedBy == null && annotFmd.mappedBy != null)
{
primaryFmd.mappedBy = annotFmd.mappedBy;
}
if (primaryFmd.valueStrategy == null && annotFmd.valueStrategy != null)
{
primaryFmd.valueStrategy = annotFmd.valueStrategy;
}
if (primaryFmd.sequence == null && annotFmd.sequence != null)
{
primaryFmd.sequence = annotFmd.sequence;
}
if (primaryFmd.valueGeneratorName == null && annotFmd.valueGeneratorName != null)
{
primaryFmd.valueGeneratorName = annotFmd.valueGeneratorName;
}
if (primaryFmd.indexed == null && annotFmd.indexed != null)
{
primaryFmd.indexed = annotFmd.indexed;
}
if (annotFmd.nullValue != NullValue.NONE)
{
primaryFmd.nullValue = annotFmd.nullValue;
}
if (annotFmd.cascadePersist != null && primaryFmd.cascadePersist == null)
{
primaryFmd.cascadePersist = annotFmd.cascadePersist;
}
if (annotFmd.cascadeAttach != null && primaryFmd.cascadeAttach == null)
{
primaryFmd.cascadeAttach = annotFmd.cascadeAttach;
}
if (annotFmd.cascadeDelete != null && primaryFmd.cascadeDelete == null)
{
primaryFmd.cascadeDelete = annotFmd.cascadeDelete;
}
if (annotFmd.cascadeRefresh != null && primaryFmd.cascadeRefresh == null)
{
primaryFmd.cascadeRefresh = annotFmd.cascadeRefresh;
}
if (primaryFmd.joinMetaData == null && annotFmd.joinMetaData != null)
{
primaryFmd.setJoinMetaData(annotFmd.joinMetaData);
}
if (primaryFmd.embeddedMetaData == null && annotFmd.embeddedMetaData != null)
{
primaryFmd.setEmbeddedMetaData(annotFmd.embeddedMetaData);
}
if (primaryFmd.elementMetaData == null && annotFmd.elementMetaData != null)
{
primaryFmd.setElementMetaData(annotFmd.elementMetaData);
}
if (primaryFmd.keyMetaData == null && annotFmd.keyMetaData != null)
{
primaryFmd.setKeyMetaData(annotFmd.keyMetaData);
}
if (primaryFmd.valueMetaData == null && annotFmd.valueMetaData != null)
{
primaryFmd.setValueMetaData(annotFmd.valueMetaData);
}
if (primaryFmd.orderMetaData == null && annotFmd.orderMetaData != null)
{
primaryFmd.setOrderMetaData(annotFmd.orderMetaData);
}
if (primaryFmd.foreignKeyMetaData == null && annotFmd.foreignKeyMetaData != null)
{
primaryFmd.foreignKeyMetaData = annotFmd.foreignKeyMetaData;
primaryFmd.foreignKeyMetaData.parent = primaryFmd;
}
if (primaryFmd.indexMetaData == null && annotFmd.indexMetaData != null)
{
primaryFmd.indexMetaData = annotFmd.indexMetaData;
primaryFmd.indexMetaData.parent = primaryFmd;
}
if (primaryFmd.uniqueMetaData == null && annotFmd.uniqueMetaData != null)
{
primaryFmd.uniqueMetaData = annotFmd.uniqueMetaData;
primaryFmd.uniqueMetaData.parent = primaryFmd;
}
if (primaryFmd.columns.isEmpty() && !annotFmd.columns.isEmpty())
{
// Columns specified in annotations but not in XML
ColumnMetaData[] annotColumns = annotFmd.getColumnMetaData();
if (annotColumns != null)
{
for (int i = 0; i < annotColumns.length; i++)
{
primaryFmd.columns.add(annotColumns[i]);
}
}
}
// Add any extensions supplied in the annotations
Map annotExtensions = annotFmd.getExtensions();
if (annotExtensions != null)
{
primaryFmd.addExtensions(annotExtensions);
}
}
}