001 /** 002 * planningtool - A Planning Tool with Critiquing Support. 003 * 004 * Copyright (C) 2006 olale 005 006 * This program is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU General Public License 008 * as published by the Free Software Foundation; either version 2 009 * of the License, or (at your option) any later version. 010 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 016 * You should have received a copy of the GNU General Public License 017 * along with this program; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 019 020 * Contact information: 021 * E-mail: olale@ida.liu.se 022 * olale@lysator.liu.se 023 */ 024 package se.liu.ida.critiquer.constraints; 025 026 import java.awt.Graphics2D; 027 import java.util.ArrayList; 028 import java.util.Collection; 029 import java.util.HashSet; 030 031 import se.liu.ida.critiquer.activities.Activity; 032 import se.liu.ida.critiquer.activities.ActivityConsistencyCheck; 033 import se.liu.ida.critiquer.activities.ActivityUtils; 034 import se.liu.ida.critiquer.activities.parameters.AgentParameter; 035 import se.liu.ida.critiquer.activities.parameters.Commander; 036 import se.liu.ida.critiquer.activities.parameters.Parameter; 037 import se.liu.ida.critiquer.gui.View; 038 import se.liu.ida.critiquer.mics.Comparer; 039 import se.liu.ida.critiquer.mics.ReferenceHolder; 040 import se.liu.ida.critiquer.mics.Utils; 041 import se.liu.ida.critiquer.resources.Agent; 042 043 /** 044 * 045 * Checks whether or not an agent can be added to a commander, depending on if 046 * there are any other activities the agent is engaged in. 047 * 048 * @author olale 049 * 050 */ 051 public class AgentMutex extends StandardConstraint implements ActivityConsistencyCheck,TextCritic { 052 053 private static AgentMutex singleton = null; 054 055 /** 056 * 057 * 058 */ 059 public AgentMutex() { 060 super(); 061 062 /** 063 * Ensure that there is only one instance created through 064 * ConstraintFactory.createSingletonVisualConstraint 065 */ 066 assert (singleton == null); 067 Activity.addStaticConsistencyChecker(this); 068 singleton = this; 069 } 070 071 /** 072 * 073 */ 074 private static final long serialVersionUID = 1L; 075 076 private String information = ""; 077 078 private boolean overlapsAny(Activity activity, ArrayList<Activity> activities) { 079 assert (!activities.contains(activity)); 080 information=""; 081 for (Activity otherActivity : activities) { 082 if (ActivityUtils.overlap(activity, otherActivity)) { 083 HashSet<Agent> agentsInActivity = ActivityUtils.getAgentsInActivity(activity); 084 agentsInActivity.retainAll(ActivityUtils.getAgentsInActivity(otherActivity)); 085 information = ""; 086 for (Agent agent : agentsInActivity) { 087 088 information += "\n"+agent + " is already committed to activity " 089 + otherActivity 090 + " at the same time so it cannot perform " 091 + activity; 092 } 093 return true; 094 } 095 } 096 return false; 097 } 098 099 100 /** 101 * 102 * Checks if the currently selected set of agents is consistent with respect 103 * to when the activities they are supposed to be used in take place in 104 * time. 105 * 106 * @see se.liu.ida.critiquer.activities.ActivityConsistencyCheck#paramValueCheck(se.liu.ida.critiquer.activities.Activity, 107 * se.liu.ida.critiquer.activities.parameters.Parameter<T>, T) 108 */ 109 @SuppressWarnings("unchecked") 110 public <T> boolean paramValueCheck(Activity a, Parameter<T> p, T newValue) { 111 setConsistent(checkParameter(a, p, newValue)); 112 return isConsistent(); 113 } 114 115 /** 116 * The activity parameter is null here since we are called from an 117 * AgentParameter which is not directly connected to an activity. However, 118 * we can use the <code>Commander</code> of the 119 * <code>AgentParameter</code> <i>p</i> to retrieve a list of activities 120 * for which the current selection of agents is about to be selected. 121 * If there is an overlap in time between any of them and the other 122 * activities to which these agents are already assigned, the check fails. 123 * 124 * @param <T> 125 * type of parameter value. 126 * @param a 127 * Activity that fired this event or null if this was a parameter 128 * not directly connected to an activity. It is of little 129 * interest here since we use the activities available through 130 * the <code>Commander</code> 131 * @param p 132 * The parameter that caused this event. 133 * @param newValue 134 * The new value that we are supposed to check. 135 * @return 136 */ 137 protected <T> boolean checkParameter(Activity a, Parameter<T> p, T newValue) { 138 if (p instanceof AgentParameter) { 139 AgentParameter agentParam = (AgentParameter) p; 140 Commander myCommander = agentParam.getCommander(); 141 ArrayList<Activity> myActivities = (ArrayList<Activity>) myCommander.getAllActivities().clone(); 142 HashSet<Agent> agents = (HashSet<Agent>) newValue; 143 ArrayList<Activity> otherActivities = new ArrayList<Activity>(); 144 for (Agent agent : agents) { 145 otherActivities.addAll(agent.getActivitiesForAgent()); 146 } 147 otherActivities.removeAll(myActivities); 148 while (!myActivities.isEmpty() && !otherActivities.isEmpty()) { 149 Activity activity = myActivities.remove(0); 150 if (overlapsAny(activity, otherActivities)) { 151 return false; 152 } 153 } 154 } 155 return true; 156 } 157 158 /** 159 * 160 * Critiquing method that reacts to an agent being used at the same time by 161 * two different commanders 162 * 163 * @see se.liu.ida.critiquer.activities.AbstractParamChangedListener#paramChanged(se.liu.ida.critiquer.activities.Activity, 164 * se.liu.ida.critiquer.activities.parameters.Parameter) 165 */ 166 @Override 167 public <T> void paramChanged(Activity activity, Parameter<T> p) { 168 setConsistent(checkParameter(activity, p, null)); 169 } 170 171 /* 172 * (non-Javadoc) 173 * 174 * @see se.liu.ida.critiquer.activities.ActivityConsistencyCheck#childOfCheck(se.liu.ida.critiquer.activities.Activity, 175 * se.liu.ida.critiquer.activities.Activity) 176 */ 177 public boolean childOfCheck(Activity parentActivity, Activity Child) { 178 // TODO Auto-generated method stub 179 return true; 180 } 181 182 /* 183 * (non-Javadoc) 184 * 185 * @see se.liu.ida.critiquer.activities.ActivityConsistencyCheck#orderingCheck(se.liu.ida.critiquer.activities.Activity, 186 * se.liu.ida.critiquer.activities.Activity) 187 */ 188 public boolean orderingCheck(Activity beforeActivity, Activity AfterActivity) { 189 // TODO Auto-generated method stub 190 return true; 191 } 192 193 /* 194 * (non-Javadoc) 195 * 196 * @see se.liu.ida.critiquer.constraints.SingletonConstraint#getDescription() 197 */ 198 public String getDescription() { 199 return "Make sure agents cannot be employed by more than one commander at the same time"; 200 } 201 202 /* 203 * (non-Javadoc) 204 * 205 * @see se.liu.ida.critiquer.gui.ViewRenderingListener#viewUpdated(se.liu.ida.critiquer.gui.View, 206 * java.awt.Graphics2D) 207 */ 208 public void viewUpdated(View v, Graphics2D g2) { 209 // TODO Auto-generated method stub 210 211 } 212 213 /** 214 * Returns the textual information that should be presented by this critic 215 * @see se.liu.ida.critiquer.constraints.TextCritic#getText() 216 */ 217 public String getText() { 218 return information; 219 } 220 221 }