blob: 8c17607cd552f15032012ff40cbab681710e9348 [file] [log] [blame]
/**
* <copyright>
*
* Copyright (c) 2015 itemis 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:
* itemis - Initial API and implementation
*
* </copyright>
*/
package org.eclipse.sphinx.emf.compare.report
import java.io.ByteArrayInputStream
import java.util.Map
import org.eclipse.core.resources.IFile
import org.eclipse.core.resources.IProject
import org.eclipse.core.runtime.NullProgressMonitor
import org.eclipse.emf.common.notify.Notifier
import org.eclipse.emf.common.util.Monitor
import org.eclipse.emf.common.util.URI
import org.eclipse.emf.compare.AttributeChange
import org.eclipse.emf.compare.Comparison
import org.eclipse.emf.compare.Diff
import org.eclipse.emf.compare.DifferenceKind
import org.eclipse.emf.compare.DifferenceSource
import org.eclipse.emf.compare.Match
import org.eclipse.emf.compare.MatchResource
import org.eclipse.emf.compare.ReferenceChange
import org.eclipse.emf.compare.postprocessor.IPostProcessor
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.EStructuralFeature
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.sphinx.emf.compare.util.ModelCompareUtil
import org.eclipse.sphinx.emf.util.EObjectUtil
import org.eclipse.sphinx.emf.util.EcorePlatformUtil
import org.eclipse.sphinx.emf.util.EcoreResourceUtil
import org.eclipse.core.resources.IFolder
public abstract class AbstractModelCompareReportGenerator implements IPostProcessor {
public static final String MODEL_DIFF_REPORT_KIND = "kind"; //$NON-NLS-1$
public static final String MODEL_DIFF_REPORT_LEFT_DIFF_URI = "leftURI"; //$NON-NLS-1$
public static final String MODEL_DIFF_REPORT_LEFT_DIFF_TEXT = "leftChangeText"; //$NON-NLS-1$
public static final String MODEL_DIFF_REPORT_RIGHT_DIFF_URI = "rightURI"; //$NON-NLS-1$
public static final String MODEL_DIFF_REPORT_RIGHT_DIFF_TEXT = "rightChangeText"; //$NON-NLS-1$
public static final String MODEL_DIFF_REPORT_TARGET_REPORT_FOLDER_NAME = "reports"; //$NON-NLS-1$
protected abstract def CharSequence doGenerate(Comparison comparison)
public def generate(Comparison comparison, IFile targetFile) {
writeFile(targetFile, comparison.doGenerate)
}
def Notifier getLeftObject(Comparison comparison) {
if (comparison != null) {
if (!comparison.getMatchedResources().isEmpty()) {
val MatchResource matchResource = comparison.getMatchedResources().get(0)
return matchResource.getLeft()
} else {
// This is a comparison of EObjects
if (!comparison.getMatches().isEmpty()) {
val Match match = comparison.getMatches().get(0)
return match.getLeft()
}
}
}
null
}
def Notifier getRightObject(Comparison comparison) {
if (comparison != null) {
if (!comparison.getMatchedResources().isEmpty()) {
val MatchResource matchResource = comparison.getMatchedResources().get(0)
return matchResource.getRight()
} else {
// This is a comparison of EObjects
if (!comparison.getMatches().isEmpty()) {
val Match match = comparison.getMatches().get(0)
return match.getRight()
}
}
}
null
}
def IProject getTargetProject(Comparison comparison) {
if (comparison != null) {
if (comparison.getMatchedResources().isEmpty()) {
// This is a comparison of EObjects
for (Match match : comparison.getMatches()) {
var IFile file = EcorePlatformUtil.getFile(match.getLeft())
if (file == null) {
file = EcorePlatformUtil.getFile(match.getRight())
}
if (file != null) {
return file.getProject()
}
}
} else {
for (MatchResource matchResource : comparison.getMatchedResources()) {
var IFile file = EcorePlatformUtil.getFile(matchResource.getLeft())
if (file == null) {
file = EcorePlatformUtil.getFile(matchResource.getRight())
}
if (file != null) {
return file.getProject()
}
}
}
}
return null
}
def String getModelCompareInputText(Object object) {
var String label = ""
if (object instanceof EObject) {
val URI uri = EcoreResourceUtil.getURI(object, true)
label = uri.trimQuery().toString()
} else if (object instanceof Resource) {
label = object.getURI().trimQuery().toString()
}
return label;
}
def String getName(Object object) {
var String name = ""
if (object instanceof EObject) {
val EStructuralFeature eStructuralFeature = EObjectUtil.getEStructuralFeature(object.eClass, "name")
if (eStructuralFeature != null) {
name = object.eGet(eStructuralFeature, false)?.toString
} else {
name = object.eClass.name + "@" + Integer.toHexString(object.hashCode)
}
} else if (object instanceof Resource) {
name = object.getURI().trimQuery().lastSegment
}
return name;
}
def String getDiffKindText(Diff diff) {
val kind = diff?.kind
if (kind == DifferenceKind.DELETE) {
if (diff instanceof ReferenceChange) {
val reference = diff.reference
if (reference.isContainment) {
return "DELETED from "
} else {
return "REMOVED from "
}
}
} else if (kind == DifferenceKind.ADD) {
return "ADDED to "
}
return kind + "D "
}
def String getDiffKindLabel(DifferenceKind kind) {
switch kind {
case ADD:
return "+-"
case DELETE:
return "-+"
case CHANGE:
return "<>"
case MOVE:
return "~"
default:
return "<>"
}
}
def Map<String, Object> handleDifferences(Comparison comparison, Diff diff) {
var Map<String, Object> map = newHashMap()
if (diff != null) {
val DifferenceKind kind = diff.getKind()
map.put(MODEL_DIFF_REPORT_KIND, getDiffKindLabel(kind))
map.put(MODEL_DIFF_REPORT_LEFT_DIFF_URI, getDiffObjectURIFragment(diff, DifferenceSource.LEFT))
map.put(MODEL_DIFF_REPORT_RIGHT_DIFF_URI, getDiffObjectURIFragment(diff, DifferenceSource.RIGHT))
// Attribute changed
if (diff instanceof AttributeChange) {
map.put(MODEL_DIFF_REPORT_LEFT_DIFF_TEXT, getAttributeChangeText(diff))
map.put(MODEL_DIFF_REPORT_RIGHT_DIFF_TEXT, getAttributeChangeText(diff))
} else {
if (diff.source == DifferenceSource.LEFT) {
// left addition
if (kind == DifferenceKind.ADD) {
map.put(MODEL_DIFF_REPORT_LEFT_DIFF_TEXT, getReferenceChangeText(diff, false));
map.put(MODEL_DIFF_REPORT_RIGHT_DIFF_TEXT, getReferenceChangeText(diff, true));
} else if (kind == DifferenceKind.DELETE) {
// left deletion
map.put(MODEL_DIFF_REPORT_LEFT_DIFF_TEXT, getReferenceChangeText(diff, false));
map.put(MODEL_DIFF_REPORT_RIGHT_DIFF_TEXT, getReferenceChangeText(diff, true));
} else if (kind == DifferenceKind.MOVE) {
// Object moved
map.put(MODEL_DIFF_REPORT_LEFT_DIFF_TEXT, getReferenceChangeText(diff, false));
map.put(MODEL_DIFF_REPORT_RIGHT_DIFF_TEXT, getReferenceChangeText(diff, true));
}
} else {
// right addition
if (kind == DifferenceKind.ADD) {
map.put(MODEL_DIFF_REPORT_LEFT_DIFF_TEXT, getReferenceChangeText(diff, true));
map.put(MODEL_DIFF_REPORT_RIGHT_DIFF_TEXT, getReferenceChangeText(diff, false));
} else if (kind == DifferenceKind.DELETE) {
// right deletion
map.put(MODEL_DIFF_REPORT_LEFT_DIFF_TEXT, getReferenceChangeText(diff, true));
map.put(MODEL_DIFF_REPORT_RIGHT_DIFF_TEXT, getReferenceChangeText(diff, false));
} else if (kind == DifferenceKind.MOVE) {
// Object moved
map.put(MODEL_DIFF_REPORT_LEFT_DIFF_TEXT, getReferenceChangeText(diff, true));
map.put(MODEL_DIFF_REPORT_RIGHT_DIFF_TEXT, getReferenceChangeText(diff, false));
}
}
}
}
return map;
}
def StringBuffer getDiffObjectURIFragment(Diff diff, DifferenceSource source) {
var StringBuffer label = new StringBuffer
var EObject value
if (diff instanceof AttributeChange){
val Match match = diff.getMatch();
value = if(source == DifferenceSource.LEFT) match.left else match.right
} else if (diff instanceof ReferenceChange){
value = ModelCompareUtil.getValue(diff.match.comparison, diff)
}
if (value != null) {
label.append(EcoreResourceUtil.getURI(value)?.fragment)
}
label
}
def StringBuffer getAttributeChangeText(AttributeChange attributeChange) {
var StringBuffer label = new StringBuffer
if (attributeChange != null) {
label.append("[" + attributeChange.attribute?.name + " " + attributeChange.kind + "D" + "]")
}
label
}
def StringBuffer getReferenceChangeText(Diff diff, boolean opposite) {
var StringBuffer label = new StringBuffer
if (diff instanceof ReferenceChange) {
val kind = diff.kind
var String kindLabel = ""
if (!opposite) {
kindLabel = diff.diffKindText
} else {
if (kind == DifferenceKind.ADD) {
kindLabel = "DELETED from "
val reference = diff.reference
if (!reference.isContainment) {
kindLabel = "REMOVED from "
}
} else if (kind == DifferenceKind.DELETE) {
kindLabel = "ADDED to "
} else {
kindLabel = kind + "D "
}
}
val EObject matchValue = if(!opposite) diff.match.left else diff.match.right
return label.append(" [").append(kindLabel).append(
getName(matchValue) + "." + diff.reference?.name).append("]")
}
label
}
def writeFile(IFile targetFile, CharSequence content) {
val monitor = new NullProgressMonitor
if (targetFile.exists)
targetFile.delete(true, monitor)
targetFile.create(new ByteArrayInputStream(content.toString.bytes), true, monitor)
}
def createFolder(IFolder folder) {
val monitor = new NullProgressMonitor
if (!folder.exists)
folder.create(true, false, monitor)
}
override postComparison(Comparison comparison, Monitor monitor) {
// Do nothing by default
}
override postConflicts(Comparison comparison, Monitor monitor) {
// Do nothing by default
}
override postDiff(Comparison comparison, Monitor monitor) {
// Do nothing by default
}
override postEquivalences(Comparison comparison, Monitor monitor) {
// Do nothing by default
}
override postMatch(Comparison comparison, Monitor monitor) {
// Do nothing by default
}
override postRequirements(Comparison comparison, Monitor monitor) {
// Do nothing by default
}
}