/******************************************************************************* * Copyright (c) 2007, 2013 Borland Software Corporation and others. * * 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: * Borland Software Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.m2m.tests.qvt.oml.api.framework.comparator.emf; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.util.FeatureMap; import org.eclipse.emf.ecore.util.FeatureMap.Entry; import org.eclipse.m2m.tests.qvt.oml.api.framework.comparator.CompareUtil; import org.eclipse.m2m.tests.qvt.oml.api.framework.comparator.tree.ComparatorTreeNode; import org.eclipse.m2m.tests.qvt.oml.api.framework.comparator.tree.ContentChange; /** @author pkobiakov */ public class EmfObjectComparatorTreeNode extends ComparatorTreeNode { public EmfObjectComparatorTreeNode(ComparatorTreeNode parent, EObject node) { super(parent); if(node == null) { throw new IllegalArgumentException("emf node cannot be null"); //$NON-NLS-1$ } myNode = node; } public EObject getNode() { return myNode; } @Override public List<ComparatorTreeNode> getChildrenImpl() { List<ComparatorTreeNode> children = getRefs(true); children.addAll(getRefs(false)); children.addAll(getFeatureMapRefs()); return children; } @Override public List<ComparatorTreeNode> getNoncontainmentRefsImpl() { return Collections.emptyList(); } private List<ComparatorTreeNode> getRefs(boolean containment) { List<ComparatorTreeNode> children = new ArrayList<ComparatorTreeNode>(); for(EReference ref : myNode.eClass().getEAllReferences()) { if(ref.isDerived()) { continue; } if(containment ^ ref.isContainment()) { continue; } Object value = myNode.eGet(ref); if(value == null) { continue; } if(value instanceof List<?> && ((List<?>)value).isEmpty()) { continue; } children.add(new EmfContainmentComparatorTreeNode(this, ref)); } return children; } private List<EmfFeatureMapReferenceComparatorTreeNode> getFeatureMapRefs() { List<EmfFeatureMapReferenceComparatorTreeNode> children = new ArrayList<EmfFeatureMapReferenceComparatorTreeNode>(); for(EAttribute attr : myNode.eClass().getEAllAttributes()) { if(attr.isDerived()) { continue; } Object value = myNode.eGet(attr); if(value instanceof FeatureMap) { FeatureMap map = (FeatureMap)value; children.add(new EmfFeatureMapReferenceComparatorTreeNode(this, attr, map)); } } return children; } @Override public ContentChange compareClassesImpl(ComparatorTreeNode to) { EmfObjectComparatorTreeNode emfTo = (EmfObjectComparatorTreeNode)to; return new EClassContentChange(myNode.eClass(), emfTo.myNode.eClass()); } @Override public ContentChange compareAttributesImpl(ComparatorTreeNode to) { EmfObjectComparatorTreeNode emfTo = (EmfObjectComparatorTreeNode)to; EClass metaclass = myNode.eClass(); for(EAttribute attr : metaclass.getEAllAttributes()) { Object leftValue = myNode.eGet(attr); Object rightValue = emfTo.myNode.eGet(attr); ContentChange change = compareAttributeValues(attr, leftValue, rightValue); if(change != ContentChange.NULL_CHANGE) { return change; } } return ContentChange.NULL_CHANGE; } @SuppressWarnings("unchecked") private ContentChange compareAttributeValues(EAttribute attr, Object leftValue, Object rightValue) { if(leftValue == null && rightValue == null) { return ContentChange.NULL_CHANGE; } int cmp = CompareUtil.compareNulls(leftValue, rightValue); if(cmp != 0) { return new AttrContentChange(myNode, attr, leftValue, rightValue, cmp); } if(!leftValue.equals(rightValue)) { if(leftValue instanceof Comparable) { cmp = ((Comparable<Object>)leftValue).compareTo(rightValue); if(cmp != 0) { return new AttrContentChange(myNode, attr, leftValue, rightValue, cmp); } } if(rightValue instanceof Comparable) { cmp = ((Comparable<Object>)rightValue).compareTo(leftValue); if(cmp != 0) { return new AttrContentChange(myNode, attr, leftValue, rightValue, cmp); } } cmp = leftValue.getClass().getName().compareTo(rightValue.getClass().getName()); if(cmp != 0) { return new AttrContentChange(myNode, attr, leftValue, rightValue, cmp); } if(leftValue instanceof FeatureMap && rightValue instanceof FeatureMap) { FeatureMap leftMap = (FeatureMap)leftValue; FeatureMap rightMap = (FeatureMap)rightValue; ContentChange change = compareFeatureMaps(attr, leftMap, rightMap); return change; } if(leftValue instanceof FeatureMap.Entry && rightValue instanceof FeatureMap.Entry) { FeatureMap.Entry leftEntry = (Entry)leftValue; FeatureMap.Entry rightEntry = (Entry)rightValue; ContentChange change = compareFeatureMapEntries(attr, leftEntry, rightEntry); return change; } cmp = leftValue.toString().compareTo(rightValue.toString()); if(cmp != 0) { return new AttrContentChange(myNode, attr, leftValue, rightValue, cmp); } } return ContentChange.NULL_CHANGE; } private ContentChange compareFeatureMaps(EAttribute attr, FeatureMap leftMap, FeatureMap rightMap) { if(leftMap.size() != rightMap.size()) { return new AttrContentChange(myNode, attr, leftMap, rightMap, leftMap.size()-rightMap.size()); } for(Iterator<?> leftIt = leftMap.iterator(), rightIt = rightMap.iterator(); leftIt.hasNext(); ) { FeatureMap.Entry leftEntry = (Entry) leftIt.next(); FeatureMap.Entry rightEntry = (Entry) rightIt.next(); ContentChange change = compareFeatureMapEntries(attr, leftEntry, rightEntry); if(change != ContentChange.NULL_CHANGE) { return change; } } return ContentChange.NULL_CHANGE; } private ContentChange compareFeatureMapEntries(EAttribute attr, FeatureMap.Entry leftEntry, FeatureMap.Entry rightEntry) { int cmp = leftEntry.getEStructuralFeature().getClass().getName().compareTo( rightEntry.getEStructuralFeature().getClass().getName()); if(cmp != 0) { return new AttrContentChange(myNode, attr, leftEntry.getClass(), rightEntry.getClass(), cmp); } if(leftEntry.getEStructuralFeature() instanceof EAttribute && rightEntry.getEStructuralFeature() instanceof EAttribute) { EAttribute leftAttr = (EAttribute) leftEntry.getEStructuralFeature(); EAttribute rightAttr = (EAttribute) rightEntry.getEStructuralFeature(); if(!leftAttr.equals(rightAttr)) { return new AttrContentChange(myNode, attr, leftAttr, rightAttr, 1); } ContentChange change = compareAttributeValues(leftAttr, leftEntry.getValue(), rightEntry.getValue()); if(change != ContentChange.NULL_CHANGE) { return change; } } // references are represented as separate tree nodes return ContentChange.NULL_CHANGE; } @Override public boolean equals(Object o) { if(o instanceof EmfObjectComparatorTreeNode == false) { return false; } EmfObjectComparatorTreeNode node = (EmfObjectComparatorTreeNode)o; return getChange(node).getCmp() == 0; } @Override public int hashCode() { return 0; } @Override public String toString() { return Util.toString(myNode); } private final EObject myNode; }