blob: 4fae0acdbca4ed086d403d2c05fdc56b87cc96b8 [file] [log] [blame]
/*******************************************************************************
* 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())
);
}
}
}
}