package org.jnario.feature.jvmmodel; import static com.google.common.base.Objects.equal; import static com.google.common.collect.Iterables.concat; import static com.google.common.collect.Iterables.filter; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.xtext.common.types.JvmField; import org.eclipse.xtext.common.types.JvmGenericType; import org.eclipse.xtext.common.types.JvmMember; import org.eclipse.xtext.common.types.JvmType; import org.eclipse.xtext.common.types.JvmTypeReference; import org.eclipse.xtext.xbase.jvmmodel.IJvmModelAssociations; import org.eclipse.xtext.xbase.util.XbaseUsageCrossReferencer; import org.jnario.jvmmodel.ExtendedJvmTypesBuilder; import com.google.inject.Inject; public class JvmFieldReferenceUpdater { @SuppressWarnings("serial") private class FieldReferenceFinder extends XbaseUsageCrossReferencer{ private JvmGenericType newType; private JvmGenericType originalType; protected FieldReferenceFinder(EObject eObject) { super(eObject); } protected boolean crossReference(EObject eObject, EReference eReference, EObject crossReferencedEObject) { if(crossReferencedEObject instanceof JvmField){ return updateFieldReference(eObject, eReference, (JvmField)crossReferencedEObject); } if(crossReferencedEObject == originalType){ EcoreUtil.replace(eObject, eReference, originalType, newType); } return false; } protected boolean updateFieldReference(EObject eObject, EReference eReference, JvmField sourceField) { if(sourceField.isStatic()){ return false; } if(!sourceField.getDeclaringType().getSimpleName().equals(originalType.getSimpleName())){ return false; } JvmField newField = findMatchingField(sourceField); EcoreUtil.replace(eObject, eReference, sourceField, newField); return true; } private JvmField findMatchingField(JvmField sourceField) { Iterable<JvmMember> members = allMembersOf(newType); for (JvmField candidate : filter(members, JvmField.class)) { if(candidate.getSimpleName() == null && equal(candidate.getType().getQualifiedName(), sourceField.getType().getQualifiedName())){ candidate.setSimpleName(sourceField.getSimpleName()); return candidate; } if(equal(candidate.getSimpleName(), sourceField.getSimpleName())){ return candidate; } } EObject source = associations.getPrimarySourceElement(sourceField); JvmField newField = typesBuilder.toField(source, sourceField.getSimpleName(), sourceField.getType()); newType.getMembers().add(newField); return newField; } public Iterable<JvmMember> allMembersOf(JvmGenericType type) { Iterable<JvmMember> members = type.getMembers(); for (JvmTypeReference superTypeReference : type.getSuperTypes()) { JvmType superType = superTypeReference.getType(); if(superType != null && superType instanceof JvmGenericType){ members = concat(members, ((JvmGenericType)superType).getMembers()); } } return members; } public void updateFields(JvmGenericType originalType, JvmGenericType newType){ this.originalType = originalType; this.newType = newType; crossReference(); done(); } @Override protected void done() { super.done(); newType = null; } } @Inject ExtendedJvmTypesBuilder typesBuilder; @Inject IJvmModelAssociations associations; public void updateReferences(EObject eObject, JvmGenericType originalType, JvmGenericType newType) { FieldReferenceFinder referenceFinder = new FieldReferenceFinder(eObject); referenceFinder.updateFields(originalType, newType); } }