Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkmoore2012-01-20 19:34:35 +0000
committerkmoore2012-01-20 19:34:35 +0000
commit2258fbd13be54d5fccdbb1d24970472f993b57c5 (patch)
tree16f51029f718adc444206e778263c866cdb4cb3f /jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context
parent2906afe6464d3be54b3d0455f1b3dd71603f7efd (diff)
downloadwebtools.dali-2258fbd13be54d5fccdbb1d24970472f993b57c5.tar.gz
webtools.dali-2258fbd13be54d5fccdbb1d24970472f993b57c5.tar.xz
webtools.dali-2258fbd13be54d5fccdbb1d24970472f993b57c5.zip
added preliminary support for EclipseLink access-methods and VIRTUAL access type
Diffstat (limited to 'jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context')
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentAttribute.java2
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentType.java4
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractEntityMappings.java2
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractOrmXmlContextNode.java2
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/SpecifiedOrmPersistentAttribute.java4
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/SpecifiedOrmPersistentType.java1401
6 files changed, 1408 insertions, 7 deletions
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentAttribute.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentAttribute.java
index 6438772fb5..bddecd461e 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentAttribute.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentAttribute.java
@@ -176,7 +176,7 @@ public abstract class AbstractJavaPersistentAttribute
*/
protected AccessType buildSpecifiedAccess() {
Access2_0Annotation accessAnnotation = this.getAccessAnnotation();
- return (accessAnnotation == null) ? null : AccessType.fromJavaResourceModel(accessAnnotation.getValue());
+ return (accessAnnotation == null) ? null : AccessType.fromJavaResourceModel(accessAnnotation.getValue(), this.getJpaPlatform(), this.getResourceType());
}
protected Access2_0Annotation getAccessAnnotation() {
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentType.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentType.java
index 8b7c8ae5e4..53506af8ce 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentType.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2011 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2012 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0, which accompanies this distribution
* and is available at http://www.eclipse.org/legal/epl-v10.html.
@@ -240,7 +240,7 @@ public abstract class AbstractJavaPersistentType
}
protected AccessType buildSpecifiedAccess() {
- return AccessType.fromJavaResourceModel(this.getAccessAnnotation().getValue());
+ return AccessType.fromJavaResourceModel(this.getAccessAnnotation().getValue(), this.getJpaPlatform(), this.getResourceType());
}
public AccessType getDefaultAccess() {
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractEntityMappings.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractEntityMappings.java
index 8184ae5fa5..0e6a9023ab 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractEntityMappings.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractEntityMappings.java
@@ -332,7 +332,7 @@ public abstract class AbstractEntityMappings
}
protected AccessType buildSpecifiedAccess() {
- return AccessType.fromOrmResourceModel(this.xmlEntityMappings.getAccess());
+ return AccessType.fromOrmResourceModel(this.xmlEntityMappings.getAccess(), this.getJpaPlatform(), this.getResourceType());
}
public AccessType getDefaultAccess() {
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractOrmXmlContextNode.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractOrmXmlContextNode.java
index d6ec443ca7..75569ed57a 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractOrmXmlContextNode.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractOrmXmlContextNode.java
@@ -60,7 +60,7 @@ public abstract class AbstractOrmXmlContextNode
protected boolean isOrmXml2_0Compatible() {
String version = this.getMappingFileRoot().getVersion();
try {
- return (version != null) && SimpleVersion.JPA_VERSION_COMPARATOR.compare(version, "2.0") >= 0; //$NON-NLS-1$
+ return (version != null) && SimpleVersion.VERSION_COMPARATOR.compare(version, "2.0") >= 0; //$NON-NLS-1$
} catch (VersionFormatException ex) {
return false;
}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/SpecifiedOrmPersistentAttribute.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/SpecifiedOrmPersistentAttribute.java
index 04178ae078..b2fc33f978 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/SpecifiedOrmPersistentAttribute.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/SpecifiedOrmPersistentAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2011 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2012 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0, which accompanies this distribution
* and is available at http://www.eclipse.org/legal/epl-v10.html.
@@ -380,7 +380,7 @@ public abstract class SpecifiedOrmPersistentAttribute
}
protected AccessType buildSpecifiedAccess() {
- return AccessType.fromOrmResourceModel(this.getXmlAccessHolder().getAccess());
+ return AccessType.fromOrmResourceModel(this.getXmlAccessHolder().getAccess(), this.getJpaPlatform(), this.getResourceType());
}
protected XmlAccessHolder getXmlAccessHolder() {
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/SpecifiedOrmPersistentType.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/SpecifiedOrmPersistentType.java
new file mode 100644
index 0000000000..aad8269592
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/SpecifiedOrmPersistentType.java
@@ -0,0 +1,1401 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.context.orm;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Vector;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jpt.common.core.resource.java.JavaResourceAbstractType;
+import org.eclipse.jpt.common.core.resource.java.JavaResourceAnnotatedElement.Kind;
+import org.eclipse.jpt.common.core.resource.java.JavaResourceField;
+import org.eclipse.jpt.common.core.resource.java.JavaResourceMethod;
+import org.eclipse.jpt.common.core.resource.java.JavaResourceType;
+import org.eclipse.jpt.common.core.utility.BodySourceWriter;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.ClassName;
+import org.eclipse.jpt.common.utility.internal.CollectionTools;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.common.utility.internal.Tools;
+import org.eclipse.jpt.common.utility.internal.iterables.ChainIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.CompositeIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.CompositeListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.EmptyListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.FilteringIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.ListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.SingleElementIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.SuperListIterableWrapper;
+import org.eclipse.jpt.common.utility.internal.iterables.TransformationIterable;
+import org.eclipse.jpt.jpa.core.JpaStructureNode;
+import org.eclipse.jpt.jpa.core.JptJpaCorePlugin;
+import org.eclipse.jpt.jpa.core.context.AccessType;
+import org.eclipse.jpt.jpa.core.context.PersistentType;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyPersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
+import org.eclipse.jpt.jpa.core.context.orm.EntityMappings;
+import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMapping;
+import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMappingDefinition;
+import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentType;
+import org.eclipse.jpt.jpa.core.context.orm.OrmReadOnlyPersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.orm.OrmStructureNodes;
+import org.eclipse.jpt.jpa.core.context.orm.OrmTypeMapping;
+import org.eclipse.jpt.jpa.core.context.orm.OrmTypeMappingDefinition;
+import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools;
+import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaPersistentType;
+import org.eclipse.jpt.jpa.core.internal.context.java.PropertyAccessor;
+import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode;
+import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages;
+import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages;
+import org.eclipse.jpt.jpa.core.jpa2.context.MetamodelSourceType;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaPersistentType2_0;
+import org.eclipse.jpt.jpa.core.jpa2.context.orm.OrmPersistentType2_0;
+import org.eclipse.jpt.jpa.core.resource.orm.Attributes;
+import org.eclipse.jpt.jpa.core.resource.orm.OrmPackage;
+import org.eclipse.jpt.jpa.core.resource.orm.XmlAttributeMapping;
+import org.eclipse.jpt.jpa.core.resource.orm.XmlTypeMapping;
+import org.eclipse.jpt.jpa.core.resource.xml.EmfTools;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * specified <code>orm.xml</code> persistent type:<ul>
+ * <li>mapping
+ * <li>access
+ * <li>attributes
+ * <li>super persistent type
+ * <li>Java persistent type
+ * </ul>
+ */
+public abstract class SpecifiedOrmPersistentType
+ extends AbstractOrmXmlContextNode
+ implements OrmPersistentType2_0
+{
+ protected OrmTypeMapping mapping; // never null
+
+ protected JavaPersistentType javaPersistentType;
+
+ protected AccessType specifiedAccess;
+ protected AccessType defaultAccess; // never null
+
+ protected final Vector<OrmPersistentAttribute> specifiedAttributes = new Vector<OrmPersistentAttribute>();
+ protected final SpecifiedAttributeContainerAdapter specifiedAttributeContainerAdapter = new SpecifiedAttributeContainerAdapter();
+
+ protected final Vector<OrmReadOnlyPersistentAttribute> virtualAttributes = new Vector<OrmReadOnlyPersistentAttribute>();
+
+ protected PersistentType superPersistentType;
+
+ protected String declaringTypeName;
+
+ protected final MetamodelSourceType.Synchronizer metamodelSynchronizer;
+
+
+ protected SpecifiedOrmPersistentType(EntityMappings parent, XmlTypeMapping xmlTypeMapping) {
+ super(parent);
+ this.mapping = this.buildMapping(xmlTypeMapping);
+ // 'javaPersistentType' is resolved in the update
+ this.specifiedAccess = this.buildSpecifiedAccess();
+ this.defaultAccess = AccessType.FIELD; // keep this non-null
+ this.initializeSpecifiedAttributes();
+ this.metamodelSynchronizer = this.buildMetamodelSynchronizer();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.mapping.synchronizeWithResourceModel();
+ this.syncJavaPersistentType();
+ this.setSpecifiedAccess_(this.buildSpecifiedAccess());
+ this.syncSpecifiedAttributes();
+ this.synchronizeNodesWithResourceModel(this.getVirtualAttributes());
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.mapping.update();
+ this.updateJavaPersistentType();
+ this.setDefaultAccess(this.buildDefaultAccess());
+ this.updateNodes(this.getSpecifiedAttributes());
+ this.updateVirtualAttributes();
+ this.setSuperPersistentType(this.buildSuperPersistentType());
+ this.setDeclaringTypeName(this.buildDeclaringTypeName());
+ }
+
+
+ // ********** mapping **********
+
+ public OrmTypeMapping getMapping() {
+ return this.mapping;
+ }
+
+ public String getMappingKey() {
+ return this.mapping.getKey();
+ }
+
+ public void setMappingKey(String mappingKey) {
+ if (this.valuesAreDifferent(this.getMappingKey(), mappingKey)) {
+ this.setMappingKey_(mappingKey);
+ }
+ }
+
+ protected void setMappingKey_(String mappingKey) {
+ OrmTypeMapping old = this.mapping;
+ OrmTypeMappingDefinition mappingDefinition = this.getMappingFileDefinition().getTypeMappingDefinition(mappingKey);
+ XmlTypeMapping xmlTypeMapping = mappingDefinition.buildResourceMapping(this.getResourceNodeFactory());
+ this.mapping = this.buildMapping(xmlTypeMapping);
+ this.getEntityMappings().changeMapping(this, old, this.mapping);
+ this.firePropertyChanged(MAPPING_PROPERTY, old, this.mapping);
+ }
+
+ protected OrmTypeMapping buildMapping(XmlTypeMapping xmlTypeMapping) {
+ OrmTypeMappingDefinition md = this.getMappingFileDefinition().getTypeMappingDefinition(xmlTypeMapping.getMappingKey());
+ return md.buildContextMapping(this, xmlTypeMapping, this.getContextNodeFactory());
+ }
+
+ protected XmlTypeMapping getXmlTypeMapping() {
+ return this.mapping.getXmlTypeMapping();
+ }
+
+ public boolean isMapped() {
+ return true;
+ }
+
+
+ // ********** name **********
+
+ public String getName() {
+ return (this.javaPersistentType != null) ?
+ this.javaPersistentType.getName() :
+ this.getMappingClassName();
+ }
+
+ protected String getMappingClassName() {
+ return this.convertMappingClassName(this.mapping.getClass_());
+ }
+
+ public String getSimpleName(){
+ String className = this.getName();
+ return StringTools.stringIsEmpty(className) ? null : ClassName.getSimpleName(className);
+ }
+
+ /**
+ * We clear out {@link #javaPersistentType} here because we cannot compare its name
+ * to the mapping's class name, since it may have been prefixed by the entity
+ * mappings package.
+ */
+ public void mappingClassChanged(String oldClass, String newClass) {
+ this.firePropertyChanged(NAME_PROPERTY, this.convertMappingClassName(oldClass), this.convertMappingClassName(newClass));
+ // clear out the Java type here, it will be rebuilt during "update"
+ if (this.javaPersistentType != null) {
+ this.javaPersistentType.dispose();
+ this.setJavaPersistentType(null);
+ }
+ }
+
+ /**
+ * Nested class names are specified with a <code>'$'</code>
+ * in <code>orm.xml</code>.
+ */
+ protected String convertMappingClassName(String name) {
+ return (name == null) ? null : name.replace('$', '.');
+ }
+
+
+ // ********** Java persistent type **********
+
+ public JavaPersistentType getJavaPersistentType() {
+ return this.javaPersistentType;
+ }
+
+ protected void setJavaPersistentType(JavaPersistentType javaPersistentType) {
+ JavaPersistentType old = this.javaPersistentType;
+ this.javaPersistentType = javaPersistentType;
+ this.firePropertyChanged(JAVA_PERSISTENT_TYPE_PROPERTY, old, javaPersistentType);
+ }
+
+ /**
+ * If the persistent type's mapping's class (name) changes during
+ * <em>sync</em>, the Java persistent type will be cleared out in
+ * {@link #mappingClassChanged(String, String)}. If we get here and
+ * the Java persistent type is still present, we can
+ * <em>sync</em> it. Of course, it might still be obsolete if the
+ * entity mappings's package has changed....
+ *
+ * @see #updateJavaPersistentType()
+ */
+ protected void syncJavaPersistentType() {
+ if (this.javaPersistentType != null) {
+ this.javaPersistentType.synchronizeWithResourceModel();
+ }
+ }
+
+ /**
+ * @see #syncJavaPersistentType()
+ */
+ protected void updateJavaPersistentType() {
+ JavaResourceAbstractType resourceType = this.resolveJavaResourceType();
+ if (resourceType == null) {
+ if (this.javaPersistentType != null) {
+ this.javaPersistentType.dispose();
+ this.setJavaPersistentType(null);
+ }
+ } else {
+ if (this.javaPersistentType == null) {
+ this.setJavaPersistentType(this.buildJavaPersistentType(resourceType));
+ } else {
+ if (this.javaPersistentType.getJavaResourceType() == resourceType) {
+ this.javaPersistentType.update();
+ } else {
+ this.javaPersistentType.dispose();
+ this.setJavaPersistentType(this.buildJavaPersistentType(resourceType));
+ }
+ }
+ }
+ }
+
+ /**
+ * Use {@link #getMappingClassName()} instead of {@link #getName()} to
+ * look up the Java resource type because {@link #getName()}
+ * simply delegates to the existing Java resource persistent type. (In
+ * which case we wouldn't need to resolve it, would we?) [bug 339560]
+ * @see #updateJavaPersistentType()
+ */
+ protected JavaResourceAbstractType resolveJavaResourceType() {
+ return this.getEntityMappings().resolveJavaResourceType(this.getMappingClassName());
+ }
+
+ /**
+ * Return null it's an enum; don't build a JavaPersistentType
+ */
+ protected JavaPersistentType buildJavaPersistentType(JavaResourceAbstractType jrat) {
+ return jrat.getKind() == Kind.TYPE ? this.buildJavaPersistentType((JavaResourceType) jrat) : null;
+ }
+
+ protected JavaPersistentType buildJavaPersistentType(JavaResourceType jrpt) {
+ return this.getJpaFactory().buildJavaPersistentType(this, jrpt);
+ }
+
+
+ // ********** access **********
+
+ public AccessType getAccess() {
+ return (this.specifiedAccess != null) ? this.specifiedAccess : this.defaultAccess;
+ }
+
+ public AccessType getSpecifiedAccess() {
+ return this.specifiedAccess;
+ }
+
+ public void setSpecifiedAccess(AccessType access) {
+ this.setSpecifiedAccess_(access);
+ this.getXmlTypeMapping().setAccess(AccessType.toOrmResourceModel(access));
+ }
+
+ protected void setSpecifiedAccess_(AccessType access) {
+ AccessType old = this.specifiedAccess;
+ this.specifiedAccess = access;
+ this.firePropertyChanged(SPECIFIED_ACCESS_PROPERTY, old, access);
+ }
+
+ protected AccessType buildSpecifiedAccess() {
+ return AccessType.fromOrmResourceModel(this.getXmlTypeMapping().getAccess(), this.getJpaPlatform(), this.getResourceType());
+ }
+
+ public AccessType getDefaultAccess() {
+ return this.defaultAccess;
+ }
+
+ protected void setDefaultAccess(AccessType access) {
+ AccessType old = this.defaultAccess;
+ this.defaultAccess = access;
+ this.firePropertyChanged(DEFAULT_ACCESS_PROPERTY, old, access);
+ }
+
+ protected AccessType buildDefaultAccess() {
+ if ( ! this.mapping.isMetadataComplete()) {
+ if (this.javaPersistentType != null) {
+ if (this.javaPersistentTypeHasSpecifiedAccess()) {
+ return this.javaPersistentType.getAccess();
+ }
+ if (this.superPersistentType != null) {
+ return this.superPersistentType.getAccess();
+ }
+ }
+ }
+ AccessType access = this.getMappingFileRoot().getAccess();
+ return (access != null) ? access : AccessType.FIELD; // default to FIELD if no specified access found
+ }
+
+ /**
+ * pre-condition: {@link #javaPersistentType} is not <code>null</code>
+ */
+ protected boolean javaPersistentTypeHasSpecifiedAccess() {
+ return (this.javaPersistentType.getSpecifiedAccess() != null) ||
+ this.javaPersistentType.hasAnyAnnotatedAttributes();
+ }
+
+ public AccessType getOwnerOverrideAccess() {
+ return this.getEntityMappings().getOverridePersistentTypeAccess();
+ }
+
+ public AccessType getOwnerDefaultAccess() {
+ return this.getEntityMappings().getDefaultPersistentTypeAccess();
+ }
+
+
+ // ********** attributes **********
+
+ @SuppressWarnings("unchecked")
+ public ListIterable<OrmReadOnlyPersistentAttribute> getAttributes() {
+ return new CompositeListIterable<OrmReadOnlyPersistentAttribute>(this.getReadOnlySpecifiedAttributes(), this.getVirtualAttributes());
+ }
+
+ //TODO remove this compatibility method in the Juno release
+ public ListIterator<OrmReadOnlyPersistentAttribute> attributes() {
+ return this.getAttributes().iterator();
+ }
+
+
+ public int getAttributesSize() {
+ return this.getSpecifiedAttributesSize() + this.getVirtualAttributesSize();
+ }
+
+ public Iterable<String> getAttributeNames() {
+ return this.convertToNames(this.getAttributes());
+ }
+
+ public OrmReadOnlyPersistentAttribute getAttributeNamed(String attributeName) {
+ Iterator<OrmReadOnlyPersistentAttribute> stream = this.getAttributesNamed(attributeName).iterator();
+ return stream.hasNext() ? stream.next() : null;
+ }
+
+ public Iterable<ReadOnlyPersistentAttribute> getAllAttributes() {
+ return new CompositeIterable<ReadOnlyPersistentAttribute>(
+ new TransformationIterable<PersistentType, Iterable<ReadOnlyPersistentAttribute>>(this.getInheritanceHierarchy()) {
+ @Override
+ protected Iterable<ReadOnlyPersistentAttribute> transform(PersistentType pt) {
+ return new SuperListIterableWrapper<ReadOnlyPersistentAttribute>(pt.getAttributes());
+ }
+ }
+ );
+ }
+
+ //TODO remove this compatibility method in the Juno release
+ public Iterator<ReadOnlyPersistentAttribute> allAttributes() {
+ return getAllAttributes().iterator();
+ }
+
+ public Iterable<String> getAllAttributeNames() {
+ return this.convertToNames(this.getAllAttributes());
+ }
+
+ protected Iterable<OrmReadOnlyPersistentAttribute> getAttributesNamed(final String attributeName) {
+ return new FilteringIterable<OrmReadOnlyPersistentAttribute>(this.getAttributes()) {
+ @Override
+ protected boolean accept(OrmReadOnlyPersistentAttribute attribute) {
+ return Tools.valuesAreEqual(attributeName, attribute.getName());
+ }
+ };
+ }
+
+ public ReadOnlyPersistentAttribute resolveAttribute(String attributeName) {
+ Iterator<OrmReadOnlyPersistentAttribute> attributes = this.getAttributesNamed(attributeName).iterator();
+ if (attributes.hasNext()) {
+ OrmReadOnlyPersistentAttribute attribute = attributes.next();
+ return attributes.hasNext() ? null /* more than one */: attribute;
+ }
+ // recurse
+ return (this.superPersistentType == null) ? null : this.superPersistentType.resolveAttribute(attributeName);
+ }
+
+ protected Iterable<String> convertToNames(Iterable<? extends ReadOnlyPersistentAttribute> attributes) {
+ return new TransformationIterable<ReadOnlyPersistentAttribute, String>(attributes) {
+ @Override
+ protected String transform(ReadOnlyPersistentAttribute attribute) {
+ return attribute.getName();
+ }
+ };
+ }
+
+
+ // ********** attribute conversions **********
+
+ public OrmPersistentAttribute convertAttributeToSpecified(OrmReadOnlyPersistentAttribute virtualAttribute) {
+ return this.convertAttributeToSpecified(virtualAttribute, virtualAttribute.getMappingKey());
+ }
+
+ public OrmPersistentAttribute convertAttributeToSpecified(OrmReadOnlyPersistentAttribute virtualAttribute, String mappingKey) {
+ if ( ! virtualAttribute.isVirtual()) {
+ throw new IllegalArgumentException("Attribute is already specified: " + virtualAttribute); //$NON-NLS-1$
+ }
+ if (mappingKey == null) {
+ // this typically happens when the virtual attribute does not have a mapping
+ throw new IllegalArgumentException("Use convertAttributeToSpecified(OrmReadOnlyPersistentAttribute, String) instead and specify a mapping key"); //$NON-NLS-1$
+ }
+ return this.convertAttributeToSpecified_(virtualAttribute, mappingKey);
+ }
+
+ /**
+ * <em>Silently</em> remove the virtual attribute and add specified
+ * attribute before triggering an <em>update</em> or the dangling
+ * virtual attribute will be removed preemptively.
+ */
+ protected OrmPersistentAttribute convertAttributeToSpecified_(OrmReadOnlyPersistentAttribute virtualAttribute, String mappingKey) {
+ // silently remove the virtual attribute
+ int virtualIndex = this.virtualAttributes.indexOf(virtualAttribute);
+ this.virtualAttributes.remove(virtualIndex);
+ virtualAttribute.dispose();
+
+ // silently add the specified attribute
+ OrmAttributeMappingDefinition md = this.getMappingFileDefinition().getAttributeMappingDefinition(mappingKey);
+ XmlAttributeMapping xmlMapping = md.buildResourceMapping(this.getResourceNodeFactory());
+
+ OrmPersistentAttribute specifiedAttribute = this.buildSpecifiedAttribute(xmlMapping);
+ // we need to add the attribute to the right spot in the list - stupid spec...
+ int specifiedIndex = this.getSpecifiedAttributeInsertionIndex(specifiedAttribute);
+ this.specifiedAttributes.add(specifiedIndex, specifiedAttribute);
+
+ // this will trigger the initial update;
+ // no changes to either collection (virtual or specified) should be detected at this point
+ specifiedAttribute.getMapping().setName(virtualAttribute.getName());
+
+ // fire the list change events
+ this.fireItemRemoved(VIRTUAL_ATTRIBUTES_LIST, virtualIndex, virtualAttribute);
+ this.fireItemAdded(SPECIFIED_ATTRIBUTES_LIST, specifiedIndex, specifiedAttribute);
+
+ // it should be safe to update the XML now
+ Attributes xmlAttributes = this.getXmlAttributesForUpdate();
+ specifiedAttribute.getMapping().addXmlAttributeMappingTo(xmlAttributes);
+ // possibly a NOP, but needed when we trigger the creation of a new 'attributes'
+ this.getXmlTypeMapping().setAttributes(xmlAttributes);
+
+ // copy over the specified access(?)
+ AccessType oldAccess = virtualAttribute.getJavaPersistentAttribute().getSpecifiedAccess();
+ if (oldAccess != null) {
+ specifiedAttribute.setSpecifiedAccess(oldAccess);
+ }
+ return specifiedAttribute;
+ }
+
+ // TODO this is used only by our tests...
+ // we cannot delegate to getAttributeNamed(String).convertToSpecified()
+ // because the tests use this method to add "orphan" xml attributes (that
+ // do not have a corresponding java attribute :( )
+ public OrmPersistentAttribute addSpecifiedAttribute(String mappingKey, String attributeName) {
+ // force the creation of an empty xml attribute container beforehand or it will trigger
+ // a sync and, if we do this after adding the attribute, clear out our context attributes
+ Attributes xmlAttributes = this.getXmlAttributesForUpdate();
+ this.getXmlTypeMapping().setAttributes(xmlAttributes); // possibly a NOP
+
+ OrmAttributeMappingDefinition md = this.getMappingFileDefinition().getAttributeMappingDefinition(mappingKey);
+ XmlAttributeMapping xmlMapping = md.buildResourceMapping(this.getResourceNodeFactory());
+
+ OrmPersistentAttribute specifiedAttribute = this.buildSpecifiedAttribute(xmlMapping);
+ // we need to add the attribute to the right spot in the list - stupid spec...
+ int specifiedIndex = this.getSpecifiedAttributeInsertionIndex(specifiedAttribute);
+ // the virtual attributes list should remain unchanged since the specified attribute has no name
+ this.addItemToList(specifiedIndex, specifiedAttribute, this.specifiedAttributes, SPECIFIED_ATTRIBUTES_LIST);
+ specifiedAttribute.getMapping().addXmlAttributeMappingTo(xmlAttributes);
+
+ // this will trigger the update of the virtual attributes list
+ specifiedAttribute.getMapping().setName(attributeName);
+
+ return specifiedAttribute;
+ }
+
+ protected int getSpecifiedAttributeInsertionIndex(OrmPersistentAttribute attribute) {
+ return CollectionTools.insertionIndexOf(this.specifiedAttributes, attribute, this.getAttributeComparator());
+ }
+
+ protected Comparator<OrmPersistentAttribute> getAttributeComparator() {
+ return ATTRIBUTE_COMPARATOR;
+ }
+
+ protected static final Comparator<OrmPersistentAttribute> ATTRIBUTE_COMPARATOR =
+ new Comparator<OrmPersistentAttribute>() {
+ public int compare(OrmPersistentAttribute attribute1, OrmPersistentAttribute attribute2) {
+ int seq1 = attribute1.getMapping().getXmlSequence();
+ int seq2 = attribute2.getMapping().getXmlSequence();
+ return (seq1 == seq2) ? 0 : (seq1 < seq2) ? -1 : 1;
+ }
+ };
+
+ /**
+ * <em>Silently</em> add the new virtual attribute before removing the
+ * specified attribute, or the <em>update</em> will discover the missing
+ * virtual attribute and add it preemptively.
+ */
+ public OrmReadOnlyPersistentAttribute convertAttributeToVirtual(OrmPersistentAttribute specifiedAttribute) {
+ if (specifiedAttribute.isVirtual()) {
+ throw new IllegalArgumentException("Attribute is already virtual: " + specifiedAttribute); //$NON-NLS-1$
+ }
+
+ int virtualIndex = this.virtualAttributes.size();
+ OrmReadOnlyPersistentAttribute virtualAttribute = null;
+ // make sure the corresponding resource Java attribute actually exists in the *current* type;
+ // do *not* take the context Java attribute directly from the specified ORM
+ // attribute we are converting since it may have come from a superclass;
+ // instead, use its resource Java attribute (which will match both name and access type,
+ // but we still need to check its parent type)
+ if (specifiedAttribute.getJavaResourceAttribute() != null) {
+ if (specifiedAttribute.getJavaResourceAttribute().getKind() == Kind.FIELD) {
+ JavaResourceField javaResourceField = (JavaResourceField) specifiedAttribute.getJavaResourceAttribute();
+ if (this.javaResourceFieldWillBeVirtual(javaResourceField, specifiedAttribute)) {
+ virtualAttribute = this.buildVirtualAttribute(javaResourceField);
+ this.virtualAttributes.add(virtualIndex, virtualAttribute);
+ }
+ }
+ else {
+ PropertyAccessor propertyAccessor = (PropertyAccessor) specifiedAttribute.getJavaPersistentAttribute().getAccessor();
+ JavaResourceMethod resourceGetter = propertyAccessor.getResourceGetter();
+ JavaResourceMethod resourceSetter = propertyAccessor.getResourceSetter();
+
+ if (this.javaResourcePropertyWillBeVirtual(resourceGetter, resourceSetter, specifiedAttribute)) {
+ virtualAttribute = this.buildVirtualAttribute(resourceGetter, resourceSetter);
+ this.virtualAttributes.add(virtualIndex, virtualAttribute);
+ }
+ }
+ }
+
+ this.removeSpecifiedAttribute(specifiedAttribute); // trigger update
+
+ if (virtualAttribute != null) {
+ this.fireItemAdded(VIRTUAL_ATTRIBUTES_LIST, virtualIndex, virtualAttribute);
+ }
+ return virtualAttribute;
+ }
+
+ /**
+ * Return whether the specified Java resource attribute will be a
+ * <em>virtual</em> attribute when the specified specified attribute is
+ * removed from the type. The Java resource attribute must be among the
+ * valid Java resource attributes and it must not correspond to any of the
+ * remaining specified attributes.
+ */
+ protected boolean javaResourceFieldWillBeVirtual(JavaResourceField javaResourceField, OrmPersistentAttribute specifiedAttributeToBeRemoved) {
+ return CollectionTools.contains(this.getJavaResourceFields(), javaResourceField) &&
+ (this.getSpecifiedAttributeFor(javaResourceField, specifiedAttributeToBeRemoved) == null);
+ }
+
+ /**
+ * Return whether the specified Java resource attribute will be a
+ * <em>virtual</em> attribute when the specified specified attribute is
+ * removed from the type. The Java resource attribute must be among the
+ * valid Java resource attributes and it must not correspond to any of the
+ * remaining specified attributes.
+ */
+ protected boolean javaResourcePropertyWillBeVirtual(JavaResourceMethod javaResourceGetter, JavaResourceMethod javaResourceSetter, OrmPersistentAttribute specifiedAttributeToBeRemoved) {
+ return CollectionTools.contains(this.getJavaResourceMethods(), javaResourceGetter) &&
+ CollectionTools.contains(this.getJavaResourceMethods(), javaResourceSetter) &&
+ (this.getSpecifiedAttributeFor(javaResourceGetter, javaResourceSetter, specifiedAttributeToBeRemoved) == null);
+ }
+
+
+ // ********** xml attributes **********
+
+ /**
+ * Return <code>null</code> if the <code>attributes</code> element is missing.
+ */
+ protected Attributes getXmlAttributes() {
+ return this.getXmlTypeMapping().getAttributes();
+ }
+
+ /**
+ * Build a new <code>attributes</code> element if it is not present;
+ * but do <em>not</em> add it to the XML type mapping. Callers will have
+ * to add it to the XML type mapping when appropriate.
+ */
+ protected Attributes getXmlAttributesForUpdate() {
+ Attributes xmlAttributes = this.getXmlAttributes();
+ return (xmlAttributes != null) ? xmlAttributes : this.buildXmlAttributes();
+ }
+
+ protected Attributes buildXmlAttributes() {
+ return EmfTools.create(this.getResourceNodeFactory(), OrmPackage.eINSTANCE.getAttributes(), Attributes.class);
+ }
+
+ protected void removeXmlAttributesIfUnset() {
+ if (this.getXmlAttributes().isUnset()) {
+ this.getXmlTypeMapping().setAttributes(null);
+ }
+ }
+
+
+ // ********** specified attributes **********
+
+ public ListIterable<OrmPersistentAttribute> getSpecifiedAttributes() {
+ return new LiveCloneListIterable<OrmPersistentAttribute>(this.specifiedAttributes);
+ }
+
+ protected ListIterable<OrmReadOnlyPersistentAttribute> getReadOnlySpecifiedAttributes() {
+ return new SuperListIterableWrapper<OrmReadOnlyPersistentAttribute>(this.getSpecifiedAttributes());
+ }
+
+ public int getSpecifiedAttributesSize() {
+ return this.specifiedAttributes.size();
+ }
+
+ protected void removeSpecifiedAttribute(OrmPersistentAttribute attribute) {
+ this.removeSpecifiedAttribute_(attribute);
+ attribute.getMapping().removeXmlAttributeMappingFrom(this.getXmlAttributes());
+ this.removeXmlAttributesIfUnset();
+ }
+
+ public void changeMapping(OrmPersistentAttribute attribute, OrmAttributeMapping oldMapping, OrmAttributeMapping newMapping) {
+ // keep the context model in sync with each change to the resource model
+ int sourceIndex = this.specifiedAttributes.indexOf(attribute);
+ this.specifiedAttributes.remove(sourceIndex);
+ oldMapping.removeXmlAttributeMappingFrom(this.getXmlAttributes());
+
+ int targetIndex = this.getSpecifiedAttributeInsertionIndex(attribute);
+ this.specifiedAttributes.add(targetIndex, attribute);
+ newMapping.addXmlAttributeMappingTo(this.getXmlAttributes());
+
+ oldMapping.initializeOn(newMapping);
+
+ this.fireItemMoved(SPECIFIED_ATTRIBUTES_LIST, targetIndex, sourceIndex);
+ }
+
+ protected void initializeSpecifiedAttributes() {
+ for (XmlAttributeMapping xmlMapping : this.getXmlAttributeMappings()) {
+ this.specifiedAttributes.add(this.buildSpecifiedAttribute(xmlMapping));
+ }
+ }
+
+ protected Iterable<XmlAttributeMapping> getXmlAttributeMappings() {
+ Attributes xmlAttributes = this.getXmlAttributes();
+ return (xmlAttributes != null) ? xmlAttributes.getAttributeMappings() : EmptyIterable.<XmlAttributeMapping>instance();
+ }
+
+ protected OrmPersistentAttribute buildSpecifiedAttribute(XmlAttributeMapping xmlMapping) {
+ return this.getContextNodeFactory().buildOrmPersistentAttribute(this, xmlMapping);
+ }
+
+ protected void syncSpecifiedAttributes() {
+ ContextContainerTools.synchronizeWithResourceModel(this.specifiedAttributeContainerAdapter);
+ }
+
+ protected void moveSpecifiedAttribute_(int index, OrmPersistentAttribute attribute) {
+ this.moveItemInList(index, attribute, this.specifiedAttributes, SPECIFIED_ATTRIBUTES_LIST);
+ }
+
+ protected void addSpecifiedAttribute_(int index, XmlAttributeMapping xmlMapping) {
+ OrmPersistentAttribute attribute = this.buildSpecifiedAttribute(xmlMapping);
+ this.addItemToList(index, attribute, this.specifiedAttributes, SPECIFIED_ATTRIBUTES_LIST);
+ }
+
+ protected void removeSpecifiedAttribute_(OrmPersistentAttribute attribute) {
+ this.removeItemFromList(attribute, this.specifiedAttributes, SPECIFIED_ATTRIBUTES_LIST);
+ }
+
+ /**
+ * specified attribute container adapter
+ */
+ protected class SpecifiedAttributeContainerAdapter
+ implements ContextContainerTools.Adapter<OrmPersistentAttribute, XmlAttributeMapping>
+ {
+ public Iterable<OrmPersistentAttribute> getContextElements() {
+ return SpecifiedOrmPersistentType.this.getSpecifiedAttributes();
+ }
+ public Iterable<XmlAttributeMapping> getResourceElements() {
+ return SpecifiedOrmPersistentType.this.getXmlAttributeMappings();
+ }
+ public XmlAttributeMapping getResourceElement(OrmPersistentAttribute contextElement) {
+ return contextElement.getMapping().getXmlAttributeMapping();
+ }
+ public void moveContextElement(int index, OrmPersistentAttribute element) {
+ SpecifiedOrmPersistentType.this.moveSpecifiedAttribute_(index, element);
+ }
+ public void addContextElement(int index, XmlAttributeMapping resourceElement) {
+ SpecifiedOrmPersistentType.this.addSpecifiedAttribute_(index, resourceElement);
+ }
+ public void removeContextElement(OrmPersistentAttribute element) {
+ SpecifiedOrmPersistentType.this.removeSpecifiedAttribute_(element);
+ }
+ }
+
+
+ // ********** virtual attributes **********
+
+ public ListIterable<OrmReadOnlyPersistentAttribute> getVirtualAttributes() {
+ return new LiveCloneListIterable<OrmReadOnlyPersistentAttribute>(this.virtualAttributes);
+ }
+
+ public int getVirtualAttributesSize() {
+ return this.virtualAttributes.size();
+ }
+
+ /**
+ * The attributes are synchronized during the <em>update</em> because
+ * the list of resource attributes is determined by the access type
+ * which can be controlled in a number of different places....
+ */
+ protected void updateVirtualAttributes() {
+ if (getVirtualJavaAccess() == AccessType.FIELD) {
+ this.syncFieldAccessVirtualAttributes();
+ }
+ else if (getVirtualJavaAccess() == AccessType.PROPERTY) {
+ this.syncPropertyAccessVirtualAttributes();
+ }
+ }
+
+ /**
+ * Initialize the attributes for AccessType.FIELD
+ * 1. all non-transient, non-static fields
+ * 2. all annotated methods(getters/setters)
+ */
+ private void syncFieldAccessVirtualAttributes() {
+ HashSet<OrmReadOnlyPersistentAttribute> contextAttributes = CollectionTools.set(this.getVirtualAttributes());
+
+ this.syncFieldVirtualAttributes(contextAttributes, buildNonTransientNonStaticResourceFieldsFilter());
+ if (!getMapping().isMetadataComplete()) {
+ this.syncAnnotatedPropertyVirtualAttributes(contextAttributes);
+ }
+
+ // remove any leftover context attributes
+ for (OrmReadOnlyPersistentAttribute contextAttribute : contextAttributes) {
+ this.removeVirtualAttribute(contextAttribute);
+ }
+ }
+
+ /**
+ * Initialize the attributes for XmlAccessType.PROPERTY
+ * 1. all getter/setter javabeans pairs
+ * 2. all annotated fields
+ * 3. all annotated methods getters/setters that don't have a matching pair
+ */
+ private void syncPropertyAccessVirtualAttributes() {
+ HashSet<OrmReadOnlyPersistentAttribute> contextAttributes = CollectionTools.set(this.getVirtualAttributes());
+
+ if (!getMapping().isMetadataComplete()) {
+ this.syncFieldVirtualAttributes(contextAttributes, AbstractJavaPersistentType.ANNOTATED_RESOURCE_FIELDS_FILTER);
+ }
+
+ Collection<JavaResourceMethod> resourceMethods = CollectionTools.collection(this.getJavaResourceMethods());
+ //iterate through all resource methods searching for persistable getters
+ for (JavaResourceMethod getterMethod : this.getJavaResourceMethods(this.buildPersistablePropertyGetterMethodsFilter())) {
+ JavaResourceMethod setterMethod = AbstractJavaPersistentType.getValidSiblingSetMethod(getterMethod, resourceMethods);
+ if (javaResourcePropertyIsVirtual(getterMethod, setterMethod)) {
+ if (AbstractJavaPersistentType.methodsArePersistableProperties(getterMethod, setterMethod)) {
+ boolean match = false;
+ for (Iterator<OrmReadOnlyPersistentAttribute> stream = contextAttributes.iterator(); stream.hasNext();) {
+ OrmReadOnlyPersistentAttribute contextAttribute = stream.next();
+ if (contextAttribute.isFor(getterMethod, setterMethod)) {
+ match = true;
+ contextAttribute.update();
+ stream.remove();
+ break;
+ }
+ }
+ if (!match) {
+ this.addVirtualAttribute(getVirtualAttributesSize(), this.buildVirtualAttribute(getterMethod, setterMethod));
+ }
+ }
+ }
+ resourceMethods.remove(getterMethod);
+ resourceMethods.remove(setterMethod);
+ }
+ this.syncRemainingResourceVirtualMethods(contextAttributes, resourceMethods);
+
+ // remove any leftover context attributes
+ for (OrmReadOnlyPersistentAttribute contextAttribute : contextAttributes) {
+ this.removeVirtualAttribute(contextAttribute);
+ }
+ }
+
+ private void syncAnnotatedPropertyVirtualAttributes(HashSet<OrmReadOnlyPersistentAttribute> contextAttributes) {
+ Collection<JavaResourceMethod> resourceMethods = CollectionTools.collection(this.getJavaResourceMethods());
+ //iterate through all resource methods searching for persistable getters
+ for (JavaResourceMethod getterMethod : this.getJavaResourceMethods(buildPersistablePropertyGetterMethodsFilter())) {
+ JavaResourceMethod setterMethod = AbstractJavaPersistentType.getValidSiblingSetMethod(getterMethod, resourceMethods);
+ if (javaResourcePropertyIsVirtual(getterMethod, setterMethod)) {
+ if (getterMethod.isAnnotated() || (setterMethod != null && setterMethod.isAnnotated())) {
+ boolean match = false;
+ for (Iterator<OrmReadOnlyPersistentAttribute> stream = contextAttributes.iterator(); stream.hasNext();) {
+ OrmReadOnlyPersistentAttribute contextAttribute = stream.next();
+ if (contextAttribute.isFor(getterMethod, setterMethod)) {
+ match = true;
+ contextAttribute.update();
+ stream.remove();
+ break;
+ }
+ }
+ if (!match) {
+ this.addVirtualAttribute(getVirtualAttributesSize(), this.buildVirtualAttribute(getterMethod, setterMethod));
+ }
+ }
+ }
+ resourceMethods.remove(getterMethod);
+ resourceMethods.remove(setterMethod);
+ }
+ this.syncRemainingResourceVirtualMethods(contextAttributes, resourceMethods);
+ }
+
+ private void syncFieldVirtualAttributes(HashSet<OrmReadOnlyPersistentAttribute> contextAttributes, Filter<JavaResourceField> filter) {
+ for (JavaResourceField resourceField : this.getVirtualJavaResourceFields(filter)) {
+ boolean match = false;
+ for (Iterator<OrmReadOnlyPersistentAttribute> stream = contextAttributes.iterator(); stream.hasNext(); ) {
+ OrmReadOnlyPersistentAttribute contextAttribute = stream.next();
+ if (contextAttribute.isFor(resourceField)) {
+ match = true;
+ contextAttribute.update();
+ stream.remove();
+ break;
+ }
+ }
+ if (!match) {
+ // added elements are sync'ed during construction or will be
+ // updated during the next "update" (which is triggered by
+ // their addition to the model)
+ this.addVirtualAttribute(this.getVirtualAttributesSize(), this.buildVirtualAttribute(resourceField));
+ }
+ }
+ }
+
+ private void syncRemainingResourceVirtualMethods(HashSet<OrmReadOnlyPersistentAttribute> contextAttributes, Collection<JavaResourceMethod> resourceMethods) {
+ //iterate through remaining resource methods and search for those that are annotated.
+ //all getter methods will already be used.
+ for (JavaResourceMethod resourceMethod : resourceMethods) {
+ if (resourceMethod.isAnnotated()) {
+ boolean match = false;
+ //annotated setter(or other random method) with no corresponding getter, bring into context model for validation purposes
+ for (Iterator<OrmReadOnlyPersistentAttribute> stream = contextAttributes.iterator(); stream.hasNext();) {
+ OrmReadOnlyPersistentAttribute contextAttribute = stream.next();
+ if (contextAttribute.isFor(null, resourceMethod)) {
+ match = true;
+ contextAttribute.update();
+ stream.remove();
+ break;
+ }
+ }
+ if (!match) {
+ this.addVirtualAttribute(getVirtualAttributesSize(), this.buildVirtualAttribute(null, resourceMethod));
+ }
+ }
+ }
+ }
+
+ /**
+ * Return all the Java resource fields that do not have a
+ * corresponding <code>orm.xml</code> mapping currently
+ * specified in the <code>orm.xml</code> persistent type.
+ */
+ protected Iterable<JavaResourceField> getVirtualJavaResourceFields() {
+ return new FilteringIterable<JavaResourceField>(this.getJavaResourceFields()) {
+ @Override
+ protected boolean accept(JavaResourceField javaResourceField) {
+ return SpecifiedOrmPersistentType.this.javaResourceFieldIsVirtual(javaResourceField);
+ }
+ };
+ }
+
+ protected Iterable<JavaResourceField> getJavaResourceFields() {
+ JavaResourceType javaResourceType = this.getJavaResourceType();
+ if (javaResourceType == null) {
+ return EmptyListIterable.instance();
+ }
+ return javaResourceType.getFields();
+ }
+
+ protected Iterable<JavaResourceField> getVirtualJavaResourceFields(Filter<JavaResourceField> filter) {
+ return new FilteringIterable<JavaResourceField>(getVirtualJavaResourceFields(), filter);
+ }
+
+ protected Iterable<JavaResourceMethod> getJavaResourceMethods(Filter<JavaResourceMethod> filter) {
+ return new FilteringIterable<JavaResourceMethod>(getJavaResourceMethods(), filter);
+ }
+
+ protected Iterable<JavaResourceMethod> getJavaResourceMethods() {
+ JavaResourceType javaResourceType = this.getJavaResourceType();
+ if (javaResourceType == null) {
+ return EmptyListIterable.instance();
+ }
+ return javaResourceType.getMethods();
+ }
+
+ public static Filter<JavaResourceField> buildNonTransientNonStaticResourceFieldsFilter() {
+ return AbstractJavaPersistentType.buildNonTransientNonStaticResourceFieldsFilter();
+ }
+
+ protected Filter<JavaResourceMethod> buildPersistablePropertyGetterMethodsFilter() {
+ return new Filter<JavaResourceMethod>() {
+ public boolean accept(JavaResourceMethod resourceMethod) {
+ return AbstractJavaPersistentType.methodIsPersistablePropertyGetter(resourceMethod, getJavaResourceMethods());
+ }
+ };
+ }
+
+ protected JavaResourceType getJavaResourceType() {
+ return (this.javaPersistentType == null) ? null : this.javaPersistentType.getJavaResourceType();
+ }
+
+ /**
+ * Return the access type that determines which Java attributes are to be
+ * used for the <code>orm.xml</code> type's <em>virtual</em> attributes.
+ */
+ protected AccessType getVirtualJavaAccess() {
+ if (this.specifiedAccess != null) {
+ return this.specifiedAccess;
+ }
+ if (this.mapping.isMetadataComplete()) {
+ return this.defaultAccess;
+ }
+ AccessType javaAccess = this.javaPersistentType == null ? null : this.javaPersistentType.getSpecifiedAccess();
+ return (javaAccess != null) ? javaAccess : this.defaultAccess;
+ }
+
+ protected boolean javaResourceFieldIsVirtual(JavaResourceField javaResourceField) {
+ return this.getSpecifiedAttributeFor(javaResourceField) == null;
+ }
+
+ protected OrmPersistentAttribute getSpecifiedAttributeFor(JavaResourceField javaResourceField) {
+ return this.getSpecifiedAttributeFor(javaResourceField, null);
+ }
+
+ /**
+ * Return the specified attribute corresponding to the specified Java
+ * resource field, ignoring the specified excluded attribute (since
+ * there can be more than one specified attribute per Java resource
+ * attribute; albeit erroneously).
+ */
+ protected OrmPersistentAttribute getSpecifiedAttributeFor(JavaResourceField javaResourceField, OrmPersistentAttribute exclude) {
+ for (OrmPersistentAttribute ormAttribute : this.getSpecifiedAttributes()) {
+ if (ormAttribute == exclude) {
+ continue; // skip
+ }
+ if (ormAttribute.isFor(javaResourceField)) {
+ return ormAttribute;
+ }
+ }
+ return null;
+ }
+
+ protected boolean javaResourcePropertyIsVirtual(JavaResourceMethod javaResourceGetter, JavaResourceMethod javaResourceSetter) {
+ return this.getSpecifiedAttributeFor(javaResourceGetter, javaResourceSetter) == null;
+ }
+
+ protected OrmPersistentAttribute getSpecifiedAttributeFor(JavaResourceMethod javaResourceGetter, JavaResourceMethod javaResourceSetter) {
+ return this.getSpecifiedAttributeFor(javaResourceGetter, javaResourceSetter, null);
+ }
+
+ /**
+ * Return the specified attribute corresponding to the specified Java
+ * resource field, ignoring the specified excluded attribute (since
+ * there can be more than one specified attribute per Java resource
+ * attribute; albeit erroneously).
+ */
+ protected OrmPersistentAttribute getSpecifiedAttributeFor(JavaResourceMethod javaResourceGetter, JavaResourceMethod javaResourceSetter, OrmPersistentAttribute exclude) {
+ for (OrmPersistentAttribute ormAttribute : this.getSpecifiedAttributes()) {
+ if (ormAttribute == exclude) {
+ continue; // skip
+ }
+ if (ormAttribute.isFor(javaResourceGetter, javaResourceSetter)) {
+ return ormAttribute;
+ }
+ }
+ return null;
+ }
+
+ protected void moveVirtualAttribute(int index, OrmReadOnlyPersistentAttribute virtualAttribute) {
+ this.moveItemInList(index, virtualAttribute, this.virtualAttributes, VIRTUAL_ATTRIBUTES_LIST);
+ }
+
+ protected void addVirtualAttribute(int index, OrmReadOnlyPersistentAttribute virtualAttribute) {
+ this.addItemToList(index, virtualAttribute, this.virtualAttributes, VIRTUAL_ATTRIBUTES_LIST);
+ }
+
+ protected OrmReadOnlyPersistentAttribute buildVirtualAttribute(JavaResourceField javaResourceField) {
+ return this.getContextNodeFactory().buildVirtualOrmPersistentField(this, javaResourceField);
+ }
+
+ protected OrmReadOnlyPersistentAttribute buildVirtualAttribute(JavaResourceMethod javaResourceGetter, JavaResourceMethod javaResourceSetter) {
+ return this.getContextNodeFactory().buildVirtualOrmPersistentProperty(this, javaResourceGetter, javaResourceSetter);
+ }
+
+ protected void removeVirtualAttribute(OrmReadOnlyPersistentAttribute virtualAttribute) {
+ virtualAttribute.dispose();
+ this.removeItemFromList(virtualAttribute, this.virtualAttributes, VIRTUAL_ATTRIBUTES_LIST);
+ }
+
+
+ // ********** super persistent type **********
+
+ public PersistentType getSuperPersistentType() {
+ return this.superPersistentType;
+ }
+
+ protected void setSuperPersistentType(PersistentType persistentType) {
+ PersistentType old = this.superPersistentType;
+ this.superPersistentType = persistentType;
+ this.firePropertyChanged(SUPER_PERSISTENT_TYPE_PROPERTY, old, persistentType);
+ }
+
+ protected PersistentType buildSuperPersistentType() {
+ PersistentType spt = this.buildSuperPersistentType_();
+ if (spt == null) {
+ return null;
+ }
+ // check for circular inheritance
+ return CollectionTools.contains(spt.getInheritanceHierarchy(), this) ? null : spt;
+ }
+
+ protected PersistentType buildSuperPersistentType_() {
+ return (this.javaPersistentType == null) ? null : this.javaPersistentType.getSuperPersistentType();
+ }
+
+
+ // ********** inheritance **********
+
+ public Iterable<PersistentType> getInheritanceHierarchy() {
+ return this.getInheritanceHierarchyOf(this);
+ }
+
+ public Iterable<PersistentType> getAncestors() {
+ return this.getInheritanceHierarchyOf(this.superPersistentType);
+ }
+
+ protected Iterable<PersistentType> getInheritanceHierarchyOf(PersistentType start) {
+ // using a chain iterable to traverse up the inheritance tree
+ return new ChainIterable<PersistentType>(start) {
+ @Override
+ protected PersistentType nextLink(PersistentType persistentType) {
+ return persistentType.getSuperPersistentType();
+ }
+ };
+ }
+
+
+ // ********** declaring type name **********
+
+ public String getDeclaringTypeName() {
+ return this.declaringTypeName;
+ }
+
+ protected void setDeclaringTypeName(String name) {
+ String old = this.declaringTypeName;
+ this.declaringTypeName = name;
+ this.firePropertyChanged(DECLARING_TYPE_NAME_PROPERTY, old, name);
+ }
+
+ protected String buildDeclaringTypeName() {
+ return this.isJpa2_0Compatible() ? this.buildDeclaringTypeName_() : null;
+ }
+
+ protected String buildDeclaringTypeName_() {
+ return (this.javaPersistentType == null) ?
+ null : ((JavaPersistentType2_0) this.javaPersistentType).getDeclaringTypeName();
+ }
+
+
+ // ********** metamodel **********
+
+ protected MetamodelSourceType.Synchronizer buildMetamodelSynchronizer() {
+ return this.isJpa2_0Compatible() ?
+ this.getJpaFactory2_0().buildMetamodelSynchronizer(this) :
+ null;
+ }
+
+ public IFile getMetamodelFile() {
+ return (this.javaPersistentType == null) ? null : this.metamodelSynchronizer.getFile();
+ }
+
+ public void initializeMetamodel() {
+ // do nothing - probably shouldn't be called...
+ }
+
+ public boolean isManaged() {
+ return true;
+ }
+
+ /**
+ * All <code>orm.xml</code> persistent types must be able to generate a static metamodel
+ * because 1.0 <code>orm.xml</code> files can be referenced from 2.0 persistence.xml files.
+ */
+ public void synchronizeMetamodel(Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ if (this.javaPersistentType != null) {
+ this.metamodelSynchronizer.synchronize(memberTypeTree);
+ }
+ }
+
+ public void printBodySourceOn(BodySourceWriter pw, Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ if (this.javaPersistentType != null) {
+ this.metamodelSynchronizer.printBodySourceOn(pw, memberTypeTree);
+ }
+ }
+
+ public void disposeMetamodel() {
+ // do nothing - probably shouldn't be called...
+ }
+
+
+ // ********** JpaStructureNode implementation **********
+
+ public String getId() {
+ return OrmStructureNodes.PERSISTENT_TYPE_ID;
+ }
+
+ public JpaStructureNode getStructureNode(int textOffset) {
+ for (OrmPersistentAttribute attribute : this.getSpecifiedAttributes()) {
+ if (attribute.contains(textOffset)) {
+ return attribute;
+ }
+ }
+ return this;
+ }
+
+ public TextRange getSelectionTextRange() {
+ return this.mapping.getSelectionTextRange();
+ }
+
+ public void dispose() {
+ if (this.javaPersistentType != null) {
+ this.javaPersistentType.dispose();
+ }
+ for (OrmReadOnlyPersistentAttribute virtualAttribute : this.getVirtualAttributes()) {
+ virtualAttribute.dispose();
+ }
+ }
+
+
+ // ********** PersistentType.Owner implementation **********
+
+ public AccessType getOverridePersistentTypeAccess() {
+ if (this.specifiedAccess != null) {
+ return this.specifiedAccess;
+ }
+
+ if (this.superPersistentType instanceof OrmPersistentType) {
+ AccessType accessType = ((OrmPersistentType) this.superPersistentType).getSpecifiedAccess();
+ if (accessType != null) {
+ return accessType;
+ }
+ }
+
+ if (this.mapping.isMetadataComplete()) {
+ AccessType accessType = this.getOwnerDefaultAccess();
+ if (accessType != null) {
+ return accessType;
+ }
+ }
+
+ // no override access type
+ return null;
+ }
+
+ public AccessType getDefaultPersistentTypeAccess() {
+ if (this.superPersistentType instanceof OrmPersistentType) {
+ AccessType accessType = ((OrmPersistentType) this.superPersistentType).getDefaultAccess();
+ if (accessType != null) {
+ return accessType;
+ }
+ }
+
+ return this.getOwnerDefaultAccess();
+ }
+
+
+ //*********** refactoring ***********
+
+ public Iterable<DeleteEdit> createDeleteTypeEdits(IType type) {
+ return this.isFor(type.getFullyQualifiedName('.')) ?
+ new SingleElementIterable<DeleteEdit>(this.mapping.createDeleteEdit()) :
+ EmptyIterable.<DeleteEdit>instance();
+ }
+
+ @SuppressWarnings("unchecked")
+ public Iterable<ReplaceEdit> createRenameTypeEdits(IType originalType, String newName) {
+ return new CompositeIterable<ReplaceEdit>(
+ this.mapping.createRenameTypeEdits(originalType, newName),
+ this.createSpecifiedAttributesRenameTypeEdits(originalType, newName)
+ );
+ }
+
+ protected Iterable<ReplaceEdit> createSpecifiedAttributesRenameTypeEdits(final IType originalType, final String newName) {
+ return new CompositeIterable<ReplaceEdit>(
+ new TransformationIterable<OrmPersistentAttribute, Iterable<ReplaceEdit>>(this.getSpecifiedAttributes()) {
+ @Override
+ protected Iterable<ReplaceEdit> transform(OrmPersistentAttribute persistentAttribute) {
+ return persistentAttribute.createRenameTypeEdits(originalType, newName);
+ }
+ }
+ );
+ }
+
+ @SuppressWarnings("unchecked")
+ public Iterable<ReplaceEdit> createMoveTypeEdits(IType originalType, IPackageFragment newPackage) {
+ return new CompositeIterable<ReplaceEdit>(
+ this.mapping.createMoveTypeEdits(originalType, newPackage),
+ this.createSpecifiedAttributesMoveTypeEdits(originalType, newPackage)
+ );
+ }
+
+ protected Iterable<ReplaceEdit> createSpecifiedAttributesMoveTypeEdits(final IType originalType, final IPackageFragment newPackage) {
+ return new CompositeIterable<ReplaceEdit>(
+ new TransformationIterable<OrmPersistentAttribute, Iterable<ReplaceEdit>>(this.getSpecifiedAttributes()) {
+ @Override
+ protected Iterable<ReplaceEdit> transform(OrmPersistentAttribute persistentAttribute) {
+ return persistentAttribute.createMoveTypeEdits(originalType, newPackage);
+ }
+ }
+ );
+ }
+
+ @SuppressWarnings("unchecked")
+ public Iterable<ReplaceEdit> createRenamePackageEdits(IPackageFragment originalPackage, String newName) {
+ return new CompositeIterable<ReplaceEdit>(
+ this.mapping.createRenamePackageEdits(originalPackage, newName),
+ this.createSpecifiedAttributesRenamePackageEdits(originalPackage, newName)
+ );
+ }
+
+ protected Iterable<ReplaceEdit> createSpecifiedAttributesRenamePackageEdits(final IPackageFragment originalPackage, final String newName) {
+ return new CompositeIterable<ReplaceEdit>(
+ new TransformationIterable<OrmPersistentAttribute, Iterable<ReplaceEdit>>(this.getSpecifiedAttributes()) {
+ @Override
+ protected Iterable<ReplaceEdit> transform(OrmPersistentAttribute persistentAttribute) {
+ return persistentAttribute.createRenamePackageEdits(originalPackage, newName);
+ }
+ }
+ );
+ }
+
+
+ // ********** validation **********
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter) {
+ super.validate(messages, reporter);
+ this.validateClass(messages);
+ this.validateMapping(messages, reporter);
+ this.validateAttributes(messages, reporter);
+ }
+
+ protected void validateClass(List<IMessage> messages) {
+ if (this.javaPersistentType == null) {
+ messages.add(
+ DefaultJpaValidationMessages.buildMessage(
+ IMessage.HIGH_SEVERITY,
+ JpaValidationMessages.PERSISTENT_TYPE_UNRESOLVED_CLASS,
+ new String[] {this.getName()},
+ this,
+ this.mapping.getClassTextRange()
+ )
+ );
+ }
+ }
+
+ protected void validateMapping(List<IMessage> messages, IReporter reporter) {
+ try {
+ this.mapping.validate(messages, reporter);
+ } catch(Throwable t) {
+ JptJpaCorePlugin.log(t);
+ }
+ }
+
+ protected void validateAttributes(List<IMessage> messages, IReporter reporter) {
+ for (OrmReadOnlyPersistentAttribute attribute : this.getAttributes()) {
+ this.validateAttribute(attribute, messages, reporter);
+ }
+ }
+
+ protected void validateAttribute(OrmReadOnlyPersistentAttribute attribute, List<IMessage> messages, IReporter reporter) {
+ try {
+ attribute.validate(messages, reporter);
+ } catch(Throwable t) {
+ JptJpaCorePlugin.log(t);
+ }
+ }
+
+ public TextRange getValidationTextRange() {
+ return this.mapping.getValidationTextRange();
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ public EntityMappings getParent() {
+ return (EntityMappings) super.getParent();
+ }
+
+ protected EntityMappings getEntityMappings() {
+ return this.getParent();
+ }
+
+ public String getDefaultPackage() {
+ return this.getEntityMappings().getPackage();
+ }
+
+ public boolean isFor(String typeName) {
+ String name = this.getName();
+ if (name == null) {
+ return false;
+ }
+ if (name.equals(typeName)) {
+ return true;
+ }
+ String defaultPackage = this.getDefaultPackage();
+ if (defaultPackage == null) {
+ return false;
+ }
+ return (defaultPackage + '.' + name).equals(typeName);
+ }
+
+ public boolean isIn(IPackageFragment packageFragment) {
+ String packageName = this.getPackageName();
+ if (Tools.valuesAreEqual(packageName, packageFragment.getElementName())) {
+ return true;
+ }
+ String defaultPackage = this.getDefaultPackage();
+ if (defaultPackage == null) {
+ return false;
+ }
+ packageName = (packageName == null) ? defaultPackage : defaultPackage + '.' + packageName;
+ return packageName.equals(packageFragment.getElementName());
+ }
+
+ protected String getPackageName() {
+ String className = this.getName();
+ if (className == null) {
+ return null;
+ }
+ int lastPeriod = className.lastIndexOf('.');
+ return (lastPeriod == -1) ? null : className.substring(0, lastPeriod);
+ }
+
+ public boolean contains(int textOffset) {
+ return this.mapping.containsOffset(textOffset);
+ }
+
+ public PersistentType getOverriddenPersistentType() {
+ return this.mapping.isMetadataComplete() ? null : this.javaPersistentType;
+ }
+
+ @Override
+ public void toString(StringBuilder sb) {
+ sb.append(this.getName());
+ }
+}

Back to the top