/* 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.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import com.crispico.flower.mp.codesync.base.AbstractModelAdapter;
import com.crispico.flower.mp.codesync.base.CodeSyncAlgorithm;
import com.crispico.flower.mp.codesync.base.CodeSyncPlugin;
import com.crispico.flower.mp.codesync.base.IModelAdapter;
import com.crispico.flower.mp.codesync.base.ModelAdapterFactorySet;
import com.crispico.flower.mp.codesync.base.action.ActionResult;
/**
*
*/
public class EObjectModelAdapter extends AbstractModelAdapter {
private ModelAdapterFactorySet modelAdapterFactorySet;
@Override
public ModelAdapterFactorySet getModelAdapterFactorySet() {
return modelAdapterFactorySet;
}
@Override
public IModelAdapter setModelAdapterFactorySet(ModelAdapterFactorySet modelAdapterFactorySet) {
this.modelAdapterFactorySet = modelAdapterFactorySet;
return this;
}
@Override
public boolean hasChildren(Object modelElement) {
return !((EObject) modelElement).eContents().isEmpty();
}
@Override
public List<?> getChildren(Object modelElement) {
return ((EObject) modelElement).eContents();
}
@Override
public String getLabel(Object modelElement) {
// if (modelElement instanceof NamedElement)
// return ((NamedElement) modelElement).getName();
// else
return "%" + modelElement.getClass().getSimpleName() + "%";
}
@Override
public List<String> getIconUrls(Object modelElement) {
// return ImageURLFactory.INSTANCE.computeIconPathListForEObject((EObject) modelElement, false);
return null;
}
/**
* @author Cristi
* @author Mariana
*/
@Override
public Iterable<?> getContainmentFeatureIterable(Object element, Object feature, Iterable<?> correspondingIterable) {
EObject object = (EObject) element;
if (object.eResource() == null) {
return getUndefinedList(correspondingIterable);
}
EStructuralFeature structuralFeature = (EStructuralFeature) feature;
Object listCandidate = object.eGet(structuralFeature);
if (structuralFeature.isMany())
return (List) listCandidate; // "many" feature
else if (listCandidate != null)
return Collections.singletonList(listCandidate); // "one" feature
else
return Collections.emptyList();
}
/**
* @author Mariana
*/
protected Iterable<?> getUndefinedList(Iterable<?> result) {
if (result == null)
return Collections.emptyList();
return Collections.nCopies(((Collection) result).size(), CodeSyncAlgorithm.UNDEFINED);
}
/**
* @author Mariana
*/
protected boolean isUndefinedList(Iterable<?> result) {
List list = (List) result;
if (list.size() == 0) {
return false;
}
if (list.get(0).equals(CodeSyncAlgorithm.UNDEFINED)) {
return true;
}
return false;
}
// @Override
// public List<?> getFeatures(Object element) {
// return ((EObject) element).eClass().getEAllStructuralFeatures();
// }
//
// @Override
// public int getFeatureType(Object feature) {
// EStructuralFeature structuralFeature = (EStructuralFeature) feature;
// if (structuralFeature instanceof EReference && ((EReference) structuralFeature).isContainment())
// return FEATURE_TYPE_CONTAINMENT;
// else if (structuralFeature.isDerived() ||
// structuralFeature.isTransient() ||
// !structuralFeature.isChangeable() ||
//// ModelMerge.codeSyncTimeStampFeature.equals(structuralFeature) ||
//// UMLPackage.eINSTANCE.getNamedElement_ClientDependency().equals(structuralFeature) ||
//// UMLPackage.eINSTANCE.getAssociation_NavigableOwnedEnd().equals(feature) ||
// structuralFeature instanceof EReference && structuralFeature.isMany() && ((EReference) structuralFeature).getEOpposite() != null && !((EReference) structuralFeature).getEOpposite().isMany())
// return FEATURE_TYPE_DONT_PROCESS; // filter out features that don't need to be processed
// else
// return FEATURE_TYPE_VALUE;
//
// }
//
// public String getFeatureName(Object feature) {
// EStructuralFeature structuralFeature = (EStructuralFeature) feature;
// return structuralFeature.getName();
// }
public Object getMatchKey(Object element) {
EObject object = (EObject) element;
return object.eResource() == null ? null : object.eResource().getURIFragment(object);
}
@Override
public void addToMap(Object element, Map<Object, Object> map) {
map.put(getMatchKey(element), element);
}
@Override
public Object removeFromMap(Object element, Map<Object, Object> leftOrRightMap, boolean isRight) {
return leftOrRightMap.remove(getMatchKey(element));
}
/**
* @author Cristi
* @author Mariana
*/
@Override
public Object getValueFeatureValue(Object element, Object feature, Object correspondingValue) {
EStructuralFeature structuralFeature = (EStructuralFeature) feature;
EObject object = (EObject) element;
if (object.eResource() == null) {
return CodeSyncAlgorithm.UNDEFINED;
}
if (feature instanceof EReference) {
Object value = object.eGet(structuralFeature);
if (structuralFeature.isMany())
if (((List) value).size() > 1) {
// throw new RuntimeException(String.format("%s feature %s has more that 1 references; this is not supported.", getFullyQualifiedName(object), feature));
// System.err.println(">>>>>>>>>>>>>>>>>>>>>>>>>>> " + feature.getName());
return null;
} else if (((List) value).size() == 1) {
value = ((List) value).get(0);
} else
value = null; // empty list
return new Reference((EObject) value);
}
return object.eGet(structuralFeature);
}
@Override
public void setValueFeatureValue(Object element, Object feature, Object newValue) {
Object newValueForLog = newValue;
EObject object = (EObject) element;
EStructuralFeature structuralFeature = (EStructuralFeature) feature;
if (newValue instanceof Reference) {
Reference ref = (Reference) newValue;
if (ref.getReferencedObject() == null)
newValue = null; // the referenced object may be null
else {
newValue = object.eResource().getEObject(ref.getXmiId());
if (newValue == null) {
// // the referenced object doesn't exist (yet) in the resource; setting it should be deferred
// log("\t\tThe referenced object doesn't exist (yet) in the resource; deferring the feature set.");
// deferredReferenceToSetEntries.add(new DeferredReferenceToSetEntry(object, feature, ref));
// return false;
throw new UnsupportedOperationException("Setting a reference that doens't exist on target.");
}
}
}
// if (ancestorExists || logNewElementNestedAddAndCopy)
// log("%s%s, feature %s: COPIED right to left\n\tOld left value:\t%s\n\tNew left value:\t%s",
// ancestorExists ? "" : ">>>", getFullyQualifiedName(object), feature.getName(),
// getFeature(object, feature), newValueForLog);
if (structuralFeature instanceof EReference && structuralFeature.isMany()) {
if (newValue == null)
return;
// throw new UnsupportedOperationException(String.format("%s feature %s is being set to null. This is not normal and might mean that the EReference has more than 1 values, which is not supported. ", ModelMerge.getFullyQualifiedName(object), structuralFeature.getName()));
List<EObject> list = (List<EObject>) object.eGet(structuralFeature);
if (list.size() > 1) {
throw new UnsupportedOperationException(String.format("%s feature %s has more that 1 references; this is not supported.", ModelMerge.getFullyQualifiedName(object), structuralFeature.getName()));
} else if (list.size() == 1) {
list.set(0, (EObject) newValue);
} else
list.add((EObject) newValue);
} else
object.eSet(structuralFeature, newValue);
}
/**
* @author Cristi
* @author Mariana
*/
@Override
public Object createChildOnContainmentFeature(Object element, Object feature, Object correspondingChild) {
EObject object = (EObject) element;
EStructuralFeature structuralFeature = (EStructuralFeature) feature;
Object newChild = createCorrespondingModelElement(correspondingChild);
if (structuralFeature.isMany()) {
((List<Object>) object.eGet(structuralFeature)).add(newChild);
} else {
object.eSet(structuralFeature, newChild);
}
return newChild;
}
/**
* @author Mariana
*/
@Override
public void removeChildrenOnContainmentFeature(Object parent, Object feature, Object child) {
EStructuralFeature structuralFeature = (EStructuralFeature) feature;
EObject parentEObject = (EObject) parent;
if (structuralFeature.isMany()) {
((List<Object>) parentEObject.eGet(structuralFeature)).remove(child);
} else {
if (parentEObject.eGet(structuralFeature).equals(child)) {
parentEObject.eSet(structuralFeature, null);
}
}
}
/**
* @author Mariana
*/
@Override
public Object createCorrespondingModelElement(Object element) {
EObject corresp = (EObject) element;
EObject newObject = corresp.eClass().getEPackage().getEFactoryInstance().create(corresp.eClass());
return newObject;
}
/**
* @author Mariana
*/
@Override
public boolean save(Object element) {
EObject eObject = (EObject) element;
CodeSyncPlugin.getInstance().saveResource(eObject.eResource());
return false;
}
/**
* @author Mariana
*/
@Override
public boolean discard(Object element) {
EObject eObject = (EObject) element;
CodeSyncPlugin.getInstance().discardResource(eObject.eResource());
return false;
}
/**
* @author Mariana
*/
@Override
public void actionPerformed(Object element, Object feature, ActionResult result) {
// nothing to do
}
/**
* @author Mariana
*/
@Override
public void allActionsPerformedForFeature(Object element, Object correspondingElement, Object feature) {
// nothing to do
}
/**
* @author Mariana
*/
@Override
public void allActionsPerformed(Object element, Object correspondingElement) {
for (Object feature : getModelAdapterFactorySet().getFeatureProvider(element).getFeatures(element)) {
// if (getModelAdapterFactorySet().getFeatureProvider(element).getFeatureType(feature) == FEATURE_TYPE_CONTAINMENT) {
allActionsPerformedForFeature(element, correspondingElement, feature);
// }
}
}
/**
* @author Mariana
*/
@Override
public void beforeFeaturesProcessed(Object element, Object correspondingElement) {
// nothing to do
}
/**
* @author Mariana
*/
@Override
public void featuresProcessed(Object element) {
// nothing to do
}
}