| /******************************************************************************* |
| * 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.content.java; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.List; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.notify.NotificationChain; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.InternalEObject; |
| import org.eclipse.emf.ecore.impl.ENotificationImpl; |
| import org.eclipse.emf.ecore.util.EObjectContainmentEList; |
| import org.eclipse.emf.ecore.util.InternalEList; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IField; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IMember; |
| import org.eclipse.jdt.core.IMethod; |
| import org.eclipse.jdt.core.ISourceRange; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.dom.CompilationUnit; |
| import org.eclipse.jpt.core.internal.AccessType; |
| import org.eclipse.jpt.core.internal.IJpaContentNode; |
| import org.eclipse.jpt.core.internal.IPersistentAttribute; |
| import org.eclipse.jpt.core.internal.IPersistentType; |
| import org.eclipse.jpt.core.internal.ITextRange; |
| import org.eclipse.jpt.core.internal.JpaCorePackage; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaAssociationOverride; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaAttributeOverride; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaBasic; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaColumn; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaEmbeddableProvider; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaEmbedded; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaEmbeddedId; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaEntityProvider; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaGeneratedValue; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaId; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaJoinColumn; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaJoinTable; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaManyToMany; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaManyToOne; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaMappedSuperclassProvider; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaNullTypeMappingProvider; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaOneToMany; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaOneToOne; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaOrderBy; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaPrimaryKeyJoinColumn; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaSequenceGenerator; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaTableGenerator; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaTransient; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaVersion; |
| import org.eclipse.jpt.core.internal.jdtutility.Attribute; |
| import org.eclipse.jpt.core.internal.jdtutility.AttributeAnnotationTools; |
| import org.eclipse.jpt.core.internal.jdtutility.DeclarationAnnotationAdapter; |
| import org.eclipse.jpt.core.internal.jdtutility.FieldAttribute; |
| import org.eclipse.jpt.core.internal.jdtutility.JDTTools; |
| import org.eclipse.jpt.core.internal.jdtutility.MethodAttribute; |
| import org.eclipse.jpt.core.internal.jdtutility.Type; |
| import org.eclipse.jpt.core.internal.platform.DefaultsContext; |
| import org.eclipse.jpt.utility.internal.Filter; |
| import org.eclipse.jpt.utility.internal.iterators.ArrayIterator; |
| import org.eclipse.jpt.utility.internal.iterators.ChainIterator; |
| import org.eclipse.jpt.utility.internal.iterators.CompositeIterator; |
| import org.eclipse.jpt.utility.internal.iterators.ReadOnlyIterator; |
| import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; |
| |
| /** |
| * <!-- begin-user-doc --> |
| * A representation of the model object '<em><b>Java Type</b></em>'. |
| * <!-- end-user-doc --> |
| * |
| * <p> |
| * The following features are supported: |
| * <ul> |
| * <li>{@link org.eclipse.jpt.core.internal.content.java.JavaPersistentType#getMapping <em>Mapping</em>}</li> |
| * <li>{@link org.eclipse.jpt.core.internal.content.java.JavaPersistentType#getAttributes <em>Attributes</em>}</li> |
| * <li>{@link org.eclipse.jpt.core.internal.content.java.JavaPersistentType#getAccess <em>Access</em>}</li> |
| * </ul> |
| * </p> |
| * |
| * @see org.eclipse.jpt.core.internal.content.java.JpaJavaPackage#getJavaPersistentType() |
| * @model kind="class" |
| * @generated |
| */ |
| public class JavaPersistentType extends JavaEObject implements IPersistentType |
| { |
| /** |
| * The default value of the '{@link #getMappingKey() <em>Mapping Key</em>}' attribute. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getMappingKey() |
| * @generated |
| * @ordered |
| */ |
| protected static final String MAPPING_KEY_EDEFAULT = null; |
| |
| /** |
| * The cached value of the '{@link #getMappingKey() <em>Mapping Key</em>}' attribute. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getMappingKey() |
| * @generated |
| * @ordered |
| */ |
| protected String mappingKey = MAPPING_KEY_EDEFAULT; |
| |
| /** |
| * The cached value of the '{@link #getMapping() <em>Mapping</em>}' containment reference. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getMapping() |
| * @generated |
| * @ordered |
| */ |
| protected IJavaTypeMapping mapping; |
| |
| /** |
| * The cached value of the '{@link #getAttributes() <em>Attributes</em>}' containment reference list. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getAttributes() |
| * @generated |
| * @ordered |
| */ |
| protected EList<JavaPersistentAttribute> attributes; |
| |
| /** |
| * The default value of the '{@link #getAccess() <em>Access</em>}' attribute. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getAccess() |
| * @generated |
| * @ordered |
| */ |
| protected static final AccessType ACCESS_EDEFAULT = AccessType.DEFAULT; |
| |
| /** |
| * The cached value of the '{@link #getAccess() <em>Access</em>}' attribute. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getAccess() |
| * @generated |
| * @ordered |
| */ |
| protected AccessType access = ACCESS_EDEFAULT; |
| |
| private Type type; |
| |
| private IJavaTypeMappingProvider[] typeMappingProviders; |
| |
| private DeclarationAnnotationAdapter[] attributeMappingAnnotationAdapters; |
| |
| /** |
| * Store the parentPersistentType during default calculation. This will |
| * be the first persisentType found in the hierarchy, the JPA spec allows |
| * for non-persistent types to be part of the hierarchy. |
| * Example: |
| * |
| * @Entity public abstract class Model {} |
| * |
| * public abstract class Animal extends Model {} |
| * |
| * @Entity public class Cat extends Animal {} |
| * |
| * If this is the Cat JavaPersistentType then parentPersistentType is the Model JavaPersistentType |
| * The parentPersistentType could be found in java or xml. |
| */ |
| private IPersistentType parentPersistentType; |
| |
| protected JavaPersistentType() { |
| super(); |
| this.typeMappingProviders = this.buildTypeMappingProviders(); |
| this.attributeMappingAnnotationAdapters = this.buildAttributeMappingAnnotationAdapters(); |
| } |
| |
| private IJavaTypeMappingProvider[] buildTypeMappingProviders() { |
| ArrayList<IJavaTypeMappingProvider> providers = new ArrayList<IJavaTypeMappingProvider>(); |
| this.addTypeMappingProvidersTo(providers); |
| return providers.toArray(new IJavaTypeMappingProvider[providers.size()]); |
| } |
| |
| /** |
| * Override this to specify more or different type mapping providers. |
| * The default includes the JPA spec-defined type mappings of |
| * Entity, MappedSuperclass, and Embeddable |
| */ |
| protected void addTypeMappingProvidersTo(Collection<IJavaTypeMappingProvider> providers) { |
| providers.add(JavaNullTypeMappingProvider.instance()); |
| providers.add(JavaEntityProvider.instance()); |
| providers.add(JavaMappedSuperclassProvider.instance()); |
| providers.add(JavaEmbeddableProvider.instance()); |
| } |
| |
| private DeclarationAnnotationAdapter[] buildAttributeMappingAnnotationAdapters() { |
| ArrayList<DeclarationAnnotationAdapter> adapters = new ArrayList<DeclarationAnnotationAdapter>(); |
| this.addAttributeMappingAnnotationAdaptersTo(adapters); |
| return adapters.toArray(new DeclarationAnnotationAdapter[adapters.size()]); |
| } |
| |
| /** |
| * Override this to specify more or different attribute mapping annotation |
| * adapters. The default includes the JPA spec-defined attribute mapping |
| * annotations. |
| */ |
| protected void addAttributeMappingAnnotationAdaptersTo(Collection<DeclarationAnnotationAdapter> adapters) { |
| adapters.add(JavaAssociationOverride.SINGLE_DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaAssociationOverride.MULTIPLE_DECLARATION_ANNOTATION_ADAPTER); // AssociationOverrides |
| adapters.add(JavaAttributeOverride.SINGLE_DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaAttributeOverride.MULTIPLE_DECLARATION_ANNOTATION_ADAPTER); // AttributeOverrides |
| adapters.add(JavaBasic.DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaColumn.MAPPING_DECLARATION_ANNOTATION_ADAPTER); // standalone Column |
| adapters.add(JavaEmbedded.DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaEmbeddedId.DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaBasic.ENUMERATED_ADAPTER); |
| adapters.add(JavaGeneratedValue.DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaId.DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaJoinColumn.SINGLE_DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaJoinColumn.MULTIPLE_DECLARATION_ANNOTATION_ADAPTER); // JoinColumns |
| adapters.add(JavaJoinTable.DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaBasic.LOB_ADAPTER); |
| adapters.add(JavaManyToMany.DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaManyToOne.DECLARATION_ANNOTATION_ADAPTER); |
| // TODO ? adapters.add(JavaMultiRelationshipMapping.MAP_KEY_ADAPTER); |
| adapters.add(JavaOneToMany.DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaOneToOne.DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaOrderBy.DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaPrimaryKeyJoinColumn.MULTIPLE_DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaPrimaryKeyJoinColumn.SINGLE_DECLARATION_ANNOTATION_ADAPTER); // PrimaryKeyJoinColumns |
| adapters.add(JavaSequenceGenerator.DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaTableGenerator.DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaBasic.TEMPORAL_ADAPTER); |
| adapters.add(JavaTransient.DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaVersion.DECLARATION_ANNOTATION_ADAPTER); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| protected EClass eStaticClass() { |
| return JpaJavaPackage.Literals.JAVA_PERSISTENT_TYPE; |
| } |
| |
| /** |
| * Returns the value of the '<em><b>Mapping Key</b></em>' attribute. |
| * <!-- begin-user-doc --> |
| * <p> |
| * If the meaning of the '<em>Mapping Key</em>' attribute isn't clear, |
| * there really should be more of a description here... |
| * </p> |
| * <!-- end-user-doc --> |
| * @return the value of the '<em>Mapping Key</em>' attribute. |
| * @see #setMappingKey(String) |
| * @see org.eclipse.jpt.core.internal.content.java.JpaJavaPackage#getIPersistentType_MappingKey() |
| * @model required="true" |
| * @generated |
| */ |
| public String getMappingKey() { |
| return mappingKey; |
| } |
| |
| /** |
| * Sets the value of the '{@link org.eclipse.jpt.core.internal.content.java.JavaPersistentType#getMappingKey <em>Mapping Key</em>}' attribute. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @param value the new value of the '<em>Mapping Key</em>' attribute. |
| * @see #getMappingKey() |
| * @generated |
| */ |
| public void setMappingKeyGen(String newMappingKey) { |
| String oldMappingKey = mappingKey; |
| mappingKey = newMappingKey; |
| if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.SET, JpaJavaPackage.JAVA_PERSISTENT_TYPE__MAPPING_KEY, oldMappingKey, mappingKey)); |
| } |
| |
| /** |
| * This is called by the UI, it should not be called when updating |
| * the persistence model from the java model. |
| */ |
| public void setMappingKey(String newMappingKey) { |
| if (newMappingKey == this.mappingKey) { |
| return; |
| } |
| setMapping(buildJavaTypeMapping(newMappingKey)); |
| setMappingKeyGen(newMappingKey); |
| } |
| |
| /** |
| * Returns the value of the '<em><b>Mapping</b></em>' containment reference. |
| * The default value is <code>""</code>. |
| * <!-- begin-user-doc --> |
| * <p> |
| * If the meaning of the '<em>Mapping</em>' containment reference isn't clear, |
| * there really should be more of a description here... |
| * </p> |
| * <!-- end-user-doc --> |
| * @return the value of the '<em>Mapping</em>' containment reference. |
| * @see #setMapping(IJavaTypeMapping) |
| * @see org.eclipse.jpt.core.internal.content.java.JpaJavaPackage#getJavaPersistentType_Mapping() |
| * @model containment="true" required="true" |
| * @generated |
| */ |
| public IJavaTypeMapping getMapping() { |
| return mapping; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public NotificationChain basicSetMapping(IJavaTypeMapping newMapping, NotificationChain msgs) { |
| IJavaTypeMapping oldMapping = mapping; |
| mapping = newMapping; |
| if (eNotificationRequired()) { |
| ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, JpaJavaPackage.JAVA_PERSISTENT_TYPE__MAPPING, oldMapping, newMapping); |
| if (msgs == null) |
| msgs = notification; |
| else |
| msgs.add(notification); |
| } |
| return msgs; |
| } |
| |
| /** |
| * Sets the value of the '{@link org.eclipse.jpt.core.internal.content.java.JavaPersistentType#getMapping <em>Mapping</em>}' containment reference. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @param value the new value of the '<em>Mapping</em>' containment reference. |
| * @see #getMapping() |
| * @generated |
| */ |
| public void setMappingGen(IJavaTypeMapping newMapping) { |
| if (newMapping != mapping) { |
| NotificationChain msgs = null; |
| if (mapping != null) |
| msgs = ((InternalEObject) mapping).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - JpaJavaPackage.JAVA_PERSISTENT_TYPE__MAPPING, null, msgs); |
| if (newMapping != null) |
| msgs = ((InternalEObject) newMapping).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - JpaJavaPackage.JAVA_PERSISTENT_TYPE__MAPPING, null, msgs); |
| msgs = basicSetMapping(newMapping, msgs); |
| if (msgs != null) |
| msgs.dispatch(); |
| } |
| else if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.SET, JpaJavaPackage.JAVA_PERSISTENT_TYPE__MAPPING, newMapping, newMapping)); |
| } |
| |
| /** |
| * This should not be called when updating the persistence model |
| * from the java model, it should only be called when going in the |
| * other direction. This will update the java code appropriately |
| * to the change in mapping in the persistence model. |
| */ |
| public void setMapping(IJavaTypeMapping newMapping) { |
| this.type.removeAnnotation(this.annotationAdapterForTypeMappingKey(this.mapping.getKey())); |
| this.type.newMarkerAnnotation(this.annotationAdapterForTypeMappingKey(newMapping.getKey())); |
| this.setMappingGen(newMapping); |
| } |
| |
| private DeclarationAnnotationAdapter annotationAdapterForTypeMappingKey(String typeMappingKey) { |
| return this.typeMappingProviderFor(typeMappingKey).declarationAnnotationAdapter(); |
| } |
| |
| private IJavaTypeMappingProvider typeMappingProviderFor(String typeMappingKey) { |
| for (IJavaTypeMappingProvider provider : this.typeMappingProviders) { |
| if (provider.key() == typeMappingKey) { |
| return provider; |
| } |
| } |
| throw new IllegalArgumentException("Unsupported type mapping key: " + typeMappingKey); |
| } |
| |
| /** |
| * Returns the value of the '<em><b>Attributes</b></em>' containment reference list. |
| * The list contents are of type {@link org.eclipse.jpt.core.internal.content.java.JavaPersistentAttribute}. |
| * <!-- begin-user-doc --> |
| * <p> |
| * If the meaning of the '<em>Attributes</em>' containment reference list isn't clear, |
| * there really should be more of a description here... |
| * </p> |
| * <!-- end-user-doc --> |
| * @return the value of the '<em>Attributes</em>' containment reference list. |
| * @see org.eclipse.jpt.core.internal.content.java.JpaJavaPackage#getJavaPersistentType_Attributes() |
| * @model type="org.eclipse.jpt.core.internal.content.java.JavaPersistentAttribute" containment="true" |
| * @generated |
| */ |
| public EList<JavaPersistentAttribute> getAttributes() { |
| if (attributes == null) { |
| attributes = new EObjectContainmentEList<JavaPersistentAttribute>(JavaPersistentAttribute.class, this, JpaJavaPackage.JAVA_PERSISTENT_TYPE__ATTRIBUTES); |
| } |
| return attributes; |
| } |
| |
| /** |
| * Returns the value of the '<em><b>Access</b></em>' attribute. |
| * The default value is <code>""</code>. |
| * The literals are from the enumeration {@link org.eclipse.jpt.core.internal.AccessType}. |
| * <!-- begin-user-doc --> |
| * <p> |
| * If the meaning of the '<em>Access</em>' attribute isn't clear, |
| * there really should be more of a description here... |
| * </p> |
| * <!-- end-user-doc --> |
| * @return the value of the '<em>Access</em>' attribute. |
| * @see org.eclipse.jpt.core.internal.AccessType |
| * @see org.eclipse.jpt.core.internal.content.java.JpaJavaPackage#getJavaPersistentType_Access() |
| * @model default="" changeable="false" |
| * @generated |
| */ |
| public AccessType getAccess() { |
| return access; |
| } |
| |
| private void setAccess(AccessType newAccess) { |
| AccessType oldAccess = access; |
| access = newAccess == null ? ACCESS_EDEFAULT : newAccess; |
| if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.SET, JpaJavaPackage.JAVA_PERSISTENT_TYPE__ACCESS, oldAccess, access)); |
| } |
| |
| /* @see IJpaContentNode#getId() */ |
| public Object getId() { |
| return IJavaContentNodes.PERSISTENT_TYPE_ID; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) { |
| switch (featureID) { |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__MAPPING : |
| return basicSetMapping(null, msgs); |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__ATTRIBUTES : |
| return ((InternalEList<?>) getAttributes()).basicRemove(otherEnd, msgs); |
| } |
| return super.eInverseRemove(otherEnd, featureID, msgs); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public Object eGet(int featureID, boolean resolve, boolean coreType) { |
| switch (featureID) { |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__MAPPING_KEY : |
| return getMappingKey(); |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__MAPPING : |
| return getMapping(); |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__ATTRIBUTES : |
| return getAttributes(); |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__ACCESS : |
| return getAccess(); |
| } |
| return super.eGet(featureID, resolve, coreType); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @SuppressWarnings("unchecked") |
| @Override |
| public void eSet(int featureID, Object newValue) { |
| switch (featureID) { |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__MAPPING_KEY : |
| setMappingKey((String) newValue); |
| return; |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__MAPPING : |
| setMapping((IJavaTypeMapping) newValue); |
| return; |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__ATTRIBUTES : |
| getAttributes().clear(); |
| getAttributes().addAll((Collection<? extends JavaPersistentAttribute>) newValue); |
| return; |
| } |
| super.eSet(featureID, newValue); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public void eUnset(int featureID) { |
| switch (featureID) { |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__MAPPING_KEY : |
| setMappingKey(MAPPING_KEY_EDEFAULT); |
| return; |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__MAPPING : |
| setMapping((IJavaTypeMapping) null); |
| return; |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__ATTRIBUTES : |
| getAttributes().clear(); |
| return; |
| } |
| super.eUnset(featureID); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public boolean eIsSet(int featureID) { |
| switch (featureID) { |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__MAPPING_KEY : |
| return MAPPING_KEY_EDEFAULT == null ? mappingKey != null : !MAPPING_KEY_EDEFAULT.equals(mappingKey); |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__MAPPING : |
| return mapping != null; |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__ATTRIBUTES : |
| return attributes != null && !attributes.isEmpty(); |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__ACCESS : |
| return access != ACCESS_EDEFAULT; |
| } |
| return super.eIsSet(featureID); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public int eBaseStructuralFeatureID(int derivedFeatureID, Class<?> baseClass) { |
| if (baseClass == IJpaContentNode.class) { |
| switch (derivedFeatureID) { |
| default : |
| return -1; |
| } |
| } |
| if (baseClass == IPersistentType.class) { |
| switch (derivedFeatureID) { |
| case JpaJavaPackage.JAVA_PERSISTENT_TYPE__MAPPING_KEY : |
| return JpaCorePackage.IPERSISTENT_TYPE__MAPPING_KEY; |
| default : |
| return -1; |
| } |
| } |
| return super.eBaseStructuralFeatureID(derivedFeatureID, baseClass); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public int eDerivedStructuralFeatureID(int baseFeatureID, Class<?> baseClass) { |
| if (baseClass == IJpaContentNode.class) { |
| switch (baseFeatureID) { |
| default : |
| return -1; |
| } |
| } |
| if (baseClass == IPersistentType.class) { |
| switch (baseFeatureID) { |
| case JpaCorePackage.IPERSISTENT_TYPE__MAPPING_KEY : |
| return JpaJavaPackage.JAVA_PERSISTENT_TYPE__MAPPING_KEY; |
| default : |
| return -1; |
| } |
| } |
| return super.eDerivedStructuralFeatureID(baseFeatureID, baseClass); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public String toString() { |
| if (eIsProxy()) |
| return super.toString(); |
| StringBuffer result = new StringBuffer(super.toString()); |
| result.append(" (mappingKey: "); |
| result.append(mappingKey); |
| result.append(", access: "); |
| result.append(access); |
| result.append(')'); |
| return result.toString(); |
| } |
| |
| public void setJdtType(IType iType, CompilationUnit astRoot) { |
| this.type = new Type(iType); |
| this.setAccess(this.javaAccessType(astRoot)); |
| this.createAndSetPersistentTypeMappingFromJava(this.javaTypeMappingKey(astRoot)); |
| } |
| |
| public JavaPersistentAttribute addJavaPersistentAttribute(IMember jdtMember) { |
| JavaPersistentAttribute persistentAttribute = createJavaPersistentAttribute(jdtMember); |
| getAttributes().add(persistentAttribute); |
| return persistentAttribute; |
| } |
| |
| public JavaPersistentAttribute createJavaPersistentAttribute(IMember member) { |
| Attribute attribute = null; |
| if (member instanceof IField) { |
| attribute = new FieldAttribute((IField) member); |
| } |
| else if (member instanceof IMethod) { |
| attribute = new MethodAttribute((IMethod) member); |
| } |
| else { |
| throw new IllegalArgumentException(); |
| } |
| return JpaJavaFactory.eINSTANCE.createJavaPersistentAttribute(attribute); |
| } |
| |
| private void createAndSetPersistentTypeMappingFromJava(String key) { |
| setMappingGen(buildJavaTypeMapping(key)); |
| setMappingKeyGen(key); |
| } |
| |
| private IJavaTypeMapping buildJavaTypeMapping(String key) { |
| return this.typeMappingProviderFor(key).buildMapping(this.type); |
| } |
| |
| public Type getType() { |
| return this.type; |
| } |
| |
| public String fullyQualifiedTypeName() { |
| return jdtType().getFullyQualifiedName(); |
| } |
| |
| public IType jdtType() { |
| return getType().jdtType(); |
| } |
| |
| /** |
| * This implementation of IPersistentType#findJdtType() will |
| * *always* find its type |
| */ |
| public IType findJdtType() { |
| return jdtType(); |
| } |
| |
| public boolean isFor(IType member) { |
| return this.type.wraps(member); |
| } |
| |
| protected void updateFromJava(CompilationUnit astRoot) { |
| this.setAccess(this.javaAccessType(astRoot)); |
| String jpaKey = this.getMapping().getKey(); |
| String javaKey = this.javaTypeMappingKey(astRoot); |
| if (jpaKey != javaKey) { |
| this.createAndSetPersistentTypeMappingFromJava(javaKey); |
| } |
| this.getMapping().updateFromJava(astRoot); |
| this.updatePersistentAttributes(astRoot); |
| } |
| |
| private void updatePersistentAttributes(CompilationUnit astRoot) { |
| List<JavaPersistentAttribute> persistentAttributesToRemove = new ArrayList<JavaPersistentAttribute>(getAttributes()); |
| if (getAccess() == AccessType.FIELD) { |
| updatePersistentFields(astRoot, persistentAttributesToRemove); |
| } |
| else if (getAccess() == AccessType.PROPERTY) { |
| updatePersistentProperties(astRoot, persistentAttributesToRemove); |
| } |
| getAttributes().removeAll(persistentAttributesToRemove); |
| } |
| |
| private void updatePersistentFields(CompilationUnit astRoot, List<JavaPersistentAttribute> persistentAttributesToRemove) { |
| for (IField field : this.jdtPersistableFields()) { |
| JavaPersistentAttribute persistentAttribute = persistentAttributeFor(field); |
| if (persistentAttribute == null) { |
| persistentAttribute = addJavaPersistentAttribute(field); |
| } |
| else { |
| persistentAttributesToRemove.remove(persistentAttribute); |
| } |
| persistentAttribute.updateFromJava(astRoot); |
| } |
| } |
| |
| private void updatePersistentProperties(CompilationUnit astRoot, List<JavaPersistentAttribute> persistentAttributesToRemove) { |
| for (IMethod method : this.jdtPersistableProperties()) { |
| JavaPersistentAttribute persistentAttribute = persistentAttributeFor(method); |
| if (persistentAttribute == null) { |
| addJavaPersistentAttribute(method); |
| } |
| else { |
| persistentAttributesToRemove.remove(persistentAttribute); |
| persistentAttribute.updateFromJava(astRoot); |
| } |
| } |
| } |
| |
| private IField[] jdtPersistableFields() { |
| return AttributeAnnotationTools.persistableFields(jdtType()); |
| } |
| |
| private IMethod[] jdtPersistableProperties() { |
| return AttributeAnnotationTools.persistablePropertyGetters(jdtType()); |
| } |
| |
| private String javaTypeMappingKey(CompilationUnit astRoot) { |
| for (IJavaTypeMappingProvider provider : this.typeMappingProviders) { |
| if (this.type.containsAnnotation(provider.declarationAnnotationAdapter(), astRoot)) { |
| return provider.key(); |
| } |
| } |
| return null; |
| } |
| |
| public Iterator<String> candidateMappingKeys() { |
| return new TransformationIterator<IJavaTypeMappingProvider, String>(new ArrayIterator<IJavaTypeMappingProvider>(this.typeMappingProviders)) { |
| @Override |
| protected String transform(IJavaTypeMappingProvider p) { |
| return p.key(); |
| } |
| }; |
| } |
| |
| public JavaPersistentAttribute attributeNamed(String attributeName) { |
| for (JavaPersistentAttribute attribute : this.getAttributes()) { |
| if (attributeName.equals(attribute.getName())) { |
| return attribute; |
| } |
| } |
| return null; |
| } |
| |
| public boolean containsOffset(int offset) { |
| try { |
| ISourceRange sourceRange = jdtType().getSourceRange(); |
| return (sourceRange.getOffset() <= offset) && (offset < sourceRange.getOffset() + sourceRange.getLength()); |
| } |
| catch (JavaModelException jme) { |
| return false; |
| } |
| } |
| |
| public Iterator<String> candidateValuesFor(int pos, Filter<String> filter, CompilationUnit astRoot) { |
| Iterator<String> values = this.mapping.candidateValuesFor(pos, filter, astRoot); |
| if (values != null) { |
| return values; |
| } |
| for (JavaPersistentAttribute attribute : this.getAttributes()) { |
| values = attribute.candidateValuesFor(pos, filter, astRoot); |
| if (values != null) { |
| return values; |
| } |
| } |
| return null; |
| } |
| |
| public IJpaContentNode contentNodeAt(int offset) { |
| ICompilationUnit unit = this.type.jdtType().getCompilationUnit(); |
| if (unit == null) { |
| return null; |
| } |
| IJavaElement javaElement = null; |
| try { |
| javaElement = unit.getElementAt(offset); |
| } |
| catch (JavaModelException ex) { |
| // fall through |
| } |
| if (javaElement == null) { |
| // typically happens between the package declarations and the source type |
| return null; |
| } |
| switch (javaElement.getElementType()) { |
| case IJavaElement.TYPE : |
| if (((IType) javaElement).getKey().equals(this.type.jdtType().getKey())) { |
| return this; |
| } |
| break; |
| case IJavaElement.FIELD : |
| case IJavaElement.METHOD : |
| return this.persistentAttributeFor((IMember) javaElement); |
| default : |
| break; |
| } |
| return this; |
| } |
| |
| public ITextRange getTextRange() { |
| return type.textRange(); |
| } |
| |
| private JavaPersistentAttribute persistentAttributeFor(IMember member) { |
| for (JavaPersistentAttribute attribute : this.getAttributes()) { |
| if (attribute.isFor(member)) { |
| return attribute; |
| } |
| } |
| return null; |
| } |
| |
| public Iterator<IPersistentAttribute> attributes() { |
| return new ReadOnlyIterator<IPersistentAttribute>(getAttributes()); |
| } |
| |
| public Iterator<IPersistentAttribute> allAttributes() { |
| return new CompositeIterator<IPersistentAttribute>(new TransformationIterator<IPersistentType, Iterator<IPersistentAttribute>>(this.inheritanceHierarchy()) { |
| @Override |
| protected Iterator<IPersistentAttribute> transform(IPersistentType pt) { |
| return pt.attributes(); |
| } |
| }); |
| } |
| |
| public Iterator<IPersistentType> inheritanceHierarchy() { |
| // using a chain iterator to traverse up the inheritance tree |
| return new ChainIterator<IPersistentType>(this) { |
| @Override |
| protected IPersistentType nextLink(IPersistentType pt) { |
| return pt.parentPersistentType(); |
| } |
| }; |
| } |
| |
| public IPersistentType parentPersistentType() { |
| return this.parentPersistentType; |
| } |
| |
| private String superclassTypeSignature() { |
| try { |
| return this.jdtType().getSuperclassTypeSignature(); |
| } |
| catch (JavaModelException ex) { |
| throw new RuntimeException(ex); |
| } |
| } |
| |
| /** |
| * Return the AccessType currently implied by the Java source code: |
| * - if only Fields are annotated => FIELD |
| * - if only Properties are annotated => PROPERTY |
| * - if both Fields and Properties are annotated => FIELD |
| * - if nothing is annotated |
| * - and fields exist => FIELD |
| * - and properties exist, but no fields exist => PROPERTY |
| * - and neither fields nor properties exist => FIELD |
| */ |
| private AccessType javaAccessType(CompilationUnit astRoot) { |
| IType jdtType = this.jdtType(); |
| boolean hasPersistableFields = false; |
| boolean hasPersistableProperties = false; |
| for (IField field : AttributeAnnotationTools.persistableFields(jdtType)) { |
| hasPersistableFields = true; |
| FieldAttribute fa = new FieldAttribute(field); |
| if (fa.containsAnyAnnotation(this.attributeMappingAnnotationAdapters, astRoot)) { |
| // any field is annotated => FIELD |
| return AccessType.FIELD; |
| } |
| } |
| for (IMethod method : AttributeAnnotationTools.persistablePropertyGetters(jdtType)) { |
| hasPersistableProperties = true; |
| MethodAttribute ma = new MethodAttribute(method); |
| if (ma.containsAnyAnnotation(this.attributeMappingAnnotationAdapters, astRoot)) { |
| // none of the fields are annotated and a getter is annotated => PROPERTY |
| return AccessType.PROPERTY; |
| } |
| } |
| // no annotations exist - default to fields, unless it's *obvious* to use properties |
| if (hasPersistableProperties && !hasPersistableFields) { |
| return AccessType.PROPERTY; |
| } |
| return AccessType.FIELD; |
| } |
| |
| public void refreshDefaults(DefaultsContext context) { |
| refreshParentPersistentType(context); |
| } |
| |
| private void refreshParentPersistentType(DefaultsContext context) { |
| String superclassTypeSignature = this.superclassTypeSignature(); |
| if (superclassTypeSignature == null) { |
| this.parentPersistentType = null; |
| return; |
| } |
| String fullyQualifiedTypeName = JDTTools.resolveSignature(superclassTypeSignature, this.jdtType()); |
| if (fullyQualifiedTypeName == null) { |
| this.parentPersistentType = null; |
| return; |
| } |
| IPersistentType possibleParent = context.persistentType(fullyQualifiedTypeName); |
| if (possibleParent == null) { |
| //TODO look to superclass |
| this.parentPersistentType = null; |
| return; |
| } |
| if (possibleParent.getMappingKey() != null) { |
| this.parentPersistentType = possibleParent; |
| } |
| else { |
| this.parentPersistentType = possibleParent.parentPersistentType(); |
| } |
| } |
| } // JavaType |