| /******************************************************************************* |
| * 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.IField; |
| import org.eclipse.jdt.core.IMember; |
| import org.eclipse.jdt.core.IMethod; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.dom.CompilationUnit; |
| import org.eclipse.jdt.core.dom.ITypeBinding; |
| 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.JavaEmbedded; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JavaEmbeddedId; |
| 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.JavaMultiRelationshipMapping; |
| 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.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.MethodAttribute; |
| import org.eclipse.jpt.core.internal.jdtutility.Type; |
| import org.eclipse.jpt.core.internal.platform.DefaultsContext; |
| import org.eclipse.jpt.utility.internal.CommandExecutorProvider; |
| import org.eclipse.jpt.utility.internal.Filter; |
| import org.eclipse.jpt.utility.internal.iterators.ChainIterator; |
| import org.eclipse.jpt.utility.internal.iterators.CloneIterator; |
| import org.eclipse.jpt.utility.internal.iterators.CompositeIterator; |
| import org.eclipse.jpt.utility.internal.iterators.FilteringIterator; |
| 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 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.attributeMappingAnnotationAdapters = this.buildAttributeMappingAnnotationAdapters(); |
| } |
| |
| 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); |
| adapters.add(JavaMultiRelationshipMapping.ORDER_BY_ADAPTER); |
| adapters.add(JavaMultiRelationshipMapping.MAP_KEY_ADAPTER); |
| adapters.add(JavaOneToMany.DECLARATION_ANNOTATION_ADAPTER); |
| adapters.add(JavaOneToOne.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. |
| * <!-- 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.typeMappingProvider(typeMappingKey).declarationAnnotationAdapter(); |
| } |
| |
| protected Iterator<IJavaTypeMappingProvider> typeMappingProviders() { |
| return jpaPlatform().javaTypeMappingProviders(); |
| } |
| |
| private IJavaTypeMappingProvider typeMappingProvider(String typeMappingKey) { |
| return jpaPlatform().javaTypeMappingProvider(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 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 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 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(); |
| } |
| |
| /** |
| * delegate to the type's project (there is one provider per project) |
| */ |
| private CommandExecutorProvider modifySharedDocumentCommandExecutorProvider() { |
| return this.getJpaProject().modifySharedDocumentCommandExecutorProvider(); |
| } |
| |
| public void setJdtType(IType iType, CompilationUnit astRoot) { |
| this.type = new Type(iType, this.modifySharedDocumentCommandExecutorProvider()); |
| 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, this.modifySharedDocumentCommandExecutorProvider()); |
| } |
| else if (member instanceof IMethod) { |
| attribute = new MethodAttribute((IMethod) member, this.modifySharedDocumentCommandExecutorProvider()); |
| } |
| 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.typeMappingProvider(key).buildMapping(this.type, this.jpaFactory()); |
| } |
| |
| public Type getType() { |
| return this.type; |
| } |
| |
| public String fullyQualifiedTypeName() { |
| return jdtType().getFullyQualifiedName(); |
| } |
| |
| public IType jdtType() { |
| return getType().getJdtMember(); |
| } |
| |
| /** |
| * 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) { |
| updatePersistentAttributes(astRoot, persistentAttributesToRemove, this.jdtPersistableFields()); |
| } |
| |
| private void updatePersistentProperties(CompilationUnit astRoot, List<JavaPersistentAttribute> persistentAttributesToRemove) { |
| updatePersistentAttributes(astRoot, persistentAttributesToRemove, this.jdtPersistableProperties()); |
| } |
| |
| private void updatePersistentAttributes(CompilationUnit astRoot, List<JavaPersistentAttribute> persistentAttributesToRemove, IMember[] members) { |
| for (IMember member : members) { |
| JavaPersistentAttribute persistentAttribute = persistentAttributeFor(member); |
| if (persistentAttribute == null) { |
| persistentAttribute = addJavaPersistentAttribute(member); |
| } |
| 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 (Iterator<IJavaTypeMappingProvider> i = this.typeMappingProviders(); i.hasNext();) { |
| IJavaTypeMappingProvider provider = i.next(); |
| if (this.type.containsAnnotation(provider.declarationAnnotationAdapter(), astRoot)) { |
| return provider.key(); |
| } |
| } |
| return null; |
| } |
| |
| protected Iterator<JavaPersistentAttribute> attributesNamed(final String attributeName) { |
| return new FilteringIterator<JavaPersistentAttribute>(attributes()) { |
| @Override |
| protected boolean accept(Object o) { |
| return attributeName.equals(((JavaPersistentAttribute) o).getName()); |
| } |
| }; |
| } |
| |
| public JavaPersistentAttribute attributeNamed(String attributeName) { |
| Iterator<JavaPersistentAttribute> stream = attributesNamed(attributeName); |
| return (stream.hasNext()) ? stream.next() : null; |
| } |
| |
| public IPersistentAttribute resolveAttribute(String attributeName) { |
| Iterator<JavaPersistentAttribute> stream = attributesNamed(attributeName); |
| if (stream.hasNext()) { |
| JavaPersistentAttribute attribute = stream.next(); |
| return (stream.hasNext()) ? null /*more than one*/: attribute; |
| } |
| return (parentPersistentType() == null) ? null : parentPersistentType().resolveAttribute(attributeName); |
| } |
| |
| @Override |
| public Iterator<String> candidateValuesFor(int pos, Filter<String> filter, CompilationUnit astRoot) { |
| Iterator<String> result = super.candidateValuesFor(pos, filter, astRoot); |
| if (result != null) { |
| return result; |
| } |
| Iterator<String> values = this.mapping.candidateValuesFor(pos, filter, astRoot); |
| if (values != null) { |
| return values; |
| } |
| for (Iterator<JavaPersistentAttribute> stream = attributes(); stream.hasNext();) { |
| values = stream.next().candidateValuesFor(pos, filter, astRoot); |
| if (values != null) { |
| return values; |
| } |
| } |
| return null; |
| } |
| |
| public IJpaContentNode contentNodeAt(int offset) { |
| for (Iterator<JavaPersistentAttribute> i = attributes(); i.hasNext();) { |
| JavaPersistentAttribute persistentAttribute = i.next(); |
| if (persistentAttribute.includes(offset)) { |
| return persistentAttribute; |
| } |
| } |
| return null; |
| } |
| |
| public boolean includes(int offset) { |
| return this.fullTextRange().includes(offset); |
| } |
| |
| public ITextRange fullTextRange() { |
| return this.type.textRange(); |
| } |
| |
| public ITextRange validationTextRange() { |
| return this.selectionTextRange(); |
| } |
| |
| public ITextRange selectionTextRange() { |
| return this.type.nameTextRange(); |
| } |
| |
| public ITextRange getTextRange() { |
| return type.textRange(); |
| } |
| |
| private JavaPersistentAttribute persistentAttributeFor(IMember member) { |
| for (Iterator<JavaPersistentAttribute> i = attributes(); i.hasNext();) { |
| JavaPersistentAttribute attribute = i.next(); |
| if (attribute.isFor(member)) { |
| return attribute; |
| } |
| } |
| return null; |
| } |
| |
| public Iterator<JavaPersistentAttribute> attributes() { |
| return new CloneIterator<JavaPersistentAttribute>(getAttributes()); |
| } |
| |
| public Iterator<String> attributeNames() { |
| return this.attributeNames(this.attributes()); |
| } |
| |
| private Iterator<String> attributeNames(Iterator<? extends IPersistentAttribute> attrs) { |
| return new TransformationIterator<IPersistentAttribute, String>(attrs) { |
| @Override |
| protected String transform(IPersistentAttribute attribute) { |
| return attribute.getName(); |
| } |
| }; |
| } |
| |
| public Iterator<IPersistentAttribute> allAttributes() { |
| return new CompositeIterator<IPersistentAttribute>(new TransformationIterator<IPersistentType, Iterator<IPersistentAttribute>>(this.inheritanceHierarchy()) { |
| @Override |
| protected Iterator<IPersistentAttribute> transform(IPersistentType pt) { |
| //TODO how to remove this warning? |
| return (Iterator<IPersistentAttribute>) pt.attributes(); |
| } |
| }); |
| } |
| |
| public Iterator<String> allAttributeNames() { |
| return this.attributeNames(this.allAttributes()); |
| } |
| |
| 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, null); // a bit hacky... |
| 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, null); // a bit hacky... |
| 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) { |
| ITypeBinding typeBinding = getType().typeBinding(context.astRoot()); |
| this.parentPersistentType = parentPersistentType(context, typeBinding); |
| } |
| |
| public static IPersistentType parentPersistentType(DefaultsContext context, ITypeBinding typeBinding) { |
| if (typeBinding == null) { |
| return null; |
| } |
| ITypeBinding superClassTypeBinding = typeBinding.getSuperclass(); |
| if (superClassTypeBinding == null) { |
| return null; |
| } |
| String fullyQualifiedTypeName = superClassTypeBinding.getQualifiedName(); |
| IPersistentType possibleParent = context.persistentType(fullyQualifiedTypeName); |
| if (possibleParent == null) { |
| //TODO look to superclass |
| return null; |
| } |
| if (possibleParent.getMappingKey() != null) { |
| return possibleParent; |
| } |
| return possibleParent.parentPersistentType(); |
| } |
| } |