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.activities.parameters;
025    
026    import java.io.Serializable;
027    import java.util.ArrayList;
028    import java.util.Collection;
029    import java.util.HashMap;
030    import java.util.HashSet;
031    import java.util.Stack;
032    
033    import se.liu.ida.critiquer.activities.Activity;
034    import se.liu.ida.critiquer.activities.ActivityUtils;
035    import se.liu.ida.critiquer.resources.Agent;
036    
037    /**
038     * 
039     * A commander has a list of activities for which this commander is responsible.
040     * Whenever choices are made in the CommanderParameter, Commander objects are
041     * notified that they should update their information on which activities they
042     * are responsible for.
043     * 
044     * Agents are added to commanding activities, but commanders may choose not to
045     * use agents for specific tasks. Therefore it is possible to remove agents on a
046     * per-activity basis.
047     * 
048     * To enable a more fine-grained control over which activities are associated
049     * with which agents, agents can be removed from individual sub-activities that
050     * this commander controls,
051     * 
052     * @author olale
053     * 
054     */
055    public class Commander implements Serializable {
056    
057            /**
058         * 
059         */
060            private static final long                                serialVersionUID = 1L;
061    
062            private String                                                  name;
063    
064            private AgentParameter                                  agentParameter;
065    
066            /**
067             */
068            private HashMap<Activity, HashSet<Agent>> agentMappings     = new HashMap<Activity, HashSet<Agent>>();
069    
070            private ArrayList<Activity>                          activities;
071    
072            public void agentAdded(Agent a) {
073                    ArrayList<Activity> allActivities = getAllActivities();
074                    for (Activity activity : allActivities) {
075                            addMapping(activity, a);
076                    }
077            }
078    
079            public void addMapping(Activity activity, Agent agent) {
080                    if (agentMappings.containsKey(activity)) {
081                            agentMappings.get(activity).add(agent);
082                    } else {
083                            HashSet<Agent> map = new HashSet<Agent>();
084                            map.add(agent);
085                            agentMappings.put(activity, map);
086                    }
087            }
088    
089            public HashSet<Agent> getAgentsInActivity(Activity activity) {
090                    return agentMappings.get(activity);
091            }
092    
093            public void agentRemoved(Activity activity, Agent agent) {
094                    if (agentMappings.containsKey(activity)) {
095                            agentMappings.get(activity).remove(agent);
096                    }
097            }
098    
099            public Commander(String name) {
100                    this.name = name;
101                    this.activities = new ArrayList<Activity>();
102                    agentParameter = new AgentParameter("main agent", this);
103            }
104    
105            public void addActivity(Activity a) {
106                    activities.add(a);
107                    ArrayList<Activity> newActivities = getActivitiesFrom(a);
108                    for (Activity activity : newActivities) {
109                            agentMappings.put(activity, (HashSet<Agent>) getSubordinates().clone());
110                    }
111            }
112    
113            public void removeActivity(Activity a) {
114                    activities.remove(a);
115                    ArrayList<Activity> activitiesToRemove = getActivitiesFrom(a);
116                    for (Activity activity : activitiesToRemove) {
117                            agentMappings.remove(activity);
118                    }
119            }
120    
121            @Override
122            public String toString() {
123                    return getName();
124            }
125    
126            /**
127         * @return Returns the name.
128         */
129            public String getName() {
130                    return name;
131            }
132    
133            /**
134         * @return Returns the agents that this commanders controls.
135         */
136            public HashSet<Agent> getSubordinates() {
137                    HashSet<Agent> myAgents = new HashSet<Agent>();
138                    Collection<HashSet<Agent>> agentSets = agentMappings.values();
139                    for (HashSet<Agent> set : agentSets) {
140                            myAgents.addAll(set);
141                    }
142                    return myAgents;
143            }
144    
145            /**
146         * @return Returns the agentParameter.
147         */
148            public AgentParameter getAgentParameter() {
149                    return agentParameter;
150            }
151    
152            /**
153         * get the activities that have this commander as the value of their
154         * CommanderParameter.
155         * 
156         * @return Returns the activities.
157         */
158            public ArrayList<Activity> getActivities() {
159                    return activities;
160            }
161    
162            /**
163         * Recurse through the activity forest and return a list of all activities.
164         * 
165         * @return
166         */
167            public ArrayList<Activity> getAllActivities() {
168                    Stack<Activity> queue = new Stack<Activity>();
169                    queue.addAll(activities);
170                    return recursivelyListActivities(queue);
171            }
172    
173            /**
174         * Recurse through the activity tree starting at rootActivity and return a
175         * list of all activities.
176         * 
177         * @return
178         */
179    
180            public ArrayList<Activity> getActivitiesFrom(Activity rootActivity) {
181                    Stack<Activity> queue = new Stack<Activity>();
182                    queue.push(rootActivity);
183                    return recursivelyListActivities(queue);
184            }
185    
186            private ArrayList<Activity> recursivelyListActivities(Stack<Activity> queue) {
187                    ArrayList<Activity> allActivities = new ArrayList<Activity>();
188                    while (!queue.isEmpty()) {
189                            Activity activity = queue.pop();
190                            allActivities.add(activity);
191                            queue.addAll(activity.getChildren());
192                    }
193                    return allActivities;
194            }
195    
196            /**
197         * There is no special updating to do other than related to time
198         * 
199         * We must remember to update the dependent activities as well however
200         * 
201         */
202            public void notifyActivities() {
203                    for (Activity activity : getAllActivities()) {
204                            ActivityUtils.runActivityTimeNotifier(activity);
205                    }
206            }
207    
208    }