/*******************************************************************************
* Copyright (c) 2006-2012
* Software Technology Group, Dresden University of Technology
* DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026
*
* 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:
* Software Technology Group - TU Dresden, Germany;
* DevBoost GmbH - Berlin, Germany
* - initial API and implementation
******************************************************************************/
package org.reuseware.lacome.layoutlanguage.topcased;
import org.reuseware.lacome.DiagramDescription;
import org.reuseware.lacome.strategy.DiagramAligner;
import org.topcased.modeler.diagrams.model.Diagrams;
/**
* Diagram aligner for Topcased diagrams.
*/
public class TopcasedAligner implements DiagramAligner {
/**
* @param diagram diagram to align
* @return true if the first element in the receiving diagram is an instance of
* <code>org.topcased.modeler.diagrams.model.Diagrams</code>.
*/
public boolean canAlign(DiagramDescription diagram) {
if (!diagram.getDiagramRoots().isEmpty()) {
return diagram.getDiagramRoots().get(0) instanceof Diagrams;
}
return false;
}
/**
* Currently not implemented.
*
* @param newDiagram new version of composed diagram
* @param oldDiagram old version of composed diagram
*/
public void align(DiagramDescription newDiagram, DiagramDescription oldDiagram) {
//TODO #1473: implement this Topcased specific
/*
EList<EObject> newDiagrams = newDiagram.getDiagramRoots();
EList<EObject> oldDiagrams = oldDiagram.getDiagramRoots();
for(EObject newRoot : newDiagrams) {
for(EObject oldRoot : oldDiagrams) {
compareAndAlign(newRoot, oldRoot);
for(TreeIterator<EObject> newElementIt = newRoot.eAllContents(); newElementIt.hasNext(); ) {
EObject newElement = newElementIt.next();
for(TreeIterator<EObject> oldElementIt = oldRoot.eAllContents(); oldElementIt.hasNext(); ) {
EObject oldElement = oldElementIt.next();
if(compareAndAlign(newElement, oldElement)) {
break;
}
}
}
}
}
*/
}
/*
private EObject findSematicModelElement(EObject diagramElement) {
EObject element = null;
//TOPCASED
EStructuralFeature feature = diagramElement.eClass().getEStructuralFeature("semanticModel");
if (feature instanceof EReference) {
EObject bridge = (EObject) diagramElement.eGet(feature);
element = (EObject) bridge.eGet(bridge.eClass().getEStructuralFeature("element"));
}
//GMF
if (feature == null && !diagramElement.eClass().getName().equals("EMFSemanticModelBridge")) {
feature = diagramElement.eClass().getEStructuralFeature("element");
if (feature instanceof EReference) {
element = (EObject) diagramElement.eGet(feature);
}
}
return element;
}
private boolean compareAndAlign(EObject newDiagramElement, EObject oldDiagramElement) {
//diagram type check
if (!newDiagramElement.eClass().equals(oldDiagramElement.eClass())) {
return false;
}
EObject newModelElement = findSematicModelElement(newDiagramElement);
EObject oldModelElement = findSematicModelElement(oldDiagramElement);
if (newModelElement == null || oldModelElement == null) {
return false;
}
//semantic model element type check
if (!newModelElement.eClass().equals(oldModelElement.eClass())) {
return false;
}
//compare features of model element: compare attributes and attributes of next neighbors
if (!compareAttributes(newModelElement, oldModelElement)) {
return false;
}
for (EStructuralFeature feature : newModelElement.eClass().getEAllStructuralFeatures()) {
if (!feature.isDerived()) {
if (feature instanceof EReference) {
Object newNeighbor = newModelElement.eGet(feature);
Object oldNeighbor = oldModelElement.eGet(feature);
if (newNeighbor == null || oldNeighbor == null) {
if (oldNeighbor != null) {
return false;
}
if (newNeighbor != null) {
return false;
}
} else if (newNeighbor instanceof EList) {
EList<EObject> newNeighborList = (EList<EObject>) newNeighbor;
EList<EObject> oldNeighborList = (EList<EObject>) oldNeighbor;
if (newNeighborList.size() != oldNeighborList.size()) {
return false;
}
for (int i = 0; i < newNeighborList.size(); i++) {
if (!compareAttributes(newNeighborList.get(i), oldNeighborList.get(i))) {
return false;
}
}
} else {
if (!compareAttributes((EObject) newNeighbor, (EObject) oldNeighbor)) {
return false;
}
}
}
}
}
//align features of diagram element
for (EStructuralFeature feature : newDiagramElement.eClass().getEAllStructuralFeatures()) {
if (!feature.isDerived() && !feature.isTransient()
//below: references that concern the structure depend on
// the semantic model and are not considered here
//TOPCASED
&& !feature.getName().equals("semanticModel")
&& !feature.getName().equals("anchorage")
&& !feature.getName().equals("contained")) {
if (true) { //holdsOnlyAttributes(oldDiagramElement, feature)) {
try {
Object oldValue = oldDiagramElement.eGet(feature);
if (oldValue instanceof EList) {
EList<Object> oldValueList = (EList<Object>) oldValue;
//even if a list is empty, setting it (addAll) does something
//(which is not desired -> effect can be seen for instance in TOPCASED UML Class Diagrams)
//probably because of some notifier that is triggered
if (!oldValueList.isEmpty()) {
EList<Object> newValueList = (EList<Object>) newDiagramElement.eGet(feature);
newValueList.clear();
newValueList.addAll(oldValueList);
}
} else {
try {
newDiagramElement.eSet(feature, oldValue);
} catch (UnsupportedOperationException e) {
//
}
}
} catch (UnsupportedOperationException e) {
//catch exception if not possible (thrown e.g. by Diagram.setMeasurementUnit() of GMF)
}
}
}
}
return true;
}
private boolean compareAttributes(EObject newModelElement,
EObject oldModelElement) {
for (EStructuralFeature feature : newModelElement.eClass().getEAllStructuralFeatures()) {
if (feature instanceof EAttribute) {
Object value1 = newModelElement.eGet(feature);
Object value2 = oldModelElement.eGet(feature);
if (value1 == null && value2 != null) {
return false;
} else if (value1 != null && value2 == null) {
return false;
} else if (value1 != null && value2 != null) {
if (!newModelElement.eGet(feature).equals(oldModelElement.eGet(feature))) {
return false;
}
}
}
}
return true;
}
private boolean holdsOnlyAttributes(EObject element, EStructuralFeature feature) {
if(feature instanceof EAttribute) {
return true;
}
Object value = element.eGet(feature);
if(value == null) {
for(EReference childReference : ((EClass)feature.getEType()).getEAllReferences()) {
if(childReference instanceof EReference) {
return false;
}
}
return true;
}
if(value instanceof EList) {
@SuppressWarnings("unchecked")
EList<EObject> valueList = (EList<EObject>)value;
for(EObject listElement : valueList) {
for(EReference childReference : listElement.eClass().getEAllReferences()) {
if(childReference instanceof EReference) {
return false;
}
}
}
}
else {
for(EReference childReference : ((EObject)value).eClass().getEAllReferences()) {
if(childReference instanceof EReference) {
return false;
}
}
}
return true;
}
*/
}