| /******************************************************************************* |
| * 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.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.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 |
| { |
| 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$ |
| |
| |
| 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); |
| } |
| |
| |
| // ********** 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 MappingFileRef addImpliedEclipseLinkMappingFileRef() { |
| if (this.impliedEclipseLinkMappingFileRef != null) { |
| throw new IllegalStateException("The implied EclipseLink mapping file ref is already present: " + this.impliedEclipseLinkMappingFileRef); //$NON-NLS-1$ |
| } |
| MappingFileRef mappingFileRef = this.buildEclipseLinkImpliedMappingFileRef(); |
| this.impliedEclipseLinkMappingFileRef = mappingFileRef; |
| this.firePropertyChanged(IMPLIED_ECLIPSELINK_MAPPING_FILE_REF_PROPERTY, null, mappingFileRef); |
| return mappingFileRef; |
| } |
| |
| private ImpliedMappingFileRef buildEclipseLinkImpliedMappingFileRef() { |
| return new ImpliedMappingFileRef(this, JptJpaEclipseLinkCorePlugin.DEFAULT_ECLIPSELINK_ORM_XML_RUNTIME_PATH.toString()); |
| } |
| |
| protected void removeImpliedEclipseLinkMappingFileRef() { |
| if (this.impliedEclipseLinkMappingFileRef == null) { |
| throw new IllegalStateException("The implied EclipseLink mapping file ref is null."); //$NON-NLS-1$ |
| } |
| MappingFileRef mappingFileRef = this.impliedEclipseLinkMappingFileRef; |
| this.impliedEclipseLinkMappingFileRef.dispose(); |
| this.impliedEclipseLinkMappingFileRef = null; |
| this.firePropertyChanged(IMPLIED_ECLIPSELINK_MAPPING_FILE_REF_PROPERTY, mappingFileRef, null); |
| } |
| |
| @Override |
| protected void syncImpliedMappingFileRef() { |
| super.syncImpliedMappingFileRef(); |
| if (this.impliedEclipseLinkMappingFileRef != null) { |
| this.impliedEclipseLinkMappingFileRef.synchronizeWithResourceModel(); |
| } |
| } |
| |
| @Override |
| protected void updateImpliedMappingFileRef() { |
| super.updateImpliedMappingFileRef(); |
| |
| if (this.buildsImpliedEclipseLinkMappingFile()) { |
| if (this.impliedEclipseLinkMappingFileRef == null) { |
| this.addImpliedEclipseLinkMappingFileRef(); |
| } else { |
| this.impliedEclipseLinkMappingFileRef.update(); |
| } |
| } else { |
| if (this.impliedEclipseLinkMappingFileRef != null) { |
| this.removeImpliedEclipseLinkMappingFileRef(); |
| } |
| } |
| } |
| |
| /** |
| * Build a virtual 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 buildsImpliedEclipseLinkMappingFile() { |
| 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; |
| } |
| |
| public 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; |
| } |
| |
| // ********** 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.checkForDuplicateConverters(messages); |
| for (EclipseLinkConverter converter : this.getConverters()) { |
| this.validate(converter, messages, reporter); |
| } |
| } |
| |
| protected void checkForDuplicateConverters(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) { |
| // if duplicate name exists, check the types of the converters with the duplicate name |
| HashMap<Class<? extends JpaNamedContextNode>, ArrayList<EclipseLinkConverter>> convertersByType = this.mapByType(dups); |
| // if more than one types of converters have the same name, |
| // report duplicate error on every converter in the list; |
| if (convertersByType.size() > 1) { |
| String[] parms = new String[] {converterName}; |
| for (EclipseLinkConverter dup : dups) { |
| messages.add( |
| DefaultEclipseLinkJpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| EclipseLinkJpaValidationMessages.CONVERTER_DUPLICATE_NAME, |
| parms, |
| dup, |
| this.extractNameTextRange(dup) |
| ) |
| ); |
| } |
| } else { |
| // otherwise if all the converters are with the same type, check every converter |
| // to see if its definition is not equivalent with any one of the converters in the list; |
| // if any one of the converters is NOT equivalent, add errors for all of them; otherwise do nothing |
| if (this.anyNodesAreInequivalent(dups)) { |
| String[] parms = new String[] {converterName}; |
| 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); |
| } |
| } |
| |
| @Override |
| protected void checkForDuplicateGenerators(List<IMessage> messages) { |
| HashMap<String, ArrayList<Generator>> generatorsByName = this.mapByName(this.getGenerators()); |
| for (Map.Entry<String, ArrayList<Generator>> entry : generatorsByName.entrySet()) { |
| String generatorName = entry.getKey(); |
| if (StringTools.stringIsNotEmpty(generatorName)) { // ignore empty names |
| ArrayList<Generator> dups = entry.getValue(); |
| if (dups.size() > 1) { |
| // if duplicate name exists, check the types of the generators with the duplicate name |
| HashMap<Class<? extends JpaNamedContextNode>, ArrayList<Generator>> generatorsByType = this.mapByType(dups); |
| // if more than one types of generators have the same name, |
| // report duplicate error on every generator in the list; |
| if (generatorsByType.size() > 1) { |
| String[] parms = new String[] {generatorName}; |
| for (Generator dup : dups) { |
| messages.add( |
| DefaultEclipseLinkJpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| EclipseLinkJpaValidationMessages.GENERATOR_DUPLICATE_NAME, |
| parms, |
| dup, |
| this.extractNameTextRange(dup) |
| ) |
| ); |
| } |
| } else { |
| // if all the generators are "equivalent", add info 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 { |
| // otherwise if all the generators are with the same type, check every generator |
| // to see if its definition is not equivalent with any one of the generators in the list; |
| // if any one of the generators is NOT equivalent, add errors for all of them; otherwise do nothing |
| String[] parms = new String[] {generatorName}; |
| for (Generator dup : dups) { |
| messages.add( |
| DefaultEclipseLinkJpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| EclipseLinkJpaValidationMessages.GENERATOR_DUPLICATE_NAME, |
| parms, |
| dup, |
| this.extractNameTextRange(dup) |
| ) |
| ); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| @Override |
| protected void checkForDuplicateQueries(List<IMessage> messages) { |
| HashMap<String, ArrayList<Query>> queriesByName = this.mapByName(this.getQueries()); |
| for (Map.Entry<String, ArrayList<Query>> entry : queriesByName.entrySet()) { |
| String queryName = entry.getKey(); |
| if (StringTools.stringIsNotEmpty(queryName)) { // ignore empty names |
| ArrayList<Query> dups = entry.getValue(); |
| if (dups.size() > 1) { |
| // if duplicate name exists, check the types of the queries with the duplicate name |
| HashMap<Class<? extends JpaNamedContextNode>, ArrayList<Query>> querisByType = this.mapByType(dups); |
| // if more than one types of queries have the same name, |
| // report duplicate error on every query in the list; |
| if (querisByType.size() > 1) { |
| String[] parms = new String[] {queryName}; |
| for (Query dup : dups) { |
| messages.add( |
| DefaultEclipseLinkJpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| EclipseLinkJpaValidationMessages.QUERY_DUPLICATE_NAME, |
| parms, |
| dup, |
| this.extractNameTextRange(dup) |
| ) |
| ); |
| } |
| } else { |
| // if all the queries are "equivalent", add info 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 { |
| // otherwise if all the queries are with the same type, check every query |
| // to see if its definition is not equivalent with any one of the queries in the list; |
| // if any one of the queries is NOT equivalent, add errors for all of them; otherwise do nothing |
| String[] parms = new String[] {queryName}; |
| for (Query dup : dups) { |
| messages.add( |
| DefaultEclipseLinkJpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| EclipseLinkJpaValidationMessages.QUERY_DUPLICATE_NAME, |
| parms, |
| dup, |
| this.extractNameTextRange(dup) |
| ) |
| ); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| protected <N extends JpaNamedContextNode> HashMap<Class<? extends JpaNamedContextNode>, ArrayList<N>> mapByType(Iterable<N> nodes) { |
| HashMap<Class<? extends JpaNamedContextNode>, ArrayList<N>> map = new HashMap<Class<? extends JpaNamedContextNode>, ArrayList<N>>(); |
| for (N node : nodes) { |
| Class<? extends JpaNamedContextNode> type = node.getType(); |
| ArrayList<N> list = map.get(type); |
| if (list == null) { |
| list = new ArrayList<N>(); |
| map.put(type, list); |
| } |
| list.add(node); |
| } |
| return map; |
| } |
| |
| // ********** 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.JPA_METADATA_CONVERSION_CONVERTING, work); |
| for (Map.Entry<String, ArrayList<JavaQuery>> entry : convertibleJavaQueries.entrySet()) { |
| this.convertJavaQueriesWithSameName(queryContainer, entry, sm.newChild(entry.getValue().size())); |
| } |
| sm.setTaskName(JptCoreMessages.JPA_METADATA_CONVERSION_OPERATION_COMPLETE); |
| } |
| |
| protected void convertJavaQueriesWithSameName(OrmQueryContainer queryContainer, Map.Entry<String, ArrayList<JavaQuery>> entry, SubMonitor monitor) { |
| if (monitor.isCanceled()) { |
| throw new OperationCanceledException(JptCoreMessages.JPA_METADATA_CONVERSION_OPERATION_CANCELED); |
| } |
| monitor.setTaskName(NLS.bind(JptCoreMessages.JPA_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.JPA_METADATA_CONVERSION_CONVERTING, work); |
| for (Map.Entry<String, ArrayList<JavaGenerator>> entry : convertibleJavaGenerators.entrySet()) { |
| this.convertJavaGeneratorsWithSameName(entityMappings, entry, sm.newChild(entry.getValue().size())); |
| } |
| sm.setTaskName(JptCoreMessages.JPA_METADATA_CONVERSION_OPERATION_COMPLETE); |
| } |
| |
| protected void convertJavaGeneratorsWithSameName(EntityMappings entityMappings, Map.Entry<String, ArrayList<JavaGenerator>> entry, SubMonitor monitor) { |
| if (monitor.isCanceled()) { |
| throw new OperationCanceledException(JptCoreMessages.JPA_METADATA_CONVERSION_OPERATION_CANCELED); |
| } |
| monitor.setTaskName(NLS.bind(JptCoreMessages.JPA_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.JPA_METADATA_CONVERSION_CONVERTING, work); |
| for (Map.Entry<String, ArrayList<JavaEclipseLinkConverter<?>>> entry : convertibleJavaConverters.entrySet()) { |
| this.convertJavaConvertersWithSameName(ormConverterContainer, entry, sm.newChild(entry.getValue().size())); |
| } |
| sm.setTaskName(JptCoreMessages.JPA_METADATA_CONVERSION_OPERATION_COMPLETE); |
| } |
| |
| protected void convertJavaConvertersWithSameName(OrmEclipseLinkConverterContainer ormConverterContainer, Map.Entry<String, ArrayList<JavaEclipseLinkConverter<?>>> entry, SubMonitor monitor) { |
| if (monitor.isCanceled()) { |
| throw new OperationCanceledException(JptCoreMessages.JPA_METADATA_CONVERSION_OPERATION_CANCELED); |
| } |
| monitor.setTaskName(NLS.bind(JptJpaEclipseLinkCoreMessages.JPA_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; |
| } |
| } |