blob: 00a7723f71a51e17f33e42f5e7fed016058e3ada [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2012 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0, which accompanies this distribution
* and is available at http://www.eclipse.org/legal/epl-v10.html.
*
* Contributors:
* Oracle - initial API and implementation
*******************************************************************************/
package org.eclipse.jpt.jpa.eclipselink.core.context.persistence;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
import org.eclipse.jpt.common.core.internal.utility.JDTTools;
import org.eclipse.jpt.common.core.utility.TextRange;
import org.eclipse.jpt.common.utility.internal.ArrayTools;
import org.eclipse.jpt.common.utility.internal.CollectionTools;
import org.eclipse.jpt.common.utility.internal.NonEmptyStringFilter;
import org.eclipse.jpt.common.utility.internal.StringTools;
import org.eclipse.jpt.common.utility.internal.iterables.CompositeIterable;
import org.eclipse.jpt.common.utility.internal.iterables.CompositeListIterable;
import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;
import org.eclipse.jpt.common.utility.internal.iterables.EmptyListIterable;
import org.eclipse.jpt.common.utility.internal.iterables.FilteringIterable;
import org.eclipse.jpt.common.utility.internal.iterables.ListIterable;
import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneIterable;
import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneListIterable;
import org.eclipse.jpt.common.utility.internal.iterables.SubIterableWrapper;
import org.eclipse.jpt.common.utility.internal.iterables.SuperListIterableWrapper;
import org.eclipse.jpt.common.utility.internal.iterables.TransformationIterable;
import org.eclipse.jpt.jpa.core.context.Generator;
import org.eclipse.jpt.jpa.core.context.JpaNamedContextNode;
import org.eclipse.jpt.jpa.core.context.MappingFile;
import org.eclipse.jpt.jpa.core.context.MappingFilePersistenceUnitMetadata;
import org.eclipse.jpt.jpa.core.context.MappingFileRoot;
import org.eclipse.jpt.jpa.core.context.PersistentType;
import org.eclipse.jpt.jpa.core.context.Query;
import org.eclipse.jpt.jpa.core.context.TypeMapping;
import org.eclipse.jpt.jpa.core.context.java.JavaGenerator;
import org.eclipse.jpt.jpa.core.context.java.JavaQuery;
import org.eclipse.jpt.jpa.core.context.orm.EntityMappings;
import org.eclipse.jpt.jpa.core.context.orm.OrmQueryContainer;
import org.eclipse.jpt.jpa.core.context.persistence.MappingFileRef;
import org.eclipse.jpt.jpa.core.context.persistence.Persistence;
import org.eclipse.jpt.jpa.core.internal.JptCoreMessages;
import org.eclipse.jpt.jpa.core.internal.context.persistence.AbstractPersistenceUnit;
import org.eclipse.jpt.jpa.core.internal.jpa1.context.persistence.ImpliedMappingFileRef;
import org.eclipse.jpt.jpa.core.jpa2.context.persistence.options.SharedCacheMode;
import org.eclipse.jpt.jpa.core.jpql.JpaJpqlQueryHelper;
import org.eclipse.jpt.jpa.core.resource.persistence.XmlPersistenceUnit;
import org.eclipse.jpt.jpa.eclipselink.core.EclipseLinkJpaProject;
import org.eclipse.jpt.jpa.eclipselink.core.JptJpaEclipseLinkCorePlugin;
import org.eclipse.jpt.jpa.eclipselink.core.context.EclipseLinkConverter;
import org.eclipse.jpt.jpa.eclipselink.core.context.EclipseLinkTypeMapping;
import org.eclipse.jpt.jpa.eclipselink.core.context.ReadOnlyTenantDiscriminatorColumn2_3;
import org.eclipse.jpt.jpa.eclipselink.core.context.orm.EclipseLinkEntityMappings;
import org.eclipse.jpt.jpa.eclipselink.core.context.orm.EclipseLinkOrmPersistentType;
import org.eclipse.jpt.jpa.eclipselink.core.context.orm.EclipseLinkPersistenceUnitDefaults;
import org.eclipse.jpt.jpa.eclipselink.core.context.orm.OrmEclipseLinkConverterContainer;
import org.eclipse.jpt.jpa.eclipselink.core.internal.DefaultEclipseLinkJpaValidationMessages;
import org.eclipse.jpt.jpa.eclipselink.core.internal.EclipseLinkJpaJpqlQueryHelper;
import org.eclipse.jpt.jpa.eclipselink.core.internal.EclipseLinkJpaValidationMessages;
import org.eclipse.jpt.jpa.eclipselink.core.internal.JptJpaEclipseLinkCoreMessages;
import org.eclipse.jpt.jpa.eclipselink.core.internal.context.java.JavaEclipseLinkConverter;
import org.eclipse.jpt.jpa.eclipselink.core.internal.context.orm.OrmEclipseLinkConverter;
import org.eclipse.jpt.jpa.eclipselink.core.internal.context.orm.OrmEclipseLinkPersistenceUnitMetadata;
import org.eclipse.jpt.jpa.eclipselink.core.internal.context.persistence.EclipseLinkCaching;
import org.eclipse.jpt.jpa.eclipselink.core.internal.context.persistence.EclipseLinkCustomization;
import org.eclipse.jpt.jpa.eclipselink.core.internal.context.persistence.EclipseLinkGeneralProperties;
import org.eclipse.jpt.jpa.eclipselink.core.internal.context.persistence.EclipseLinkSchemaGeneration;
import org.eclipse.osgi.util.NLS;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
/**
* EclipseLink persistence unit
*/
public class EclipseLinkPersistenceUnit
extends AbstractPersistenceUnit
{
/**
* Will be null if the implied EL mapping file should not be part of the context model.
* Otherwise will be equal to potentialImpliedEclipseLinkMappingFileRef.
*
* @see #potentialImpliedEclipseLinkMappingFileRef
*/
protected MappingFileRef impliedEclipseLinkMappingFileRef;
/**
* String constant associated with changes to the implied eclipselink mapping file ref
*/
public static final String IMPLIED_ECLIPSELINK_MAPPING_FILE_REF_PROPERTY = "impliedEclipseLinkMappingFileRef"; //$NON-NLS-1$
/**
* Store the implied EL mapping file ref even if it is not part of the context model.
* This allows us to sync it in the syncWithResourceModel. In the update, determine if
* it should be part of the context model and set the impliedEclipseLinkMappingFileRef appropriately.
*
* @see #impliedEclipseLinkMappingFileRef
* @see #usesImpliedEclipseLinkMappingFile()
*/
protected final MappingFileRef potentialImpliedEclipseLinkMappingFileRef;
private/*final*/ GeneralProperties generalProperties;
private Customization customization;
private Caching caching;
private Logging logging;
private SchemaGeneration schemaGeneration;
/* global converter definitions, defined elsewhere in model */
protected final Vector<EclipseLinkConverter> converters = new Vector<EclipseLinkConverter>();
protected final Vector<ReadOnlyTenantDiscriminatorColumn2_3> defaultTenantDiscriminatorColumns = new Vector<ReadOnlyTenantDiscriminatorColumn2_3>();
protected String defaultGetMethod;
protected String defaultSetMethod;
public EclipseLinkPersistenceUnit(Persistence parent, XmlPersistenceUnit xmlPersistenceUnit) {
super(parent, xmlPersistenceUnit);
this.potentialImpliedEclipseLinkMappingFileRef = this.buildEclipseLinkImpliedMappingFileRef();
}
// ********** synchronize/update **********
@Override
public void update() {
super.update();
this.setConverters(this.buildConverters());
OrmEclipseLinkPersistenceUnitMetadata metadata = this.getEclipseLinkMetadata();
EclipseLinkPersistenceUnitDefaults defaults = (metadata == null) ? null : metadata.getPersistenceUnitDefaults();
this.setDefaultTenantDiscriminatorColumns(this.buildDefaultTenantDiscriminatorColumns(defaults));
}
protected OrmEclipseLinkPersistenceUnitMetadata getEclipseLinkMetadata() {
MappingFilePersistenceUnitMetadata metadata = super.getMetadata();
if (metadata instanceof OrmEclipseLinkPersistenceUnitMetadata) {
return (OrmEclipseLinkPersistenceUnitMetadata) metadata;
}
return null;
}
@Override
protected void updatePersistenceUnitMetadata() {
super.updatePersistenceUnitMetadata();
OrmEclipseLinkPersistenceUnitMetadata metadata = this.getEclipseLinkMetadata();
EclipseLinkPersistenceUnitDefaults defaults = (metadata == null) ? null : metadata.getPersistenceUnitDefaults();
this.setDefaultGetMethod(this.buildDefaultGetMethod(defaults));
this.setDefaultSetMethod(this.buildDefaultSetMethod(defaults));
}
// ********** properties **********
public GeneralProperties getGeneralProperties() {
return this.generalProperties;
}
@Override
public Connection getConnection() {
return (Connection) super.getConnection();
}
public Customization getCustomization() {
return this.customization;
}
public Caching getCaching() {
return this.caching;
}
public String getDefaultCacheTypePropertyValue() {
Property cacheTypeDefaultProperty = getCacheTypeDefaultProperty();
return cacheTypeDefaultProperty != null ? cacheTypeDefaultProperty.getValue() : null;
}
public String getDefaultCacheSizePropertyValue() {
Property cacheSizeDefaultProperty = getCacheSizeDefaultProperty();
return cacheSizeDefaultProperty != null ? cacheSizeDefaultProperty.getValue() : null;
}
public String getDefaultCacheSharedPropertyValue() {
Property cacheSharedDefaultProperty = getCacheSharedDefaultProperty();
return cacheSharedDefaultProperty != null ? cacheSharedDefaultProperty.getValue() : null;
}
public Logging getLogging() {
return this.logging;
}
@Override
public Options getOptions() {
return (Options) super.getOptions();
}
public SchemaGeneration getSchemaGeneration() {
return this.schemaGeneration;
}
protected GeneralProperties buildEclipseLinkGeneralProperties() {
return new EclipseLinkGeneralProperties(this);
}
protected Connection buildEclipseLinkConnection() {
return (Connection) this.getContextNodeFactory().buildConnection(this);
}
protected Customization buildEclipseLinkCustomization() {
return new EclipseLinkCustomization(this);
}
protected Caching buildEclipseLinkCaching() {
return new EclipseLinkCaching(this);
}
protected Logging buildEclipseLinkLogging() {
return (Logging) this.getContextNodeFactory().buildLogging(this);
}
protected Options buildEclipseLinkOptions() {
return (Options) this.getContextNodeFactory().buildOptions(this);
}
protected SchemaGeneration buildEclipseLinkSchemaGeneration() {
return new EclipseLinkSchemaGeneration(this);
}
@Override
protected void initializeProperties() {
super.initializeProperties();
this.generalProperties = this.buildEclipseLinkGeneralProperties();
this.customization = this.buildEclipseLinkCustomization();
this.caching = this.buildEclipseLinkCaching();
this.logging = this.buildEclipseLinkLogging();
this.schemaGeneration = this.buildEclipseLinkSchemaGeneration();
}
@Override
public void propertyValueChanged(String propertyName, String newValue) {
super.propertyValueChanged(propertyName, newValue);
this.generalProperties.propertyValueChanged(propertyName, newValue);
this.customization.propertyValueChanged(propertyName, newValue);
this.caching.propertyValueChanged(propertyName, newValue);
this.logging.propertyValueChanged(propertyName, newValue);
this.schemaGeneration.propertyValueChanged(propertyName, newValue);
}
@Override
public void propertyRemoved(String propertyName) {
super.propertyRemoved(propertyName);
this.generalProperties.propertyRemoved(propertyName);
this.customization.propertyRemoved(propertyName);
this.caching.propertyRemoved(propertyName);
this.logging.propertyRemoved(propertyName);
this.schemaGeneration.propertyRemoved(propertyName);
}
// ********** mapping file refs **********
@Override
public ListIterable<MappingFileRef> getMappingFileRefs() {
return (this.impliedEclipseLinkMappingFileRef == null) ?
super.getMappingFileRefs() :
new CompositeListIterable<MappingFileRef>(super.getMappingFileRefs(), this.impliedEclipseLinkMappingFileRef);
}
@Override
public int getMappingFileRefsSize() {
return (this.impliedEclipseLinkMappingFileRef == null) ?
super.getMappingFileRefsSize() :
super.getMappingFileRefsSize() + 1;
}
// ********** implied eclipselink mapping file ref **********
public MappingFileRef getImpliedEclipseLinkMappingFileRef() {
return this.impliedEclipseLinkMappingFileRef;
}
protected void setImpliedEclipseLinkMappingFileRef(MappingFileRef mappingFileRef) {
MappingFileRef old = this.impliedEclipseLinkMappingFileRef;
this.impliedEclipseLinkMappingFileRef = mappingFileRef;
this.firePropertyChanged(IMPLIED_ECLIPSELINK_MAPPING_FILE_REF_PROPERTY, old, mappingFileRef);
}
private ImpliedMappingFileRef buildEclipseLinkImpliedMappingFileRef() {
return new ImpliedMappingFileRef(this, JptJpaEclipseLinkCorePlugin.DEFAULT_ECLIPSELINK_ORM_XML_RUNTIME_PATH.toString());
}
@Override
protected void syncImpliedMappingFileRef() {
super.syncImpliedMappingFileRef();
this.potentialImpliedEclipseLinkMappingFileRef.synchronizeWithResourceModel();
}
@Override
protected void updateImpliedMappingFileRef() {
super.updateImpliedMappingFileRef();
if (this.usesImpliedEclipseLinkMappingFile()) {
this.setImpliedEclipseLinkMappingFileRef(this.potentialImpliedEclipseLinkMappingFileRef);
this.potentialImpliedEclipseLinkMappingFileRef.update();
}
else {
this.setImpliedEclipseLinkMappingFileRef(null);
//this is needed to unregister the root structure node, how we build the root structure nodes probably needs to change.
this.potentialImpliedEclipseLinkMappingFileRef.dispose();
}
}
/**
* Use the implied EclipseLink mapping file if all the following are true:<ul>
* <li>the properties do not explicitly exclude it
* <li>it is not specified explicitly in the persistence unit
* <li>the file actually exists
* </ul>
*/
private boolean usesImpliedEclipseLinkMappingFile() {
return this.impliedEclipseLinkMappingFileIsNotExcluded() &&
this.impliedEclipseLinkMappingFileIsNotSpecified() &&
this.impliedEclipseLinkMappingFileExists();
}
protected boolean impliedEclipseLinkMappingFileIsNotExcluded() {
return ! this.impliedEclipseLinkMappingFileIsExcluded();
}
protected boolean impliedEclipseLinkMappingFileIsExcluded() {
return this.getGeneralProperties().getExcludeEclipselinkOrm() == Boolean.TRUE;
}
protected boolean impliedEclipseLinkMappingFileIsNotSpecified() {
return ! this.impliedEclipseLinkMappingFileIsSpecified();
}
protected boolean impliedEclipseLinkMappingFileIsSpecified() {
return this.mappingFileIsSpecified(JptJpaEclipseLinkCorePlugin.DEFAULT_ECLIPSELINK_ORM_XML_RUNTIME_PATH.toString());
}
protected boolean impliedEclipseLinkMappingFileExists() {
return this.getJpaProject().getDefaultEclipseLinkOrmXmlResource() != null;
}
// ********** default tenant discriminator columns **********
/**
* String constant associated with changes to the persistence unit's
* list of default tenant discriminator Columns
*/
public static final String DEFAULT_TENANT_DISCRIMINATOR_COLUMNS_LIST = "defaultTenantDiscriminatorColumns"; //$NON-NLS-1$
public ListIterable<ReadOnlyTenantDiscriminatorColumn2_3> getDefaultTenantDiscriminatorColumns() {
return new LiveCloneListIterable<ReadOnlyTenantDiscriminatorColumn2_3>(this.defaultTenantDiscriminatorColumns);
}
protected void setDefaultTenantDiscriminatorColumns(Iterable<ReadOnlyTenantDiscriminatorColumn2_3> tenantDiscriminatorColumns) {
this.synchronizeList(tenantDiscriminatorColumns, this.defaultTenantDiscriminatorColumns, DEFAULT_TENANT_DISCRIMINATOR_COLUMNS_LIST);
}
protected ListIterable<ReadOnlyTenantDiscriminatorColumn2_3> buildDefaultTenantDiscriminatorColumns(EclipseLinkPersistenceUnitDefaults defaults) {
return (defaults == null) ? EmptyListIterable.<ReadOnlyTenantDiscriminatorColumn2_3> instance() : new SuperListIterableWrapper<ReadOnlyTenantDiscriminatorColumn2_3>(defaults.getTenantDiscriminatorColumns());
}
// ********** converters **********
/**
* String constant associated with changes to the persistence unit's
* collection of "global" converters.
*/
public static final String CONVERTERS_COLLECTION = "converters"; //$NON-NLS-1$
/**
* Return the "active" converters defined within the persistence unit's scope,
* including converters with duplicate names. "Active" converters are:<ul>
* <li>any converter defined in mapping files
* <li>any converter defined via Java annotations that is not "overridden"
* by a mapping file converter with the same name
* </ul>
* <strong>NB:</strong> A Java converter defined on a class or attribute
* that is overridden in a mapping file is <em>not</em>, as a result,
* itself overridden. A Java converter can only be overridden by a mapping
* file converter with the same name.
* <p>
* <strong>NB:</strong> A Java converter defined on a class or attribute
* whose corresponding mapping file mapping (or mapping file) is marked
* "metadata complete" is ignored.
*/
// TODO bjv change to getConverterNames() etc.
public Iterable<EclipseLinkConverter> getAllConverters() {
return this.getConverters();
}
public Iterable<EclipseLinkConverter> getConverters() {
return new LiveCloneIterable<EclipseLinkConverter>(this.converters);
}
public int getConvertersSize() {
return this.converters.size();
}
/**
* Return the names of the "active" converters defined in the persistence
* unit's scope, with duplicates removed.
*/
public Iterable<String> getUniqueConverterNames() {
return CollectionTools.set(this.getNonEmptyConverterNames(), this.getConvertersSize());
}
protected Iterable<String> getNonEmptyConverterNames() {
return new FilteringIterable<String>(this.getConverterNames(), NonEmptyStringFilter.instance());
}
protected Iterable<String> getConverterNames() {
return new TransformationIterable<EclipseLinkConverter, String>(this.getConverters(), JpaNamedContextNode.NameTransformer.<EclipseLinkConverter>instance());
}
protected void setConverters(Iterable<EclipseLinkConverter> converters) {
this.synchronizeCollection(converters, this.converters, CONVERTERS_COLLECTION);
}
/**
* Converters are much like queries.
* @see #buildQueries()
*/
protected Iterable<EclipseLinkConverter> buildConverters() {
ArrayList<EclipseLinkConverter> result = CollectionTools.list(this.getMappingFileConverters());
HashSet<String> mappingFileConverterNames = this.convertToNames(result);
HashMap<String, ArrayList<JavaEclipseLinkConverter<?>>> javaConverters = this.mapByName(this.getAllJavaConverters());
for (Map.Entry<String, ArrayList<JavaEclipseLinkConverter<?>>> entry : javaConverters.entrySet()) {
if ( ! mappingFileConverterNames.contains(entry.getKey())) {
result.addAll(entry.getValue());
}
}
return result;
}
protected Iterable<EclipseLinkConverter> getMappingFileConverters() {
return new CompositeIterable<EclipseLinkConverter>(this.getMappingFileConverterLists());
}
protected Iterable<Iterable<EclipseLinkConverter>> getMappingFileConverterLists() {
return new TransformationIterable<MappingFile, Iterable<EclipseLinkConverter>>(this.getMappingFiles()) {
@Override
protected Iterable<EclipseLinkConverter> transform(MappingFile mappingFile) {
MappingFileRoot root = mappingFile.getRoot();
return (root instanceof EclipseLinkEntityMappings) ?
((EclipseLinkEntityMappings) root).getMappingFileConverters() :
EmptyIterable.<EclipseLinkConverter>instance();
}
};
}
/**
* Include "overridden" Java converters.
*/
public Iterable<JavaEclipseLinkConverter<?>> getAllJavaConverters() {
return new CompositeIterable<JavaEclipseLinkConverter<?>>(this.getAllJavaTypeMappingConverterLists());
}
protected Iterable<Iterable<JavaEclipseLinkConverter<?>>> getAllJavaTypeMappingConverterLists() {
return new TransformationIterable<TypeMapping, Iterable<JavaEclipseLinkConverter<?>>>(this.getAllJavaTypeMappingsUnique()) {
@Override
protected Iterable<JavaEclipseLinkConverter<?>> transform(TypeMapping typeMapping) {
return new SubIterableWrapper<EclipseLinkConverter, JavaEclipseLinkConverter<?>>(this.transform_(typeMapping));
}
protected Iterable<EclipseLinkConverter> transform_(TypeMapping typeMapping) {
// Java "null" type mappings are not EclipseLink mappings
return (typeMapping instanceof EclipseLinkTypeMapping) ?
((EclipseLinkTypeMapping) typeMapping).getConverters() :
EmptyIterable.<EclipseLinkConverter>instance();
}
};
}
// ********** misc **********
@Override
public EclipseLinkJpaProject getJpaProject() {
return (EclipseLinkJpaProject) super.getJpaProject();
}
@Override
public EclipseLinkPersistenceXmlContextNodeFactory getContextNodeFactory() {
return (EclipseLinkPersistenceXmlContextNodeFactory) super.getContextNodeFactory();
}
@Override
public void setSpecifiedSharedCacheMode(SharedCacheMode specifiedSharedCacheMode) {
super.setSpecifiedSharedCacheMode(specifiedSharedCacheMode);
if(specifiedSharedCacheMode == SharedCacheMode.NONE) {
this.caching.removeDefaultCachingProperties();
}
}
@Override
protected SharedCacheMode buildDefaultSharedCacheMode() {
return SharedCacheMode.DISABLE_SELECTIVE;
}
@Override
public boolean calculateDefaultCacheable() {
SharedCacheMode sharedCacheMode = this.getSharedCacheMode();
if (sharedCacheMode == null) {
return true;
}
switch (sharedCacheMode) {
case NONE:
case ENABLE_SELECTIVE:
return false;
case ALL:
case DISABLE_SELECTIVE:
case UNSPECIFIED:
return true;
}
return true;
}
public String getDefaultGetMethod() {
return this.defaultGetMethod;
}
protected void setDefaultGetMethod(String getMethod) {
String old = this.defaultGetMethod;
this.defaultGetMethod = getMethod;
this.firePropertyChanged(DEFAULT_GET_METHOD_PROPERTY, old, getMethod);
}
/**
* String constant associated with changes to the persistence unit's
* default get method.
*/
public static final String DEFAULT_GET_METHOD_PROPERTY = "defaultGetMethod"; //$NON-NLS-1$
protected String buildDefaultGetMethod(EclipseLinkPersistenceUnitDefaults defaults) {
String getMethod = (defaults == null) ? null : defaults.getGetMethod();
return (getMethod != null) ? getMethod : null;
}
public String getDefaultSetMethod() {
return this.defaultSetMethod;
}
protected void setDefaultSetMethod(String setMethod) {
String old = this.defaultSetMethod;
this.defaultSetMethod = setMethod;
this.firePropertyChanged(DEFAULT_SET_METHOD_PROPERTY, old, setMethod);
}
/**
* String constant associated with changes to the persistence unit's
* default set method.
*/
public static final String DEFAULT_SET_METHOD_PROPERTY = "defaultSetMethod"; //$NON-NLS-1$
protected String buildDefaultSetMethod(EclipseLinkPersistenceUnitDefaults defaults) {
String setMethod = (defaults == null) ? null : defaults.getSetMethod();
return (setMethod != null) ? setMethod : null;
}
public Iterable<String> getEclipseLinkDynamicPersistentTypeNames() {
return new TransformationIterable<EclipseLinkOrmPersistentType, String>(this.getEclipseLinkDynamicPersistentTypes()) {
@Override
protected String transform(EclipseLinkOrmPersistentType type) {
return type.getName();
}
};
}
public Iterable<EclipseLinkOrmPersistentType> getEclipseLinkDynamicPersistentTypes() {
return new FilteringIterable<EclipseLinkOrmPersistentType>(this.getEclipseLinkOrmPersistentTypes()) {
@Override
protected boolean accept(EclipseLinkOrmPersistentType pType) {
return pType.isDynamic();
}
};
}
public Iterable<EclipseLinkOrmPersistentType> getEclipseLinkOrmPersistentTypes() {
return new TransformationIterable<PersistentType, EclipseLinkOrmPersistentType>(
new FilteringIterable<PersistentType>(this.getMappingFilePersistentTypes()) {
@Override
protected boolean accept(PersistentType pType) {
return pType instanceof EclipseLinkOrmPersistentType;
}
}) {
@Override
protected EclipseLinkOrmPersistentType transform(PersistentType pType) {
return (EclipseLinkOrmPersistentType) pType;
}
};
}
// ********** validation **********
public JpaJpqlQueryHelper createJpqlQueryHelper() {
return new EclipseLinkJpaJpqlQueryHelper(this.getJpaPlatform().getJpqlGrammar());
}
@Override
public void validate(List<IMessage> messages, IReporter reporter) {
super.validate(messages, reporter);
this.validateConverters(messages, reporter);
}
@Override
protected void validateProperties(List<IMessage> messages, IReporter reporter) {
if(this.isJpa2_0Compatible()) {
for(Property property: this.getLegacyEntityCachingProperties()) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.NORMAL_SEVERITY,
EclipseLinkJpaValidationMessages.PERSISTENCE_UNIT_LEGACY_ENTITY_CACHING,
new String[] {property.getName()},
this.getPersistenceUnit(),
property.getValidationTextRange()
)
);
}
for(Property property: this.getLegacyDescriptorCustomizerProperties()) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.NORMAL_SEVERITY,
EclipseLinkJpaValidationMessages.PERSISTENCE_UNIT_LEGACY_DESCRIPTOR_CUSTOMIZER,
new String[] {property.getName()},
this.getPersistenceUnit(),
property.getValidationTextRange()
)
);
}
this.validateDefaultCachingProperty(this.getCacheTypeDefaultProperty(), messages);
this.validateDefaultCachingProperty(this.getCacheSizeDefaultProperty(), messages);
this.validateDefaultCachingProperty(this.getFlushClearCacheProperty(), messages);
this.validateLoggerProperty(this.getLoggerProperty(), messages);
this.validateExceptionHandlerProperty(this.getExceptionHandlerProperty(), messages);
this.validatePerformanceProfilerProperty(this.getPerformanceProfilerProperty(), messages);
this.validateSessionCustomizerProperty(this.getSessionCustomizerProperties(), messages);
}
}
protected void validateDefaultCachingProperty(Property cachingProperty, List<IMessage> messages) {
if(this.getSharedCacheMode() == SharedCacheMode.NONE) {
if(cachingProperty != null) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.NORMAL_SEVERITY,
EclipseLinkJpaValidationMessages.PERSISTENCE_UNIT_CACHING_PROPERTY_IGNORED,
new String[] {cachingProperty.getName()},
this.getPersistenceUnit(),
cachingProperty.getValidationTextRange()
)
);
}
}
}
protected void validateLoggerProperty(Property loggerProperty, List<IMessage> messages) {
if ((loggerProperty == null) || (loggerProperty.getValue() == null) ) {
return;
}
if (ArrayTools.contains(Logging.RESERVED_LOGGER_NAMES, loggerProperty.getValue())) {
return;
}
IJavaProject javaProject = getJpaProject().getJavaProject();
if (StringTools.stringIsEmpty(loggerProperty.getValue())) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
EclipseLinkJpaValidationMessages.SESSION_LOGGER_CLASS_NOT_SPECIFIED,
EMPTY_STRING_ARRAY,
this.getPersistenceUnit(),
loggerProperty.getValidationTextRange()
)
);
} else if (JDTTools.findType(javaProject, loggerProperty.getValue()) == null) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
EclipseLinkJpaValidationMessages.SESSION_LOGGER_CLASS_NOT_EXIST,
new String[] {loggerProperty.getValue()},
this.getPersistenceUnit(),
loggerProperty.getValidationTextRange()
)
);
} else if (!JDTTools.typeIsSubType(
javaProject, loggerProperty.getValue(), Logging.ECLIPSELINK_LOGGER_CLASS_NAME)
) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
EclipseLinkJpaValidationMessages.SESSION_LOGGER_CLASS_IMPLEMENTS_SESSION_LOG,
new String[] {loggerProperty.getValue()},
this.getPersistenceUnit(),
loggerProperty.getValidationTextRange()
)
);
}
}
private void validateExceptionHandlerProperty(Property handlerProperty, List<IMessage> messages) {
if ((handlerProperty == null) || (handlerProperty.getValue() == null) ) {
return;
}
IJavaProject javaProject = getJpaProject().getJavaProject();
if (StringTools.stringIsEmpty(handlerProperty.getValue())) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
EclipseLinkJpaValidationMessages.EXCEPTION_HANDLER_CLASS_NOT_SPECIFIED,
EMPTY_STRING_ARRAY,
this.getPersistenceUnit(),
handlerProperty.getValidationTextRange()
)
);
} else if (JDTTools.findType(javaProject, handlerProperty.getValue()) == null) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
EclipseLinkJpaValidationMessages.EXCEPTION_HANDLER_CLASS_NOT_EXIST,
new String[] {handlerProperty.getValue()},
this.getPersistenceUnit(),
handlerProperty.getValidationTextRange()
)
);
} else if (!JDTTools.classHasPublicZeroArgConstructor(javaProject, handlerProperty.getValue())) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
EclipseLinkJpaValidationMessages.EXCEPTION_HANDLER_CLASS_NOT_VALID,
new String[] {handlerProperty.getValue()},
this.getPersistenceUnit(),
handlerProperty.getValidationTextRange()
)
);
} else if (!JDTTools.typeIsSubType(
javaProject, handlerProperty.getValue(), Customization.ECLIPSELINK_EXCEPTION_HANDLER_CLASS_NAME)
) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
EclipseLinkJpaValidationMessages.EXCEPTION_HANDLER_CLASS_IMPLEMENTS_EXCEPTION_HANDLER,
new String[] {handlerProperty.getValue()},
this.getPersistenceUnit(),
handlerProperty.getValidationTextRange()
)
);
}
}
private void validatePerformanceProfilerProperty(Property profilerProperty, List<IMessage> messages) {
if ((profilerProperty == null) || (profilerProperty.getValue() == null) ) {
return;
}
if (ArrayTools.contains(Customization.RESERVED_PROFILER_NAMES, profilerProperty.getValue())) {
return;
}
IJavaProject javaProject = getJpaProject().getJavaProject();
if (StringTools.stringIsEmpty(profilerProperty.getValue())) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
EclipseLinkJpaValidationMessages.SESSION_PROFILER_CLASS_NOT_SPECIFIED,
EMPTY_STRING_ARRAY,
this.getPersistenceUnit(),
profilerProperty.getValidationTextRange()
)
);
} else if (JDTTools.findType(javaProject, profilerProperty.getValue()) == null) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
EclipseLinkJpaValidationMessages.SESSION_PROFILER_CLASS_NOT_EXIST,
new String[] {profilerProperty.getValue()},
this.getPersistenceUnit(),
profilerProperty.getValidationTextRange()
)
);
} else if (!JDTTools.classHasPublicZeroArgConstructor(javaProject, profilerProperty.getValue())){
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
EclipseLinkJpaValidationMessages.SESSION_PROFILER_CLASS_NOT_VALID,
new String[] {profilerProperty.getValue()},
this.getPersistenceUnit(),
profilerProperty.getValidationTextRange()
)
);
} else if (!JDTTools.typeIsSubType(
javaProject, profilerProperty.getValue(), Customization.ECLIPSELINK_SESSION_PROFILER_CLASS_NAME)
) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
EclipseLinkJpaValidationMessages.SESSION_PROFILER_CLASS_IMPLEMENTS_SESSIONP_ROFILER,
new String[] {profilerProperty.getValue()},
this.getPersistenceUnit(),
profilerProperty.getValidationTextRange()
)
);
}
}
private void validateSessionCustomizerProperty( Iterable<Property> properties, List<IMessage> messages) {
for (Property property : properties) {
if (property.getValue() == null) {
return;
}
IJavaProject javaProject = getJpaProject().getJavaProject();
if (StringTools.stringIsEmpty(property.getValue())) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
EclipseLinkJpaValidationMessages.SESSION_CUSTOMIZER_CLASS_NOT_SPECIFIED,
EMPTY_STRING_ARRAY,
this.getPersistenceUnit(),
property.getValidationTextRange()
)
);
} else if (JDTTools.findType(javaProject, property.getValue()) == null) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
EclipseLinkJpaValidationMessages.SESSION_CUSTOMIZER_CLASS_NOT_EXIST,
new String[] {property.getValue()},
this.getPersistenceUnit(),
property.getValidationTextRange()
)
);
} else if (!JDTTools.classHasPublicZeroArgConstructor(javaProject, property.getValue())){
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
EclipseLinkJpaValidationMessages.SESSION_CUSTOMIZER_CLASS_NOT_VALID,
new String[] {property.getValue()},
this.getPersistenceUnit(),
property.getValidationTextRange()
)
);
} else if (!JDTTools.typeIsSubType(
javaProject, property.getValue(), Customization.ECLIPSELINK_SESSION_CUSTOMIZER_CLASS_NAME)
) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
EclipseLinkJpaValidationMessages.SESSION_CUSTOMIZER_CLASS_IMPLEMENTS_SESSION_CUSTOMIZER,
new String[] {property.getValue()},
this.getPersistenceUnit(),
property.getValidationTextRange()
)
);
}
}
}
protected ArrayList<Property> getLegacyDescriptorCustomizerProperties() {
ArrayList<Property> result = new ArrayList<Property>();
CollectionTools.addAll(result, this.getDescriptorCustomizerProperties());
return result;
}
protected ArrayList<Property> getLegacyEntityCachingProperties() {
ArrayList<Property> result = new ArrayList<Property>();
CollectionTools.addAll(result, this.getSharedCacheProperties());
CollectionTools.addAll(result, this.getEntityCacheTypeProperties());
CollectionTools.addAll(result, this.getEntityCacheSizeProperties());
return result;
}
private Property getCacheTypeDefaultProperty() {
return this.getProperty(Caching.ECLIPSELINK_CACHE_TYPE_DEFAULT);
}
private Property getCacheSizeDefaultProperty() {
return this.getProperty(Caching.ECLIPSELINK_CACHE_SIZE_DEFAULT);
}
private Property getCacheSharedDefaultProperty() {
return this.getProperty(Caching.ECLIPSELINK_CACHE_SHARED_DEFAULT);
}
private Property getFlushClearCacheProperty() {
return this.getProperty(Caching.ECLIPSELINK_FLUSH_CLEAR_CACHE);
}
/**
* Returns all Shared Cache Properties, including Entity and default.
*/
private Iterable<Property> getSharedCacheProperties() {
return this.getPropertiesWithNamePrefix(Caching.ECLIPSELINK_SHARED_CACHE);
}
/**
* Returns Entity Cache Size Properties, excluding default.
*/
private Iterable<Property> getEntityCacheSizeProperties() {
return this.getEntityPropertiesWithPrefix(Caching.ECLIPSELINK_CACHE_SIZE);
}
/**
* Returns Entity Cache Type Properties, excluding default.
*/
private Iterable<Property> getEntityCacheTypeProperties() {
return this.getEntityPropertiesWithPrefix(Caching.ECLIPSELINK_CACHE_TYPE);
}
/**
* Returns Descriptor Customizer Properties.
*/
private Iterable<Property> getDescriptorCustomizerProperties() {
return this.getEntityPropertiesWithPrefix(Customization.ECLIPSELINK_DESCRIPTOR_CUSTOMIZER);
}
/**
* Returns Entity Properties with the given prefix,
* excluding Entity which name equals "default".
*/
private Iterable<Property> getEntityPropertiesWithPrefix(String prefix) {
return new FilteringIterable<Property>(this.getPropertiesWithNamePrefix(prefix)) {
@Override
protected boolean accept(Property next) {
return ! next.getName().endsWith("default"); //$NON-NLS-1$
}
};
}
private Property getLoggerProperty() {
return this.getProperty(Logging.ECLIPSELINK_LOGGER);
}
private Property getExceptionHandlerProperty() {
return this.getProperty(Customization.ECLIPSELINK_EXCEPTION_HANDLER);
}
private Property getPerformanceProfilerProperty() {
return this.getProperty(Customization.ECLIPSELINK_PROFILER);
}
/**
* Returns all Session Customizer Properties.
*/
private Iterable<Property> getSessionCustomizerProperties() {
return this.getPropertiesWithNamePrefix(Customization.ECLIPSELINK_SESSION_CUSTOMIZER);
}
/**
* <strong>NB:</strong> We validate converters here.
* @see #validateGenerators(List, IReporter)
*/
protected void validateConverters(List<IMessage> messages, IReporter reporter) {
this.checkForConvertersWithSameName(messages);
for (EclipseLinkConverter converter : this.getConverters()) {
this.validate(converter, messages, reporter);
}
}
protected void checkForConvertersWithSameName(List<IMessage> messages) {
HashMap<String, ArrayList<EclipseLinkConverter>> convertersByName = this.mapByName(this.getConverters());
for (Map.Entry<String, ArrayList<EclipseLinkConverter>> entry : convertersByName.entrySet()) {
String converterName = entry.getKey();
if (StringTools.stringIsNotEmpty(converterName)) { // ignore empty names
ArrayList<EclipseLinkConverter> dups = entry.getValue();
if (dups.size() > 1) {
this.validateConvertersWithSameName(converterName, dups, messages);
}
}
}
}
/**
* <strong>NB:</strong> Unlike generators and queries, we do not mark
* "equivalent" converters with info messages - we just ignore them
* because they cannot be "portable" (since only EclipseLink has converters).
*/
protected void validateConvertersWithSameName(String converterName, ArrayList<EclipseLinkConverter> dups, List<IMessage> messages) {
String[] parms = new String[] {converterName};
if (this.anyNodesAreInequivalent(dups)) {
for (EclipseLinkConverter dup : dups) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
EclipseLinkJpaValidationMessages.CONVERTER_DUPLICATE_NAME,
parms,
dup,
this.extractNameTextRange(dup)
)
);
}
}
}
/**
* Return whether all the specified nodes are "equivalent"
* (i.e. they all have the same state).
*/
protected boolean allNodesAreEquivalent(ArrayList<? extends JpaNamedContextNode> nodes) {
return ! this.anyNodesAreInequivalent(nodes);
}
protected boolean anyNodesAreInequivalent(ArrayList<? extends JpaNamedContextNode> nodes) {
if (nodes.size() < 2) {
throw new IllegalArgumentException();
}
Iterator<? extends JpaNamedContextNode> stream = nodes.iterator();
JpaNamedContextNode first = stream.next();
while (stream.hasNext()) {
if ( ! stream.next().isEquivalentTo(first)) {
return true;
}
}
return false;
}
// TODO bjv isn't it obvious?
protected TextRange extractNameTextRange(EclipseLinkConverter converter) {
return (converter instanceof OrmEclipseLinkConverter<?>) ?
((OrmEclipseLinkConverter<?>) converter).getNameTextRange() :
((JavaEclipseLinkConverter<?>) converter).getNameTextRange(null);
}
// TODO bjv isn't it obvious?
protected void validate(EclipseLinkConverter converter, List<IMessage> messages, IReporter reporter) {
if (converter instanceof OrmEclipseLinkConverter<?>) {
((OrmEclipseLinkConverter<?>) converter).validate(messages, reporter);
} else {
((JavaEclipseLinkConverter<?>) converter).validate(messages, reporter, null);
}
}
/**
* If all the generators are "equivalent" add info messages;
* otherwise mark them all as duplicates.
*/
@Override
protected void validateGeneratorsWithSameName(String generatorName, ArrayList<Generator> dups, List<IMessage> messages) {
if (this.allNodesAreEquivalent(dups)) {
String[] parms = new String[] {generatorName};
for (Generator dup : dups) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.LOW_SEVERITY,
EclipseLinkJpaValidationMessages.GENERATOR_EQUIVALENT,
parms,
dup,
this.extractNameTextRange(dup)
)
);
}
} else {
super.validateGeneratorsWithSameName(generatorName, dups, messages);
}
}
/**
* @see #validateGeneratorsWithSameName(String, ArrayList, List)
*/
@Override
protected void validateQueriesWithSameName(String queryName, ArrayList<Query> dups, List<IMessage> messages) {
if (this.allNodesAreEquivalent(dups)) {
String[] parms = new String[] {queryName};
for (Query dup : dups) {
messages.add(
DefaultEclipseLinkJpaValidationMessages.buildMessage(
IMessage.LOW_SEVERITY,
EclipseLinkJpaValidationMessages.QUERY_EQUIVALENT,
parms,
dup,
this.extractNameTextRange(dup)
)
);
}
} else {
super.validateQueriesWithSameName(queryName, dups, messages);
}
}
// ********** refactoring **********
@Override
@SuppressWarnings("unchecked")
protected Iterable<ReplaceEdit> createPersistenceUnitPropertiesRenameTypeEdits(IType originalType, String newName) {
return new CompositeIterable<ReplaceEdit>(
super.createPersistenceUnitPropertiesRenameTypeEdits(originalType, newName),
this.customization.createRenameTypeEdits(originalType, newName),
this.logging.createRenameTypeEdits(originalType, newName)
);
}
@Override
@SuppressWarnings("unchecked")
protected Iterable<ReplaceEdit> createPersistenceUnitPropertiesMoveTypeEdits(IType originalType, IPackageFragment newPackage) {
return new CompositeIterable<ReplaceEdit>(
super.createPersistenceUnitPropertiesMoveTypeEdits(originalType, newPackage),
this.customization.createMoveTypeEdits(originalType, newPackage),
this.logging.createMoveTypeEdits(originalType, newPackage)
);
}
@Override
@SuppressWarnings("unchecked")
protected Iterable<ReplaceEdit> createPersistenceUnitPropertiesRenamePackageEdits(IPackageFragment originalPackage, String newName) {
return new CompositeIterable<ReplaceEdit>(
super.createPersistenceUnitPropertiesRenamePackageEdits(originalPackage, newName),
this.customization.createRenamePackageEdits(originalPackage, newName),
this.logging.createRenamePackageEdits(originalPackage, newName)
);
}
// ********** metadata conversion **********
// ***** queries
/**
* @see #convertJavaQueries(EntityMappings, IProgressMonitor)
*/
@Override
public boolean hasConvertibleJavaQueries() {
return ! this.getEclipseLinkConvertibleJavaQueries().isEmpty();
}
/**
* Return whether the persistence unit has any equivalent Java generators.
*/
public boolean hasAnyEquivalentJavaQueries() {
return this.hasAnyEquivalentJavaNodes(this.getAllJavaQueries(), this.getMappingFileQueries());
}
/**
* Override the default implementation because EclipseLink allows
* "equivalent" queries.
*/
@Override
public void convertJavaQueries(EntityMappings entityMappings, IProgressMonitor monitor) {
OrmQueryContainer queryContainer = entityMappings.getQueryContainer();
HashMap<String, ArrayList<JavaQuery>> convertibleJavaQueries = this.getEclipseLinkConvertibleJavaQueries();
int work = this.calculateCumulativeSize(convertibleJavaQueries.values());
SubMonitor sm = SubMonitor.convert(monitor, JptCoreMessages.JAVA_METADATA_CONVERSION_IN_PROGRESS, work);
for (Map.Entry<String, ArrayList<JavaQuery>> entry : convertibleJavaQueries.entrySet()) {
this.convertJavaQueriesWithSameName(queryContainer, entry, sm.newChild(entry.getValue().size()));
}
sm.setTaskName(JptCoreMessages.JAVA_METADATA_CONVERSION_COMPLETE);
}
protected void convertJavaQueriesWithSameName(OrmQueryContainer queryContainer, Map.Entry<String, ArrayList<JavaQuery>> entry, SubMonitor monitor) {
if (monitor.isCanceled()) {
throw new OperationCanceledException(JptCoreMessages.JAVA_METADATA_CONVERSION_CANCELED);
}
monitor.setTaskName(NLS.bind(JptCoreMessages.JAVA_METADATA_CONVERSION_CONVERT_QUERY, entry.getKey()));
ArrayList<JavaQuery> javaQueriesWithSameName = entry.getValue();
JavaQuery first = javaQueriesWithSameName.get(0);
first.convertTo(queryContainer);
first.delete(); // delete any converted queries
monitor.worked(1);
for (int i = 1; i < javaQueriesWithSameName.size(); i++) { // NB: start with 1!
javaQueriesWithSameName.get(i).delete();
monitor.worked(1);
}
}
/**
* @see #extractEclipseLinkConvertibleJavaNodes(Iterable, Iterable)
*/
protected HashMap<String, ArrayList<JavaQuery>> getEclipseLinkConvertibleJavaQueries() {
return this.extractEclipseLinkConvertibleJavaNodes(this.getAllJavaQueries(), this.getMappingFileQueries());
}
// ***** generators
/**
* @see #convertJavaGenerators(EntityMappings, IProgressMonitor)
*/
@Override
public boolean hasConvertibleJavaGenerators() {
return ! this.getEclipseLinkConvertibleJavaGenerators().isEmpty();
}
/**
* Return whether the persistence unit has any equivalent Java generators.
*/
public boolean hasAnyEquivalentJavaGenerators() {
return this.hasAnyEquivalentJavaNodes(this.getAllJavaGenerators(), this.getMappingFileGenerators());
}
/**
* Override the default implementation because EclipseLink allows
* "equivalent" generators.
*/
@Override
public void convertJavaGenerators(EntityMappings entityMappings, IProgressMonitor monitor) {
HashMap<String, ArrayList<JavaGenerator>> convertibleJavaGenerators = this.getEclipseLinkConvertibleJavaGenerators();
int work = this.calculateCumulativeSize(convertibleJavaGenerators.values());
SubMonitor sm = SubMonitor.convert(monitor, JptCoreMessages.JAVA_METADATA_CONVERSION_IN_PROGRESS, work);
for (Map.Entry<String, ArrayList<JavaGenerator>> entry : convertibleJavaGenerators.entrySet()) {
this.convertJavaGeneratorsWithSameName(entityMappings, entry, sm.newChild(entry.getValue().size()));
}
sm.setTaskName(JptCoreMessages.JAVA_METADATA_CONVERSION_COMPLETE);
}
protected void convertJavaGeneratorsWithSameName(EntityMappings entityMappings, Map.Entry<String, ArrayList<JavaGenerator>> entry, SubMonitor monitor) {
if (monitor.isCanceled()) {
throw new OperationCanceledException(JptCoreMessages.JAVA_METADATA_CONVERSION_CANCELED);
}
monitor.setTaskName(NLS.bind(JptCoreMessages.JAVA_METADATA_CONVERSION_CONVERT_GENERATOR, entry.getKey()));
ArrayList<JavaGenerator> javaGeneratorsWithSameName = entry.getValue();
JavaGenerator first = javaGeneratorsWithSameName.get(0);
first.convertTo(entityMappings);
first.delete(); // delete any converted generators
monitor.worked(1);
for (int i = 1; i < javaGeneratorsWithSameName.size(); i++) { // NB: start with 1!
javaGeneratorsWithSameName.get(i).delete();
monitor.worked(1);
}
}
/**
* @see #extractEclipseLinkConvertibleJavaNodes(Iterable, Iterable)
*/
protected HashMap<String, ArrayList<JavaGenerator>> getEclipseLinkConvertibleJavaGenerators() {
return this.extractEclipseLinkConvertibleJavaNodes(this.getAllJavaGenerators(), this.getMappingFileGenerators());
}
// ***** converters
/**
* @see #convertJavaConverters(EclipseLinkEntityMappings, IProgressMonitor)
*/
public boolean hasConvertibleJavaConverters() {
return ! this.getEclipseLinkConvertibleJavaConverters().isEmpty();
}
/**
* Return whether the persistence unit has any equivalent Java generators.
*/
public boolean hasAnyEquivalentJavaConverters() {
return this.hasAnyEquivalentJavaNodes(this.getAllJavaConverters(), this.getMappingFileConverters());
}
/**
* Override the default implementation because EclipseLink allows
* "equivalent" converters.
*/
public void convertJavaConverters(EclipseLinkEntityMappings entityMappings, IProgressMonitor monitor) {
OrmEclipseLinkConverterContainer ormConverterContainer = entityMappings.getConverterContainer();
HashMap<String, ArrayList<JavaEclipseLinkConverter<?>>> convertibleJavaConverters = this.getEclipseLinkConvertibleJavaConverters();
int work = this.calculateCumulativeSize(convertibleJavaConverters.values());
SubMonitor sm = SubMonitor.convert(monitor, JptCoreMessages.JAVA_METADATA_CONVERSION_IN_PROGRESS, work);
for (Map.Entry<String, ArrayList<JavaEclipseLinkConverter<?>>> entry : convertibleJavaConverters.entrySet()) {
this.convertJavaConvertersWithSameName(ormConverterContainer, entry, sm.newChild(entry.getValue().size()));
}
sm.setTaskName(JptCoreMessages.JAVA_METADATA_CONVERSION_COMPLETE);
}
protected void convertJavaConvertersWithSameName(OrmEclipseLinkConverterContainer ormConverterContainer, Map.Entry<String, ArrayList<JavaEclipseLinkConverter<?>>> entry, SubMonitor monitor) {
if (monitor.isCanceled()) {
throw new OperationCanceledException(JptCoreMessages.JAVA_METADATA_CONVERSION_CANCELED);
}
monitor.setTaskName(NLS.bind(JptJpaEclipseLinkCoreMessages.JAVA_METADATA_CONVERSION_CONVERT_CONVERTER, entry.getKey()));
ArrayList<JavaEclipseLinkConverter<?>> javaConvertersWithSameName = entry.getValue();
JavaEclipseLinkConverter<?> first = javaConvertersWithSameName.get(0);
first.convertTo(ormConverterContainer);
first.delete(); // delete any converted generators
monitor.worked(1);
for (int i = 1; i < javaConvertersWithSameName.size(); i++) { // NB: start with 1!
javaConvertersWithSameName.get(i).delete();
monitor.worked(1);
}
}
/**
* @see #extractEclipseLinkConvertibleJavaNodes(Iterable, Iterable)
*/
protected HashMap<String, ArrayList<JavaEclipseLinkConverter<?>>> getEclipseLinkConvertibleJavaConverters() {
return this.extractEclipseLinkConvertibleJavaNodes(this.getAllJavaConverters(), this.getMappingFileConverters());
}
protected int calculateCumulativeSize(Collection<? extends Collection<?>> collections) {
int cumulativeSize = 0;
for (Collection<?> collection : collections) {
cumulativeSize += collection.size();
}
return cumulativeSize;
}
protected <N extends JpaNamedContextNode> boolean hasAnyEquivalentJavaNodes(Iterable<N> allJavaNodes, Iterable<? extends JpaNamedContextNode> mappingFileNodes) {
HashMap<String, ArrayList<N>> convertibleJavaNodes = this.extractEclipseLinkConvertibleJavaNodes(allJavaNodes, mappingFileNodes);
for (Map.Entry<String, ArrayList<N>> entry : convertibleJavaNodes.entrySet()) {
if (entry.getValue().size() > 1) {
return true;
}
}
return false;
}
/**
* Return the Java nodes that are neither overridden nor duplicated
* (by default any Java nodes with the same name are "duplicates");
* but, in EclipseLink we return any "equivalent" nodes also.
*/
protected <N extends JpaNamedContextNode> HashMap<String, ArrayList<N>> extractEclipseLinkConvertibleJavaNodes(Iterable<N> allJavaNodes, Iterable<? extends JpaNamedContextNode> mappingFileNodes) {
HashMap<String, ArrayList<N>> convertibleNodes = new HashMap<String, ArrayList<N>>();
HashSet<String> mappingFileNodeNames = this.convertToNames(CollectionTools.list(mappingFileNodes));
HashMap<String, ArrayList<N>> allJavaNodesByName = this.mapByName(allJavaNodes);
for (Map.Entry<String, ArrayList<N>> entry : allJavaNodesByName.entrySet()) {
String javaNodeName = entry.getKey();
if (StringTools.stringIsEmpty(javaNodeName)) {
continue; // ignore any nodes with an empty name(?)
}
if (mappingFileNodeNames.contains(javaNodeName)) {
continue; // ignore any Java nodes overridden in the mapping file
}
ArrayList<N> javaNodesWithSameName = entry.getValue();
if ((javaNodesWithSameName.size() == 1) || this.allNodesAreEquivalent(javaNodesWithSameName)) {
convertibleNodes.put(javaNodeName, javaNodesWithSameName);
} else {
// ignore multiple Java nodes with the same name but that are not all "equivalent"
}
}
return convertibleNodes;
}
}