/* * Copyright (C) Yutaka Matsuno 2010-2012 All rights reserved. */ package net.dependableos.dcase.diagram.editor.logic.compare; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import net.dependableos.dcase.diagram.common.model.AttributeType; import net.dependableos.dcase.diagram.common.model.LinkInfo; import net.dependableos.dcase.diagram.common.model.NodeInfo; import net.dependableos.dcase.diagram.common.model.NodeType; import net.dependableos.dcase.diagram.common.util.LinkManager; import net.dependableos.dcase.diagram.common.util.Menus; import net.dependableos.dcase.diagram.common.util.MessageTypeImpl; import net.dependableos.dcase.diagram.common.util.Messages; import net.dependableos.dcase.diagram.edit.parts.ArgumentEditPart; import net.dependableos.dcase.diagram.edit.parts.custom.DcaseDelegateEditPart; import net.dependableos.dcase.diagram.edit.parts.custom.DcaseLinkEditPart; import net.dependableos.dcase.diagram.edit.parts.custom.DcaseNodeEditPart; import net.dependableos.dcase.diagram.editor.command.ChangeForegroundColorEditPartsCommand; import net.dependableos.dcase.diagram.editor.command.ChangeLineWidthCommand; import net.dependableos.dcase.diagram.editor.common.util.DcaseEditorUtil; import net.dependableos.dcase.diagram.editor.common.util.MessageWriter; import org.eclipse.draw2d.ColorConstants; import org.eclipse.gef.commands.CompoundCommand; import org.eclipse.gmf.runtime.common.core.command.ICommand; import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy; import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionNodeEditPart; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.RGB; /** * A class that compares 2 D-Cases. */ public class ExpressModelDiffrenceLogic { /** * the property key of line separator. */ private static final String LINE_SEPARATOR = "line.separator"; //$NON-NLS-1$ /** * the format string for node name. */ private static final String NODENAME_FORMAT = "\"%1s\""; //$NON-NLS-1$ /** * the number of default line width. */ private static final Integer DEFAULT_LINE_WIDTH = 1; /** * the number of change line width. */ private static final Integer CHANGE_LINE_WIDTH = 3; /** * the type of the edit part. */ private enum EditPartType { /** Node. */ NODE, /** Link. */ LINK; }; /** * the status. */ private enum CompareStatus { /** New. */ NEW, /** Deleted. */ DELETED, /** Changed. */ CHANGED, /** Not changed. */ EQUAL; }; /** * the link manager of the source. */ private LinkManager sourceLinkManager; /** * the link manager of the target. */ private LinkManager targetLinkManager; /** * the map of the status. */ private Map<String, CompareItem> compareResultMap; /** * the ID of the argument. */ private String argumentNodeId = null; /** * Creates an instance and initialized it. * * @param source the link manager of the source. * @param target the link manager of the target */ public ExpressModelDiffrenceLogic(LinkManager source, LinkManager target) { sourceLinkManager = source; targetLinkManager = target; } /** * Compares the source and the target. */ public void compare() { // clears the map of the status. if (compareResultMap != null) { compareResultMap.clear(); } else { compareResultMap = new HashMap<String, CompareItem>(); } // compares the nodes. Set<String> nodeIdSet = sourceLinkManager.getAllNodes(); for (String nodeId : nodeIdSet) { NodeInfo sourceNodeInfo = sourceLinkManager.getNodeInfo(nodeId); NodeInfo targetNodeInfo = targetLinkManager.getNodeInfo(nodeId); // gets the ID of Argument. if (sourceNodeInfo.getNodeType() == NodeType.ARGUMENT) { argumentNodeId = nodeId; } CompareItem compareItem = new CompareItem(); // tests whether the node is new. if (targetNodeInfo == null) { compareItem.setEditPartType(EditPartType.NODE); compareItem.setStatus(CompareStatus.NEW); } else { // tests whether the node is changed. boolean isDiff = isDiffrentAttribute(sourceNodeInfo .getAttributeMap(), targetNodeInfo.getAttributeMap()); if (isDiff) { compareItem.setEditPartType(EditPartType.NODE); compareItem.setStatus(CompareStatus.CHANGED); } else { compareItem.setEditPartType(EditPartType.NODE); compareItem.setStatus(CompareStatus.EQUAL); } } compareResultMap.put(nodeId, compareItem); } // finds deleted nodes. Set<String> leftNodeIdSet = targetLinkManager.getAllNodes(); for (String nodeId : leftNodeIdSet) { if (!nodeIdSet.contains(nodeId)) { // doesn't set Argument as a deleted node. if (targetLinkManager.getNodeInfo(nodeId).getNodeType() == NodeType.ARGUMENT) { continue; } // sets as a deleted node. CompareItem compareItem = new CompareItem(); compareItem.setEditPartType(EditPartType.NODE); compareItem.setStatus(CompareStatus.DELETED); compareItem.setName((String) targetLinkManager.getNodeInfo( nodeId).getAttribute(AttributeType.NAME)); compareResultMap.put(nodeId, compareItem); } } // compares the links. Set<String> linkIdSet = sourceLinkManager.getAllLinks(); for (String linkId : linkIdSet) { LinkInfo sourceLinkInfo = sourceLinkManager.getLinkInfo(linkId); LinkInfo targetLinkInfo = targetLinkManager.getLinkInfo(linkId); CompareItem compareItem = new CompareItem(); // tests whether the link is new. if (targetLinkInfo == null) { compareItem.setEditPartType(EditPartType.LINK); compareItem.setStatus(CompareStatus.NEW); } else { // tests whether the link is changed. boolean isDiff = isDiffrentAttribute(sourceLinkInfo .getAttributeMap(), targetLinkInfo.getAttributeMap()); if (isDiff) { compareItem.setEditPartType(EditPartType.LINK); compareItem.setStatus(CompareStatus.CHANGED); } else { compareItem.setEditPartType(EditPartType.LINK); compareItem.setStatus(CompareStatus.EQUAL); } } compareResultMap.put(linkId, compareItem); } // finds deleted links Set<String> leftLinkIdSet = targetLinkManager.getAllLinks(); for (String linkId : leftLinkIdSet) { if (!linkIdSet.contains(linkId)) { CompareItem compareItem = new CompareItem(); compareItem.setEditPartType(EditPartType.LINK); compareItem.setStatus(CompareStatus.DELETED); compareItem.setName((String) targetLinkManager.getLinkInfo( linkId).getAttribute(AttributeType.NAME)); compareResultMap.put(linkId, compareItem); } } } /** * Compares the attributes. * * @param sourceMap the map of the attributes of the source node. * @param targetMap the map of the attributes of the target node. * @return true if and only any change exists;false otherwise. */ private boolean isDiffrentAttribute(Map<AttributeType, Object> sourceMap, Map<AttributeType, Object> targetMap) { boolean result = false; Set<Map.Entry<AttributeType, Object>> sourceEntrySet = sourceMap .entrySet(); for (Map.Entry<AttributeType, Object> entry : sourceEntrySet) { Object sourceObj = entry.getValue(); Object targetObj = targetMap.get(entry.getKey()); if (sourceObj == null) { if (targetObj == null) { continue; } else { result = true; break; } } else { if (targetObj == null) { result = true; break; } else { if (!sourceObj.equals(targetObj)) { result = true; break; } } } } return result; } /** * Returns the node name. * * @param nodeId the ID of the node. * @return the node name. */ private String getNodeName(String nodeId) { return (String) targetLinkManager.getNodeInfo(nodeId).getAttribute( AttributeType.NAME); } /** * Creates and returns the command to express differences on the D-Case diagram. * * @return the command to express differences on the D-Case diagram. */ @SuppressWarnings("rawtypes") public CompoundCommand getCommand() { String separator = System.getProperty(LINE_SEPARATOR); String message = separator; // a start message. message = message.concat(NLS.bind( Messages.ExpressModelDiffrenceLogic_0, new String[] { sourceLinkManager.getUri().toPlatformString(false), targetLinkManager.getUri().toPlatformString(false) })); // differences of Arguments. CompareItem argumentInfo = compareResultMap.get(argumentNodeId); if (argumentInfo.getStatus() == CompareStatus.NEW || argumentInfo.getStatus() == CompareStatus.CHANGED) { message = message.concat(separator).concat( Messages.ExpressModelDiffrenceLogic_1); } // deleted parts. Set<Map.Entry<String, CompareItem>> compareItemSet = compareResultMap .entrySet(); for (Map.Entry<String, CompareItem> item : compareItemSet) { if (item.getValue().getStatus() == CompareStatus.DELETED) { message = message.concat(separator); CompareItem value = item.getValue(); // a node. if (value.getEditPartType() == EditPartType.NODE) { List<String> parentIdList = targetLinkManager .getSource(item.getKey()); if (parentIdList != null) { String parentNamesStr = null; for (String parentId : parentIdList) { if (parentNamesStr == null) { parentNamesStr = String.format( NODENAME_FORMAT, getNodeName(parentId)); } else { parentNamesStr = parentNamesStr.concat(",") //$NON-NLS-1$ .concat( String.format(NODENAME_FORMAT, getNodeName(parentId))); } } message = message.concat(NLS .bind(Messages.ExpressModelDiffrenceLogic_2, new String[] { value.getName(), parentNamesStr })); } else { message = message.concat(NLS.bind( Messages.ExpressModelDiffrenceLogic_2, new String[] { value.getName(), "" })); //$NON-NLS-1$ } } else { // a link. LinkInfo linkInfo = targetLinkManager.getLinkInfo(item .getKey()); String sourceNodeId = (String) linkInfo .getAttribute(AttributeType.SOURCE); String targetNodeId = (String) linkInfo .getAttribute(AttributeType.TARGET); message = message.concat(NLS.bind( Messages.ExpressModelDiffrenceLogic_3, new String[] { item.getValue().getName(), getNodeName(sourceNodeId), getNodeName(targetNodeId) })); } } } // writes the message. MessageWriter.writeMessageToConsole(message, MessageTypeImpl.WRITE_COMPARE_INFO); //creates and initializes the map of edit parts to change the line color. Map<DcaseDelegateEditPart, Color> changeLineColorMap = new HashMap<DcaseDelegateEditPart, Color>(); // creates and initializes the map of edit parts to change the line width. Map<DcaseDelegateEditPart, Integer> changeLineWidthMap = new HashMap<DcaseDelegateEditPart, Integer>(); ArgumentEditPart argumentEditPart = DcaseEditorUtil .getCurrentArgumentEditPart(); // nodes. List edirPartList = argumentEditPart.getChildren(); RGB black = new RGB(0, 0, 0); for (Object editPart : edirPartList) { if (!(editPart instanceof DcaseNodeEditPart)) { continue; } String uuId = DcaseEditorUtil .getUUIDs((DcaseNodeEditPart) editPart); CompareItem item = compareResultMap.get(uuId); Color color = item.getLineColor(); changeLineColorMap.put((DcaseDelegateEditPart) editPart, color); if (!color.getRGB().equals(black)) { changeLineWidthMap.put((DcaseDelegateEditPart) editPart, CHANGE_LINE_WIDTH); } else { changeLineWidthMap.put((DcaseDelegateEditPart) editPart, DEFAULT_LINE_WIDTH); } } // links. List connectionList = argumentEditPart.getConnections(); for (Object linkPart : connectionList) { if (!(linkPart instanceof DcaseLinkEditPart)) { continue; } String uuId = DcaseEditorUtil .getUUIDs((ConnectionNodeEditPart) linkPart); CompareItem item = compareResultMap.get(uuId); Color color = item.getLineColor(); changeLineColorMap.put((DcaseLinkEditPart) linkPart, color); if (!color.getRGB().equals(black)) { changeLineWidthMap.put((DcaseDelegateEditPart) linkPart, CHANGE_LINE_WIDTH); } else { changeLineWidthMap.put((DcaseDelegateEditPart) linkPart, DEFAULT_LINE_WIDTH); } } CompoundCommand cc = new CompoundCommand(Menus.ExpressModelDiffrenceLogic_0); // creates and initializes the command to change the line color of edit parts. ICommand cmdChangeColor = new ChangeForegroundColorEditPartsCommand( Menus.ExpressModelDiffrenceLogic_1, changeLineColorMap); cc.add(new ICommandProxy(cmdChangeColor)); // creates and initializes the command to change the line width of edit parts. ChangeLineWidthCommand cmdLineWidth = new ChangeLineWidthCommand( Menus.ExpressModelDiffrenceLogic_2, changeLineWidthMap); cc.add(new ICommandProxy(cmdLineWidth)); return cc; } /** * A class which represents a deference. */ private static class CompareItem { /** * the status. */ private CompareStatus status = null; /** * the type of the edit part. */ private EditPartType editPartType = null; /** * the name of the edit part. */ private String name = null; /** * Returns the type of the edit part. * * @return the type of the edit part. */ public EditPartType getEditPartType() { return editPartType; } /** * Sets the type of the edit part. * * @param editPartType the type of the edit part. */ public void setEditPartType(EditPartType editPartType) { this.editPartType = editPartType; } /** * Returns the status. * * @return the status. */ public CompareStatus getStatus() { return status; } /** * Sets the status. * * @param status the status. */ public void setStatus(CompareStatus status) { this.status = status; } /** * Returns the name of the edit part. * * @return the name of the edit part. */ public String getName() { return name; } /** * Sets the name of the edit part. * * @param name the name of the edit part. */ public void setName(String name) { this.name = name; } /** * Returns the line color that represents the status. * * @return the line color that represents the status. */ public Color getLineColor() { Color result = null; switch (status) { case NEW: result = ColorConstants.blue; break; case CHANGED: result = ColorConstants.red; break; case EQUAL: result = ColorConstants.black; break; default: result = ColorConstants.black; break; } return result; } } }