| /******************************************************************************* |
| * Copyright (c) 2006 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.platform; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.List; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jem.java.JavaClass; |
| import org.eclipse.jpt.core.internal.AccessType; |
| import org.eclipse.jpt.core.internal.IJpaFile; |
| import org.eclipse.jpt.core.internal.IJpaProject; |
| import org.eclipse.jpt.core.internal.IMappingKeys; |
| import org.eclipse.jpt.core.internal.IPersistentType; |
| import org.eclipse.jpt.core.internal.content.java.IJavaTypeMapping; |
| import org.eclipse.jpt.core.internal.content.java.JavaPersistentType; |
| import org.eclipse.jpt.core.internal.content.orm.PersistenceUnitDefaults; |
| import org.eclipse.jpt.core.internal.content.orm.PersistenceUnitMetadata; |
| import org.eclipse.jpt.core.internal.content.orm.XmlRootContentNode; |
| import org.eclipse.jpt.core.internal.content.persistence.JavaClassRef; |
| import org.eclipse.jpt.core.internal.content.persistence.MappingFileRef; |
| import org.eclipse.jpt.core.internal.content.persistence.PersistenceUnit; |
| import org.eclipse.jpt.core.internal.validation.IJpaValidationMessages; |
| import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; |
| import org.eclipse.jpt.utility.internal.CollectionTools; |
| import org.eclipse.jpt.utility.internal.HashBag; |
| import org.eclipse.jpt.utility.internal.iterators.CompositeIterator; |
| import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; |
| import org.eclipse.wst.validation.internal.provisional.core.IMessage; |
| |
| public class PersistenceUnitContext extends BaseContext |
| { |
| private PersistenceUnit persistenceUnit; |
| |
| private List<PersistenceUnitMetadata> persistenceUnitMetadatas; // datas ?? datae ?? datata ?? |
| |
| private List<MappingFileContext> mappingFileContexts; |
| private List<JavaTypeContext> javaPersistentTypeContexts; |
| //private Collection<JarFileContext> jarFilesContexts; |
| |
| private IGeneratorRepository generatorRepository; |
| /** |
| * Stores the JavaPersistentTypeContext for JavaPersistentTypes that are referenced |
| * by more than one orm.xml file. An error will be given to the user for this condition |
| * and the defaults will not be based on a persistence unit or orm.xml file. |
| */ |
| private Collection<JavaTypeContext> duplicateJavaPersistentTypes; |
| |
| |
| public PersistenceUnitContext(IContext parentContext, PersistenceUnit persistenceUnit) { |
| super(parentContext); |
| this.persistenceUnit = persistenceUnit; |
| this.persistenceUnitMetadatas = buildPersistenceUnitMetadatas(); |
| this.duplicateJavaPersistentTypes = new ArrayList<JavaTypeContext>(); |
| this.mappingFileContexts = buildMappingFileContexts(); |
| this.javaPersistentTypeContexts = buildJavaClassesContexts(); |
| this.generatorRepository = buildGeneratorRepository(); |
| } |
| |
| @Override |
| protected void initialize() { |
| } |
| |
| private List<PersistenceUnitMetadata> buildPersistenceUnitMetadatas() { |
| List<PersistenceUnitMetadata> metadatas = new ArrayList<PersistenceUnitMetadata>(); |
| for (MappingFileRef mappingFileRef : persistenceUnit.getMappingFiles()) { |
| XmlRootContentNode content = xmlRootContentNodeFor(mappingFileRef); |
| if (content != null && content.getEntityMappings() != null |
| && ! content.getEntityMappings().getPersistenceUnitMetadata().isAllFeaturesUnset()) { |
| metadatas.add(content.getEntityMappings().getPersistenceUnitMetadata()); |
| } |
| } |
| return metadatas; |
| } |
| |
| protected List<MappingFileContext> buildMappingFileContexts() { |
| List<MappingFileContext> contexts = new ArrayList<MappingFileContext>(); |
| for (MappingFileRef mappingFileRef : persistenceUnit.getMappingFiles()) { |
| XmlRootContentNode xmlRootContentNode = xmlRootContentNodeFor(mappingFileRef); |
| if (xmlRootContentNode != null && xmlRootContentNode.getEntityMappings() != null) { |
| contexts.add(new MappingFileContext(this, xmlRootContentNode)); |
| } |
| } |
| return contexts; |
| } |
| |
| private XmlRootContentNode xmlRootContentNodeFor(MappingFileRef mappingFileRef) { |
| IJpaFile jpaFile = mappingFileRef.getMappingFile(); |
| if (jpaFile != null) { |
| try { |
| return (XmlRootContentNode) jpaFile.getContent(); |
| } |
| catch (ClassCastException cce) { /* do nothing, return null */ } |
| } |
| return null; |
| } |
| |
| protected List<JavaTypeContext> buildJavaClassesContexts() { |
| List<JavaTypeContext> javaPersistentTypeContexts = new ArrayList<JavaTypeContext>(); |
| for (JavaClassRef javaClassRef : persistenceUnit.getClasses()) { |
| JavaPersistentType javaPersistentType = javaPersistentTypeFor(javaClassRef); |
| if (javaPersistentType != null) { |
| //if it's already specified in an orm.xml file then that is its context, |
| //no need to add a javaTypeMappingContext |
| if (xmlTypeMappingContextFor(javaPersistentType.getMapping())== null) { |
| JavaTypeContext javaTypeContext = |
| (JavaTypeContext) getPlatform().buildJavaTypeContext(this, javaPersistentType.getMapping()); |
| javaPersistentTypeContexts.add(javaTypeContext); |
| } |
| } |
| } |
| |
| return javaPersistentTypeContexts; |
| } |
| |
| /** |
| * Iterate JavaTypeContexts firt to add generators to the repository. |
| * Then iterator through the MappingFileContexts and override any generators |
| * with the same name in the java |
| * |
| * @return |
| */ |
| protected IGeneratorRepository buildGeneratorRepository() { |
| GeneratorRepository generatorRepository = new GeneratorRepository(); |
| for (JavaTypeContext context : this.javaPersistentTypeContexts) { |
| context.populateGeneratorRepository(generatorRepository); |
| } |
| for (MappingFileContext context : this.mappingFileContexts) { |
| context.populateGeneratorRepository(generatorRepository); |
| } |
| |
| return generatorRepository; |
| } |
| |
| private JavaPersistentType javaPersistentTypeFor(JavaClassRef javaClassRef) { |
| JavaClass javaClass = javaClassRef.getJavaClass(); |
| if (javaClass == null) { |
| return null; |
| } |
| IType type = (IType) javaClass.getReflectionType(); |
| return jpaProject().findJavaPersistentType(type); |
| } |
| |
| /** |
| * Find an XmlTypeMappingContext that references the given IJavaTYpeMapping by |
| * specifying that java class for one of its entities, embeddables, or mapped superclasses |
| |
| */ |
| public XmlTypeContext xmlTypeMappingContextFor(IJavaTypeMapping javaTypeMapping) { |
| for (MappingFileContext context : this.mappingFileContexts) { |
| XmlTypeContext xmlTypeMappingContext = context.xmlTypeMappingContextFor(javaTypeMapping); |
| if (xmlTypeMappingContext != null) { |
| return xmlTypeMappingContext; |
| } |
| } |
| return null; |
| } |
| |
| protected IJpaProject jpaProject() { |
| return this.persistenceUnit.getJpaProject(); |
| } |
| |
| public void refreshDefaults(DefaultsContext parentDefaults) { |
| super.refreshDefaults(parentDefaults); |
| for (JavaTypeContext context : this.duplicateJavaPersistentTypes) { |
| // context for duplicates not be based on the persistenceUnit defaults, |
| // so we're going to use the one passed here without wrapping it |
| context.refreshDefaults(parentDefaults); |
| } |
| DefaultsContext defaults = wrapDefaultsContext(parentDefaults); |
| for (MappingFileContext context : this.mappingFileContexts) { |
| context.refreshDefaults(defaults); |
| } |
| for (JavaTypeContext context : this.javaPersistentTypeContexts) { |
| context.refreshDefaults(defaults); |
| } |
| |
| //TODO somehow need to clear out defaults for the duplicateJpaFiles, |
| //do i have to build JavaTypeContext for those as well? |
| } |
| |
| protected DefaultsContext wrapDefaultsContext(DefaultsContext defaults) { |
| final DefaultsContext puDefaults = buildPersistenceUnitDefaults(defaults); |
| return new DefaultsContext(){ |
| public Object getDefault(String key) { |
| return puDefaults.getDefault(key); |
| } |
| public IPersistentType persistentType(String fullyQualifiedTypeName) { |
| for (Iterator<TypeContext> i = typeContexts(); i.hasNext(); ) { |
| TypeContext typeContext = i.next(); |
| IPersistentType persistentType = typeContext.getPersistentType(); |
| IType jdtType = persistentType.findJdtType(); |
| if (jdtType != null |
| && fullyQualifiedTypeName.equals(jdtType.getFullyQualifiedName())) { |
| if (! typeContext.isRefreshed()) { |
| typeContext.refreshDefaults(this); |
| } |
| return persistentType; |
| } |
| } |
| return null; |
| } |
| }; |
| } |
| |
| protected DefaultsContext buildPersistenceUnitDefaults(final DefaultsContext defaults) { |
| if (persistenceUnitMetadatas.size() == 1) { |
| final PersistenceUnitDefaults puDefaults = persistenceUnitMetadatas.get(0).getPersistenceUnitDefaults(); |
| if (puDefaults.isAllFeaturesUnset()) { |
| return defaults; |
| } |
| |
| return new DefaultsContext() { |
| public Object getDefault(String key) { |
| if (key.equals(BaseJpaPlatform.DEFAULT_TABLE_SCHEMA_KEY) |
| || key.equals(BaseJpaPlatform.DEFAULT_TABLE_GENERATOR_SCHEMA_KEY)) { |
| String schema = puDefaults.getSchema(); |
| if (schema != null) { |
| return schema; |
| } |
| } |
| if (key.equals(BaseJpaPlatform.DEFAULT_TABLE_CATALOG_KEY)) { |
| String catalog = puDefaults.getCatalog(); |
| if (catalog != null) { |
| return catalog; |
| } |
| } |
| if (key.equals(BaseJpaPlatform.DEFAULT_ACCESS_KEY)) { |
| AccessType access = puDefaults.getAccess(); |
| if (access != null) { |
| return access; |
| } |
| } |
| return defaults.getDefault(key); |
| } |
| public IPersistentType persistentType(String fullyQualifiedTypeName) { |
| return defaults.persistentType(fullyQualifiedTypeName); |
| } |
| }; |
| } |
| |
| return defaults; |
| } |
| |
| private Iterator<TypeContext> typeContexts() { |
| return new CompositeIterator<TypeContext>(mappingFileTypeContexts(), javaTypeContexts()); |
| } |
| |
| private Iterator mappingFileTypeContexts() { |
| return new CompositeIterator( |
| new TransformationIterator(this.mappingFileContexts.iterator()) { |
| protected Object transform(Object next) { |
| return ((MappingFileContext) next).typeContexts(); |
| } |
| } |
| ); |
| } |
| |
| private Iterator javaTypeContexts() { |
| return this.javaPersistentTypeContexts.iterator(); |
| } |
| |
| public void addDuplicateJpaFile(JavaTypeContext javaPersistentTypeContext) { |
| this.duplicateJavaPersistentTypes.add(javaPersistentTypeContext); |
| } |
| |
| public boolean containsDuplicateJavaPersistentType(JavaPersistentType javaPersistentType) { |
| for (JavaTypeContext context : this.duplicateJavaPersistentTypes) { |
| if (context.getPersistentType() == javaPersistentType) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public boolean contains(IPersistentType persistentType) { |
| for (MappingFileContext context : this.mappingFileContexts) { |
| if (context.contains(persistentType)) { |
| return true; |
| } |
| } |
| for (JavaTypeContext context : this.javaPersistentTypeContexts) { |
| if (context.contains(persistentType)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public IGeneratorRepository getGeneratorRepository() { |
| return this.generatorRepository; |
| } |
| |
| public void addToMessages(List<IMessage> messages) { |
| super.addToMessages(messages); |
| addMappingFileMessages(messages); |
| addClassMessages(messages); |
| } |
| |
| protected void addMappingFileMessages(List<IMessage> messages) { |
| addMultipleMetadataMessages(messages); |
| addUnspecifiedMappingFileMessages(messages); |
| addUnresolvedMappingFileMessages(messages); |
| addInvalidMappingFileContentMessage(messages); |
| addDuplicateMappingFileMessages(messages); |
| |
| for (MappingFileContext mappingFileContext : mappingFileContexts) { |
| mappingFileContext.addToMessages(messages); |
| } |
| } |
| |
| protected void addMultipleMetadataMessages(List<IMessage> messages) { |
| if (persistenceUnitMetadatas.size() > 1) { |
| for (PersistenceUnitMetadata metadata : persistenceUnitMetadatas) { |
| messages.add( |
| JpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| IJpaValidationMessages.ENTITY_MAPPINGS_MULTIPLE_METADATA, |
| new String[] {persistenceUnit.getName()}, |
| metadata, metadata.getTextRange()) |
| ); |
| } |
| } |
| } |
| |
| protected void addUnspecifiedMappingFileMessages(List<IMessage> messages) { |
| for (MappingFileRef mappingFileRef : persistenceUnit.getMappingFiles()) { |
| if (mappingFileRef.getFileName() == null || mappingFileRef.getFileName().equals("")) { |
| messages.add( |
| JpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| IJpaValidationMessages.PERSISTENCE_UNIT_UNSPECIFIED_MAPPING_FILE, |
| mappingFileRef, mappingFileRef.getTextRange()) |
| ); |
| } |
| } |
| } |
| |
| protected void addUnresolvedMappingFileMessages(List<IMessage> messages) { |
| for (Iterator stream = persistenceUnit.getMappingFiles().iterator(); stream.hasNext(); ) { |
| MappingFileRef mappingFileRef = (MappingFileRef) stream.next(); |
| if (! (mappingFileRef.getFileName() == null || mappingFileRef.getFileName().equals("")) |
| && mappingFileRef.getMappingFile() == null) { |
| messages.add( |
| JpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| IJpaValidationMessages.PERSISTENCE_UNIT_NONEXISTENT_MAPPING_FILE, |
| new String[] {mappingFileRef.getFileName()}, |
| mappingFileRef, mappingFileRef.getTextRange()) |
| ); |
| } |
| } |
| } |
| |
| protected void addInvalidMappingFileContentMessage(List<IMessage> messages) { |
| for (Iterator stream = persistenceUnit.getMappingFiles().iterator(); stream.hasNext(); ) { |
| MappingFileRef mappingFileRef = (MappingFileRef) stream.next(); |
| if (mappingFileRef.getMappingFile() != null |
| && xmlRootContentNodeFor(mappingFileRef) == null) { |
| messages.add( |
| JpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| IJpaValidationMessages.PERSISTENCE_UNIT_INVALID_MAPPING_FILE, |
| new String[] {mappingFileRef.getFileName()}, |
| mappingFileRef, mappingFileRef.getTextRange()) |
| ); |
| } |
| } |
| } |
| |
| protected void addDuplicateMappingFileMessages(List<IMessage> messages) { |
| HashBag fileBag = new HashBag( |
| CollectionTools.collection( |
| new TransformationIterator(persistenceUnit.getMappingFiles().iterator()) { |
| @Override |
| protected Object transform(Object next) { |
| return ((MappingFileRef) next).getFileName(); |
| } |
| } |
| ) |
| ); |
| for (MappingFileRef mappingFileRef : persistenceUnit.getMappingFiles()) { |
| if (fileBag.count(mappingFileRef.getFileName()) > 1) { |
| messages.add( |
| JpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| IJpaValidationMessages.PERSISTENCE_UNIT_DUPLICATE_MAPPING_FILE, |
| new String[] {mappingFileRef.getFileName()}, |
| mappingFileRef, mappingFileRef.getTextRange()) |
| ); |
| } |
| } |
| } |
| |
| protected void addClassMessages(List<IMessage> messages) { |
| addUnspecifiedClassMessages(messages); |
| addUnresolvedClassMessages(messages); |
| addInvalidClassContentMessages(messages); |
| addDuplicateClassMessages(messages); |
| |
| for (JavaTypeContext persistentTypeContext : javaPersistentTypeContexts) { |
| persistentTypeContext.addToMessages(messages); |
| } |
| } |
| |
| protected void addUnspecifiedClassMessages(List<IMessage> messages) { |
| for (JavaClassRef javaClassRef : persistenceUnit.getClasses()) { |
| JavaClass javaClass = javaClassRef.getJavaClass(); |
| if (javaClass == null) { |
| messages.add( |
| JpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| IJpaValidationMessages.PERSISTENCE_UNIT_UNSPECIFIED_CLASS, |
| javaClassRef, javaClassRef.getTextRange()) |
| ); |
| } |
| } |
| } |
| |
| protected void addUnresolvedClassMessages(List<IMessage> messages) { |
| for (JavaClassRef javaClassRef : persistenceUnit.getClasses()) { |
| JavaClass javaClass = javaClassRef.getJavaClass(); |
| if (javaClass != null && javaClass.getReflectionType() == null) { |
| messages.add( |
| JpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| IJpaValidationMessages.PERSISTENCE_UNIT_NONEXISTENT_CLASS, |
| new String[] {javaClass.getQualifiedName()}, |
| javaClassRef, javaClassRef.getTextRange()) |
| ); |
| } |
| } |
| } |
| |
| protected void addInvalidClassContentMessages(List<IMessage> messages) { |
| for (JavaClassRef javaClassRef : persistenceUnit.getClasses()) { |
| JavaClass javaClass = javaClassRef.getJavaClass(); |
| if (javaClass != null && javaClass.getReflectionType() != null |
| && (javaPersistentTypeFor(javaClassRef) == null |
| || javaPersistentTypeFor(javaClassRef).getMappingKey() == IMappingKeys.NULL_TYPE_MAPPING_KEY)) { |
| messages.add( |
| JpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| IJpaValidationMessages.PERSISTENCE_UNIT_INVALID_CLASS, |
| new String[] {javaClassRef.getJavaClass().getQualifiedName()}, |
| javaClassRef, javaClassRef.getTextRange()) |
| ); |
| } |
| } |
| } |
| |
| protected void addDuplicateClassMessages(List<IMessage> messages) { |
| HashBag fileBag = new HashBag( |
| CollectionTools.collection( |
| new TransformationIterator(persistenceUnit.getClasses().iterator()) { |
| @Override |
| protected Object transform(Object next) { |
| JavaClass javaClass = ((JavaClassRef) next).getJavaClass(); |
| return (javaClass == null) ? null : javaClass.getQualifiedName(); |
| } |
| } |
| ) |
| ); |
| for (JavaClassRef javaClassRef : persistenceUnit.getClasses()) { |
| if (javaClassRef.getJavaClass() != null |
| && fileBag.count(javaClassRef.getJavaClass().getQualifiedName()) > 1) { |
| messages.add( |
| JpaValidationMessages.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| IJpaValidationMessages.PERSISTENCE_UNIT_DUPLICATE_CLASS, |
| new String[] {javaClassRef.getJavaClass().getQualifiedName()}, |
| javaClassRef, javaClassRef.getTextRange()) |
| ); |
| } |
| } |
| } |
| } |