/*
* Copyright (C) Yutaka Matsuno 2010-2012 All rights reserved.
*/
package net.dependableos.dcase.diagram.edit.parts.custom;
import static net.dependableos.dcase.diagram.common.constant.SystemPropertyKeyConst.DSTAR_FILE_EXTENSION;
import net.dependableos.dcase.Argument;
import net.dependableos.dcase.BasicNode;
import net.dependableos.dcase.System;
import net.dependableos.dcase.Userdef001;
import net.dependableos.dcase.Userdef005;
import net.dependableos.dcase.impl.ParameterItem;
import net.dependableos.dcase.provider.DcaseEditPlugin;
import net.dependableos.dcase.diagram.common.util.FileUtil;
import net.dependableos.dcase.diagram.common.util.Messages;
import net.dependableos.dcase.diagram.common.util.PropertyUtil;
import net.dependableos.dcase.diagram.edit.parts.ArgumentEditPart;
import net.dependableos.dcase.diagram.edit.parts.SystemEditPart;
import net.dependableos.dcase.diagram.ui.editpolicies.BasicNodeOpenEditPolicy;
import net.dependableos.dcase.diagram.part.DcaseDiagramEditor;
import net.dependableos.dcase.diagram.part.DcaseDiagramEditorUtil;
import net.dependableos.dcase.diagram.part.PatternUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.IFigure;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
import org.eclipse.draw2d.Shape;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeNodeEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles;
import org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.FillStyle;
import org.eclipse.gmf.runtime.notation.NotationPackage;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.emf.workspace.util.WorkspaceSynchronizer;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.ui.IActionFilter;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.MessageConsole;
import org.eclipse.ui.console.MessageConsoleStream;
import org.eclipse.ui.part.FileEditorInput;
/**
* An abstract class represents a node editpart.
*/
public abstract class DcaseNodeEditPart extends ShapeNodeEditPart implements
DcaseDelegateNodeEditPart, DcaseDelegateEditPart {
/**
* The module name of d*.
*/
private static final String DSTAR_MODULE_NAME = PatternUtil.getMainModuleName();
/**
* The console name.
*/
private static final String CONSOLE_NAME = "Console"; //$NON-NLS-1$
/**
* The key of Parameter subtype.
*/
private static final String SUBTYPE_PARAMETER = "_UI_System_subType_param"; //$NON-NLS-1$
private String subTypeParameter;
/**
* Allocates a DcaseNodeEditPart object.
*
* @param view owned view by this edit part
*/
public DcaseNodeEditPart(View view) {
super(view);
subTypeParameter = DcaseEditPlugin.getPlugin().getString(SUBTYPE_PARAMETER);
}
/**
* {@inheritDoc}
*/
@Override
protected abstract NodeFigure createNodeFigure();
/**
* Returns the primary shape.
*
* @return primaryShape the primary shape.
*/
public abstract IFigure getPrimaryShape();
/**
* Returns the background color.
*
* @return the background color.
*/
public Color getBackgroundColorEx() {
IFigure primaryShape = getPrimaryShape();
if (primaryShape != null) {
return primaryShape.getBackgroundColor();
}
return null;
}
/**
* Sets the background color.
*
* @param color the background color.
*/
public void setBackgroundColorEx(Color color) {
setBackgroundColor(color);
}
/**
* {@inheritDoc}
*/
@Override
protected void createDefaultEditPolicies() {
super.createDefaultEditPolicies();
// installs a edit policy to open a property input dialog.
installEditPolicy(EditPolicyRoles.OPEN_ROLE,
new BasicNodeOpenEditPolicy());
}
/**
* Sets the foreground color.
*
* @param color the foreground color.
*/
public void setForegroundColorEx(Color color) {
setForegroundColor(color);
}
/**
* Returns the foreground color.
*
* @return the foreground color.
*/
public Color getForegroundColorEx() {
IFigure primaryShape = getPrimaryShape();
if (primaryShape != null) {
return primaryShape.getForegroundColor();
}
return null;
}
//@SuppressWarnings("unchecked")
@Override
public Object getAdapter(Class adapter) {
if (adapter == IActionFilter.class) {
return SetParametersActionFilter.getSingleton();
}
return super.getAdapter(adapter);
}
/**
* Returns the line width.
*
* @return the line width.
*/
public int getLineWidthEx() {
return super.getLineWidth();
}
/**
* Sets the line width.
*
* @param width the line width.
*/
public void setLineWidthEx(int width) {
if (width < 0) {
width = 1;
}
((Shape) getPrimaryShape()).setLineWidth(width);
}
// AUTO_GENERATED:END
/**
* {@inheritDoc}
*/
protected void addNotationalListeners() {
super.addNotationalListeners();
addListenerFilter("PrimaryView", this, getPrimaryView()); //$NON-NLS-1$
}
/**
* {@inheritDoc}
*/
protected void removeNotationalListeners() {
super.removeNotationalListeners();
removeListenerFilter("PrimaryView"); //$NON-NLS-1$
}
/**
* Handles the event for changing Attachment.
* @param event the event.
*/
protected void handleNotificationEvent(Notification event) {
Object feature = event.getFeature();
if(event.getEventType() == Notification.SET) {
if(feature instanceof EAttribute) {
// process parameters
EAttribute attr = (EAttribute)feature;
if(attr.getName().equals("parameterVals") || //$NON-NLS-1$
attr.getName().equals("subType")) { //$NON-NLS-1$
this.notifyParameters();
}
// change background
refreshAttributeColor();
}
}
super.handleNotificationEvent(event);
}
private void refreshAttributeColor() {
Color color = getAttributeBackground();
if (getBackgroundColorEx() != color) {
setBackgroundColor(color);
setFillColor(color);
}
}
/**
* Notify about changing parameters.
*/
public void notifyParameters() {
// add my UUID.
BasicNode node = (BasicNode)getElement();
if(node == null) {
return;
}
HashSet<String> uuidSet = new HashSet<String>();
uuidSet.add(getUUID(node));
// notify to parent.
for(Object link : this.getTargetConnections()) {
if(link instanceof DcaseLinkEditPart) {
DcaseNodeEditPart parent = (DcaseNodeEditPart)((DcaseLinkEditPart)link).getSource();
if(parent != null) {
parent.notifyParameters(uuidSet);
}
}
}
}
/**
* Notify about changing parameters.
* @param uuidSet the current uuid set.
*/
public void notifyParameters(HashSet<String> uuidSet) {
// check and add UUID.
BasicNode node = (BasicNode)getElement();
if(node == null) {
return;
}
String uuid = getUUID(node);
if(uuidSet.contains(uuid)) {
return;
}
uuidSet.add(uuid);
// apply parameters for the element only.
applyParameters();
// set notify flag to attachment.
String attachment = node.getAttachment();
if((node instanceof Userdef005 || node instanceof Userdef001)
&& PatternUtil.isModuleReference(attachment)) {
String moduleName = PatternUtil.getModuleName(attachment);
DcaseDiagramEditor editor = getDcaseDiagramEditor(node, moduleName);
if(editor != null) {
editor.setNotifyFlag(true);
}
}
// notify to children.
for(Object link : this.getSourceConnections()) {
if(link instanceof DcaseLinkEditPart) {
DcaseNodeEditPart child = (DcaseNodeEditPart)((DcaseLinkEditPart)link).getTarget();
child.notifyParameters(uuidSet);
}
}
}
/**
* Applies parameter values to Desc attribute.
*/
public void applyParameters() {
BasicNode node = (BasicNode)getElement();
if(node == null) {
return;
}
ParameterItem.setDesc(node, getParameters(null));
}
/**
* Returns the parameter string.
* @param userdef007 the current parameter string...never used...
* @return the parameter string.
*/
public String getParameters(String userdef007) {
HashSet<String> uuidSet = new HashSet<String>();
List<ParameterData> ret = getParameters(0, userdef007, uuidSet);
return parameterListToString(ret);
}
/**
* Converts parameter list to string.
* @param paramList the parameter list.
* @return the string of parameter list.
*/
protected String parameterListToString(List<ParameterData> paramList) {
Collections.sort(paramList, new ParameterComparator());
StringBuffer ret = new StringBuffer();
ArrayList<String> nameList = null;
int prevdist = -1;
for (int i = 0; i < paramList.size(); i++) {
ParameterData curData = paramList.get(i);
/* check duplicate parameter */
if (curData.getDistance() != prevdist) {
nameList = new ArrayList<String>();
prevdist = curData.getDistance();
}
String parameters = curData.getValues();
if (parameters == null || parameters.length() == 0) {
continue;
}
for (ParameterItem item : ParameterItem.getPatameterList(parameters)) {
String name = item.getParameterId();
if (nameList.contains(name)) {
MessageConsoleStream stream = getMessageConsoleStream();
stream.println(NLS.bind(Messages.ParameterDuplicated, name));
} else {
nameList.add(name);
}
}
ret.append(curData.getValues());
if (i < paramList.size() - 1) {
ret.append(ParameterItem.SEPARATOR);
}
}
return ret.toString();
}
/**
* Returns the parameter string.
* @param distance the distance.
* @param userdef007 the current parameter string.
* @param uuidSet the node set.
* @return the parameter string.
*/
protected List<ParameterData> getParameters(int distance, String userdef007, HashSet<String> uuidSet) {
// "userdef007" is used only Parameter node.
ArrayList<ParameterData> myParameter = new ArrayList<ParameterData>();
boolean isNeedDstar = (uuidSet != null && uuidSet.size() == 0);
// check UUID
if (uuidSet != null) {
BasicNode node = (BasicNode)getElement();
if(node == null) {
return myParameter;
}
String uuid = getUUID(node);
if(uuidSet.contains(uuid)) {
return myParameter;
}
uuidSet.add(uuid);
}
// get parameters of child Parameter nodes.
for(Object link : this.getSourceConnections()) {
if(link instanceof DcaseLinkEditPart) {
DcaseNodeEditPart child = (DcaseNodeEditPart)((DcaseLinkEditPart)link).getTarget();
if (child instanceof SystemEditPart) {
BasicNode childNode = (BasicNode)child.getElement();
if (subTypeParameter.equals(((System)childNode).getSubType())) {
String childParameter = childNode.getParameterVals();
myParameter.add(new ParameterData(distance, childParameter));
}
}
}
}
// if uuidSet is null, only returns the current node's parameters.
if (uuidSet == null) {
return myParameter;
}
// get Ancestor's parameters
List<ParameterData> ret = getParentParameters(distance + 1, uuidSet);
ret.addAll(myParameter);
// get parameters of d*
if (isNeedDstar) {
DcaseDiagramEditor editor = getDstarDiagramEditor((BasicNode)getElement());
if(editor != null) {
DiagramEditPart dstarEditPart = editor.getDiagramEditPart();
if (dstarEditPart instanceof ArgumentEditPart) {
Argument argument = (Argument)getElement(dstarEditPart);
String dstarUserdef007 = argument.getParameterVals();
ret.add(new ParameterData(Integer.MAX_VALUE, dstarUserdef007));
}
}
}
return ret;
}
/**
* Returns the parameter string of ancestors.
* @return the parameter string of ancestors.
*/
private List<ParameterData> getParentParameters(int distance, HashSet<String> uuidSet) {
ArrayList<ParameterData> ret = new ArrayList<ParameterData>();
getParentParameters(ret, distance, uuidSet);
BasicNode node = (BasicNode)getElement();
if(node == null) {
return ret;
}
// check attachment
for(String nodeName : getReferringSourceNodes()) { //$NON-NLS-1$
getAnotherParameters(ret, distance + 1, nodeName, uuidSet);
}
return ret;
}
/**
* Returns the referring source node names.
* @return the referring source node names.
*/
public HashSet<String> getReferringSourceNodes() {
HashSet<String> ret = new HashSet<String>();
BasicNode node = (BasicNode)getElement();
if(node == null) {
return ret;
}
Argument argument = (Argument)node.eContainer();
String refSource = argument.getRefSource();
String parent = argument.getParent();
if (refSource != null && refSource.length() > 0 &&
parent != null && parent.length() > 0) {
// search parent module
for(String nodeName : refSource.split(PatternUtil.getReferenceSeparator())) {
if (parent.equals(PatternUtil.getModuleName(nodeName))) {
ret.add(nodeName);
}
}
}
return ret;
}
/**
* Returns the another module's parameters.
* @param parameter the current parameters.
* @param userdef011 the module name.
* @param uuidSet the node set.
* @return the another module's parameters.
*/
private void getAnotherParameters(List<ParameterData> paramList, int distance, String nodePath, HashSet<String> uuidSet) {
BasicNode node = (BasicNode)getElement();
if(node == null) {
return;
}
String moduleName = PatternUtil.getModuleName(nodePath);
String nodeName = PatternUtil.getNodeName(nodePath);
if(PatternUtil.isModuleReference(nodePath) && (! nodePath.equals(nodeName))) {
DcaseDiagramEditor editor = getDcaseDiagramEditor(node, moduleName);
if(editor == null) {
return;
}
DiagramEditPart editPart = editor.getDiagramEditPart();
if (!(editPart instanceof ArgumentEditPart)) {
return;
}
for(Object nobj : ((ArgumentEditPart)editPart).getChildren()) {
if(nobj instanceof DcaseNodeEditPart) {
BasicNode nnode = (BasicNode)getElement((DcaseNodeEditPart)nobj);
if(!nnode.getName().equals(nodeName)) {
continue;
}
List<ParameterData> nret = ((DcaseNodeEditPart)nobj).getParentParameters(distance + 1, uuidSet);
paramList.addAll(nret);
}
}
}
}
/**
* Returns the parameter string of ancestors.
* @param parameter the current parameter...do not use...
* @param uuidSet the current uuid set.
* @return the parameter string of ancestors.
*/
private void getParentParameters(List<ParameterData> paramList, int distance, HashSet<String> uuidSet) {
// add parent's parameters.
for(Object link : this.getTargetConnections()) {
if(link instanceof DcaseLinkEditPart) {
DcaseNodeEditPart parentEditPart = (DcaseNodeEditPart)((DcaseLinkEditPart)link).getSource();
BasicNode parentNode = (BasicNode)parentEditPart.getElement();
if(parentNode == null) {
continue;
}
paramList.addAll(parentEditPart.getParameters(distance, null, uuidSet));
}
}
}
/**
* Returns the element.
* @return the element.
*/
public EObject getElement() {
return getElement(this);
}
/**
* Returns the element.
* @param editPart the edit part.
* @return the element.
*/
public static EObject getElement(GraphicalEditPart editPart) {
Object model = editPart.getModel();
if(! (model instanceof View)) {
return null;
}
return ((View)model).getElement();
}
/**
* Returns the UUID.
* @param node the element.
* @return the UUID.
*/
public static String getUUID(BasicNode node) {
XMLResource resource = (XMLResource)node.eResource();
return resource.getID(node);
}
/**
* Returns the diagram editor of the specified module.
* @param node the node.
* @param moduleName the module name.
* @return the diagram editor.
*/
private DcaseDiagramEditor getDcaseDiagramEditor(BasicNode node, String moduleName) {
return getDcaseDiagramEditor(node, moduleName, false);
}
/**
* Returns the diagram editor of the specified module.
* @param node the node.
* @param moduleName the module name.
* @return the diagram editor.
*/
public DcaseDiagramEditor getDstarDiagramEditor(BasicNode node) {
return getDcaseDiagramEditor(node, DSTAR_MODULE_NAME, true);
}
/**
* Returns the diagram editor of the specified module.
* @param node the node.
* @param moduleName the module name.
* @param isDstar whether dstar or not.
* @return the diagram editor.
*/
private DcaseDiagramEditor getDcaseDiagramEditor(BasicNode node, String moduleName, boolean isDstar) {
XMLResource resource = (XMLResource)node.eResource();
IFile modelFile = WorkspaceSynchronizer.getFile(resource);
IPath diagramPath = null;
if (isDstar) {
diagramPath = PatternUtil.getDstarPath(modelFile);
} else {
diagramPath = PatternUtil.getDiagramPath(modelFile, moduleName);
}
if(diagramPath == null) {
return null;
}
IFile diagramFile = FileUtil.getWorksapceFileFromPath(diagramPath.toOSString());
IWorkbenchPage workbenchPage = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage();
IEditorPart editor = null;
try {
editor = workbenchPage.findEditor(new FileEditorInput(diagramFile));
if (editor == null && diagramFile.exists()) {
IEditorDescriptor desc = PlatformUI.getWorkbench()
.getEditorRegistry().getDefaultEditor(diagramFile.getName());
if (desc != null) {
Diagram currentDiagram = ((DcaseDiagramEditor)workbenchPage.getActiveEditor()).getDiagram();
editor = workbenchPage.openEditor(new FileEditorInput(diagramFile), desc.getId(), false);
DcaseDiagramEditorUtil.openDiagram(currentDiagram.eResource());
}
}
} catch (Exception e) {
return null;
}
return (DcaseDiagramEditor)editor;
}
protected void setFillColor(Color color) {
RGB rgb = color.getRGB();
int c = (rgb.blue<<16) | (rgb.green<<8) | rgb.red;
FillStyle fillStyle =
(FillStyle)getPrimaryView().getStyle(NotationPackage.eINSTANCE.getFillStyle());
if (fillStyle != null) {
fillStyle.setFillColor(c);
}
}
/**
* Sets the background for Attachment and RefSource.
*/
public Color getAttributeBackground() {
BasicNode node = getBasicNode();
int condition = 0;
IWorkbenchPage workbenchPage = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage();
DcaseDiagramEditor editor = (DcaseDiagramEditor)workbenchPage.getActiveEditor();
if (editor != null) {
Diagram diagram = editor.getDiagram();
String dstarDiagramName = DSTAR_MODULE_NAME + "." + PropertyUtil.getSystemProperty(DSTAR_FILE_EXTENSION); //$NON-NLS-1$
if (! diagram.getName().equals(dstarDiagramName)) {
if(node != null) {
String attachmentValue = node.getAttachment();
if(PatternUtil.isModuleReference(attachmentValue)) {
condition += 1;
}
String refSourceValue = node.getRefSource();
if(refSourceValue != null && refSourceValue.length() > 0) {
condition += 2;
}
}
}
}
switch(condition) {
case 1:
return ColorConstants.green;
case 2:
return ColorConstants.orange;
case 3:
return ColorConstants.darkGreen;
default:
return ColorConstants.white;
}
}
/**
* Gets the current BasicNode.
* @return the current BasicNode
*/
private BasicNode getBasicNode() {
Object obj = getModel();
if(obj instanceof View) {
EObject eobj = ((View)obj).getElement();
if(eobj instanceof BasicNode) {
return ((BasicNode)eobj);
}
}
return null;
}
/**
* A class for sorting parameters.
*
*/
private class ParameterData {
private int distance;
private String values;
public ParameterData(int distance, String values) {
this.distance = distance;
this.values = values;
}
public int getDistance() {
return distance;
}
public String getValues() {
return values;
}
public String toString() {
return "{" + distance + "," + values + "}"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
/**
* A class for sorting parameters.
*
*/
private class ParameterComparator implements Comparator<ParameterData> {
public int compare(ParameterData d1, ParameterData d2) {
return d1.getDistance() - d2.getDistance();
}
}
/**
* Returns the message console stream.
* @returnthe message console stream.
*/
public static MessageConsoleStream getMessageConsoleStream() {
// get or create Console ... see editor.common.util.MessageWriter class
IConsole[] consoles = ConsolePlugin.getDefault().getConsoleManager().getConsoles();
MessageConsole console = null;
for (int i = 0; i < consoles.length; i++) {
if (CONSOLE_NAME.equals(consoles[i].getName())) {
console = (MessageConsole) consoles[i];
break;
}
}
if (console == null) {
console = new MessageConsole(CONSOLE_NAME, null);
}
ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] { console });
ConsolePlugin.getDefault().getConsoleManager().showConsoleView(console);
return console.newMessageStream();
}
}