/* * LinkConstraint.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.constraint; import java.util.HashSet; import java.util.List; import java.util.Set; import eu.aniketos.wp1.ststool.Actor; import eu.aniketos.wp1.ststool.Agent; import eu.aniketos.wp1.ststool.BindingOfDuties; import eu.aniketos.wp1.ststool.CompatibleDuties; import eu.aniketos.wp1.ststool.Delegation; import eu.aniketos.wp1.ststool.Dependency; import eu.aniketos.wp1.ststool.Event; import eu.aniketos.wp1.ststool.Goal; import eu.aniketos.wp1.ststool.GoalContribution; import eu.aniketos.wp1.ststool.GoalDecomposition; import eu.aniketos.wp1.ststool.GoalDecompositionAND; import eu.aniketos.wp1.ststool.GoalDecompositionOR; import eu.aniketos.wp1.ststool.IResource; import eu.aniketos.wp1.ststool.IncompatibleDuties; import eu.aniketos.wp1.ststool.Modify; import eu.aniketos.wp1.ststool.Need; import eu.aniketos.wp1.ststool.Own; import eu.aniketos.wp1.ststool.PartOf; import eu.aniketos.wp1.ststool.Play; import eu.aniketos.wp1.ststool.Produce; import eu.aniketos.wp1.ststool.Provision; import eu.aniketos.wp1.ststool.Resource; import eu.aniketos.wp1.ststool.Role; import eu.aniketos.wp1.ststool.SeparationOfDuties; import eu.aniketos.wp1.ststool.TResource; import eu.aniketos.wp1.ststool.TangibleBy; import eu.aniketos.wp1.ststool.Threat; import eu.aniketos.wp1.ststool.Threatable; public abstract class LinkConstraint { /** * Method called to check if a Need relation can be created or reoriented * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created */ public static boolean canExistGoalNeed(Goal container,Goal source,TResource target){ if (source != null && target != null) { if (!source.getActorOwner().equals(target.getActorOwner())) return false; for (Need n : source.getResourceNeeded()) { if (n.getTarget() == target) return false; } } return true; } /** * Method called to check if a Produce relation can be created or reoriented * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created */ public static boolean canExistGoalProduce(Goal container,Goal source,TResource target){ if (source != null && target != null) { if (!source.getActorOwner().equals(target.getActorOwner())) return false; if (target.getGoalsProducing().size() > 0) return false; if (target.getProvidedFrom().size() > 0) return false; for (Produce n : source.getResourcesProduced()) { if (n.getTarget() == target) return false; } /*for (Modify n : source.getResourcesModified()) { if (n.getTarget() == target) return false; }*/ } return true; } /** * Method called to check if a Modify relation can be created or reoriented * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created */ public static boolean canExistGoalModify(Goal container,Goal source,TResource target){ if (source != null && target != null) { if (!source.getActorOwner().equals(target.getActorOwner())) return false; for (Modify n : source.getResourcesModified()) { if (n.getTarget() == target) return false; } /*for (Produce p : source.getResourcesProduced()) { if (p.getTarget() == target) return false; }*/ } return true; } /** * Method called to check if a Positive Contribution relation can be created or reoriented * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created */ public static boolean canExistContributionPositive(Goal container,Goal source,Goal target){ if (target == null) return true; if (source == target) return false; Goal g = source; for (GoalContribution c : g.getOutgoingContributions()) { if (c.getTarget() == target) { return false; } } while (g != null) { if (g.getIncomingDecompositions() != null) { if (g.getIncomingDecompositions().getSource() == target) {//parent return false; } else { g = g.getIncomingDecompositions().getSource(); } } else { g = null; }//end while } if (isGoalChildOfDecompositionRecursive(source, target)) return false; if (getOriginalDelegatedGoal(source) == getOriginalDelegatedGoal(target)) return false; return true; } /** * Method called to check if a Negative Contribution relation can be created or reoriented * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created */ public static boolean canExistContributionNegative(Goal container,Goal source,Goal target){ if (target == null) return true; if (source == target) return false; Goal g = source; for (GoalContribution c : g.getOutgoingContributions()) { if (c.getTarget() == target) return false; } while (g != null) { //check if is a parent if (g.getIncomingDecompositions() != null) { if (g.getIncomingDecompositions().getSource() == target) {//parent return false; } else { g = g.getIncomingDecompositions().getSource(); } } else { g = null; }//end while } if (isGoalChildOfDecompositionRecursive(source, target)) return false; if (getOriginalDelegatedGoal(source) == getOriginalDelegatedGoal(target)) return false; return true; } /** * Method called to check if a Decomposition And relation can be created or reoriented * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created */ public static boolean canExistDecomposition_AND(Goal container,Goal source,Goal target){ if(source !=null && source.getDelegatedTo().size()>0)return false; if(source !=null && source.isCapability())return false; if (!(source.getOutgoingDecompositions().isEmpty()) && !(source.getOutgoingDecompositions().get(0) instanceof GoalDecompositionAND)) return false; if (target == null) return true; if (target == source) return false; if (source != null && target != null) { if (!source.getActorOwner().equals(target.getActorOwner())) return false; } if (target.getIncomingDecompositions() != null) return false; for (GoalDecomposition r : source.getOutgoingDecompositions()) { if (r.getTarget() == target) return false; } for (GoalDecomposition r : target.getOutgoingDecompositions()) { if (r.getTarget() == source) return false; } for (IncompatibleDuties id : source.getIncompatibleDutiesOut()) { if (id.getTarget() == target || isG1childofG2((Goal) id.getTarget(), target)) { return false; } } for (IncompatibleDuties id : source.getIncompatibleDutiesIn()) { if (isG1childofG2((Goal) id.getSource(), target)) { return false; } } for (IncompatibleDuties id : target.getIncompatibleDutiesOut()) { if (id.getTarget() == source || isG1childofG2(source, (Goal) id.getTarget())) { return false; } } for (IncompatibleDuties id : target.getIncompatibleDutiesIn()) { if (isG1childofG2(source, (Goal) id.getSource())) { return false; } } for (CompatibleDuties id : source.getCompatibleDutiesOut()) { if (id.getTarget() == target || isG1childofG2((Goal) id.getTarget(), target)) { return false; } } for (CompatibleDuties id : source.getCompatibleDutiesIn()) { if (isG1childofG2((Goal) id.getSource(), target)) { return false; } } for (CompatibleDuties id : target.getCompatibleDutiesOut()) { if (id.getTarget() == source || isG1childofG2(source, (Goal) id.getTarget())) { return false; } } for (CompatibleDuties id : target.getCompatibleDutiesIn()) { if (isG1childofG2(source, (Goal) id.getSource())) { return false; } } return evaluateGoalCicle(source, target); } /** * Method called to check if a Decomposition OR relation can be created or reoriented * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created */ public static boolean canExistDecomposition_OR(Goal container,Goal source,Goal target){ if(source !=null && source.getDelegatedTo().size()>0)return false; if(source !=null && source.isCapability())return false; if (!(source.getOutgoingDecompositions().isEmpty()) && !(source.getOutgoingDecompositions().get(0) instanceof GoalDecompositionOR)) return false; if (target == null) return true; if (target == source) return false; if (source != null && target != null) { if (!source.getActorOwner().equals(target.getActorOwner())) return false; } if (target.getIncomingDecompositions() != null) return false; for (GoalDecomposition r : source.getOutgoingDecompositions()) { if (r.getTarget() == target) return false; } for (GoalDecomposition r : target.getOutgoingDecompositions()) { if (r.getTarget() == source) return false; } for (IncompatibleDuties id : source.getIncompatibleDutiesOut()) { if (id.getTarget() == target || isG1childofG2((Goal) id.getTarget(), target)) { return false; } } for (IncompatibleDuties id : source.getIncompatibleDutiesIn()) { if (isG1childofG2((Goal) id.getSource(), target)) { return false; } } for (IncompatibleDuties id : target.getIncompatibleDutiesOut()) { if (id.getTarget() == source || isG1childofG2(source, (Goal) id.getTarget())) { return false; } } for (IncompatibleDuties id : target.getIncompatibleDutiesIn()) { if (isG1childofG2(source, (Goal) id.getSource())) { return false; } } for (CompatibleDuties id : source.getCompatibleDutiesOut()) { if (id.getTarget() == target || isG1childofG2((Goal) id.getTarget(), target)) { return false; } } for (CompatibleDuties id : source.getCompatibleDutiesIn()) { if (isG1childofG2((Goal) id.getSource(), target)) { return false; } } for (CompatibleDuties id : target.getCompatibleDutiesOut()) { if (id.getTarget() == source || isG1childofG2(source, (Goal) id.getTarget())) { return false; } } for (CompatibleDuties id : target.getCompatibleDutiesIn()) { if (isG1childofG2(source, (Goal) id.getSource())) { return false; } } return evaluateGoalCicle(source, target); } private static boolean isG1childofG2(Goal g1,Goal g2){ Goal gTest = g1; while (gTest != null) { if (gTest.getIncomingDecompositions() != null) { if (gTest.getIncomingDecompositions().getSource() == g2) {//parent return true; } else { gTest = gTest.getIncomingDecompositions().getSource(); } } else { gTest = null; } } return false; } /** * Method called to check if a Own relation can be created or reoriented * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created */ public static boolean canExistActorOwn(Actor container,Actor source,IResource target){ if (target != null && target.getOwners().size() > 0) return false; if (source != null && target != null) { for (Own r : source.getIResources()) { if (r.getTarget() == target) return false; } } return true; } /** * Method called to check if a PartOf relation can be created or reoriented * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created */ public static boolean canExistPartOf(Resource container,Resource source,Resource target){ if (source != null && target != null) { if (source == target) return false; if (source.getClass() != target.getClass()) return false; for (PartOf r : source.getPartsOf()) { if (r.getTarget() == target) return false; } for (PartOf r : target.getPartsOf()) { if (r.getTarget() == source) return false; } } return true; } /** * Method called to check if a TangibleBy relation can be created or reoriented * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created */ public static boolean canExistTangibleBy(IResource container,IResource source,TResource target){ if (source != null && target != null) { for (TangibleBy r : source.getTangibleElements()) { if (r.getTarget() == target) return false; } } return true; } /** * Method called to check if a Paly relation can be created or reoriented * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created */ public static boolean canExistAgentPlays(Agent container,Agent source,Role target){ if (source != null && target != null) { for (Play r : source.getPlayedRoles()) { if (r.getTarget() == target) return false; } } return true; } /** * Method called to check if a Authorisation relation can be created or reoriented * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created */ public static boolean canExistAuthorisation(Actor container,Actor source,Actor target){ if (source == target) return false; return true; } /** * Method called to check if a Provision relation can be created or reoriented * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created */ public static boolean canExistProvision(Actor container,Actor source,Actor target){ if (source == target) return false; return true; } public static boolean canExistProvision(Actor source,Actor target,TResource provided){ if (source == target) return false; for (Provision p : source.getOutgoingProvisions()) { if (p.getTarget() == target && p.getSourceResource() == provided) return false; } /*Provision p = provided.getProvidedFrom(); while (p != null) { if (p.getSource() == target) return false; p = p.getPreviousProvision(); }*/ return true; } /** * Method called to check if a Delegation relation can be created or reoriented * * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created * @deprecated disabled from version 1.0.6 */ public static boolean canExistDelegation(Actor container,Actor source,Actor target){ if (source == target) return false; return true; } public static boolean canExistDelegation(Actor source,Goal delegated){ return true; } public static boolean canExistDelegation(Actor source,Actor target,Goal delegated){ if (delegated.getOutgoingDecompositions().size()>0)return false; if (source == target) return false; for (Delegation d : source.getOutgoingDelegations()) { if (d.getTarget() == target && d.getSourceGoal() == delegated) return false; } if (evaluateDelegationCicles(target, delegated.getDelegatedFrom())) return false; return true; } private static boolean evaluateDelegationCicles(Actor target,List<Delegation> delegation){ if (delegation.size() == 0) return false; for (Delegation d : delegation) { if (d.getSource() == target || evaluateDelegationCicles(target, d.getPreviousDelegation())) return true; } return false; } /** * Method called to check if a Threat relation can be created or reoriented * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created */ public static boolean canExistThreat(Event container,Event source,Threatable target){ for (Threat t : source.getThreatedElements()) { if (t.getTarget() == target) return false; } return true; } /** * Method called to check if a Incompatible relation can be created or reoriented * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created */ public static boolean canExistIncompatibleDuties(SeparationOfDuties container,SeparationOfDuties source,SeparationOfDuties target){ if (source == null || target == null) return true; if (source == target) return false; if (source instanceof BindingOfDuties) { for (CompatibleDuties i : ((BindingOfDuties) source).getCompatibleDutiesOut()) { if (i.getTarget() == target) return false; } } if (target instanceof BindingOfDuties) { for (CompatibleDuties i : ((BindingOfDuties) target).getCompatibleDutiesOut()) { if (i.getTarget() == source) return false; } } if (source.getClass() != target.getClass()) return false; if (source instanceof Goal) { Goal s = (Goal) source; Goal t = (Goal) target; if (isGoalChildOfDecompositionRecursive(s, t) || isGoalChildOfDecompositionRecursive(t, s)) return false; } for (IncompatibleDuties id : source.getIncompatibleDutiesOut()) { if (id.getTarget() == target) return false; } for (IncompatibleDuties id : source.getIncompatibleDutiesIn()) { if (id.getSource() == target) return false; } return true; } /** * Method called to check if a Threat relation can be created or reoriented * * @param container * the container of the Need relation * @param source * the source of the relation (can be null) * @param target * the target of the relation (can be null) * * @return true if the relation can be created */ public static boolean canExistCompatibleDuties(BindingOfDuties container,BindingOfDuties source,BindingOfDuties target){ if (source == null || target == null) return true; if (source == target) return false; if (source instanceof SeparationOfDuties) { for (IncompatibleDuties i : ((SeparationOfDuties) source).getIncompatibleDutiesOut()) { if (i.getTarget() == target) return false; } } if (target instanceof SeparationOfDuties) { for (IncompatibleDuties i : ((SeparationOfDuties) target).getIncompatibleDutiesOut()) { if (i.getTarget() == source) return false; } } if (source.getClass() != target.getClass()) return false; if (source instanceof Goal) { Goal s = (Goal) source; Goal t = (Goal) target; if (isGoalChildOfDecompositionRecursive(s, t) || isGoalChildOfDecompositionRecursive(t, s)) return false; } for (CompatibleDuties id : source.getCompatibleDutiesOut()) { if (id.getTarget() == target) return false; } for (CompatibleDuties id : source.getCompatibleDutiesIn()) { if (id.getSource() == target) return false; } return true; } public static boolean canExistDependency(Role container,Role source,Role target){ if (source != null && target != null) { if(source==target)return false; for (Dependency d : source.getDependBy()) { if (d.getTarget() == target) return false; } for (Dependency d : target.getDependBy()) { if (d.getTarget() == source) return false; } } return true; } /** * Evaluate if a decomposition relation can exist without creating loop in the tree * * @param source * the source of the relation * @param target * the target of the relation * * @return true if the relation can be created */ public static boolean evaluateGoalCicle(Goal source,Goal target){ Set initialSet = new HashSet<Goal>(); initialSet.add(target); return !haveDecompositionCicles(source, initialSet); //ew HashSet(); } /** * Recursive method to evaluate loop in a tree of decomposition * * @param source * the source of the relation * @param initialSet * an empty set of goal to initialize the recursive function * * @return true if the relation can be created */ private static boolean haveDecompositionCicles(Goal source,Set<Goal> initialSet){ if (source.getIncomingDecompositions() == null) return false; else { Goal g = source.getIncomingDecompositions().getSource(); if (initialSet.add(g)) { return haveDecompositionCicles(g, initialSet); } else { return true; } } } /** * Evaluate if a Goal is a child of a decomposition * * @param parent * the parent goal * @param child * goal to test if is a child * * @return true if the testChild goal is a child */ private static boolean isGoalChildOfDecompositionRecursive(Goal parent,Goal testChild){ if (parent == testChild) return true; else { for (GoalDecomposition d : parent.getOutgoingDecompositions()) { if (isGoalChildOfDecompositionRecursive(d.getTarget(), testChild)) return true; } } return false; } private static Goal getOriginalDelegatedGoal(Goal delegatedGoal){ if (delegatedGoal.getDelegatedFrom().size() == 0) { return delegatedGoal; } return getOriginalDelegatedGoal(delegatedGoal.getDelegatedFrom().get(0).getSourceGoal()); } }