001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.planning.ldm.lps;
028:
029: import java.util.ArrayList;
030: import java.util.Collection;
031: import java.util.Iterator;
032:
033: import org.cougaar.core.blackboard.Directive;
034: import org.cougaar.core.domain.LogicProvider;
035: import org.cougaar.core.domain.MessageLogicProvider;
036: import org.cougaar.core.domain.RootPlan;
037: import org.cougaar.planning.ldm.LogPlan;
038: import org.cougaar.planning.ldm.PlanningFactory;
039: import org.cougaar.planning.ldm.asset.Asset;
040: import org.cougaar.planning.ldm.plan.AssetRescind;
041: import org.cougaar.planning.ldm.plan.AssignedAvailabilityElement;
042: import org.cougaar.planning.ldm.plan.AssignedRelationshipElement;
043: import org.cougaar.planning.ldm.plan.HasRelationships;
044: import org.cougaar.planning.ldm.plan.NewRoleSchedule;
045: import org.cougaar.planning.ldm.plan.NewSchedule;
046: import org.cougaar.planning.ldm.plan.Relationship;
047: import org.cougaar.planning.ldm.plan.RelationshipSchedule;
048: import org.cougaar.planning.ldm.plan.Schedule;
049: import org.cougaar.util.Enumerator;
050: import org.cougaar.util.MutableTimeSpan;
051: import org.cougaar.util.UnaryPredicate;
052: import org.cougaar.util.log.Logger;
053: import org.cougaar.util.log.Logging;
054:
055: /**
056: * Catch assets so that we can relink the relationships properly.
057: **/
058:
059: public class ReceiveAssetRescindLP implements LogicProvider,
060: MessageLogicProvider {
061: private static final Logger logger = Logging
062: .getLogger(ReceiveAssetRescindLP.class);
063:
064: private final RootPlan rootplan;
065: private final LogPlan logplan;
066: private final PlanningFactory ldmf;
067:
068: public ReceiveAssetRescindLP(RootPlan rootplan, LogPlan logplan,
069: PlanningFactory ldmf) {
070: this .rootplan = rootplan;
071: this .logplan = logplan;
072: this .ldmf = ldmf;
073: }
074:
075: public void init() {
076: }
077:
078: /**
079: * perform updates -- per Rescind ALGORITHM --
080: *
081: **/
082: public void execute(Directive dir, Collection changes) {
083: // drop changes
084: if (dir instanceof AssetRescind) {
085: receiveAssetRescind((AssetRescind) dir);
086: }
087: }
088:
089: private final static boolean related(Asset a) {
090: return (a instanceof HasRelationships);
091: }
092:
093: private void receiveAssetRescind(AssetRescind ar) {
094: Asset localAsset = logplan.findAsset(ar.getAsset());
095: if (localAsset == null) {
096: logger.error("Rescinded asset - " + ar.getAsset()
097: + " - not found in logplan.");
098: return;
099: }
100:
101: Asset localAssignee = logplan.findAsset(ar.getRescindee());
102: if (localAssignee == null) {
103: logger.error("Assignee asset - " + ar.getRescindee()
104: + " - not found in logplan.");
105: return;
106: }
107:
108: if (related(ar.getAsset()) && related(ar.getRescindee())) {
109: updateRelationshipSchedules(ar, localAsset, localAssignee);
110: }
111:
112: updateAvailSchedule(ar, localAsset, localAssignee);
113:
114: rootplan.change(localAsset, null);
115: rootplan.change(localAssignee, null);
116: }
117:
118: private void updateRelationshipSchedules(AssetRescind ar,
119: Asset asset, Asset assignee) {
120:
121: RelationshipSchedule assetRelationshipSchedule = ((HasRelationships) asset)
122: .getRelationshipSchedule();
123:
124: RelationshipSchedule assigneeRelationshipSchedule = ((HasRelationships) assignee)
125: .getRelationshipSchedule();
126:
127: // Remove matching relationships
128: Collection rescinds = convertToRelationships(ar, asset,
129: assignee);
130:
131: assetRelationshipSchedule.removeAll(rescinds);
132:
133: assigneeRelationshipSchedule.removeAll(rescinds);
134: }
135:
136: // Update availability info for the asset (aka transferring asset)
137: // AvailableSchedule reflects availablity within the current agent
138: private void updateAvailSchedule(AssetRescind ar, Asset asset,
139: final Asset assignee) {
140:
141: NewSchedule assetAvailSchedule = (NewSchedule) asset
142: .getRoleSchedule().getAvailableSchedule();
143:
144: if (assetAvailSchedule == null) {
145: if (logger.isDebugEnabled()) {
146: logger.debug("Asset for rescinded asset transfer "
147: + asset.getItemIdentificationPG()
148: .getItemIdentification()
149: + " did not have an availability schedule.");
150:
151: }
152:
153: assetAvailSchedule = ldmf.newAssignedAvailabilitySchedule();
154: ((NewRoleSchedule) asset.getRoleSchedule())
155: .setAvailableSchedule(assetAvailSchedule);
156: }
157:
158: if (!related(asset)) {
159:
160: // Remove Matching Availabilities
161: synchronized (assetAvailSchedule) {
162: assetAvailSchedule.removeAll(ar.getSchedule());
163: }
164:
165: // We're done
166: return;
167: }
168:
169: //For Assets with relationships, need to recompute the avail schedule
170: //based on the relationship schedule
171:
172: // Remove all current entries denoting asset avail to assignee
173: synchronized (assetAvailSchedule) {
174: Collection remove = assetAvailSchedule
175: .filter(new UnaryPredicate() {
176: public boolean execute(Object o) {
177: return ((o instanceof AssignedAvailabilityElement) && (((AssignedAvailabilityElement) o)
178: .getAssignee().equals(assignee)));
179: }
180: });
181: assetAvailSchedule.removeAll(remove);
182:
183: // Get all relationships between asset and assignee
184: RelationshipSchedule relationshipSchedule = ((HasRelationships) asset)
185: .getRelationshipSchedule();
186: Collection collection = relationshipSchedule
187: .getMatchingRelationships(
188: (HasRelationships) assignee,
189: new MutableTimeSpan());
190:
191: // If any relationships, add a single avail element with the
192: // min start and max end
193: if (collection.size() > 0) {
194: Schedule schedule = ldmf.newSchedule(new Enumerator(
195: collection));
196:
197: // Add a new avail element
198: assetAvailSchedule.add(ldmf
199: .newAssignedAvailabilityElement(assignee,
200: schedule.getStartTime(), schedule
201: .getEndTime()));
202: }
203: } // end sync block
204: }
205:
206: protected Collection convertToRelationships(AssetRescind ar,
207: Asset asset, Asset assignee) {
208: ArrayList relationships = new ArrayList(ar.getSchedule().size());
209:
210: // Safe because ar.getSchedule is an AssignedRelationshipScheduleImpl.
211: // AssignedRelationshipImpl supports iterator. (Assumption is that
212: // AssignedRelaionshipImpl is only used/processed by LPs.)
213: for (Iterator iterator = ar.getSchedule().iterator(); iterator
214: .hasNext();) {
215: AssignedRelationshipElement rescindElement = (AssignedRelationshipElement) iterator
216: .next();
217:
218: Relationship relationship = ldmf.newRelationship(
219: rescindElement, asset, assignee);
220:
221: relationships.add(relationship);
222: }
223:
224: return relationships;
225: }
226: }
|