package org.framed.orm.ui.editPolicy;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy;
import org.eclipse.gef.requests.CreateConnectionRequest;
import org.eclipse.gef.requests.ReconnectRequest;
import org.framed.orm.model.Model;
import org.framed.orm.model.NamedElement;
import org.framed.orm.model.OrmFactory;
import org.framed.orm.model.Relation;
import org.framed.orm.model.Shape;
import org.framed.orm.model.Type;
import org.framed.orm.ui.command.connectionkinds.ORMRelationCreateCommand;
import org.framed.orm.ui.command.connectionkinds.ORMRelationshipConstraintCreateCommand;
import org.framed.orm.ui.editPart.ORMModelEditPart;
import org.framed.orm.ui.editPart.shape.ORMShapeWithSegmentEditPart;
/**
* This {@link GraphicalNodeEditPolicy} handles request for the creations of all kinds of
* {@link Relation}s between {@link Shape}s and creates and returns the necessary commands for that
* purpose. NewObject = O/o SourceEditPart = S/s TargetEditPart = T/t
*
* @author Kay Bierzynski
* */
public class ORMShapeGraphicalNodeEditPolicy extends GraphicalNodeEditPolicy {
/**
* A {@link Relation} from type relationship that exist between source edit part and target edit
* part.
* */
private Relation testedRelationship = null;
/**
* {@inheritDoc} The feedback is only shown when the target edit part model is not the model
* parent of the source edit part model. (this restriction is important for the creation of
* {@link Relation}s in a {@link Shape} from type role group)
*/
@Override
protected void showCreationFeedback(final CreateConnectionRequest request) {
if (!parentTest(request.getTargetEditPart(), request.getSourceEditPart())) {
super.showCreationFeedback(request);
}
}
/**
* {@inheritDoc}
*
* @return {@link ORMRelationshipConstraintCreateCommand}( in case a {@link Relation} from type
* cyclic, total, acyclic, reflexive or irreflexive should be created) or {@link ORMRelationCreateCommand}( in
* case any other Relation should be created)
* */
@Override
protected Command getConnectionCompleteCommand(final CreateConnectionRequest request) {
Command retVal = null;
if (!(request.getNewObjectType().equals(Type.RELATIONSHIP_IMPLICATION)||
request.getNewObjectType().equals(Type.RELATIONSHIP_EXCLUSION))) {
if (isCompleteOK(request)) {
retVal = setupConnectionCompleteCommand(request);
}
// Irreflexive Acyclic Total Cyclic Reflexive End
if ((oSTCheck(request, Type.CYCLIC, Type.ROLE_TYPE, Type.ROLE_TYPE)
|| oSTCheck(request, Type.IRREFLEXIVE, Type.ROLE_TYPE, Type.ROLE_TYPE) || oSTCheck(
request, Type.TOTAL, Type.ROLE_TYPE, Type.ROLE_TYPE) || oSTCheck(
request, Type.ACYCLIC, Type.ROLE_TYPE, Type.ROLE_TYPE) || oSTCheck(
request, Type.REFLEXIVE, Type.ROLE_TYPE, Type.ROLE_TYPE))
&& tNotEqualSCheck(request)
&& hasARelationship(request, true) && !hasConstraintsKind(request)) {
final ORMRelationshipConstraintCreateCommand result =
(ORMRelationshipConstraintCreateCommand) request.getStartCommand();
result.setTarget((Shape) getHost().getModel());
ArrayList<Relation> refrencedRelations = new ArrayList<Relation>();
refrencedRelations.add(testedRelationship);
result.setRefrencedRelations(refrencedRelations);
retVal = result;
}
}
return retVal;
}
/**
* {@inheritDoc}
*
* @return {@link ORMRelationshipConstraintCreateCommand}( in case a {@link Relation} from type
* cyclic, total, acyclic, reflexive or irreflexive should be created) or {@link ORMRelationCreateCommand}( in
* case any other Relation should be created)
* */
@Override
protected Command getConnectionCreateCommand(final CreateConnectionRequest request) {
Command retVal = null;
if (!(request.getNewObjectType().equals(Type.RELATIONSHIP_IMPLICATION) ||
request.getNewObjectType().equals(Type.RELATIONSHIP_EXCLUSION))) {
if (isStartOK(request)) {
retVal =
setupConnectionStartCommand(request, ((Shape) getHost().getModel()).getContainer());
}
// Irreflexive Acyclic Total start
if ((oTCheck(request, Type.CYCLIC, Type.ROLE_TYPE)
|| oTCheck(request, Type.IRREFLEXIVE, Type.ROLE_TYPE) || oTCheck(request, Type.TOTAL,
Type.ROLE_TYPE)|| oTCheck(request, Type.ACYCLIC, Type.ROLE_TYPE) || oTCheck(
request, Type.REFLEXIVE, Type.ROLE_TYPE)) && hasARelationship(request, false)) {
final ORMRelationshipConstraintCreateCommand result =
new ORMRelationshipConstraintCreateCommand();
result.setSource((Shape) getHost().getModel());
result.setRelation((Relation) request.getNewObject());
request.setStartCommand(result);
result.setRelationContainer(((Shape) getHost().getModel()).getContainer());
retVal = result;
}
}
return retVal;
}
/**
* {@inheritDoc}
*
* @return null
* */
@Override
protected Command getReconnectTargetCommand(ReconnectRequest request) {
return null;
}
/**
* {@inheritDoc}
*
* @return null
* */
@Override
protected Command getReconnectSourceCommand(ReconnectRequest request) {
return null;
}
/**
* This method tests if the type of the new object given by the request equals the objecttype, the
* source edit part model type given by the request equals the sourcetype and the target edit part
* model type given by the request equals of targettype.
*
* @fullname newObjectSourceEditPartTargetEditPartCheck
* @return boolean
* */
private boolean oSTCheck(final CreateConnectionRequest request, final Type objecttype,
final Type sourcetype, final Type targettype) {
Shape source = (Shape) request.getSourceEditPart().getModel();
Shape target = (Shape) request.getTargetEditPart().getModel();
return request.getNewObjectType().equals(objecttype) && targettype.equals(target.getType())
&& sourcetype.equals(source.getType());
}
/**
* This method tests if the new object given by the request equals objecttype and the target edit
* part model type given by the request equals targettype.
*
* @fullname newObjectTargetEditPartCheck
* @return boolean
* */
private boolean oTCheck(final CreateConnectionRequest request, final Type objecttype,
final Type targettype) {
Shape target = (Shape) request.getTargetEditPart().getModel();
return request.getNewObjectType().equals(objecttype) && targettype.equals(target.getType());
}
/**
* This method tests if the source edit part given by the request doesn't equals the target edit
* part given by the request.
*
* @fullname targetEditPartNotEqualSourceEditPartCheck
* @return boolean
* */
private boolean tNotEqualSCheck(final CreateConnectionRequest request) {
return !(request.getTargetEditPart().equals(request.getSourceEditPart()));
}
/**
* This method completes and return the creation commands for all {@link Relation}s except for
* {@link Relation}s from type cyclic, irreflexive, acyclic, reflexive and total.
*
* @return {@link ORMRelationCreateCommand}
* */
private ORMRelationCreateCommand setupConnectionCompleteCommand(
final CreateConnectionRequest request) {
final ORMRelationCreateCommand result = (ORMRelationCreateCommand) request.getStartCommand();
result.setTarget((Shape) getHost().getModel());
return result;
}
/**
* This method creates and return the creation command for all {@link Relation}s except the
* relations from type cyclic, total, acyclic, reflexive and irrflexive.
*
* @return {@link ORMRelationCreateCommand}
* */
private ORMRelationCreateCommand setupConnectionStartCommand(
final CreateConnectionRequest request, final Model container) {
final ORMRelationCreateCommand result = new ORMRelationCreateCommand();
result.setSource((Shape) getHost().getModel());
result.setRelation((Relation) request.getNewObject());
result.setRelationContainer(container);
if (request.getNewObjectType().equals(Type.RELATIONSHIP)) {
NamedElement ele = OrmFactory.eINSTANCE.createNamedElement();
ele.setName("*");
result.setSourceLabel(ele);
NamedElement ele2 = OrmFactory.eINSTANCE.createNamedElement();
ele2.setName("*");
result.setTargetLabel(ele2);
((Relation) request.getNewObject()).getConnectionAnchor().setContainer(container);
}
request.setStartCommand(result);
return result;
}
/**
* This method tests if target edit part model is the parent model of the source edit part model.
*
* @return boolean
* */
public boolean parentTest(final EditPart target, final EditPart source) {
boolean flag = false;
if (target != null && source != null) {
if (target.equals(source.getParent())) {
return true;
} else {
if (source.getParent() instanceof ORMModelEditPart) {
return false;
} else {
flag = parentTest(target, source.getParent());
}
}
}
return flag;
}
/**
* This method tests if the conditions for the creation completion of a {@link Relation}
* kind(except {@link Relation}s from type total, irreflexive and cyclic, acyclic, reflexive) are fulfilled.
*
* @return boolean
* */
public boolean isCompleteOK(final CreateConnectionRequest request) {
// Fulfillment Test End
return oSTCheck(request, Type.FULFILLMENT, Type.NATURAL_TYPE, Type.COMPARTMENT_TYPE)
|| oSTCheck(request, Type.FULFILLMENT, Type.DATA_TYPE, Type.COMPARTMENT_TYPE)
|| oSTCheck(request, Type.FULFILLMENT, Type.COMPARTMENT_TYPE, Type.COMPARTMENT_TYPE)
// Role Implication TesT End
|| ((oSTCheck(request, Type.ROLE_IMPLICATION, Type.ROLE_GROUP, Type.ROLE_GROUP)
|| oSTCheck(request, Type.ROLE_IMPLICATION, Type.ROLE_GROUP, Type.ROLE_TYPE)
|| oSTCheck(request, Type.ROLE_IMPLICATION, Type.ROLE_TYPE, Type.ROLE_GROUP) || oSTCheck(
request, Type.ROLE_IMPLICATION, Type.ROLE_TYPE, Type.ROLE_TYPE))
&& tNotEqualSCheck(request)
&& !parentTest(request.getTargetEditPart(), request.getSourceEditPart()) && !childrenTest(
request.getTargetEditPart(), request.getSourceEditPart()))
// Role Equilvalence Test End
|| ((oSTCheck(request, Type.ROLE_EQUIVALENCE, Type.ROLE_GROUP, Type.ROLE_GROUP)
|| oSTCheck(request, Type.ROLE_EQUIVALENCE, Type.ROLE_GROUP, Type.ROLE_TYPE)
|| oSTCheck(request, Type.ROLE_EQUIVALENCE, Type.ROLE_TYPE, Type.ROLE_GROUP) || oSTCheck(
request, Type.ROLE_EQUIVALENCE, Type.ROLE_TYPE, Type.ROLE_TYPE))
&& tNotEqualSCheck(request)
&& !parentTest(request.getTargetEditPart(), request.getSourceEditPart()) && !childrenTest(
request.getTargetEditPart(), request.getSourceEditPart()))
// Role Prohibition Test End
|| ((oSTCheck(request, Type.ROLE_PROHIBITION, Type.ROLE_GROUP, Type.ROLE_GROUP)
|| oSTCheck(request, Type.ROLE_PROHIBITION, Type.ROLE_GROUP, Type.ROLE_TYPE)
|| oSTCheck(request, Type.ROLE_PROHIBITION, Type.ROLE_TYPE, Type.ROLE_GROUP) || oSTCheck(
request, Type.ROLE_PROHIBITION, Type.ROLE_TYPE, Type.ROLE_TYPE))
&& tNotEqualSCheck(request)
&& !parentTest(request.getTargetEditPart(), request.getSourceEditPart()) && !childrenTest(
request.getTargetEditPart(), request.getSourceEditPart()))
// Inheritance Test End
|| (oSTCheck(request, Type.INHERITANCE, Type.ROLE_TYPE, Type.ROLE_TYPE) && tNotEqualSCheck(request))
|| (oSTCheck(request, Type.INHERITANCE, Type.NATURAL_TYPE, Type.NATURAL_TYPE) && tNotEqualSCheck(request))
|| (oSTCheck(request, Type.INHERITANCE, Type.DATA_TYPE, Type.DATA_TYPE) && tNotEqualSCheck(request))
|| (oSTCheck(request, Type.INHERITANCE, Type.COMPARTMENT_TYPE, Type.COMPARTMENT_TYPE) && tNotEqualSCheck(request))
// Relationship Test End
// || (oSTCheck(request, Type.RELATIONSHIP, Type.ROLE_TYPE, Type.ROLE_TYPE)
// && tNotEqualSCheck(request) && !hasARelationship(request, true));
|| (oSTCheck(request, Type.RELATIONSHIP, Type.ROLE_TYPE, Type.ROLE_TYPE)
&& tNotEqualSCheck(request));
}
/**
* This method tests if the conditions for the creation start of a {@link Relation} kind(except
* {@link Relation}s from type total, cyclic, acyclic, reflexive and irreflexive) are fulfilled.
*
* @return boolean
* */
public boolean isStartOK(final CreateConnectionRequest request) {
// Fufillment start
return oTCheck(request, Type.FULFILLMENT, Type.NATURAL_TYPE)
|| oTCheck(request, Type.FULFILLMENT, Type.DATA_TYPE)
|| oTCheck(request, Type.FULFILLMENT, Type.COMPARTMENT_TYPE)
// Role Implication start
|| oTCheck(request, Type.ROLE_IMPLICATION, Type.ROLE_TYPE)
|| oTCheck(request, Type.ROLE_IMPLICATION, Type.ROLE_GROUP)
// Role Equivalence start
|| oTCheck(request, Type.ROLE_EQUIVALENCE, Type.ROLE_TYPE)
|| oTCheck(request, Type.ROLE_EQUIVALENCE, Type.ROLE_GROUP)
// Role Prohibition start
|| oTCheck(request, Type.ROLE_PROHIBITION, Type.ROLE_TYPE)
|| oTCheck(request, Type.ROLE_PROHIBITION, Type.ROLE_GROUP)
// Inheritance start
|| oTCheck(request, Type.INHERITANCE, Type.NATURAL_TYPE)
|| oTCheck(request, Type.INHERITANCE, Type.DATA_TYPE)
|| oTCheck(request, Type.INHERITANCE, Type.ROLE_TYPE)
|| oTCheck(request, Type.INHERITANCE, Type.COMPARTMENT_TYPE)
// Relationship start
|| oTCheck(request, Type.RELATIONSHIP, Type.ROLE_TYPE);
}
/**
* This method tests if target edit part model is a child model of the source edit part model.
*
* @return boolean
* */
public boolean childrenTest(final EditPart target, final EditPart source) {
boolean flag;
flag = false;
final ArrayList<EditPart> children = new ArrayList<EditPart>();
final ArrayList<EditPart> roleGroups = new ArrayList<EditPart>();
children.addAll(source.getChildren());
for (EditPart child : children) {
if (target.equals(child))
return true;
if (child.getModel() instanceof Shape) {
Shape shape = (Shape) child.getModel();
if (shape.getType().equals(Type.ROLE_TYPE)) {
roleGroups.add(child);
}
}
}
if (roleGroups.size() == 0) {
return false;
} else {
for (EditPart rg : roleGroups) {
flag = childrenTest(target, rg);
if (flag)
return flag;
}
}
return flag;
}
/**
* This method tests if between source edit part and traget edit part already exist a
* relationshipConstraint(total,irrflexive,cyclic, acyclic, reflexive) kind of the requested relationshipConstraint
* kind.
*
* @return boolean
* */
private boolean hasConstraintsKind(final CreateConnectionRequest request) {
if (testedRelationship != null) {
for (Relation rel : testedRelationship.getReferencedRelation()) {
if (request.getNewObjectType().equals(Type.IRREFLEXIVE)
&& rel.getType().equals(Type.IRREFLEXIVE))
return true;
if (request.getNewObjectType().equals(Type.TOTAL) && rel.getType().equals(Type.TOTAL))
return true;
if (request.getNewObjectType().equals(Type.CYCLIC) && rel.getType().equals(Type.CYCLIC))
return true;
if (request.getNewObjectType().equals(Type.ACYCLIC) && rel.getType().equals(Type.ACYCLIC))
return true;
if (request.getNewObjectType().equals(Type.REFLEXIVE) && rel.getType().equals(Type.REFLEXIVE))
return true;
}
}
return false;
}
/**
* This method tests if between source edit part and traget edit part already exist a
* {@link Relation} from type relationship.
*
* @return boolean
* */
private boolean hasARelationship(final CreateConnectionRequest request, final boolean isTargetTest) {
final List<Relation> relList = new ArrayList<Relation>();
final List<Relation> relSourceList = new ArrayList<Relation>();
// false source edit part(else) true target edit part(if)
if (isTargetTest) {
relList.addAll(((ORMShapeWithSegmentEditPart) request.getTargetEditPart())
.getModelTargetConnections());
relList.addAll(((ORMShapeWithSegmentEditPart) request.getTargetEditPart())
.getModelSourceConnections());
relSourceList.addAll(((ORMShapeWithSegmentEditPart) request.getSourceEditPart())
.getModelTargetConnections());
relSourceList.addAll(((ORMShapeWithSegmentEditPart) request.getSourceEditPart())
.getModelSourceConnections());
// test: has the target editpart the relationship connection as the source connection?
for (Relation rel : relList) {
if (rel.getType().equals(Type.RELATIONSHIP)) {
for (Relation rel2 : relSourceList) {
if (rel2.equals(rel)) {
testedRelationship = rel;
return true;
}
}
}
}
} else {
// test: has the source editpart a relationship as connection?
relList.addAll(((ORMShapeWithSegmentEditPart) request.getTargetEditPart())
.getModelSourceConnections());
relList.addAll(((ORMShapeWithSegmentEditPart) request.getTargetEditPart())
.getModelTargetConnections());
for (Relation rel : relList) {
if (rel.getType().equals(Type.RELATIONSHIP))
return true;
}
}
return false;
}
}