| /******************************************************************************* |
| * Copyright (c) 2007, 2010 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.core.internal.context.persistence; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.ListIterator; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.Vector; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jpt.core.JpaProject; |
| import org.eclipse.jpt.core.JpaStructureNode; |
| import org.eclipse.jpt.core.JptCorePlugin; |
| import org.eclipse.jpt.core.context.AccessType; |
| import org.eclipse.jpt.core.context.Embeddable; |
| import org.eclipse.jpt.core.context.Entity; |
| import org.eclipse.jpt.core.context.Generator; |
| import org.eclipse.jpt.core.context.MappingFilePersistenceUnitDefaults; |
| import org.eclipse.jpt.core.context.PersistentAttribute; |
| import org.eclipse.jpt.core.context.PersistentType; |
| import org.eclipse.jpt.core.context.Query; |
| import org.eclipse.jpt.core.context.TypeMapping; |
| import org.eclipse.jpt.core.context.persistence.ClassRef; |
| import org.eclipse.jpt.core.context.persistence.JarFileRef; |
| import org.eclipse.jpt.core.context.persistence.MappingFileRef; |
| import org.eclipse.jpt.core.context.persistence.Persistence; |
| import org.eclipse.jpt.core.context.persistence.PersistenceStructureNodes; |
| import org.eclipse.jpt.core.context.persistence.PersistenceUnit; |
| import org.eclipse.jpt.core.context.persistence.PersistenceUnitProperties; |
| import org.eclipse.jpt.core.context.persistence.PersistenceUnitTransactionType; |
| import org.eclipse.jpt.core.context.persistence.PersistentTypeContainer; |
| import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; |
| import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; |
| import org.eclipse.jpt.core.jpa2.JpaFactory2_0; |
| import org.eclipse.jpt.core.jpa2.JpaProject2_0; |
| import org.eclipse.jpt.core.jpa2.context.MappingFilePersistenceUnitDefaults2_0; |
| import org.eclipse.jpt.core.jpa2.context.MetamodelSourceType; |
| import org.eclipse.jpt.core.jpa2.context.PersistentType2_0; |
| import org.eclipse.jpt.core.jpa2.context.persistence.PersistenceUnit2_0; |
| import org.eclipse.jpt.core.jpa2.context.persistence.options.SharedCacheMode; |
| import org.eclipse.jpt.core.jpa2.context.persistence.options.ValidationMode; |
| import org.eclipse.jpt.core.jpa2.resource.java.JavaResourcePersistentType2_0; |
| import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType; |
| import org.eclipse.jpt.core.resource.persistence.PersistenceFactory; |
| import org.eclipse.jpt.core.resource.persistence.XmlJarFileRef; |
| import org.eclipse.jpt.core.resource.persistence.XmlJavaClassRef; |
| import org.eclipse.jpt.core.resource.persistence.XmlMappingFileRef; |
| import org.eclipse.jpt.core.resource.persistence.XmlPersistenceUnit; |
| import org.eclipse.jpt.core.resource.persistence.XmlProperties; |
| import org.eclipse.jpt.core.resource.persistence.XmlProperty; |
| import org.eclipse.jpt.core.utility.BodySourceWriter; |
| import org.eclipse.jpt.core.utility.TextRange; |
| import org.eclipse.jpt.utility.internal.CollectionTools; |
| import org.eclipse.jpt.utility.internal.HashBag; |
| import org.eclipse.jpt.utility.internal.NotNullFilter; |
| import org.eclipse.jpt.utility.internal.iterables.CompositeIterable; |
| import org.eclipse.jpt.utility.internal.iterables.CompositeListIterable; |
| import org.eclipse.jpt.utility.internal.iterables.FilteringIterable; |
| import org.eclipse.jpt.utility.internal.iterables.ListIterable; |
| import org.eclipse.jpt.utility.internal.iterables.LiveCloneIterable; |
| import org.eclipse.jpt.utility.internal.iterables.LiveCloneListIterable; |
| import org.eclipse.jpt.utility.internal.iterables.TransformationIterable; |
| import org.eclipse.jpt.utility.internal.iterators.CloneIterator; |
| import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; |
| import org.eclipse.jpt.utility.internal.iterators.EmptyIterator; |
| import org.eclipse.jpt.utility.internal.iterators.EmptyListIterator; |
| import org.eclipse.jpt.utility.internal.iterators.FilteringIterator; |
| import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; |
| import org.eclipse.wst.validation.internal.provisional.core.IMessage; |
| import org.eclipse.wst.validation.internal.provisional.core.IReporter; |
| |
| /** |
| * <code>persistence.xml</code> file |
| * <br> |
| * <code>persistence-unit</code> element |
| */ |
| public abstract class AbstractPersistenceUnit |
| extends AbstractPersistenceXmlContextNode |
| implements PersistenceUnit2_0 |
| { |
| protected XmlPersistenceUnit xmlPersistenceUnit; |
| |
| protected String name; |
| |
| protected PersistenceUnitTransactionType specifiedTransactionType; |
| protected PersistenceUnitTransactionType defaultTransactionType; |
| |
| protected String description; |
| |
| protected String provider; |
| |
| protected String jtaDataSource; |
| protected String nonJtaDataSource; |
| |
| protected final Vector<MappingFileRef> specifiedMappingFileRefs = new Vector<MappingFileRef>(); |
| protected MappingFileRef impliedMappingFileRef; |
| |
| protected final Vector<JarFileRef> jarFileRefs = new Vector<JarFileRef>(); |
| |
| protected final Vector<ClassRef> specifiedClassRefs = new Vector<ClassRef>(); |
| protected final Vector<ClassRef> impliedClassRefs = new Vector<ClassRef>(); |
| |
| protected Boolean specifiedExcludeUnlistedClasses; |
| |
| protected final Vector<Property> properties = new Vector<Property>(); |
| |
| /* global generator definitions, defined elsewhere in model */ |
| protected final Vector<Generator> generators = new Vector<Generator>(); |
| |
| /* global query definitions, defined elsewhere in model */ |
| protected final Vector<Query> queries = new Vector<Query>(); |
| |
| protected final Set<String> rootEntityNames = Collections.synchronizedSet(new HashSet<String>()); |
| |
| protected AccessType defaultAccess; |
| protected String defaultCatalog; |
| protected String defaultSchema; |
| protected boolean defaultCascadePersist; |
| protected boolean defaultDelimitedIdentifiers; |
| |
| //****** PersistenceUnit2_0 features |
| private PersistenceUnitProperties connection; |
| private PersistenceUnitProperties options; |
| |
| protected SharedCacheMode specifiedSharedCacheMode; |
| protected SharedCacheMode defaultSharedCacheMode; |
| |
| protected ValidationMode specifiedValidationMode; |
| protected ValidationMode defaultValidationMode; |
| |
| protected final Set<IFile> metamodelFiles = Collections.synchronizedSet(new HashSet<IFile>()); |
| |
| |
| // ********** construction/initialization ********** |
| |
| /** |
| * NB: Be careful changing the order of the statements in this method |
| * (bug 258701 is one reason). |
| */ |
| protected AbstractPersistenceUnit(Persistence parent, XmlPersistenceUnit xmlPersistenceUnit) { |
| super(parent); |
| this.xmlPersistenceUnit = xmlPersistenceUnit; |
| this.name = xmlPersistenceUnit.getName(); |
| this.specifiedExcludeUnlistedClasses = xmlPersistenceUnit.getExcludeUnlistedClasses(); |
| this.specifiedTransactionType = this.buildSpecifiedTransactionType(); |
| this.defaultTransactionType = this.buildDefaultTransactionType(); |
| this.description = xmlPersistenceUnit.getDescription(); |
| this.provider = xmlPersistenceUnit.getProvider(); |
| this.jtaDataSource = xmlPersistenceUnit.getJtaDataSource(); |
| this.nonJtaDataSource = xmlPersistenceUnit.getNonJtaDataSource(); |
| this.specifiedExcludeUnlistedClasses = xmlPersistenceUnit.getExcludeUnlistedClasses(); |
| |
| // initialize the properties before building the entities because the |
| // entities will need the properties |
| this.initializeProperties(); |
| |
| this.initializeJarFileRefs(); |
| |
| //initialize specified classRefs before mappingFileRefs because of |
| //JpaFile rootStructureNode, we want the mapping file to "win", |
| //as it would in a Jpa runtime implementation |
| this.initializeSpecifiedClassRefs(); |
| this.initializeMappingFileRefs(); |
| //initialize implied classRefs last since they depend on both |
| //specified classRefs and mappingFileRefs |
| this.initializeImpliedClassRefs(); |
| this.initializePersistenceUnitDefaults(); |
| |
| this.specifiedSharedCacheMode = this.buildSpecifiedSharedCacheMode(); |
| this.defaultSharedCacheMode = this.buildDefaultSharedCacheMode(); |
| |
| this.specifiedValidationMode = this.buildSpecifiedValidationMode(); |
| this.defaultValidationMode = this.buildDefaultValidationMode(); |
| |
| this.initializeMetamodelFiles(); |
| } |
| |
| /** |
| * These lists are just copies of what is distributed across the context |
| * model; so, if they have (virtually) changed, the resulting update has |
| * already been triggered. We don't need to trigger another one here. |
| */ |
| @Override |
| protected void addNonUpdateAspectNamesTo(Set<String> nonUpdateAspectNames) { |
| super.addNonUpdateAspectNamesTo(nonUpdateAspectNames); |
| nonUpdateAspectNames.add(GENERATORS_LIST); |
| nonUpdateAspectNames.add(QUERIES_LIST); |
| } |
| |
| |
| // ********** updating ********** |
| |
| public void update(XmlPersistenceUnit xpu) { |
| this.xmlPersistenceUnit = xpu; |
| |
| // the 'generators' and 'queries' lists are simply cleared out with each |
| // "update" and completely rebuilt as the "update" cascades through |
| // the persistence unit. When the persistence unit's "update" is |
| // complete, the lists have been populated and we fire the change event. |
| // @see #addGenerator(Generator) (and references) |
| // @see #addQuery(Query) (and references) |
| this.generators.clear(); |
| this.queries.clear(); |
| |
| this.rootEntityNames.clear(); |
| |
| this.setName(xpu.getName()); |
| this.setSpecifiedTransactionType(this.buildSpecifiedTransactionType()); |
| this.setDefaultTransactionType(this.buildDefaultTransactionType()); |
| this.setDescription(xpu.getDescription()); |
| this.setProvider(xpu.getProvider()); |
| this.setJtaDataSource(xpu.getJtaDataSource()); |
| this.setNonJtaDataSource(xpu.getNonJtaDataSource()); |
| this.updateJarFileRefs(); |
| |
| // update 'specifiedClassRefs' before 'mappingFileRefs' because of |
| // JpaFile rootStructureNode, we want the mapping file to "win", |
| // as it would in a JPA runtime implementation |
| this.updateSpecifiedClassRefs(); |
| this.updateMappingFileRefs(); |
| |
| // update 'impliedClassRefs' last since it depends on the contents of |
| // both 'specifiedClassRefs' and 'mappingFileRefs' |
| this.updateImpliedClassRefs(); |
| |
| this.setSpecifiedExcludeUnlistedClasses(xpu.getExcludeUnlistedClasses()); |
| this.updateProperties(); |
| this.updatePersistenceUnitDefaults(); |
| |
| this.setSpecifiedSharedCacheMode(this.buildSpecifiedSharedCacheMode()); |
| this.setDefaultSharedCacheMode(this.buildDefaultSharedCacheMode()); |
| this.setSpecifiedValidationMode(this.buildSpecifiedValidationMode()); |
| this.setDefaultValidationMode(this.buildDefaultValidationMode()); |
| |
| // see comment at top of method |
| this.fireListChanged(GENERATORS_LIST, this.generators); |
| this.fireListChanged(QUERIES_LIST, this.queries); |
| } |
| |
| @Override |
| public void postUpdate() { |
| super.postUpdate(); |
| for (ClassRef classRef : this.getSpecifiedClassRefs()) { |
| classRef.postUpdate(); |
| } |
| for (ClassRef classRef : this.getImpliedClassRefs()) { |
| classRef.postUpdate(); |
| } |
| for (MappingFileRef mappingFileRef : CollectionTools.iterable(this.specifiedMappingFileRefs())) { |
| mappingFileRef.postUpdate(); |
| } |
| if (this.impliedMappingFileRef != null) { |
| this.impliedMappingFileRef.postUpdate(); |
| } |
| } |
| |
| |
| // ********** JpaContextNode implementation ********** |
| |
| @Override |
| public Persistence getParent() { |
| return (Persistence) super.getParent(); |
| } |
| |
| @Override |
| public PersistenceUnit getPersistenceUnit() { |
| return this; |
| } |
| |
| |
| // ********** JpaStructureNode implementation ********** |
| |
| public String getId() { |
| return PersistenceStructureNodes.PERSISTENCE_UNIT_ID; |
| } |
| |
| public TextRange getSelectionTextRange() { |
| return this.xmlPersistenceUnit.getSelectionTextRange(); |
| } |
| |
| public void dispose() { |
| for (ClassRef classRef : this.getClassRefs()) { |
| classRef.dispose(); |
| } |
| for (MappingFileRef mappingFileRef : this.getMappingFileRefs()) { |
| mappingFileRef.dispose(); |
| } |
| } |
| |
| |
| // ********** name ********** |
| |
| public String getName() { |
| return this.name; |
| } |
| |
| public void setName(String name) { |
| String old = this.name; |
| this.name = name; |
| this.xmlPersistenceUnit.setName(name); |
| this.firePropertyChanged(NAME_PROPERTY, old, name); |
| } |
| |
| |
| // ********** transaction type ********** |
| |
| public PersistenceUnitTransactionType getTransactionType() { |
| return (this.specifiedTransactionType != null) ? this.specifiedTransactionType : this.defaultTransactionType; |
| } |
| |
| public PersistenceUnitTransactionType getSpecifiedTransactionType() { |
| return this.specifiedTransactionType; |
| } |
| |
| public void setSpecifiedTransactionType(PersistenceUnitTransactionType specifiedTransactionType) { |
| PersistenceUnitTransactionType old = this.specifiedTransactionType; |
| this.specifiedTransactionType = specifiedTransactionType; |
| this.xmlPersistenceUnit.setTransactionType(PersistenceUnitTransactionType.toXmlResourceModel(specifiedTransactionType)); |
| this.firePropertyChanged(SPECIFIED_TRANSACTION_TYPE_PROPERTY, old, specifiedTransactionType); |
| } |
| |
| public PersistenceUnitTransactionType getDefaultTransactionType() { |
| return this.defaultTransactionType; |
| } |
| |
| protected void setDefaultTransactionType(PersistenceUnitTransactionType defaultTransactionType) { |
| PersistenceUnitTransactionType old = this.defaultTransactionType; |
| this.defaultTransactionType = defaultTransactionType; |
| this.firePropertyChanged(DEFAULT_TRANSACTION_TYPE_PROPERTY, old, defaultTransactionType); |
| } |
| |
| protected PersistenceUnitTransactionType buildSpecifiedTransactionType() { |
| return PersistenceUnitTransactionType.fromXmlResourceModel(this.xmlPersistenceUnit.getTransactionType()); |
| } |
| |
| /** |
| * TODO - calculate default |
| * From the JPA spec: "In a Java EE environment, if this element is not |
| * specified, the default is JTA. In a Java SE environment, if this element |
| * is not specified, a default of RESOURCE_LOCAL may be assumed." |
| */ |
| protected PersistenceUnitTransactionType buildDefaultTransactionType() { |
| return PersistenceUnitTransactionType.JTA; //return JTA for now, fixing regression in bug 277524 |
| } |
| |
| |
| // ********** description ********** |
| |
| public String getDescription() { |
| return this.description; |
| } |
| |
| public void setDescription(String description) { |
| String old = this.description; |
| this.description = description; |
| this.xmlPersistenceUnit.setDescription(description); |
| this.firePropertyChanged(DESCRIPTION_PROPERTY, old, description); |
| } |
| |
| |
| // ********** provider ********** |
| |
| public String getProvider() { |
| return this.provider; |
| } |
| |
| public void setProvider(String provider) { |
| String old = this.provider; |
| this.provider = provider; |
| this.xmlPersistenceUnit.setProvider(provider); |
| this.firePropertyChanged(PROVIDER_PROPERTY, old, provider); |
| } |
| |
| |
| // ********** JTA/non-JTA data source ********** |
| |
| public String getJtaDataSource() { |
| return this.jtaDataSource; |
| } |
| |
| public void setJtaDataSource(String jtaDataSource) { |
| String old = this.jtaDataSource; |
| this.jtaDataSource = jtaDataSource; |
| this.xmlPersistenceUnit.setJtaDataSource(jtaDataSource); |
| this.firePropertyChanged(JTA_DATA_SOURCE_PROPERTY, old, jtaDataSource); |
| } |
| |
| public String getNonJtaDataSource() { |
| return this.nonJtaDataSource; |
| } |
| |
| public void setNonJtaDataSource(String nonJtaDataSource) { |
| String old = this.nonJtaDataSource; |
| this.nonJtaDataSource = nonJtaDataSource; |
| this.xmlPersistenceUnit.setNonJtaDataSource(nonJtaDataSource); |
| this.firePropertyChanged(NON_JTA_DATA_SOURCE_PROPERTY, old, nonJtaDataSource); |
| } |
| |
| |
| // ********** mapping file refs ********** |
| |
| public ListIterator<MappingFileRef> mappingFileRefs() { |
| return this.getMappingFileRefs().iterator(); |
| } |
| |
| protected ListIterable<MappingFileRef> getMappingFileRefs() { |
| return (this.impliedMappingFileRef == null) ? this.getSpecifiedMappingFileRefs() : this.getCombinedMappingFileRefs(); |
| } |
| |
| protected ListIterator<MappingFileRef> combinedMappingFileRefs() { |
| return getCombinedMappingFileRefs().iterator(); |
| } |
| |
| protected ListIterable<MappingFileRef> getCombinedMappingFileRefs() { |
| return new CompositeListIterable<MappingFileRef>(this.getSpecifiedMappingFileRefs(), this.impliedMappingFileRef); |
| } |
| |
| public int mappingFileRefsSize() { |
| return (this.impliedMappingFileRef == null) ? this.specifiedMappingFileRefsSize() : this.combinedMappingFileRefsSize(); |
| } |
| |
| protected int combinedMappingFileRefsSize() { |
| return this.specifiedMappingFileRefsSize() + 1; |
| } |
| |
| public Iterator<MappingFileRef> mappingFileRefsContaining(final String typeName) { |
| return new FilteringIterator<MappingFileRef> (this.mappingFileRefs()) { |
| @Override |
| protected boolean accept(MappingFileRef mappingFileRef) { |
| return mappingFileRef.getPersistentType(typeName) != null; |
| } |
| }; |
| } |
| |
| protected void initializeMappingFileRefs() { |
| for (XmlMappingFileRef xmlMappingFileRef : this.xmlPersistenceUnit.getMappingFiles()) { |
| this.specifiedMappingFileRefs.add(this.buildSpecifiedMappingFileRef(xmlMappingFileRef)); |
| } |
| if ( ! this.impliedMappingFileIsSpecified() && this.impliedMappingFileExists()) { |
| this.impliedMappingFileRef = this.buildImpliedMappingFileRef(); |
| } |
| } |
| |
| /** |
| * Since this is a *list*, we simply loop through the elements and match |
| * the context to the resource element by index, not by name like we do |
| * with 'impliedClassRefs'. |
| */ |
| protected void updateMappingFileRefs() { |
| // first update the specified mapping file refs... |
| // make a copy of the XML file refs (to prevent ConcurrentModificationException) |
| Iterator<XmlMappingFileRef> xmlFileRefs = new CloneIterator<XmlMappingFileRef>(this.xmlPersistenceUnit.getMappingFiles()); |
| |
| for (Iterator<MappingFileRef> contextFileRefs = this.specifiedMappingFileRefs(); contextFileRefs.hasNext(); ) { |
| MappingFileRef contextFileRef = contextFileRefs.next(); |
| if (xmlFileRefs.hasNext()) { |
| contextFileRef.update(xmlFileRefs.next()); |
| } else { |
| this.removeSpecifiedMappingFileRef_(contextFileRef); |
| } |
| } |
| |
| while (xmlFileRefs.hasNext()) { |
| this.addSpecifiedMappingFileRef_(this.buildSpecifiedMappingFileRef(xmlFileRefs.next())); |
| } |
| |
| // ...then update the implied mapping file ref |
| if (this.impliedMappingFileIsSpecified()) { |
| if (this.impliedMappingFileRef != null) { |
| this.unsetImpliedMappingFileRef(); |
| } |
| } else { |
| if (this.impliedMappingFileExists()) { |
| if (this.impliedMappingFileRef == null) { |
| this.setImpliedMappingFileRef(); |
| } |
| this.impliedMappingFileRef.update(null); |
| } else { |
| if (this.impliedMappingFileRef != null) { |
| this.unsetImpliedMappingFileRef(); |
| } |
| } |
| } |
| } |
| |
| protected MappingFileRef buildSpecifiedMappingFileRef(XmlMappingFileRef xmlMappingFileRef) { |
| return this.getContextNodeFactory().buildMappingFileRef(this, xmlMappingFileRef); |
| } |
| |
| protected boolean impliedMappingFileIsSpecified() { |
| String impliedMappingFileName = JptCorePlugin.DEFAULT_ORM_XML_FILE_PATH; |
| for (Iterator<MappingFileRef> stream = this.specifiedMappingFileRefs(); stream.hasNext(); ) { |
| if (impliedMappingFileName.equals(stream.next().getFileName())) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| protected boolean impliedMappingFileExists() { |
| return getJpaProject().getDefaultOrmXmlResource() != null; |
| } |
| |
| |
| // ********** specified mapping file refs ********** |
| |
| public ListIterator<MappingFileRef> specifiedMappingFileRefs() { |
| return this.getSpecifiedMappingFileRefs().iterator(); |
| } |
| |
| protected ListIterable<MappingFileRef> getSpecifiedMappingFileRefs() { |
| return new LiveCloneListIterable<MappingFileRef>(this.specifiedMappingFileRefs); |
| } |
| |
| public int specifiedMappingFileRefsSize() { |
| return this.specifiedMappingFileRefs.size(); |
| } |
| |
| public MappingFileRef addSpecifiedMappingFileRef() { |
| return this.addSpecifiedMappingFileRef(this.specifiedMappingFileRefs.size()); |
| } |
| |
| public MappingFileRef addSpecifiedMappingFileRef(int index) { |
| XmlMappingFileRef xmlMappingFileRef = this.buildXmlMappingFileRef(); |
| MappingFileRef mappingFileRef = this.buildSpecifiedMappingFileRef(xmlMappingFileRef); |
| this.specifiedMappingFileRefs.add(index, mappingFileRef); |
| this.xmlPersistenceUnit.getMappingFiles().add(index, xmlMappingFileRef); |
| this.fireItemAdded(SPECIFIED_MAPPING_FILE_REFS_LIST, index, mappingFileRef); |
| return mappingFileRef; |
| } |
| |
| protected XmlMappingFileRef buildXmlMappingFileRef() { |
| return PersistenceFactory.eINSTANCE.createXmlMappingFileRef(); |
| } |
| |
| public void removeSpecifiedMappingFileRef(MappingFileRef mappingFileRef) { |
| this.removeSpecifiedMappingFileRef(this.specifiedMappingFileRefs.indexOf(mappingFileRef)); |
| } |
| |
| public void removeSpecifiedMappingFileRef(int index) { |
| MappingFileRef mappingFileRef = this.specifiedMappingFileRefs.remove(index); |
| mappingFileRef.dispose(); |
| this.xmlPersistenceUnit.getMappingFiles().remove(index); |
| this.fireItemRemoved(SPECIFIED_MAPPING_FILE_REFS_LIST, index, mappingFileRef); |
| } |
| |
| protected void addSpecifiedMappingFileRef_(MappingFileRef mappingFileRef) { |
| this.addItemToList(mappingFileRef, this.specifiedMappingFileRefs, SPECIFIED_MAPPING_FILE_REFS_LIST); |
| } |
| |
| protected void removeSpecifiedMappingFileRef_(MappingFileRef mappingFileRef) { |
| mappingFileRef.dispose(); |
| this.removeItemFromList(mappingFileRef, this.specifiedMappingFileRefs, SPECIFIED_MAPPING_FILE_REFS_LIST); |
| } |
| |
| |
| // ********** implied mapping file ref ********** |
| |
| public MappingFileRef getImpliedMappingFileRef() { |
| return this.impliedMappingFileRef; |
| } |
| |
| protected MappingFileRef setImpliedMappingFileRef() { |
| if (this.impliedMappingFileRef != null) { |
| throw new IllegalStateException("The implied mapping file ref is already set."); //$NON-NLS-1$ |
| } |
| this.impliedMappingFileRef = this.buildImpliedMappingFileRef(); |
| this.firePropertyChanged(IMPLIED_MAPPING_FILE_REF_PROPERTY, null, this.impliedMappingFileRef); |
| return this.impliedMappingFileRef; |
| } |
| |
| protected MappingFileRef buildImpliedMappingFileRef() { |
| return this.getContextNodeFactory().buildImpliedMappingFileRef(this); |
| } |
| |
| protected void unsetImpliedMappingFileRef() { |
| if (this.impliedMappingFileRef == null) { |
| throw new IllegalStateException("The implied mapping file ref is already unset."); //$NON-NLS-1$ |
| } |
| MappingFileRef old = this.impliedMappingFileRef; |
| this.impliedMappingFileRef.dispose(); |
| this.impliedMappingFileRef = null; |
| this.firePropertyChanged(IMPLIED_MAPPING_FILE_REF_PROPERTY, old, null); |
| } |
| |
| |
| // ********** JAR file refs ********** |
| |
| public ListIterator<JarFileRef> jarFileRefs() { |
| return new CloneListIterator<JarFileRef>(this.jarFileRefs); |
| } |
| |
| protected Iterable<JarFileRef> getJarFileRefs() { |
| return new LiveCloneIterable<JarFileRef>(this.jarFileRefs); |
| } |
| |
| public int jarFileRefsSize() { |
| return this.jarFileRefs.size(); |
| } |
| |
| public JarFileRef addJarFileRef() { |
| return this.addJarFileRef(this.jarFileRefs.size()); |
| } |
| |
| public JarFileRef addJarFileRef(int index) { |
| XmlJarFileRef xmlJarFileRef = this.buildXmlJarFileRef(); |
| JarFileRef jarFileRef = this.buildJarFileRef(xmlJarFileRef); |
| this.jarFileRefs.add(index, jarFileRef); |
| this.xmlPersistenceUnit.getJarFiles().add(index, xmlJarFileRef); |
| this.fireItemAdded(JAR_FILE_REFS_LIST, index, jarFileRef); |
| return jarFileRef; |
| } |
| |
| protected XmlJarFileRef buildXmlJarFileRef() { |
| return PersistenceFactory.eINSTANCE.createXmlJarFileRef(); |
| } |
| |
| public void removeJarFileRef(JarFileRef jarFileRef) { |
| this.removeJarFileRef(this.jarFileRefs.indexOf(jarFileRef)); |
| } |
| |
| public void removeJarFileRef(int index) { |
| JarFileRef jarFileRef = this.jarFileRefs.remove(index); |
| jarFileRef.dispose(); |
| this.xmlPersistenceUnit.getJarFiles().remove(index); |
| this.fireItemRemoved(JAR_FILE_REFS_LIST, index, jarFileRef); |
| } |
| |
| protected void addJarFileRef_(JarFileRef jarFileRef) { |
| this.addItemToList(jarFileRef, this.jarFileRefs, JAR_FILE_REFS_LIST); |
| } |
| |
| protected void removeJarFileRef_(JarFileRef jarFileRef) { |
| jarFileRef.dispose(); |
| this.removeItemFromList(jarFileRef, this.jarFileRefs, JAR_FILE_REFS_LIST); |
| } |
| |
| protected void initializeJarFileRefs() { |
| for (XmlJarFileRef xmlJarFileRef : this.xmlPersistenceUnit.getJarFiles()) { |
| this.jarFileRefs.add(this.buildJarFileRef(xmlJarFileRef)); |
| } |
| } |
| |
| /** |
| * Since this is a *list*, we simply loop through the elements and match |
| * the context to the resource element by index, not by name like we do |
| * with 'impliedClassRefs'. |
| */ |
| protected void updateJarFileRefs() { |
| // make a copy of the XML file refs (to prevent ConcurrentModificationException) |
| Iterator<XmlJarFileRef> xmlFileRefs = new CloneIterator<XmlJarFileRef>(this.xmlPersistenceUnit.getJarFiles()); |
| |
| for (Iterator<JarFileRef> contextFileRefs = this.jarFileRefs(); contextFileRefs.hasNext(); ) { |
| JarFileRef contextFileRef = contextFileRefs.next(); |
| if (xmlFileRefs.hasNext()) { |
| contextFileRef.update(xmlFileRefs.next()); |
| } else { |
| this.removeJarFileRef_(contextFileRef); |
| } |
| } |
| |
| while (xmlFileRefs.hasNext()) { |
| this.addJarFileRef_(this.buildJarFileRef(xmlFileRefs.next())); |
| } |
| } |
| |
| protected JarFileRef buildJarFileRef(XmlJarFileRef xmlJarFileRef) { |
| return this.getContextNodeFactory().buildJarFileRef(this, xmlJarFileRef); |
| } |
| |
| |
| // ********** class refs ********** |
| |
| public Iterator<ClassRef> classRefs() { |
| return this.getClassRefs().iterator(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| protected Iterable<ClassRef> getClassRefs() { |
| return new CompositeIterable<ClassRef>( |
| this.getSpecifiedClassRefs(), |
| this.getImpliedClassRefs() |
| ); |
| } |
| |
| public int classRefsSize() { |
| return this.specifiedClassRefs.size() + this.impliedClassRefs.size(); |
| } |
| |
| protected Iterable<PersistentType> getNonNullClassRefPersistentTypes() { |
| return new FilteringIterable<PersistentType>(this.getClassRefPersistentTypes(), NotNullFilter.<PersistentType>instance()); |
| } |
| |
| protected Iterable<PersistentType> getClassRefPersistentTypes() { |
| return new TransformationIterable<ClassRef, PersistentType>(this.getClassRefs()) { |
| @Override |
| protected PersistentType transform(ClassRef classRef) { |
| return classRef.getJavaPersistentType(); |
| } |
| }; |
| } |
| |
| |
| // ********** specified class refs ********** |
| |
| public ListIterator<ClassRef> specifiedClassRefs() { |
| return new CloneListIterator<ClassRef>(this.specifiedClassRefs); |
| } |
| |
| protected Iterable<ClassRef> getSpecifiedClassRefs() { |
| return new LiveCloneIterable<ClassRef>(this.specifiedClassRefs); |
| } |
| |
| public int specifiedClassRefsSize() { |
| return this.specifiedClassRefs.size(); |
| } |
| |
| public ClassRef addSpecifiedClassRef() { |
| return this.addSpecifiedClassRef(this.specifiedClassRefs.size()); |
| } |
| |
| public ClassRef addSpecifiedClassRef(int index) { |
| XmlJavaClassRef xmlClassRef = this.buildXmlJavaClassRef(); |
| ClassRef classRef = this.buildClassRef(xmlClassRef); |
| this.specifiedClassRefs.add(index, classRef); |
| this.xmlPersistenceUnit.getClasses().add(index, xmlClassRef); |
| this.fireItemAdded(SPECIFIED_CLASS_REFS_LIST, index, classRef); |
| return classRef; |
| } |
| |
| protected XmlJavaClassRef buildXmlJavaClassRef() { |
| return PersistenceFactory.eINSTANCE.createXmlJavaClassRef(); |
| } |
| |
| public void removeSpecifiedClassRef(ClassRef classRef) { |
| this.removeSpecifiedClassRef(this.specifiedClassRefs.indexOf(classRef)); |
| } |
| |
| public void removeSpecifiedClassRef(int index) { |
| ClassRef classRef = this.specifiedClassRefs.remove(index); |
| classRef.dispose(); |
| this.xmlPersistenceUnit.getClasses().remove(index); |
| this.fireItemRemoved(SPECIFIED_CLASS_REFS_LIST, index, classRef); |
| } |
| |
| protected void addSpecifiedClassRef_(int index, ClassRef classRef) { |
| this.addItemToList(index, classRef, this.specifiedClassRefs, SPECIFIED_CLASS_REFS_LIST); |
| } |
| |
| protected void removeSpecifiedClassRef_(ClassRef classRef) { |
| classRef.dispose(); |
| this.removeItemFromList(classRef, this.specifiedClassRefs, SPECIFIED_CLASS_REFS_LIST); |
| } |
| |
| private void moveSpecifiedClassRef_(int index, ClassRef classRef) { |
| this.moveItemInList(index, this.specifiedClassRefs.indexOf(classRef), this.specifiedClassRefs, SPECIFIED_CLASS_REFS_LIST); |
| } |
| |
| protected void initializeSpecifiedClassRefs() { |
| for (XmlJavaClassRef xmlJavaClassRef : this.xmlPersistenceUnit.getClasses()) { |
| this.specifiedClassRefs.add(this.buildClassRef(xmlJavaClassRef)); |
| } |
| } |
| |
| /** |
| * Since this is a *list*, we simply loop through the elements and match |
| * the context to the resource element by index, not by name like we do |
| * with 'impliedClassRefs'. |
| */ |
| protected void updateSpecifiedClassRefs() { |
| HashBag<ClassRef> contextClassRefsToRemove = CollectionTools.bag(this.specifiedClassRefs(), this.specifiedClassRefsSize()); |
| ArrayList<ClassRef> contextClassRefsToUpdate = new ArrayList<ClassRef>(this.specifiedClassRefsSize()); |
| int resourceIndex = 0; |
| |
| for (Iterator<XmlJavaClassRef> xmlClassRefs = new CloneIterator<XmlJavaClassRef>(this.xmlPersistenceUnit.getClasses()); xmlClassRefs.hasNext(); ) { |
| XmlJavaClassRef resourceClassRef = xmlClassRefs.next(); |
| boolean match = false; |
| for (Iterator<ClassRef> contextClassRefs = contextClassRefsToRemove.iterator(); contextClassRefs.hasNext(); ) { |
| ClassRef contextClassRef = contextClassRefs.next(); |
| if (contextClassRef.getResourceClassRef() == resourceClassRef) { |
| this.moveSpecifiedClassRef_(resourceIndex, contextClassRef); |
| contextClassRefs.remove(); |
| contextClassRefsToUpdate.add(contextClassRef); |
| match = true; |
| break; |
| } |
| } |
| if ( ! match) { |
| this.addSpecifiedClassRef_(resourceIndex, this.buildClassRef(resourceClassRef)); |
| } |
| resourceIndex++; |
| } |
| for (ClassRef contextClassRef : contextClassRefsToRemove) { |
| this.removeSpecifiedClassRef_(contextClassRef); |
| } |
| // handle adding and removing class refs first, update the |
| // remaining class refs last; this reduces the churn during "update" |
| for (ClassRef contextClassRef : contextClassRefsToUpdate) { |
| contextClassRef.update(); |
| } |
| } |
| |
| protected ClassRef buildClassRef(XmlJavaClassRef xmlClassRef) { |
| return this.getContextNodeFactory().buildClassRef(this, xmlClassRef); |
| } |
| |
| |
| // ********** implied class refs ********** |
| |
| public Iterator<ClassRef> impliedClassRefs() { |
| return new CloneIterator<ClassRef>(this.impliedClassRefs); |
| } |
| |
| protected Iterable<ClassRef> getImpliedClassRefs() { |
| return new LiveCloneIterable<ClassRef>(this.impliedClassRefs); |
| } |
| |
| public int impliedClassRefsSize() { |
| return this.impliedClassRefs.size(); |
| } |
| |
| protected ClassRef addImpliedClassRef(String className) { |
| ClassRef classRef = this.buildClassRef(className); |
| this.addItemToCollection(classRef, this.impliedClassRefs, IMPLIED_CLASS_REFS_COLLECTION); |
| return classRef; |
| } |
| |
| protected ClassRef buildClassRef(String className) { |
| return this.getContextNodeFactory().buildClassRef(this, className); |
| } |
| |
| protected void removeImpliedClassRef(ClassRef classRef) { |
| classRef.dispose(); |
| this.removeItemFromCollection(classRef, this.impliedClassRefs, IMPLIED_CLASS_REFS_COLLECTION); |
| } |
| |
| protected void initializeImpliedClassRefs() { |
| if ( ! this.excludesUnlistedClasses()) { |
| this.initializeImpliedClassRefs_(); |
| } |
| } |
| |
| protected void initializeImpliedClassRefs_() { |
| for (Iterator<String> stream = this.getJpaProject().mappedJavaSourceClassNames(); stream.hasNext(); ) { |
| String typeName = stream.next(); |
| if ( ! this.specifiesPersistentType(typeName)) { |
| this.impliedClassRefs.add(this.buildClassRef(typeName)); |
| } |
| } |
| } |
| |
| protected void updateImpliedClassRefs() { |
| if (this.excludesUnlistedClasses()) { |
| this.clearImpliedClassRefs_(); |
| } else { |
| this.updateImpliedClassRefs_(); |
| } |
| } |
| |
| protected void updateImpliedClassRefs_() { |
| HashBag<ClassRef> impliedRefsToRemove = CollectionTools.bag(this.impliedClassRefs(), this.impliedClassRefsSize()); |
| ArrayList<ClassRef> impliedRefsToUpdate = new ArrayList<ClassRef>(this.impliedClassRefsSize()); |
| |
| for (Iterator<String> mappedClassNames = this.getJpaProject().mappedJavaSourceClassNames(); mappedClassNames.hasNext(); ) { |
| String mappedClassName = mappedClassNames.next(); |
| if ( ! this.specifiesPersistentType(mappedClassName)) { |
| boolean match = false; |
| for (Iterator<ClassRef> classRefs = impliedRefsToRemove.iterator(); classRefs.hasNext(); ) { |
| ClassRef classRef = classRefs.next(); |
| if (mappedClassName.equals(classRef.getClassName())) { |
| classRefs.remove(); |
| impliedRefsToUpdate.add(classRef); |
| match = true; |
| break; |
| } |
| } |
| if ( ! match) { |
| this.addImpliedClassRef(mappedClassName); |
| } |
| } |
| } |
| for (ClassRef classRef : impliedRefsToRemove) { |
| this.removeImpliedClassRef(classRef); |
| } |
| // handle adding and removing implied class refs first, update the |
| // remaining implied class refs last; this reduces the churn during "update" |
| for (ClassRef classRef : impliedRefsToUpdate) { |
| classRef.update(classRef.getClassName()); |
| } |
| } |
| |
| protected void clearImpliedClassRefs_() { |
| for (ClassRef classRef : this.getImpliedClassRefs()) { |
| this.removeImpliedClassRef(classRef); |
| } |
| } |
| |
| |
| // ********** exclude unlisted classes ********** |
| |
| public boolean excludesUnlistedClasses() { |
| return (this.specifiedExcludeUnlistedClasses != null) ? this.specifiedExcludeUnlistedClasses.booleanValue() : this.getDefaultExcludeUnlistedClasses(); |
| } |
| |
| public Boolean getSpecifiedExcludeUnlistedClasses() { |
| return this.specifiedExcludeUnlistedClasses; |
| } |
| |
| public void setSpecifiedExcludeUnlistedClasses(Boolean specifiedExcludeUnlistedClasses) { |
| Boolean old = this.specifiedExcludeUnlistedClasses; |
| this.specifiedExcludeUnlistedClasses = specifiedExcludeUnlistedClasses; |
| this.xmlPersistenceUnit.setExcludeUnlistedClasses(this.specifiedExcludeUnlistedClasses); |
| this.firePropertyChanged(SPECIFIED_EXCLUDE_UNLISTED_CLASSES_PROPERTY, old, specifiedExcludeUnlistedClasses); |
| } |
| |
| public boolean getDefaultExcludeUnlistedClasses() { |
| return false; // ??? |
| } |
| |
| |
| // ********** properties ********** |
| |
| public ListIterator<Property> properties() { |
| return new CloneListIterator<Property>(this.properties); |
| } |
| |
| protected Iterable<Property> getProperties() { |
| return new LiveCloneIterable<Property>(this.properties); |
| } |
| |
| public int propertiesSize() { |
| return this.properties.size(); |
| } |
| |
| public Property getProperty(String propertyName) { |
| if (propertyName == null) { |
| throw new NullPointerException(); |
| } |
| for (Property property : this.getProperties()) { |
| if (propertyName.equals(property.getName())) { |
| return property; |
| } |
| } |
| return null; |
| } |
| |
| public Iterator<Property> propertiesWithNamePrefix(final String propertyNamePrefix) { |
| if (propertyNamePrefix == null) { |
| throw new NullPointerException(); |
| } |
| return new FilteringIterator<Property>(this.properties()) { |
| @Override |
| protected boolean accept(Property property) { |
| String pName = property.getName(); |
| return (pName != null) && pName.startsWith(propertyNamePrefix); |
| } |
| }; |
| } |
| |
| public Property addProperty() { |
| return this.addProperty(this.properties.size()); |
| } |
| |
| public Property addProperty(int index) { |
| return this.addProperty(this.buildXmlProperty(), index); |
| } |
| |
| protected XmlProperty buildXmlProperty() { |
| return PersistenceFactory.eINSTANCE.createXmlProperty(); |
| } |
| |
| protected Property addProperty(XmlProperty xmlProperty, int index) { |
| Property property = this.buildProperty(xmlProperty); |
| |
| XmlProperties xmlProperties = this.xmlPersistenceUnit.getProperties(); |
| if (xmlProperties == null) { |
| xmlProperties = this.buildXmlProperties(); |
| this.xmlPersistenceUnit.setProperties(xmlProperties); |
| } |
| |
| this.properties.add(index, property); |
| xmlProperties.getProperties().add(index, xmlProperty); |
| this.fireItemAdded(PROPERTIES_LIST, index, property); |
| if (property.getName() != null) { |
| this.propertyAdded(property.getName(), property.getValue()); |
| } |
| return property; |
| } |
| |
| protected Property buildProperty(XmlProperty xmlProperty) { |
| return this.getContextNodeFactory().buildProperty(this, xmlProperty); |
| } |
| |
| protected XmlProperties buildXmlProperties() { |
| return PersistenceFactory.eINSTANCE.createXmlProperties(); |
| } |
| |
| public void setProperty(String propertyName, String value) { |
| this.setProperty(propertyName, value, false); |
| } |
| |
| public void setProperty(String propertyName, String value, boolean duplicatePropertyNamesAllowed) { |
| Property prev = this.getProperty(propertyName); |
| if (prev == null) { |
| if (value != null) { |
| this.addProperty(propertyName, value); // add [first] property |
| } |
| } else { |
| if (duplicatePropertyNamesAllowed) { |
| if (value == null) { |
| // do nothing? |
| } else { |
| this.addProperty(propertyName, value); // add [duplicate] property |
| } |
| } else { |
| if (value == null) { |
| this.removeProperty(prev); // remove existing property |
| } else { |
| prev.setValue(value); // change existing property |
| } |
| } |
| } |
| } |
| |
| protected void addProperty(String propertyName, String value) { |
| Property property = this.addProperty(); |
| property.setName(propertyName); |
| property.setValue(value); |
| } |
| |
| public void removeProperty(Property property) { |
| this.removeProperty(this.properties.indexOf(property)); |
| } |
| |
| public void removeProperty(String propertyName) { |
| if (propertyName == null) { |
| throw new NullPointerException(); |
| } |
| for (ListIterator<Property> stream = this.properties.listIterator(); stream.hasNext(); ) { |
| Property property = stream.next(); |
| if (propertyName.equals(property.getName())) { |
| this.removeProperty(stream.previousIndex()); |
| return; |
| } |
| } |
| throw new IllegalArgumentException("invalid property name: " + propertyName); //$NON-NLS-1$ |
| } |
| |
| public void removeProperty(String propertyName, String value) { |
| if ((propertyName == null) || (value == null)) { |
| throw new NullPointerException(); |
| } |
| for (ListIterator<Property> stream = this.properties.listIterator(); stream.hasNext(); ) { |
| Property property = stream.next(); |
| if (propertyName.equals(property.getName()) && value.equals(property.getValue())) { |
| this.removeProperty(stream.previousIndex()); |
| return; |
| } |
| } |
| throw new IllegalArgumentException("invalid property name/value pair: " + propertyName + " = " + value); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| protected void removeProperty(int index) { |
| Property removedProperty = this.properties.remove(index); |
| this.xmlPersistenceUnit.getProperties().getProperties().remove(index); |
| |
| if (this.xmlPersistenceUnit.getProperties().getProperties().isEmpty()) { |
| this.xmlPersistenceUnit.setProperties(null); |
| } |
| |
| this.fireItemRemoved(PROPERTIES_LIST, index, removedProperty); |
| if (removedProperty.getName() != null) { |
| this.propertyRemoved(removedProperty.getName()); |
| } |
| } |
| |
| protected void addProperty_(int index, Property property) { |
| this.addItemToList(index, property, this.properties, PROPERTIES_LIST); |
| if (property.getName() != null) { |
| this.propertyAdded(property.getName(), property.getValue()); |
| } |
| } |
| |
| protected void removeProperty_(int index) { |
| removeProperty_(this.properties.get(index)); |
| } |
| |
| protected void removeProperty_(Property property) { |
| this.removeItemFromList(property, this.properties, PROPERTIES_LIST); |
| if (property.getName() != null) { |
| this.propertyRemoved(property.getName()); |
| } |
| } |
| |
| protected void moveProperty_(int index, Property property) { |
| this.moveItemInList(index, this.properties.indexOf(property), this.properties, PROPERTIES_LIST); |
| } |
| |
| public void propertyNameChanged(String oldPropertyName, String newPropertyName, String value) { |
| if (oldPropertyName == null && value == null) { |
| //this is a property that is currently being added, we don't need to deal with it until the value is set |
| return; |
| } |
| if (oldPropertyName != null) { |
| this.propertyRemoved(oldPropertyName); |
| } |
| if (newPropertyName != null) { |
| this.propertyAdded(newPropertyName, value); |
| } |
| } |
| |
| public void propertyValueChanged(String propertyName, String newValue) { |
| this.connection.propertyValueChanged(propertyName, newValue); |
| this.options.propertyValueChanged(propertyName, newValue); |
| } |
| |
| public void propertyAdded(String propertyName, String value) { |
| this.propertyValueChanged(propertyName, value); |
| } |
| |
| public void propertyRemoved(String propertyName) { |
| this.connection.propertyRemoved(propertyName); |
| this.options.propertyRemoved(propertyName); |
| } |
| |
| protected void initializeProperties() { |
| XmlProperties xmlProperties = this.xmlPersistenceUnit.getProperties(); |
| if (xmlProperties != null) { |
| for (XmlProperty xmlProperty : xmlProperties.getProperties()) { |
| this.properties.add(this.buildProperty(xmlProperty)); |
| } |
| } |
| this.connection = this.getContextNodeFactory().buildConnection(this); |
| this.options = this.getContextNodeFactory().buildOptions(this); |
| } |
| |
| /** |
| * Match the elements based on the XmlProperty resource object and also keep the order |
| * the same as the source. |
| */ |
| protected void updateProperties() { |
| HashBag<Property> contextPropertiesToRemove = CollectionTools.bag(this.properties(), this.propertiesSize()); |
| int resourceIndex = 0; |
| |
| for (Iterator<XmlProperty> xmlProperties = this.xmlProperties(); xmlProperties.hasNext(); ) { |
| XmlProperty xmlProperty = xmlProperties.next(); |
| boolean match = false; |
| for (Iterator<Property> contextProperties = contextPropertiesToRemove.iterator(); contextProperties.hasNext();) { |
| Property contextProperty = contextProperties.next(); |
| if (contextProperty.getXmlProperty() == xmlProperty) { |
| contextProperties.remove(); |
| this.moveProperty_(resourceIndex, contextProperty); |
| contextProperty.update(); |
| match = true; |
| break; |
| } |
| } |
| if ( ! match) { |
| this.addProperty_(resourceIndex, this.buildProperty(xmlProperty)); |
| } |
| resourceIndex++; |
| } |
| for (Property contextProperty : contextPropertiesToRemove) { |
| this.removeProperty_(contextProperty); |
| } |
| } |
| |
| protected Iterator<XmlProperty> xmlProperties() { |
| XmlProperties xmlProperties = this.xmlPersistenceUnit.getProperties(); |
| // make a copy of the XML properties (to prevent ConcurrentModificationException) |
| return (xmlProperties != null) ? new CloneIterator<XmlProperty>(xmlProperties.getProperties()) : EmptyIterator.<XmlProperty>instance(); |
| } |
| |
| protected int xmlPropertiesSize() { |
| XmlProperties xmlProperties = this.xmlPersistenceUnit.getProperties(); |
| return xmlProperties == null ? 0 : xmlProperties.getProperties().size(); |
| } |
| |
| |
| // ********** ORM persistence unit defaults ********** |
| |
| public AccessType getDefaultAccess() { |
| return this.defaultAccess; |
| } |
| |
| protected void setDefaultAccess(AccessType defaultAccess) { |
| AccessType old = this.defaultAccess; |
| this.defaultAccess = defaultAccess; |
| this.firePropertyChanged(DEFAULT_ACCESS_PROPERTY, old, defaultAccess); |
| } |
| |
| protected AccessType buildDefaultAccess(MappingFilePersistenceUnitDefaults defaults) { |
| return (defaults == null) ? null : defaults.getAccess(); |
| } |
| |
| public String getDefaultCatalog() { |
| return this.defaultCatalog; |
| } |
| |
| protected void setDefaultCatalog(String defaultCatalog) { |
| String old = this.defaultCatalog; |
| this.defaultCatalog = defaultCatalog; |
| this.firePropertyChanged(DEFAULT_CATALOG_PROPERTY, old, defaultCatalog); |
| } |
| |
| protected String buildDefaultCatalog(MappingFilePersistenceUnitDefaults defaults) { |
| String catalog = (defaults == null) ? null : defaults.getCatalog(); |
| return (catalog != null) ? catalog : this.getJpaProject().getDefaultCatalog(); |
| } |
| |
| public String getDefaultSchema() { |
| return this.defaultSchema; |
| } |
| |
| protected void setDefaultSchema(String defaultSchema) { |
| String old = this.defaultSchema; |
| this.defaultSchema = defaultSchema; |
| this.firePropertyChanged(DEFAULT_SCHEMA_PROPERTY, old, defaultSchema); |
| } |
| |
| protected String buildDefaultSchema(MappingFilePersistenceUnitDefaults defaults) { |
| String schema = (defaults == null) ? null : defaults.getSchema(); |
| return (schema != null) ? schema : this.getJpaProject().getDefaultSchema(); |
| } |
| |
| public boolean getDefaultCascadePersist() { |
| return this.defaultCascadePersist; |
| } |
| |
| protected void setDefaultCascadePersist(boolean defaultCascadePersist) { |
| boolean old = this.defaultCascadePersist; |
| this.defaultCascadePersist = defaultCascadePersist; |
| this.firePropertyChanged(DEFAULT_CASCADE_PERSIST_PROPERTY, old, defaultCascadePersist); |
| } |
| |
| protected boolean buildDefaultCascadePersist(MappingFilePersistenceUnitDefaults defaults) { |
| return (defaults == null) ? false : defaults.isCascadePersist(); |
| } |
| |
| public boolean getDefaultDelimitedIdentifiers() { |
| return this.defaultDelimitedIdentifiers; |
| } |
| |
| protected void setDefaultDelimitedIdentifiers(boolean defaultDelimitedIdentifiers) { |
| boolean old = this.defaultDelimitedIdentifiers; |
| this.defaultDelimitedIdentifiers = defaultDelimitedIdentifiers; |
| this.firePropertyChanged(DEFAULT_DELIMITED_IDENTIFIERS_PROPERTY, old, defaultDelimitedIdentifiers); |
| } |
| |
| protected boolean buildDefaultDelimitedIdentifiers(MappingFilePersistenceUnitDefaults defaults) { |
| return ( ! this.isJpa2_0Compatible()) ? false : |
| (defaults == null) ? false : ((MappingFilePersistenceUnitDefaults2_0) defaults).isDelimitedIdentifiers(); |
| } |
| |
| protected void initializePersistenceUnitDefaults() { |
| MappingFilePersistenceUnitDefaults defaults = this.getDefaults(); |
| this.defaultAccess = this.buildDefaultAccess(defaults); |
| this.defaultCatalog = this.buildDefaultCatalog(defaults); |
| this.defaultSchema = this.buildDefaultSchema(defaults); |
| this.defaultCascadePersist = this.buildDefaultCascadePersist(defaults); |
| this.defaultDelimitedIdentifiers = this.buildDefaultDelimitedIdentifiers(defaults); |
| } |
| |
| protected void updatePersistenceUnitDefaults() { |
| MappingFilePersistenceUnitDefaults defaults = this.getDefaults(); |
| this.setDefaultAccess(this.buildDefaultAccess(defaults)); |
| this.setDefaultCatalog(this.buildDefaultCatalog(defaults)); |
| this.setDefaultSchema(this.buildDefaultSchema(defaults)); |
| this.setDefaultDelimitedIdentifiers(this.buildDefaultDelimitedIdentifiers(defaults)); |
| } |
| |
| /** |
| * return the first persistence unit defaults we encounter in a mapping file |
| */ |
| protected MappingFilePersistenceUnitDefaults getDefaults() { |
| for (MappingFileRef mappingFileRef : this.getMappingFileRefs()) { |
| if (mappingFileRef.persistenceUnitDefaultsExists()) { |
| return mappingFileRef.getPersistenceUnitDefaults(); |
| } |
| } |
| return null; |
| } |
| |
| |
| //************** PersistenceUnit2_0 implementation *********** |
| |
| public PersistenceUnitProperties getConnection() { |
| return this.connection; |
| } |
| |
| public PersistenceUnitProperties getOptions() { |
| return this.options; |
| } |
| |
| // ********** shared cache mode ********** |
| |
| public SharedCacheMode getSharedCacheMode() { |
| return (this.specifiedSharedCacheMode != null) ? this.specifiedSharedCacheMode : this.defaultSharedCacheMode; |
| } |
| |
| public SharedCacheMode getSpecifiedSharedCacheMode() { |
| return this.specifiedSharedCacheMode; |
| } |
| |
| public void setSpecifiedSharedCacheMode(SharedCacheMode specifiedSharedCacheMode) { |
| SharedCacheMode old = this.specifiedSharedCacheMode; |
| this.specifiedSharedCacheMode = specifiedSharedCacheMode; |
| this.xmlPersistenceUnit.setSharedCacheMode(SharedCacheMode.toXmlResourceModel(specifiedSharedCacheMode)); |
| this.firePropertyChanged(SPECIFIED_SHARED_CACHE_MODE_PROPERTY, old, specifiedSharedCacheMode); |
| } |
| |
| public SharedCacheMode getDefaultSharedCacheMode() { |
| return this.defaultSharedCacheMode; |
| } |
| |
| protected void setDefaultSharedCacheMode(SharedCacheMode defaultSharedCacheMode) { |
| SharedCacheMode old = this.defaultSharedCacheMode; |
| this.defaultSharedCacheMode = defaultSharedCacheMode; |
| this.firePropertyChanged(DEFAULT_SHARED_CACHE_MODE_PROPERTY, old, defaultSharedCacheMode); |
| } |
| |
| public boolean calculateDefaultCacheable() { |
| switch (getSharedCacheMode()) { |
| case NONE: |
| case ENABLE_SELECTIVE: |
| case UNSPECIFIED: |
| return false; |
| case ALL: |
| case DISABLE_SELECTIVE: |
| return true; |
| } |
| return false;//null |
| } |
| |
| protected SharedCacheMode buildSpecifiedSharedCacheMode() { |
| return SharedCacheMode.fromXmlResourceModel(this.xmlPersistenceUnit.getSharedCacheMode()); |
| } |
| |
| protected SharedCacheMode buildDefaultSharedCacheMode() { |
| return SharedCacheMode.UNSPECIFIED; |
| } |
| |
| // ********** validation mode ********** |
| |
| public ValidationMode getValidationMode() { |
| return (this.specifiedValidationMode != null) ? this.specifiedValidationMode : this.defaultValidationMode; |
| } |
| |
| public ValidationMode getSpecifiedValidationMode() { |
| return this.specifiedValidationMode; |
| } |
| |
| public void setSpecifiedValidationMode(ValidationMode specifiedValidationMode) { |
| ValidationMode old = this.specifiedValidationMode; |
| this.specifiedValidationMode = specifiedValidationMode; |
| this.xmlPersistenceUnit.setValidationMode(ValidationMode.toXmlResourceModel(specifiedValidationMode)); |
| this.firePropertyChanged(SPECIFIED_VALIDATION_MODE_PROPERTY, old, specifiedValidationMode); |
| } |
| |
| public ValidationMode getDefaultValidationMode() { |
| return this.defaultValidationMode; |
| } |
| |
| protected void setDefaultValidationMode(ValidationMode defaultValidationMode) { |
| ValidationMode old = this.defaultValidationMode; |
| this.defaultValidationMode = defaultValidationMode; |
| this.firePropertyChanged(DEFAULT_VALIDATION_MODE_PROPERTY, old, defaultValidationMode); |
| } |
| |
| protected ValidationMode buildSpecifiedValidationMode() { |
| return ValidationMode.fromXmlResourceModel(this.xmlPersistenceUnit.getValidationMode()); |
| } |
| |
| protected ValidationMode buildDefaultValidationMode() { |
| return DEFAULT_VALIDATION_MODE; |
| } |
| |
| |
| // ********** generators ********** |
| |
| public ListIterator<Generator> generators() { |
| return new CloneListIterator<Generator>(this.generators); |
| } |
| |
| public int generatorsSize() { |
| return this.generators.size(); |
| } |
| |
| public void addGenerator(Generator generator) { |
| this.generators.add(generator); |
| } |
| |
| public String[] uniqueGeneratorNames() { |
| HashSet<String> names = new HashSet<String>(this.generators.size()); |
| this.addNonNullGeneratorNamesTo(names); |
| return names.toArray(new String[names.size()]); |
| } |
| |
| protected void addNonNullGeneratorNamesTo(Set<String> names) { |
| for (Iterator<Generator> stream = this.generators(); stream.hasNext(); ) { |
| String generatorName = stream.next().getName(); |
| if (generatorName != null) { |
| names.add(generatorName); |
| } |
| } |
| } |
| |
| |
| // ********** queries ********** |
| |
| public ListIterator<Query> queries() { |
| return new CloneListIterator<Query>(this.queries); |
| } |
| |
| public int queriesSize() { |
| return this.queries.size(); |
| } |
| |
| public void addQuery(Query query) { |
| this.queries.add(query); |
| } |
| |
| |
| // ********** root entities ********** |
| |
| public void addRootEntityWithSubEntities(String entityName) { |
| this.rootEntityNames.add(entityName); |
| } |
| |
| public boolean entityIsRootWithSubEntities(String entityName) { |
| return this.rootEntityNames.contains(entityName); |
| } |
| |
| |
| // ********** validation ********** |
| |
| @Override |
| public void validate(List<IMessage> messages, IReporter reporter) { |
| super.validate(messages, reporter); |
| this.validateMappingFiles(messages, reporter); |
| this.validateClassRefs(messages, reporter); |
| this.validateJarFileRefs(messages, reporter); |
| this.validateProperties(messages, reporter); |
| } |
| |
| protected void validateMappingFiles(List<IMessage> messages, IReporter reporter) { |
| this.checkForMultiplePersistenceUnitDefaults(messages); |
| this.checkForDuplicateMappingFiles(messages); |
| for (MappingFileRef mappingFileRef : this.getMappingFileRefs()) { |
| mappingFileRef.validate(messages, reporter); |
| } |
| } |
| |
| protected void checkForMultiplePersistenceUnitDefaults(List<IMessage> messages) { |
| boolean first = true; |
| for (MappingFileRef mappingFileRef : this.getMappingFileRefs()) { |
| if (mappingFileRef.persistenceUnitDefaultsExists()) { |
| if (first) { |
| first = false; |
| } else { |
| messages.add( |
| DefaultJpaValidationMessages.buildMessage( |
| IMessage.NORMAL_SEVERITY, |
| JpaValidationMessages.MAPPING_FILE_EXTRANEOUS_PERSISTENCE_UNIT_DEFAULTS, |
| new String[] {mappingFileRef.getFileName()}, |
| mappingFileRef |
| ) |
| ); |
| } |
| } |
| } |
| } |
| |
| protected void checkForDuplicateMappingFiles(List<IMessage> messages) { |
| HashBag<String> fileNames = new HashBag<String>(); |
| CollectionTools.addAll(fileNames, this.mappingFileRefNames()); |
| for (MappingFileRef mappingFileRef : this.getMappingFileRefs()) { |
| String fileName = mappingFileRef.getFileName(); |
| if (fileNames.count(fileName) > 1) { |
| messages.add( |
| DefaultJpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| JpaValidationMessages.PERSISTENCE_UNIT_DUPLICATE_MAPPING_FILE, |
| new String[] {fileName}, |
| mappingFileRef, |
| mappingFileRef.getValidationTextRange() |
| ) |
| ); |
| } |
| } |
| } |
| |
| protected Iterator<String> mappingFileRefNames() { |
| return new TransformationIterator<MappingFileRef, String>(this.mappingFileRefs()) { |
| @Override |
| protected String transform(MappingFileRef mappingFileRef) { |
| return mappingFileRef.getFileName(); |
| } |
| }; |
| } |
| |
| protected void validateClassRefs(List<IMessage> messages, IReporter reporter) { |
| this.checkForDuplicateClasses(messages); |
| for (Iterator<ClassRef> stream = this.classRefs(); stream.hasNext(); ) { |
| stream.next().validate(messages, reporter); |
| } |
| } |
| |
| protected void checkForDuplicateClasses(List<IMessage> messages) { |
| HashBag<String> classNames = new HashBag<String>(); |
| CollectionTools.addAll(classNames, this.classRefNames()); |
| for (Iterator<ClassRef> stream = this.classRefs(); stream.hasNext(); ) { |
| ClassRef classRef = stream.next(); |
| String className = classRef.getClassName(); |
| if ((className != null) && (classNames.count(className) > 1)) { |
| messages.add( |
| DefaultJpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| JpaValidationMessages.PERSISTENCE_UNIT_DUPLICATE_CLASS, |
| new String[] {className}, |
| classRef, |
| classRef.getValidationTextRange() |
| ) |
| ); |
| } |
| } |
| } |
| |
| protected Iterator<String> classRefNames() { |
| return new TransformationIterator<ClassRef, String>(this.classRefs()) { |
| @Override |
| protected String transform(ClassRef classRef) { |
| return classRef.getClassName(); |
| } |
| }; |
| } |
| |
| protected void validateJarFileRefs(List<IMessage> messages, IReporter reporter) { |
| checkForDuplicateJarFileRefs(messages); |
| for (JarFileRef each : CollectionTools.iterable(jarFileRefs())) { |
| each.validate(messages, reporter); |
| } |
| } |
| |
| protected void checkForDuplicateJarFileRefs(List<IMessage> messages) { |
| HashBag<String> jarFileNames = new HashBag<String>(); |
| CollectionTools.addAll(jarFileNames, jarFileNames()); |
| for (JarFileRef jarFileRef : CollectionTools.iterable(jarFileRefs())) { |
| String jarFileName = jarFileRef.getFileName(); |
| if ((jarFileName != null) && (jarFileNames.count(jarFileName) > 1)) { |
| messages.add( |
| DefaultJpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| JpaValidationMessages.PERSISTENCE_UNIT_DUPLICATE_JAR_FILE, |
| new String[] {jarFileName}, |
| jarFileRef, |
| jarFileRef.getValidationTextRange() |
| ) |
| ); |
| } |
| } |
| } |
| |
| protected Iterator<String> jarFileNames() { |
| return new TransformationIterator<JarFileRef, String>(jarFileRefs()) { |
| @Override |
| protected String transform(JarFileRef jarFileRef) { |
| return jarFileRef.getFileName(); |
| } |
| }; |
| } |
| |
| @SuppressWarnings("unused") |
| protected void validateProperties(List<IMessage> messages, IReporter reporter) { |
| // do nothing by default |
| } |
| |
| |
| // ********** misc ********** |
| |
| public JpaStructureNode getStructureNode(int textOffset) { |
| for (Iterator<JarFileRef> stream = this.jarFileRefs(); stream.hasNext(); ) { |
| JarFileRef jarFileRef = stream.next(); |
| if (jarFileRef.containsOffset(textOffset)) { |
| return jarFileRef; |
| } |
| } |
| for (MappingFileRef mappingFileRef : this.getMappingFileRefs()) { |
| if (mappingFileRef.containsOffset(textOffset)) { |
| return mappingFileRef; |
| } |
| } |
| for (Iterator<ClassRef> stream = this.classRefs(); stream.hasNext(); ) { |
| ClassRef classRef = stream.next(); |
| if (classRef.containsOffset(textOffset)) { |
| return classRef; |
| } |
| } |
| return this; |
| } |
| |
| public boolean shouldValidateAgainstDatabase() { |
| return connectionProfileIsActive(); |
| } |
| |
| public TextRange getValidationTextRange() { |
| return this.xmlPersistenceUnit.getValidationTextRange(); |
| } |
| |
| public PersistentType getPersistentType(String typeName) { |
| for (MappingFileRef mappingFileRef : this.getMappingFileRefs()) { |
| PersistentType persistentType = mappingFileRef.getPersistentType(typeName); |
| if (persistentType != null) { |
| return persistentType; |
| } |
| } |
| for (Iterator<ClassRef> stream = this.classRefs(); stream.hasNext(); ) { |
| ClassRef classRef = stream.next(); |
| if (classRef.isFor(typeName)) { |
| return classRef.getJavaPersistentType(); |
| } |
| } |
| for (Iterator<JarFileRef> stream = this.jarFileRefs(); stream.hasNext(); ) { |
| PersistentType persistentType = stream.next().getPersistentType(typeName); |
| if (persistentType != null) { |
| return persistentType; |
| } |
| } |
| return null; |
| } |
| |
| public boolean specifiesPersistentType(String className) { |
| for (ClassRef classRef : this.getSpecifiedClassRefs()) { |
| if (classRef.isFor(className)) { |
| return true; |
| } |
| } |
| for (MappingFileRef mappingFileRef : this.getMappingFileRefs()) { |
| if (mappingFileRef.getPersistentType(className) != null) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public Entity getEntity(String typeName) { |
| PersistentType persistentType = this.getPersistentType(typeName); |
| if (persistentType == null) { |
| return null; |
| } |
| TypeMapping typeMapping = persistentType.getMapping(); |
| return (typeMapping instanceof Entity) ? (Entity) typeMapping : null; |
| } |
| |
| public Embeddable getEmbeddable(String typeName) { |
| PersistentType persistentType = this.getPersistentType(typeName); |
| if (persistentType == null) { |
| return null; |
| } |
| TypeMapping typeMapping = persistentType.getMapping(); |
| return (typeMapping instanceof Embeddable) ? (Embeddable) typeMapping : null; |
| } |
| |
| public boolean containsOffset(int textOffset) { |
| return (this.xmlPersistenceUnit != null) && this.xmlPersistenceUnit.containsOffset(textOffset); |
| } |
| |
| @Override |
| public void toString(StringBuilder sb) { |
| super.toString(sb); |
| sb.append(this.name); |
| } |
| |
| |
| // ********** metamodel ********** |
| // put metamodel stuff here so it can be shared by Generic and EclipseLink implementations |
| |
| public void initializeMetamodel() { |
| this.initializeMetamodelFiles(); |
| } |
| |
| protected void initializeMetamodelFiles() { |
| CollectionTools.addAll(this.metamodelFiles, this.getGeneratedMetamodelFiles()); |
| } |
| |
| protected Iterable<IFile> getGeneratedMetamodelFiles() { |
| return new TransformationIterable<JavaResourcePersistentType2_0, IFile>(this.getGeneratedMetamodelTopLevelTypes()) { |
| @Override |
| protected IFile transform(JavaResourcePersistentType2_0 jrpt) { |
| return jrpt.getFile(); |
| } |
| }; |
| } |
| |
| protected Iterable<JavaResourcePersistentType2_0> getGeneratedMetamodelTopLevelTypes() { |
| return ((JpaProject2_0) this.getJpaProject()).getGeneratedMetamodelTopLevelTypes(); |
| } |
| |
| /** |
| * Not the prettiest code.... |
| */ |
| public void synchronizeMetamodel() { |
| // gather up the persistent unit's types, eliminating duplicates; |
| // if we have persistent types with the same name in multiple locations, |
| // the last one we encounter wins (i.e. the classes in the orm.xml take |
| // precedence) |
| HashMap<String, PersistentType2_0> allPersistentTypes = new HashMap<String, PersistentType2_0>(); |
| this.addPersistentTypesTo_(this.getJarFileRefs(), allPersistentTypes); |
| this.addPersistentTypesTo(this.getNonNullClassRefPersistentTypes(), allPersistentTypes); |
| this.addPersistentTypesTo_(this.getMappingFileRefs(), allPersistentTypes); |
| |
| // build a list of the top-level types and a tree of their associated |
| // member types etc. |
| ArrayList<MetamodelSourceType> topLevelTypes = new ArrayList<MetamodelSourceType>(allPersistentTypes.size()); |
| HashMap<String, Collection<MetamodelSourceType>> memberTypeTree = new HashMap<String, Collection<MetamodelSourceType>>(); |
| for (PersistentType2_0 type : allPersistentTypes.values()) { |
| String declaringTypeName = type.getDeclaringTypeName(); |
| MetamodelSourceType memberType = type; |
| while (true) { |
| if (declaringTypeName == null) { |
| topLevelTypes.add(memberType); |
| break; // stop at the top-level type |
| } |
| |
| // associate the member type with its declaring type |
| Collection<MetamodelSourceType> memberTypes = memberTypeTree.get(declaringTypeName); |
| if (memberTypes == null) { |
| memberTypes = new ArrayList<MetamodelSourceType>(); |
| memberTypeTree.put(declaringTypeName, memberTypes); |
| } |
| memberTypes.add(memberType); |
| |
| // move out to the member type's declaring type |
| String memberTypeName = declaringTypeName; |
| // check for a context persistent type |
| memberType = allPersistentTypes.get(memberTypeName); |
| if (memberType != null) { |
| break; // stop - this will be processed in the outer 'for' loop |
| } |
| // check for a Java resource persistent type |
| JavaResourcePersistentType jrpt = this.getJpaProject().getJavaResourcePersistentType(memberTypeName); |
| if (jrpt != null) { |
| declaringTypeName = jrpt.getDeclaringTypeName(); |
| } else { |
| // check for a JDT type |
| IType jdtType = this.findJdtType(memberTypeName); |
| if (jdtType != null) { |
| IType jdtDeclaringType = jdtType.getDeclaringType(); |
| declaringTypeName = (jdtDeclaringType == null) ? null : jdtDeclaringType.getFullyQualifiedName('.'); |
| } else { |
| // assume we have a non-persistent top-level type...? |
| declaringTypeName = null; |
| } |
| } |
| if (declaringTypeName == null) { |
| memberType = this.selectSourceType(topLevelTypes, memberTypeName); |
| } else { |
| memberType = this.selectSourceType(memberTypeTree.get(declaringTypeName), memberTypeName); |
| } |
| if (memberType != null) { |
| break; // stop - this type has already been processed |
| } |
| memberType = this.buildNonPersistentMetamodelSourceType(memberTypeName); |
| } |
| } |
| |
| // remove any top-level type whose name differs from another only by case, |
| // since, on Windows, file names are case-insensitive :-( |
| // sort the original list so we end up with the same top-level type |
| // remaining every time (i.e. the one that sorts out first) |
| Collections.sort(topLevelTypes, MetamodelSourceType.COMPARATOR); |
| HashSet<String> names = new HashSet<String>(topLevelTypes.size()); |
| for (Iterator<MetamodelSourceType> stream = topLevelTypes.iterator(); stream.hasNext(); ) { |
| MetamodelSourceType topLevelType = stream.next(); |
| // hopefully this is case-insensitive enough... |
| if ( ! names.add(topLevelType.getName().toLowerCase())) { |
| stream.remove(); |
| } |
| } |
| |
| // copy the list of metamodel files... |
| HashSet<IFile> deadMetamodelFiles = new HashSet<IFile>(this.metamodelFiles); |
| this.metamodelFiles.clear(); |
| for (MetamodelSourceType topLevelType : topLevelTypes) { |
| IFile metamodelFile = topLevelType.getMetamodelFile(); |
| // ...remove whatever files are still present... |
| deadMetamodelFiles.remove(metamodelFile); |
| // ...rebuild the list of metamodel files... |
| if (this.fileIsGeneratedMetamodel(metamodelFile)) { // only add files with the Dali tag |
| this.metamodelFiles.add(metamodelFile); |
| } |
| } |
| // ...delete the files that are now gone |
| // [perform the deletes first - this is critical when a file has been |
| // renamed by only altering its name's case; since we will try to write |
| // out a new file that, on Windows, collides with the old file :-( ] |
| for (IFile deadMetamodelFile : deadMetamodelFiles) { |
| this.deleteMetamodelFile(deadMetamodelFile); |
| } |
| |
| // now generate the metamodel classes |
| for (MetamodelSourceType topLevelType : topLevelTypes) { |
| topLevelType.synchronizeMetamodel(memberTypeTree); |
| } |
| } |
| |
| protected void addPersistentTypesTo_(Iterable<? extends PersistentTypeContainer> ptContainers, HashMap<String, PersistentType2_0> persistentTypeMap) { |
| for (PersistentTypeContainer ptContainer : ptContainers) { |
| this.addPersistentTypesTo(ptContainer.getPersistentTypes(), persistentTypeMap); |
| } |
| } |
| |
| protected void addPersistentTypesTo(Iterable<? extends PersistentType> persistentTypes, HashMap<String, PersistentType2_0> persistentTypeMap) { |
| for (PersistentType persistentType : persistentTypes) { |
| if (persistentType.getName() != null) { |
| persistentTypeMap.put(persistentType.getName(), (PersistentType2_0) persistentType); |
| } |
| } |
| } |
| |
| protected MetamodelSourceType selectSourceType(Iterable<MetamodelSourceType> types, String typeName) { |
| if (types != null) { |
| for (MetamodelSourceType type : types) { |
| if (type.getName().equals(typeName)) { |
| return type; |
| } |
| } |
| } |
| return null; |
| } |
| |
| protected MetamodelSourceType buildNonPersistentMetamodelSourceType(String nonPersistentTypeName) { |
| return new NonPersistentMetamodelSourceType(nonPersistentTypeName, this.getJpaProject()); |
| } |
| |
| protected IType findJdtType(String typeName) { |
| try { |
| return this.getJpaProject().getJavaProject().findType(typeName); |
| } catch (JavaModelException ex) { |
| JptCorePlugin.log(ex); |
| return null; |
| } |
| } |
| |
| protected void deleteMetamodelFile(IFile file) { |
| try { |
| this.deleteMetamodelFile_(file); |
| } catch (CoreException ex) { |
| JptCorePlugin.log(ex); |
| } |
| } |
| |
| protected void deleteMetamodelFile_(IFile file) throws CoreException { |
| if (this.fileIsGeneratedMetamodel(file)) { |
| file.delete(true, null); // true = force |
| } |
| } |
| |
| protected boolean fileIsGeneratedMetamodel(IFile file) { |
| return ((JpaProject2_0) this.getJpaProject()).getGeneratedMetamodelTopLevelType(file) != null; |
| } |
| |
| public void disposeMetamodel() { |
| this.metamodelFiles.clear(); |
| } |
| |
| // ***** Metamodel source for non-persistent types |
| protected static class NonPersistentMetamodelSourceType |
| implements MetamodelSourceType |
| { |
| protected final String name; |
| protected final JpaProject jpaProject; |
| protected final MetamodelSourceType.Synchronizer metamodelSynchronizer; |
| |
| protected NonPersistentMetamodelSourceType(String name, JpaProject jpaProject) { |
| super(); |
| this.name = name; |
| this.jpaProject = jpaProject; |
| this.metamodelSynchronizer = this.buildMetamodelSynchronizer(); |
| } |
| |
| protected MetamodelSourceType.Synchronizer buildMetamodelSynchronizer() { |
| return this.getJpaFactory().buildMetamodelSynchronizer(this); |
| } |
| |
| protected JpaFactory2_0 getJpaFactory() { |
| return (JpaFactory2_0) this.getJpaProject().getJpaPlatform().getJpaFactory(); |
| } |
| |
| public String getName() { |
| return this.name; |
| } |
| |
| public boolean isManaged() { |
| return false; |
| } |
| |
| public PersistentType getSuperPersistentType() { |
| return null; |
| } |
| |
| public <T extends PersistentAttribute> ListIterator<T> attributes() { |
| return EmptyListIterator.instance(); |
| } |
| |
| public IFile getMetamodelFile() { |
| return this.metamodelSynchronizer.getFile(); |
| } |
| |
| public JpaProject getJpaProject() { |
| return this.jpaProject; |
| } |
| |
| public void synchronizeMetamodel(Map<String, Collection<MetamodelSourceType>> memberTypeTree) { |
| this.metamodelSynchronizer.synchronize(memberTypeTree); |
| } |
| |
| public void printBodySourceOn(BodySourceWriter pw, Map<String, Collection<MetamodelSourceType>> memberTypeTree) { |
| this.metamodelSynchronizer.printBodySourceOn(pw, memberTypeTree); |
| } |
| } |
| |
| } |