/*
* StsToolShapeNodeEditPart.java
*
* This file is part of the STS-Tool project.
* Copyright (c) 2011-2012 "University of Trento - DISI" All rights reserved.
*
* Is strictly forbidden to remove this copyright notice from this source code.
*
* Disclaimer of Warranty:
* STS-Tool (this software) is provided "as-is" and without warranty of any kind,
* express, implied or otherwise, including without limitation, any warranty of
* merchantability or fitness for a particular purpose.
* In no event shall the copyright holder or contributors be liable for any direct,
* indirect, incidental, special, exemplary, or consequential damages
* including, but not limited to, procurement of substitute goods or services;
* loss of use, data, or profits; or business interruption) however caused and on
* any theory of liability, whether in contract, strict liability, or tort (including
* negligence or otherwise) arising in any way out of the use of this software, even
* if advised of the possibility of such damage.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3
* as published by the Free Software Foundation with the addition of the
* following permission added to Section 15 as permitted in Section 7(a):
* FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
* "University of Trento - DISI","University of Trento - DISI" DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* See the GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, see http://www.gnu.org/licenses or write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA, 02110-1301 USA, or download the license from the following URL:
* http://www.sts-tool.eu/License.php
*
* For more information, please contact STS-Tool group at this
* address: ststool@disi.unitn.it
*
*/
package eu.aniketos.wp1.ststool.diagram.custom.editpart;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.RectangleFigure;
import org.eclipse.draw2d.Shape;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeNodeEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.ResizableShapeEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.render.editparts.RenderedDiagramRootEditPart;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewAndElementRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewAndElementRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequestFactory;
import org.eclipse.gmf.runtime.emf.type.core.IElementType;
import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest;
import org.eclipse.gmf.runtime.emf.type.core.requests.CreateRelationshipRequest;
import org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.gmf.runtime.notation.impl.ConnectorImpl;
import eu.aniketos.wp1.ststool.Actor;
import eu.aniketos.wp1.ststool.Goal;
import eu.aniketos.wp1.ststool.StsElement;
import eu.aniketos.wp1.ststool.TResource;
import eu.aniketos.wp1.ststool.diagram.custom.view.ViewsManager;
import eu.aniketos.wp1.ststool.diagram.custom.view.constraint.NodeGraphicalConstraint;
import eu.aniketos.wp1.ststool.diagram.edit.parts.AgentEditPart;
import eu.aniketos.wp1.ststool.diagram.edit.parts.RoleEditPart;
import eu.aniketos.wp1.ststool.diagram.providers.StsToolElementTypes;
/**
* Extension class of the ShapeNodeEditPart that override some method to achieve some stsTool functionality
*/
public abstract class StsToolShapeNodeEditPart extends ShapeNodeEditPart {
/**
* @see org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeNodeEditPart#ShapeNodeEditPart(Request)
*/
public StsToolShapeNodeEditPart(View view) {
super(view);
}
/**
* @see org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeNodeEditPart#createDefaultEditPolicies()
*/
@Override
protected void createDefaultEditPolicies(){
super.createDefaultEditPolicies();
//Hand connector don't work correctly so they are disabled
removeEditPolicy(EditPolicyRoles.CONNECTION_HANDLES_ROLE);
}
/**
* @see org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeNodeEditPart#getModelSourceConnections()
*/
@Override
protected List getModelSourceConnections(){
return filterList(super.getModelSourceConnections());
}
/**
* @see org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeNodeEditPart#getModelTargetConnections()
*/
@Override
protected List getModelTargetConnections(){
return filterList(super.getModelTargetConnections());
}
/**
* Filter a list of connection element based on the current view.
*
* @param list
* of element that need to be filtered
* @return the filtered list
*/
private List filterList(List list){
if (list != null) {
ArrayList result = new ArrayList();
for (Object o : list) {
if (o instanceof ConnectorImpl) {
String SvisualID = ((ConnectorImpl) o).getType();
if (SvisualID.equals("NoteAttachment")) {
result.add(o);
} else {
int visualID = Integer.parseInt(((ConnectorImpl) o).getType());
if (getViewsManager().isElementVisible(StsToolElementTypes.getElementType(visualID))) {
result.add(o);
}
}
}
}
return result;
}
return Collections.EMPTY_LIST;
}
/**
* Get the current viewManager, used to get the current view, or to change view.
*
* @return the currentViewManger
*/
public ViewsManager getViewsManager(){
CustomStsToolDiagramEditPart ep = (CustomStsToolDiagramEditPart) ((RenderedDiagramRootEditPart) getRoot()).getContents();
return ep.getViewsManager();
}
/**
* @see org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeNodeEditPart#activate()
*/
@Override
public void activate(){
super.activate();
try {
/*
* Get from the metamodel the constraint for the object of this
* editpart,
* and set the size / position of the related figure
* If is a compartment it will also set the collapse /expand value
* If no constraint is set, new constraint are created with the default
* value.
*/
StsElement element = (StsElement) getNotationView().getElement();
int view = getViewsManager().getCurrentIntView();
if (element != null) {
String constraint = getViewsManager().getObjectConstraint(view, element.getStsUniqueID());
if (constraint != null) {
NodeGraphicalConstraint c = new NodeGraphicalConstraint(constraint);
Rectangle r = new Rectangle(c.location, c.size);
if (getViewsManager().getCurrentIntView() == ViewsManager.AUTHORIZATION_VIEW) c.collapsed = true;
if ((this instanceof AgentEditPart || this instanceof RoleEditPart) && (c.collapsed)) {
r.setSize(new Dimension(100, 100));
}
((GraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), r);
if ((this instanceof AgentEditPart || this instanceof RoleEditPart)) {
IGraphicalEditPart targetEp = getChildBySemanticHint("7001");
if (targetEp == null) targetEp = getChildBySemanticHint("7002");
if (targetEp != null && targetEp instanceof StsToolShapeCompartmentEditPart) {
try {
StsToolShapeCompartmentEditPart ep = (StsToolShapeCompartmentEditPart) targetEp;
ep.collapse(c.collapsed, false);
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else {
try {
Rectangle r = getFigure().getBounds().getCopy();
NodeGraphicalConstraint c = new NodeGraphicalConstraint(r);
getViewsManager().setObjectConstraintForAllViews(element.getStsUniqueID(), c.getConstraintInString());
} catch (Exception e) {
System.err.println("Error " + e.getStackTrace()[0].getClassName() + " at line " + e.getStackTrace()[0].getLineNumber());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @see org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeNodeEditPart#getPrimaryDragEditPolicy()
*
* used to change the ghost figure of Agent and Role
*/
@Override
public EditPolicy getPrimaryDragEditPolicy(){
return new ResizableShapeEditPolicy() {
@Override
protected IFigure createDragSourceFeedbackFigure(){
Shape shape = getDragShape();
shape.setXOR(false);
shape.setLineStyle(Graphics.LINE_DOT);
shape.setForegroundColor(ColorConstants.black);
shape.setBackgroundColor(ColorConstants.lightGray);
shape.setAlpha(190);
shape.setBounds(getInitialFeedbackBounds());
addFeedback(shape);
return shape;
}
};
}
protected Shape getDragShape(){
return new RectangleFigure();
}
/**
* @see org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeNodeEditPart#getCommand(Request)
*/
@Override
public Command getCommand(Request request){
if (request instanceof CreateConnectionViewAndElementRequest) {
CreateConnectionViewAndElementRequest req = (CreateConnectionViewAndElementRequest) request;
/*
* if the request is a request for creating a delegation / provision
* relation return a compound command that
* also create the delegated Goal / provided Resource
*/
String semanticHint = req.getConnectionViewDescriptor().getSemanticHint();
if (semanticHint.equals("4012")) {
CompoundCommand resultCommand = new CompoundCommand();
resultCommand.add(new CreateTargetRelationElement(req, StsToolElementTypes.TResource_3002, getViewsManager()));
resultCommand.add(super.getCommand(request));
return resultCommand;
} else if (semanticHint.equals("4013")) {
CompoundCommand resultCommand = new CompoundCommand();
resultCommand.add(new CreateTargetRelationElement(req, StsToolElementTypes.Goal_3001, getViewsManager()));
resultCommand.add(super.getCommand(request));
return resultCommand;
}
}
return super.getCommand(request);
}
@Override
protected NodeFigure createNodeFigure(){
return null;
}
@Override
protected void handleNotificationEvent(Notification notification){
super.handleNotificationEvent(notification);
if (getParent() != null) getParent().refresh();
}
/**
* Command used to create a element when creating a delegation or a provision
*/
class CreateTargetRelationElement extends Command {
private CreateConnectionViewAndElementRequest request;
private Command command = null;
private StsElement element = null;
private IElementType elementType;
private ViewsManager vm = null;
private IGraphicalEditPart targetEp;
public CreateTargetRelationElement(CreateConnectionViewAndElementRequest request, IElementType elementType, ViewsManager vm) {
this.request = request;
this.elementType = elementType;
this.vm = vm;
}
@Override
public void execute(){
try {
targetEp = ((IGraphicalEditPart) request.getTargetEditPart()).getChildBySemanticHint("7001");
if (targetEp == null) targetEp = ((IGraphicalEditPart) request.getTargetEditPart()).getChildBySemanticHint("7002");
if (elementType == StsToolElementTypes.Goal_3001) {
Goal g = (Goal) request.getExtendedData().get("sourceGoal");
Goal reference = containGoalReference((Actor) (((IGraphicalEditPart) request.getTargetEditPart()).getPrimaryView().getElement()), g);
if (reference != null) {
CreateRelationshipRequest crr = (CreateRelationshipRequest) request.getConnectionViewAndElementDescriptor().getCreateElementRequestAdapter().getAdapter(CreateElementRequest.class);
crr.setParameter("delegatedObject", reference);
return;
}
} else if (elementType == StsToolElementTypes.TResource_3002) {
TResource r = (TResource) request.getExtendedData().get("sourceResource");
TResource reference = containResourceReference((Actor) (((IGraphicalEditPart) request.getTargetEditPart()).getPrimaryView().getElement()), r);
if (reference != null) {
CreateRelationshipRequest crr = (CreateRelationshipRequest) request.getConnectionViewAndElementDescriptor().getCreateElementRequestAdapter().getAdapter(CreateElementRequest.class);
crr.setParameter("delegatedObject", reference);
return;
}
}
CreateViewAndElementRequest req = (CreateViewAndElementRequest) CreateViewRequestFactory.getCreateShapeRequest(elementType, targetEp.getDiagramPreferencesHint());
if (req != null) {
command = targetEp.getCommand(req);
try {
command.execute();
} catch (Exception e) {
e.printStackTrace();
}
CreateElementRequest cer = (CreateElementRequest) req.getViewAndElementDescriptor().getCreateElementRequestAdapter().getAdapter(CreateElementRequest.class);
CreateRelationshipRequest crr = (CreateRelationshipRequest) request.getConnectionViewAndElementDescriptor().getCreateElementRequestAdapter().getAdapter(CreateElementRequest.class);
element = (StsElement) cer.getNewElement();
crr.setParameter("delegatedObject", element);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public boolean canExecute(){
return (request.getTargetEditPart() instanceof AgentEditPart || request.getTargetEditPart() instanceof RoleEditPart);
}
@Override
public void undo(){
String id = element.getStsUniqueID();
try {
command.undo();
} catch (Exception e) {
e.printStackTrace();
}
try {
if ((targetEp) != null) targetEp.refresh();
vm.removeObjectConstraintForAllViews(id);
} catch (Exception e) {
System.err.println("Error " + e.getStackTrace()[0].getClassName() + " at line " + e.getStackTrace()[0].getLineNumber());
}
}
@Override
public boolean canUndo(){
return false;
}
@Override
public void redo(){
}
private Goal containGoalReference(Actor a,Goal g){
Goal goalReferenceToFind = getSourceGoalOfReference(g);
for (Goal actorGoal : a.getGoals()) {
if (goalReferenceToFind == getSourceGoalOfReference(actorGoal)) { return actorGoal; }
}
return null;
}
private Goal getSourceGoalOfReference(Goal reference){
Goal g = reference;
while (g.getDelegatedFrom().size() > 0) {
g = g.getDelegatedFrom().get(0).getSourceGoal();
}
return g;
}
private TResource containResourceReference(Actor a,TResource r){
TResource resourceReferenceToFind = getSourceResourceOfReference(r);
for (TResource actorResource : a.getTResources()) {
if (resourceReferenceToFind == getSourceResourceOfReference(actorResource)) {
if (resourceReferenceToFind != actorResource) return actorResource;
}
}
return null;
}
private TResource getSourceResourceOfReference(TResource reference){
TResource g = reference;
while (g.getProvidedFrom().size() > 0) {
g = g.getProvidedFrom().get(0).getSourceResource();
}
return g;
}
}
}