/* license-start * * Copyright (C) 2008 - 2013 Crispico, <http://www.crispico.com/>. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details, at <http://www.gnu.org/licenses/>. * * Contributors: * Crispico - Initial API and implementation * * license-end */ package com.crispico.flower.mp.codesync.merge; import java.util.ArrayList; import java.util.List; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; import org.flowerplatform.codesync.remote.CodeSyncOperationsService; import com.crispico.flower.mp.codesync.base.IModelAdapter; import com.crispico.flower.mp.codesync.base.ModelAdapterFactory; import com.crispico.flower.mp.model.codesync.AstCacheElement; import com.crispico.flower.mp.model.codesync.CodeSyncElement; import com.crispico.flower.mp.model.codesync.CodeSyncPackage; import com.crispico.flower.mp.model.codesync.FeatureChange; /** * @author Mariana */ public class SyncElementModelAdapter extends EObjectModelAdapter { protected ModelAdapterFactory modelAdapterFactory; protected ModelAdapterFactory codeSyncElementConverter; protected Resource resource; public SyncElementModelAdapter setModelAdapterFactory(ModelAdapterFactory modelAdapterFactory) { this.modelAdapterFactory = modelAdapterFactory; return this; } public ModelAdapterFactory getModelAdapterFactory() { return modelAdapterFactory; } /** * @see IModelAdapter#createCorrespondingModelElement(Object) */ public SyncElementModelAdapter setEObjectConverter(ModelAdapterFactory codeSyncElementConverter) { this.codeSyncElementConverter = codeSyncElementConverter; return this; } public ModelAdapterFactory getEObjectConverter() { return codeSyncElementConverter; } public SyncElementModelAdapter setResource(Resource resource) { this.resource = resource; return this; } public void addToResource(AstCacheElement element) { resource.getContents().add(element); } /** * Checks for a {@link FeatureChange} on the name feature first. */ @Override public String getLabel(Object modelElement) { CodeSyncElement codeSyncElement = (CodeSyncElement) modelElement; FeatureChange change = codeSyncElement.getFeatureChanges().get(CodeSyncPackage.eINSTANCE.getCodeSyncElement_Name()); if (change != null) { return (String) change.getNewValue(); } return (String) getMatchKey(modelElement); } @Override public List<String> getIconUrls(Object modelElement) { return super.getIconUrls(modelElement); } @Override public Object createCorrespondingModelElement(Object element) { IModelAdapter adapter = null; if (element == null) { adapter = codeSyncElementConverter.getModelAdapterByType(getType()); } else { adapter = codeSyncElementConverter.getModelAdapter(element); } if (adapter != null) { return adapter.createCorrespondingModelElement(element); } else { return super.createCorrespondingModelElement(element); } } @Override public Iterable<?> getContainmentFeatureIterable(Object element, Object feature, Iterable<?> correspondingIterable) { EObject eObject = getContainingEObjectForFeature(element, feature); if (eObject != null) { return super.getContainmentFeatureIterable(eObject, feature, correspondingIterable); } return new ArrayList<>(); } @Override public Object getValueFeatureValue(Object element, Object feature, Object correspondingValue) { EObject eObject = getContainingEObjectForFeature(element, feature); if (eObject != null) { return super.getValueFeatureValue(eObject, feature, correspondingValue); } return null; } @Override public Object getMatchKey(Object element) { return CodeSyncOperationsService.getInstance() .getKeyFeatureValue(((CodeSyncElement) element)); } @Override public void setValueFeatureValue(Object element, Object feature, Object newValue) { EObject eObject = getContainingEObjectForFeature(element, feature); if (eObject != null) { super.setValueFeatureValue(eObject, feature, newValue); } } /** * For the <code>children</code> feature of {@link CodeSyncElement}, also add the new child to the {@link AstCacheElement}s * resource. */ @Override public Object createChildOnContainmentFeature(Object element, Object feature, Object correspondingChild) { EObject eObject = getContainingEObjectForFeature(element, feature); // first check if the child already exists Iterable<?> children = super.getContainmentFeatureIterable(eObject, feature, null); IModelAdapter adapter = codeSyncElementConverter.getModelAdapter(correspondingChild); Object matchKey = null; if (adapter != null) { matchKey = adapter.getMatchKey(correspondingChild); } else { matchKey = getMatchKey(correspondingChild); } if (matchKey != null) { for (Object child : children) { if (matchKey.equals(modelAdapterFactory.getModelAdapter(child).getMatchKey(child))) { return child; } } } if (eObject != null) { if (CodeSyncPackage.eINSTANCE.getCodeSyncElement_Children().equals(feature)) { CodeSyncElement parent = (CodeSyncElement) element; CodeSyncElement cse = CodeSyncPackage.eINSTANCE.getCodeSyncFactory().createCodeSyncElement(); AstCacheElement ace = (AstCacheElement) createCorrespondingModelElement(correspondingChild); if (ace != null) { addToResource(ace); } cse.setAstCacheElement(ace); parent.getChildren().add(cse); return cse; } else { return super.createChildOnContainmentFeature(eObject, feature, correspondingChild); } } return null; } @Override public void removeChildrenOnContainmentFeature(Object parent, Object feature, Object child) { EObject eObject = getContainingEObjectForFeature(parent, feature); if (eObject != null) { super.removeChildrenOnContainmentFeature(eObject, feature, child); } } protected FeatureChange getFeatureChange(Object element, Object feature) { CodeSyncElement cse = null; if (element instanceof CodeSyncElement) { cse = (CodeSyncElement) element; } else { if (element instanceof AstCacheElement) { cse = ((AstCacheElement) element).getCodeSyncElement(); } } if (cse != null) { return cse.getFeatureChanges().get(feature); } return null; } /** * Checks if the <code>feature</code> belongs to the {@link EClass} of the <code>element</code>. * If not, delegates to the {@link AstCacheElement} of a {@link CodeSyncElement}. */ protected EObject getContainingEObjectForFeature(Object element, Object feature) { EClass containingClass = ((EStructuralFeature) feature).getEContainingClass(); EObject eObject = (EObject) element; if (eObject != null && containingClass.isSuperTypeOf(eObject.eClass())) { // check if the feature's containing class is the same as the EObject return eObject; } if (eObject instanceof CodeSyncElement) { eObject = ((CodeSyncElement) eObject).getAstCacheElement(); return getContainingEObjectForFeature(eObject, feature); } return null; } }