blob: 24c82d31b4f285b1924e5455236c246ac8a3705b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2007 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.jpt.core.internal.IMappingKeys;
import org.eclipse.jpt.core.internal.IPersistentAttribute;
import org.eclipse.jpt.core.internal.IPersistentType;
import org.eclipse.jpt.core.internal.content.java.IJavaTypeMapping;
import org.eclipse.jpt.core.internal.content.java.JavaPersistentAttribute;
import org.eclipse.jpt.core.internal.content.java.JavaPersistentType;
import org.eclipse.jpt.core.internal.content.orm.OrmFactory;
import org.eclipse.jpt.core.internal.content.orm.XmlAttributeMapping;
import org.eclipse.jpt.core.internal.content.orm.XmlBasic;
import org.eclipse.jpt.core.internal.content.orm.XmlEmbedded;
import org.eclipse.jpt.core.internal.content.orm.XmlEmbeddedId;
import org.eclipse.jpt.core.internal.content.orm.XmlId;
import org.eclipse.jpt.core.internal.content.orm.XmlManyToMany;
import org.eclipse.jpt.core.internal.content.orm.XmlManyToOne;
import org.eclipse.jpt.core.internal.content.orm.XmlNullAttributeMapping;
import org.eclipse.jpt.core.internal.content.orm.XmlOneToMany;
import org.eclipse.jpt.core.internal.content.orm.XmlOneToOne;
import org.eclipse.jpt.core.internal.content.orm.XmlPersistentAttribute;
import org.eclipse.jpt.core.internal.content.orm.XmlPersistentType;
import org.eclipse.jpt.core.internal.content.orm.XmlTransient;
import org.eclipse.jpt.core.internal.content.orm.XmlTypeMapping;
import org.eclipse.jpt.core.internal.content.orm.XmlVersion;
import org.eclipse.jpt.core.internal.validation.IJpaValidationMessages;
import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
public abstract class XmlTypeContext extends BaseContext
implements TypeContext
{
private XmlTypeMapping xmlTypeMapping;
private JavaTypeContext javaTypeContext;
private Collection<XmlAttributeContext> attributeMappingContexts;
private Collection<XmlAttributeContext> virtualAttributeMappingContexts;
private boolean refreshed;
public XmlTypeContext(MappingFileContext parentContext, XmlTypeMapping xmlTypeMapping) {
super(parentContext);
this.xmlTypeMapping = xmlTypeMapping;
this.attributeMappingContexts = new ArrayList<XmlAttributeContext>();
this.virtualAttributeMappingContexts = new ArrayList<XmlAttributeContext>();
}
public void initialize() {
JavaPersistentType javaPersistentType = javaPersistentType();
PersistenceUnitContext puContext = getMappingFileContext().getPersistenceUnitContext();
if (javaPersistentType != null) {
if (puContext.containsDuplicateJavaPersistentType(javaPersistentType)) {
return;
}
JavaTypeContext javaContext =
(JavaTypeContext) getPlatform().buildJavaTypeContext(this, javaPersistentType.getMapping());
XmlTypeContext duplicate = puContext.xmlTypeMappingContextFor(javaPersistentType.getMapping());
if (duplicate != null) {
duplicate.setDuplicateJavaTypeMapping();
puContext.addDuplicateJpaFile(javaContext);
return;
}
this.javaTypeContext = javaContext;
}
initializeAttributeMappingContexts();
}
protected void initializeAttributeMappingContexts() {
for (XmlAttributeMapping xmlAttributeMapping: this.xmlTypeMapping.getPersistentType().getSpecifiedAttributeMappings()) {
this.attributeMappingContexts.add(buildContext(xmlAttributeMapping));
}
}
protected XmlAttributeContext buildContext(XmlAttributeMapping attributeMapping) {
String key = attributeMapping.getKey();
if (key == IMappingKeys.ID_ATTRIBUTE_MAPPING_KEY) {
return new XmlIdContext(this, (XmlId) attributeMapping);
}
else if (key == IMappingKeys.BASIC_ATTRIBUTE_MAPPING_KEY) {
return new XmlBasicContext(this, (XmlBasic) attributeMapping);
}
else if (key == IMappingKeys.ONE_TO_MANY_ATTRIBUTE_MAPPING_KEY) {
return new XmlOneToManyContext(this, (XmlOneToMany) attributeMapping);
}
else if (key == IMappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY) {
return new XmlManyToOneContext(this, (XmlManyToOne) attributeMapping);
}
else if (key == IMappingKeys.MANY_TO_MANY_ATTRIBUTE_MAPPING_KEY) {
return new XmlManyToManyContext(this, (XmlManyToMany) attributeMapping);
}
else if (key == IMappingKeys.TRANSIENT_ATTRIBUTE_MAPPING_KEY) {
return new XmlTransientContext(this, (XmlTransient) attributeMapping);
}
else if (key == IMappingKeys.EMBEDDED_ATTRIBUTE_MAPPING_KEY) {
return new XmlEmbeddedContext(this, (XmlEmbedded) attributeMapping);
}
else if (key == IMappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY) {
return new XmlEmbeddedIdContext(this, (XmlEmbeddedId) attributeMapping);
}
else if (key == IMappingKeys.VERSION_ATTRIBUTE_MAPPING_KEY) {
return new XmlVersionContext(this, (XmlVersion) attributeMapping);
}
else if (key == IMappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY) {
return new XmlOneToOneContext(this, (XmlOneToOne) attributeMapping);
}
else if (key == null) {
return new XmlNullAttributeMappingContext(this, (XmlNullAttributeMapping) attributeMapping);
}
else {
throw new IllegalArgumentException(attributeMapping.toString());
}
}
protected void populateGeneratorRepository(GeneratorRepository generatorRepository) {
//override as necessary
}
protected Collection<XmlAttributeContext> getXmlAttributeContexts() {
return this.attributeMappingContexts;
}
protected MappingFileContext getMappingFileContext() {
return (MappingFileContext) getParentContext();
}
protected XmlTypeMapping getXmlTypeMapping() {
return this.xmlTypeMapping;
}
protected JavaTypeContext getJavaPersistentTypeContext() {
return this.javaTypeContext;
}
protected IJavaTypeMapping getJavaTypeMapping() {
if (this.javaTypeContext != null) {
return this.javaTypeContext.getPersistentType().getMapping();
}
return null;
}
protected JavaPersistentType javaPersistentType() {
return this.xmlTypeMapping.getPersistentType().findJavaPersistentType();
}
protected IJavaTypeMapping javaTypeMapping() {
JavaPersistentType javaPersistentType = javaPersistentType();
if (javaPersistentType != null) {
return javaPersistentType.getMapping();
}
return null;
}
/**
* A java class is specified to be mapped in to orm.xml files in the same persistence unit.
* Null out the javaTypeMapping for this case, so that the context is no longer a particular
* orm.xml file.
*/
public void setDuplicateJavaTypeMapping() {
this.javaTypeContext = null;
}
public DefaultsContext wrapDefaultsContext(final DefaultsContext defaultsContext) {
return new DefaultsContext() {
public Object getDefault(String key) {
return XmlTypeContext.this.getDefault(key, defaultsContext);
}
public IPersistentType persistentType(String fullyQualifiedTypeName) {
return defaultsContext.persistentType(fullyQualifiedTypeName);
}
};
}
protected Object getDefault(String key, DefaultsContext defaultsContext) {
return defaultsContext.getDefault(key);
}
public XmlPersistentType getPersistentType() {
return getXmlTypeMapping().getPersistentType();
}
public boolean isRefreshed() {
return this.refreshed;
}
public void refreshDefaults(DefaultsContext parentDefaults) {
super.refreshDefaults(parentDefaults);
this.refreshed = true;
if (this.javaTypeContext != null) {
this.javaTypeContext.refreshDefaults(parentDefaults);
}
refreshPersistentType(parentDefaults);
DefaultsContext wrappedDefaultsContext = wrapDefaultsContext(parentDefaults);
refreshTableContext(wrappedDefaultsContext);
this.xmlTypeMapping.refreshDefaults(wrappedDefaultsContext);
refreshAttributeMappingContextDefaults(wrappedDefaultsContext);
}
protected void refreshTableContext(DefaultsContext defaultsContext) {
}
public void refreshAttributeMappingContextDefaults(DefaultsContext defaultsContext) {
for (XmlAttributeContext context : this.attributeMappingContexts) {
context.refreshDefaults(context.wrapDefaultsContext(defaultsContext));
}
for (XmlAttributeContext context : this.virtualAttributeMappingContexts) {
context.refreshDefaults(context.wrapDefaultsContext(defaultsContext));
}
}
protected void refreshPersistentType(DefaultsContext defaultsContext) {
XmlPersistentType xmlPersistentType = this.getXmlTypeMapping().getPersistentType();
xmlPersistentType.refreshDefaults(defaultsContext);
//get the java attribute names
//check the specified xml attributes (those with an element in the xml), add
//a xmlAttribute mapping for any java attribute name with default = true
//if we already have an xml attribute mapping, then do nothing,
//the defaults refresh will get forwarded on the attribute mappings later.
Collection<IPersistentAttribute> javaAttributes = javaAttributes();
Collection<String> javaAttributeNames = new ArrayList<String>();
for (IPersistentAttribute javaAttribute : javaAttributes) {
String javaAttributeName = javaAttribute.getName();
javaAttributeNames.add(javaAttributeName);
XmlPersistentAttribute xmlAttribute = xmlPersistentType.attributeNamed(javaAttributeName);
if (xmlAttribute == null) {
createAndAddXmlAttributeFrom(javaAttribute, xmlPersistentType);
}
else {
if (xmlAttribute.isVirtual()) {
if (xmlAttribute.typeMapping().isXmlMetadataComplete()) {
xmlAttribute.setSpecifiedMappingKey(javaAttribute.defaultMappingKey());
}
else {
xmlAttribute.setSpecifiedMappingKey(javaAttribute.mappingKey());
}
}
}
}
Collection<String> specifiedXmlAttributeNames = new ArrayList<String>();
for (XmlPersistentAttribute specifiedAttribute : xmlPersistentType.getSpecifiedPersistentAttributes()) {
String attributeName = specifiedAttribute.getName();
if (! StringTools.stringIsEmpty(attributeName)) {
specifiedXmlAttributeNames.add(attributeName);
}
}
// remove virtual attribute if there's no java representation
// *or* if it is mapped specifically
Collection<XmlAttributeMapping> mappingsToRemove = new ArrayList<XmlAttributeMapping>();
for (XmlAttributeMapping mapping : xmlPersistentType.getVirtualAttributeMappings()) {
String attributeName = mapping.getPersistentAttribute().getName();
if (! javaAttributeNames.contains(attributeName)
|| specifiedXmlAttributeNames.contains(attributeName)) {
mappingsToRemove.add(mapping);
}
}
for (XmlAttributeMapping xmlAttributeMapping : mappingsToRemove) {
xmlPersistentType.getVirtualAttributeMappings().remove(xmlAttributeMapping);
}
for (XmlAttributeMapping xmlAttributeMapping : this.xmlTypeMapping.getPersistentType().getVirtualAttributeMappings()) {
this.virtualAttributeMappingContexts.add(buildContext(xmlAttributeMapping));
}
}
private void createAndAddXmlAttributeFrom(IPersistentAttribute javaAttribute, XmlPersistentType persistentType) {
//TODO also need to check xml mapping meta data complete flags and
//probably move all of this code to the context classes
XmlAttributeMapping xmlAttributeMapping = null;
String mappingKey;
if (persistentType.getMapping().isXmlMetadataComplete()) {
mappingKey = javaAttribute.defaultMappingKey();
}
else {
mappingKey = javaAttribute.getMapping().getKey();
}
if (mappingKey == IMappingKeys.BASIC_ATTRIBUTE_MAPPING_KEY) {
xmlAttributeMapping = OrmFactory.eINSTANCE.createXmlBasic();
}
else if (mappingKey == IMappingKeys.ID_ATTRIBUTE_MAPPING_KEY) {
xmlAttributeMapping = OrmFactory.eINSTANCE.createXmlId();
}
else if (mappingKey == IMappingKeys.MANY_TO_MANY_ATTRIBUTE_MAPPING_KEY) {
xmlAttributeMapping = OrmFactory.eINSTANCE.createXmlManyToMany();
}
else if (mappingKey == IMappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY) {
xmlAttributeMapping = OrmFactory.eINSTANCE.createXmlManyToOne();
}
else if (mappingKey == IMappingKeys.ONE_TO_MANY_ATTRIBUTE_MAPPING_KEY) {
xmlAttributeMapping = OrmFactory.eINSTANCE.createXmlOneToMany();
}
else if (mappingKey == IMappingKeys.TRANSIENT_ATTRIBUTE_MAPPING_KEY) {
xmlAttributeMapping = OrmFactory.eINSTANCE.createXmlTransient();
}
else if (mappingKey == IMappingKeys.EMBEDDED_ATTRIBUTE_MAPPING_KEY) {
xmlAttributeMapping = OrmFactory.eINSTANCE.createXmlEmbedded();
}
else if (mappingKey == IMappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY) {
xmlAttributeMapping = OrmFactory.eINSTANCE.createXmlEmbeddedId();
}
else if (mappingKey == IMappingKeys.VERSION_ATTRIBUTE_MAPPING_KEY) {
xmlAttributeMapping = OrmFactory.eINSTANCE.createXmlVersion();
}
else if (mappingKey == IMappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY) {
xmlAttributeMapping = OrmFactory.eINSTANCE.createXmlOneToOne();
}
else if (mappingKey == null) {
xmlAttributeMapping = OrmFactory.eINSTANCE.createXmlNullAttributeMapping();
}
//TODO this isn't the way to do it, should update all the settings on the default mapping
// during the refresh defaults of attribute mappings
//xmlAttributeMapping.initializeFromAttributeMapping(javaAttribute.getMapping());
persistentType.getVirtualAttributeMappings().add(xmlAttributeMapping);
xmlAttributeMapping.getPersistentAttribute().setName(javaAttribute.getName());
}
protected Collection<IPersistentAttribute> javaAttributes() {
Collection<IPersistentAttribute> javaAttributes = new ArrayList<IPersistentAttribute>();
JavaPersistentType javaPersistentType = javaPersistentType();
if (javaPersistentType != null) {
for (Iterator<JavaPersistentAttribute> i = javaPersistentType.attributes(); i.hasNext(); ) {
JavaPersistentAttribute persistentAttribute = i.next();
javaAttributes.add(persistentAttribute);
}
}
return javaAttributes;
}
@Override
public void addToMessages(List<IMessage> messages) {
super.addToMessages(messages);
addClassMessages(messages);
for (XmlAttributeContext context : this.attributeMappingContexts) {
context.addToMessages(messages);
}
for (XmlAttributeContext context : this.virtualAttributeMappingContexts) {
context.addToMessages(messages);
}
}
protected void addClassMessages(List<IMessage> messages) {
addUnspecifiedClassMessage(messages);
addUnresolvedClassMessage(messages);
}
protected void addUnspecifiedClassMessage(List<IMessage> messages) {
XmlPersistentType persistentType = xmlTypeMapping.getPersistentType();
if (StringTools.stringIsEmpty(persistentType.getClass_())) {
messages.add(
JpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
IJpaValidationMessages.PERSISTENT_TYPE_UNSPECIFIED_CLASS,
persistentType, persistentType.classTextRange())
);
}
}
protected void addUnresolvedClassMessage(List<IMessage> messages) {
XmlPersistentType persistentType = xmlTypeMapping.getPersistentType();
if (! StringTools.stringIsEmpty(persistentType.getClass_())
&& persistentType.findJdtType() == null) {
messages.add(
JpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
IJpaValidationMessages.PERSISTENT_TYPE_UNRESOLVED_CLASS,
new String[] {persistentType.getClass_()},
persistentType, persistentType.classTextRange())
);
}
}
}