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.Enumeration;
032: import java.util.HashMap;
033: import java.util.Iterator;
034: import java.util.Vector;
035:
036: import org.cougaar.core.blackboard.AnonymousChangeReport;
037: import org.cougaar.core.blackboard.ChangeReport;
038: import org.cougaar.core.blackboard.EnvelopeTuple;
039: import org.cougaar.core.domain.EnvelopeLogicProvider;
040: import org.cougaar.core.domain.LogicProvider;
041: import org.cougaar.core.domain.RestartLogicProvider;
042: import org.cougaar.core.domain.RestartLogicProviderHelper;
043: import org.cougaar.core.domain.RootPlan;
044: import org.cougaar.core.mts.MessageAddress;
045: import org.cougaar.planning.ldm.LogPlan;
046: import org.cougaar.planning.ldm.PlanningFactory;
047: import org.cougaar.planning.ldm.asset.Asset;
048: import org.cougaar.planning.ldm.asset.ClusterPG;
049: import org.cougaar.planning.ldm.asset.LocalPG;
050: import org.cougaar.planning.ldm.asset.PropertyGroup;
051: import org.cougaar.planning.ldm.asset.PropertyGroupSchedule;
052: import org.cougaar.planning.ldm.plan.AssetAssignment;
053: import org.cougaar.planning.ldm.plan.AssetTransfer;
054: import org.cougaar.planning.ldm.plan.AssignedAvailabilityElement;
055: import org.cougaar.planning.ldm.plan.AssignedRelationshipElement;
056: import org.cougaar.planning.ldm.plan.HasRelationships;
057: import org.cougaar.planning.ldm.plan.NewAssetAssignment;
058: import org.cougaar.planning.ldm.plan.NewAssetVerification;
059: import org.cougaar.planning.ldm.plan.NewRoleSchedule;
060: import org.cougaar.planning.ldm.plan.NewSchedule;
061: import org.cougaar.planning.ldm.plan.Relationship;
062: import org.cougaar.planning.ldm.plan.RelationshipSchedule;
063: import org.cougaar.planning.ldm.plan.Role;
064: import org.cougaar.planning.ldm.plan.Schedule;
065: import org.cougaar.planning.ldm.plan.ScheduleElement;
066: import org.cougaar.util.Enumerator;
067: import org.cougaar.util.MutableTimeSpan;
068: import org.cougaar.util.TimeSpan;
069: import org.cougaar.util.UnaryPredicate;
070: import org.cougaar.util.log.Logger;
071: import org.cougaar.util.log.Logging;
072:
073: /** AssetTransferLP is a "LogPlan Logic Provider":
074: *
075: * it provides the logic to capture
076: * PlanElements that are AssetTransfers and send AssetAssignment tasks
077: * to the proper remote agent.
078: **/
079:
080: public class AssetTransferLP implements LogicProvider,
081: EnvelopeLogicProvider, RestartLogicProvider {
082: private static final Logger logger = Logging
083: .getLogger(AssetTransferLP.class);
084: private static final TimeSpan ETERNITY = new MutableTimeSpan();
085: private final RootPlan rootplan;
086: private final LogPlan logplan;
087: private final MessageAddress self;
088: private final PlanningFactory ldmf;
089:
090: public AssetTransferLP(RootPlan rootplan, LogPlan logplan,
091: PlanningFactory ldmf, MessageAddress self) {
092: this .rootplan = rootplan;
093: this .logplan = logplan;
094: this .ldmf = ldmf;
095: this .self = self;
096: }
097:
098: public void init() {
099: }
100:
101: /**
102: * @param o Envelopetuple,
103: * where tuple.object
104: * == PlanElement with an Allocation to an agent ADDED to LogPlan
105: *
106: * If the test returned true i.e. it was an AssetTransfer...
107: * create an AssetAssignment task and send it to a remote Agent
108: **/
109: public void execute(EnvelopeTuple o, Collection changes) {
110: Object obj;
111: if ((o.isAdd() || o.isChange())
112: && (obj = o.getObject()) != null
113: && obj instanceof AssetTransfer) {
114:
115: AssetTransfer at = (AssetTransfer) obj;
116: AssetAssignment assetassign;
117:
118: // create an AssetAssignment task
119: boolean sendRelationships = o.isAdd();
120: if (!sendRelationships
121: && ((changes != AnonymousChangeReport.LIST) && (changes != null))) {
122: for (Iterator i = changes.iterator(); i.hasNext();) {
123: ChangeReport changeReport = (ChangeReport) i.next();
124: if (changeReport instanceof RelationshipSchedule.RelationshipScheduleChangeReport) {
125: sendRelationships = true;
126: break;
127: }
128: }
129: }
130: assetassign = createAssetAssignment(at,
131: (o.isChange()) ? AssetAssignment.UPDATE
132: : AssetAssignment.NEW, sendRelationships);
133: if (assetassign != null) {
134: // Give the AssetAssignment to the blackboard for transmission
135: if (logger.isDebugEnabled())
136: logger.debug("Sending " + assetassign);
137: rootplan.sendDirective(assetassign);
138: } else {
139: if (logger.isDebugEnabled())
140: logger.debug("Not sending AssetAssignment for "
141: + at);
142: }
143: }
144: }
145:
146: // RestartLogicProvider implementation
147:
148: /**
149: * Agent restart handler. Resend all our assets to the restarted
150: * agent marking them as "REPEAT". Also send AssetVerification
151: * messages for all the assets we have received from the restarted
152: * agent. The restarted agent will rescind them if they are no
153: * longer valid.
154: **/
155: public void restart(final MessageAddress cid) {
156: UnaryPredicate pred = new UnaryPredicate() {
157: public boolean execute(Object o) {
158: if (o instanceof AssetTransfer) {
159: AssetTransfer at = (AssetTransfer) o;
160: MessageAddress assignee = at.getAssignee()
161: .getClusterPG().getMessageAddress();
162: return RestartLogicProviderHelper.matchesRestart(
163: self, cid, assignee);
164: }
165: return false;
166: }
167: };
168: Enumeration e = rootplan.searchBlackboard(pred);
169: while (e.hasMoreElements()) {
170: AssetTransfer at = (AssetTransfer) e.nextElement();
171: rootplan.sendDirective(createAssetAssignment(at,
172: AssetAssignment.REPEAT, true));
173: }
174: pred = new UnaryPredicate() {
175: public boolean execute(Object o) {
176: if (o instanceof Asset) {
177: Asset asset = (Asset) o;
178: ClusterPG clusterPG = asset.getClusterPG();
179: if (clusterPG != null) {
180: MessageAddress assetCID = clusterPG
181: .getMessageAddress();
182: return RestartLogicProviderHelper
183: .matchesRestart(self, cid, assetCID);
184: }
185: }
186: return false;
187: }
188: };
189: for (e = rootplan.searchBlackboard(pred); e.hasMoreElements();) {
190: Asset asset = (Asset) e.nextElement();
191:
192: if (related(asset)) {
193:
194: HashMap hash = new HashMap(3);
195:
196: RelationshipSchedule relationshipSchedule = (RelationshipSchedule) ((HasRelationships) asset)
197: .getRelationshipSchedule();
198:
199: Collection relationships = new ArrayList(
200: relationshipSchedule);
201: for (Iterator iterator = relationships.iterator(); iterator
202: .hasNext();) {
203: Relationship relationship = (Relationship) iterator
204: .next();
205:
206: Asset otherAsset = (Asset) relationshipSchedule
207: .getOther(relationship);
208:
209: NewSchedule verifySchedule = (NewSchedule) hash
210: .get(otherAsset);
211: if (verifySchedule == null) {
212: verifySchedule = ldmf
213: .newAssignedRelationshipSchedule();
214: hash.put(otherAsset, verifySchedule);
215: }
216:
217: verifySchedule
218: .add(ldmf
219: .newAssignedRelationshipElement(relationship));
220: }
221:
222: for (Iterator iterator = hash.keySet().iterator(); iterator
223: .hasNext();) {
224: Asset receivingAsset = (Asset) iterator.next();
225:
226: Schedule verifySchedule = (Schedule) hash
227: .get(receivingAsset);
228:
229: NewAssetVerification nav = ldmf
230: .newAssetVerification(ldmf
231: .cloneInstance(asset), ldmf
232: .cloneInstance(receivingAsset),
233: verifySchedule);
234: nav.setSource(self);
235: nav.setDestination(asset.getClusterPG()
236: .getMessageAddress());
237: rootplan.sendDirective(nav);
238: }
239: } else {
240: // BOZO - we have not tested transferring non-org assets
241: logger
242: .error("AssetTransferLP - unable to verify transfer of "
243: + asset + "\n.");
244: }
245:
246: }
247: }
248:
249: private final static boolean related(Asset a) {
250: return (a instanceof HasRelationships);
251: }
252:
253: private AssetAssignment createAssetAssignment(AssetTransfer at,
254: byte kind, boolean sendRelationships) {
255: NewAssetAssignment naa = ldmf.newAssetAssignment();
256:
257: /* copy the asset so we don't share roleschedule across
258: * agent boundaries.
259: */
260: Asset transferredAsset = ldmf.cloneInstance(at.getAsset());
261: Vector transferredPGs = transferredAsset.fetchAllProperties();
262:
263: // Remove all LocalPGs - these shouldn't go out of the agent.
264: for (Iterator pgIterator = transferredPGs.iterator(); pgIterator
265: .hasNext();) {
266: Object next = pgIterator.next();
267:
268: //Don't propagate LocalPGs
269: if (next instanceof LocalPG) {
270: if (next instanceof PropertyGroup) {
271: transferredAsset.removeOtherPropertyGroup(next
272: .getClass());
273: } else if (next instanceof PropertyGroupSchedule) {
274: transferredAsset
275: .removeOtherPropertyGroupSchedule(next
276: .getClass());
277: }
278: }
279: }
280:
281: naa.setAsset(transferredAsset);
282:
283: naa.setPlan(ldmf.getRealityPlan());
284:
285: naa.setAssignee(ldmf.cloneInstance(at.getAssignee()));
286:
287: naa.setSource(at.getAssignor());
288: naa.setDestination(at.getAssignee().getClusterPG()
289: .getMessageAddress());
290:
291: naa.setKind(kind);
292:
293: Schedule s = null; // Null if relationships not being sent
294:
295: Asset asset = naa.getAsset();
296: Asset assignee = naa.getAssignee();
297:
298: // Only fuss with relationship schedules if both Asset & Assignee implement
299: // HasRelationships
300: if (related(asset) & related(assignee)) {
301: if (sendRelationships) {
302: s = makeAARelationshipSchedule(naa, at);
303:
304: }
305: } else {
306: s = ldmf.newSchedule(at.getSchedule()
307: .getAllScheduleElements());
308: }
309:
310: naa.setSchedule(s);
311:
312: // Ensure that local info reflects the transfer
313: if (!updateLocalAssets(at, naa)) {
314: return null;
315: }
316:
317: // Clear asset and assignee relationship, role, and available schedules to ensure
318: // that there are no references to other organizations.
319: clearSchedule(asset);
320: clearSchedule(assignee);
321:
322: return naa;
323: }
324:
325: private Schedule makeAARelationshipSchedule(NewAssetAssignment naa,
326: final AssetTransfer at) {
327:
328: // construct appropriate relationship schedule for the asset assignment
329: Schedule aaAssetSchedule = ldmf
330: .newAssignedRelationshipSchedule();
331:
332: RelationshipSchedule relationshipSchedule = ((HasRelationships) at
333: .getAsset()).getRelationshipSchedule();
334: Collection relationships = relationshipSchedule
335: .filter(new UnaryPredicate() {
336: public boolean execute(Object o) {
337: Relationship relationship = (Relationship) o;
338:
339: // Verify that all relationships are with the receiver
340: if (!(relationship.getA().equals(at
341: .getAssignee()))
342: && !(relationship.getB().equals(at
343: .getAssignee()))) {
344: logger
345: .error("AssetTransferLP: Relationships on the "
346: + " AssetTransfer must be limited to the "
347: + " transferring and receiving asset.\n"
348: + "Dropping relationship "
349: + relationship
350: + " on transfer of "
351: + at.getAsset()
352: + " to "
353: + at.getAssignee());
354: return false;
355: } else {
356: return true;
357: }
358: }
359: });
360:
361: for (Iterator iterator = relationships.iterator(); iterator
362: .hasNext();) {
363: Relationship relationship = (Relationship) iterator.next();
364:
365: Asset a = (relationship.getA().equals(naa.getAsset())) ? naa
366: .getAsset()
367: : naa.getAssignee();
368: Asset b = (relationship.getB().equals(naa.getAsset())) ? naa
369: .getAsset()
370: : naa.getAssignee();
371: AssignedRelationshipElement element = ldmf
372: .newAssignedRelationshipElement(a, relationship
373: .getRoleA(), b,
374: relationship.getStartTime(), relationship
375: .getEndTime());
376: aaAssetSchedule.add(element);
377: }
378:
379: return aaAssetSchedule;
380: }
381:
382: private boolean updateLocalAssets(AssetTransfer at,
383: AssetAssignment aa) {
384: Asset localTransferringAsset = logplan.findAsset(at.getAsset());
385: if (localTransferringAsset == null) {
386: logger
387: .error("AssetTransferLP: unable to process AssetTransfer - "
388: + at.getAsset()
389: + " - transferring to "
390: + at.getAssignee()
391: + " - is not local to this agent.");
392: return false;
393: } else if (localTransferringAsset == at.getAsset()) {
394: logger
395: .error("AssetTransferLP: Transferring Assets in AssetTransfer are == but should be "
396: + " copies. AssetTransfer is "
397: + at.getUID()
398: + " Asset is "
399: + localTransferringAsset);
400: return false;
401: }
402:
403: Asset receivingAsset = at.getAssignee();
404: Asset localReceivingAsset = logplan.findAsset(receivingAsset);
405:
406: if (localReceivingAsset == null) {
407: receivingAsset = ldmf.cloneInstance(receivingAsset);
408: if (related(receivingAsset)) {
409: ((HasRelationships) receivingAsset)
410: .setRelationshipSchedule(ldmf
411: .newRelationshipSchedule((HasRelationships) receivingAsset));
412: }
413: } else {
414: receivingAsset = localReceivingAsset;
415:
416: if (localReceivingAsset == at.getAssignee()) {
417: logger
418: .error("AssetTransferLP: Assignee Assets in AssetTransfer are == but should be "
419: + " copies. AssetTransfer is "
420: + at.getUID()
421: + " Asset is "
422: + localReceivingAsset);
423: return false;
424: }
425: }
426:
427: boolean changeRelationshipRequired = fixRelationshipSchedule(
428: at, aa, localTransferringAsset, receivingAsset);
429:
430: boolean changeAvailabilityRequired = fixAvailSchedule(aa,
431: receivingAsset, localTransferringAsset);
432:
433: if (logger.isDebugEnabled()) {
434: logger
435: .debug("AssetTransferLP: changeRelationshipRequired = "
436: + changeRelationshipRequired
437: + " changeAvailabilityRequired = "
438: + changeAvailabilityRequired
439: + " for AssetTransfer - "
440: + at
441: + " transfering asset - "
442: + localTransferringAsset
443: + " receiving asset - "
444: + receivingAsset
445: + " local receiving asset - "
446: + localReceivingAsset);
447: }
448:
449: publishAsset(receivingAsset, (localReceivingAsset == null),
450: changeRelationshipRequired, changeAvailabilityRequired);
451:
452: publishAsset(localTransferringAsset, false, // local asset already exists on the blackboard
453: changeRelationshipRequired, changeAvailabilityRequired);
454:
455: return true;
456: }
457:
458: // Update availability info for the receiving asset
459: // AvailableSchedule reflects availablity within the current agent
460: private boolean fixAvailSchedule(AssetAssignment aa,
461: final Asset receivingAsset, final Asset transferringAsset) {
462:
463: NewSchedule availSchedule = (NewSchedule) transferringAsset
464: .getRoleSchedule().getAvailableSchedule();
465:
466: if (availSchedule == null) {
467: availSchedule = ldmf.newAssignedAvailabilitySchedule();
468: ((NewRoleSchedule) transferringAsset.getRoleSchedule())
469: .setAvailableSchedule(availSchedule);
470: }
471:
472: boolean change = false;
473:
474: synchronized (availSchedule) {
475: // Find all existing entries which refer to the receiving asset
476: Collection currentAvailability = availSchedule
477: .filter(new UnaryPredicate() {
478: public boolean execute(Object o) {
479: return ((o instanceof AssignedAvailabilityElement) && (((AssignedAvailabilityElement) o)
480: .getAssignee()
481: .equals(receivingAsset)));
482: }
483: });
484:
485: if ((related(transferringAsset) && related(receivingAsset))) {
486: //Construct aggregate avail info from the relationship schedule
487: RelationshipSchedule relationshipSchedule = ((HasRelationships) transferringAsset)
488: .getRelationshipSchedule();
489: Collection matchingRelationships = relationshipSchedule
490: .getMatchingRelationships(
491: (HasRelationships) receivingAsset,
492: ETERNITY);
493:
494: // If any relationships, construct a single avail element with the
495: // min start and max end
496: if (!matchingRelationships.isEmpty()) {
497: Schedule matchingRelationshipsSchedule = ldmf
498: .newSchedule(new Enumerator(
499: matchingRelationships));
500: AssignedAvailabilityElement aggregateAvailability = ldmf
501: .newAssignedAvailabilityElement(
502: receivingAsset,
503: matchingRelationshipsSchedule
504: .getStartTime(),
505: matchingRelationshipsSchedule
506: .getEndTime());
507:
508: // Compare to existing entries - only change if required.
509: if (!currentAvailability.isEmpty()) {
510: Schedule currentSchedule = ldmf
511: .newSchedule(new Enumerator(
512: currentAvailability));
513: if ((currentSchedule.getStartTime() != matchingRelationshipsSchedule
514: .getStartTime())
515: || (currentSchedule.getEndTime() != matchingRelationshipsSchedule
516: .getEndTime())) {
517: availSchedule
518: .removeAll(currentAvailability);
519: availSchedule.add(aggregateAvailability);
520: } else {
521: // No change required
522: return false;
523: }
524: } else {
525: availSchedule.add(aggregateAvailability);
526: change = true;
527: }
528: }
529: } else {
530:
531: if (((aa.isUpdate() || aa.isRepeat()) && (!currentAvailability
532: .isEmpty()))
533: && (currentAvailability.size() == aa
534: .getSchedule().size())) {
535:
536: // Compare to existing entries - only change if required.
537: Schedule currentSchedule = ldmf
538: .newSchedule(new Enumerator(
539: currentAvailability));
540:
541: for (Iterator localIterator = new ArrayList(
542: currentSchedule).iterator(), aaIterator = new ArrayList(
543: aa.getSchedule()).iterator(); localIterator
544: .hasNext();) {
545: ScheduleElement localElement = (ScheduleElement) localIterator
546: .next();
547: ScheduleElement aaElement = (ScheduleElement) aaIterator
548: .next();
549:
550: // compare timespan
551: if ((localElement.getStartTime() != aaElement
552: .getStartTime())
553: || (localElement.getEndTime() != aaElement
554: .getEndTime())) {
555: availSchedule
556: .removeAll(currentAvailability);
557: change = true;
558: break;
559: }
560: }
561: } else {
562: change = true;
563: }
564:
565: if (change) {
566: //Don't iterate over schedule directly because Schedule doesn't
567: //support iterator().
568: for (Iterator iterator = new ArrayList(aa
569: .getSchedule()).iterator(); iterator
570: .hasNext();) {
571: ScheduleElement avail = (ScheduleElement) iterator
572: .next();
573: availSchedule.add(ldmf
574: .newAssignedAvailabilityElement(
575: receivingAsset, avail
576: .getStartTime(), avail
577: .getEndTime()));
578: }
579: }
580: }
581: } // end sync block
582:
583: return change;
584: }
585:
586: private boolean fixRelationshipSchedule(AssetTransfer at,
587: AssetAssignment aa, Asset transferringAsset,
588: Asset receivingAsset) {
589: if (!(related(transferringAsset) && related(receivingAsset))) {
590: return false;
591: }
592: if ((aa.isUpdate() || aa.isRepeat())) {
593: // Check whether info already represented in the local assets
594: // No need to publish change if local assets are already current.
595: if (!localScheduleUpdateRequired((HasRelationships) at
596: .getAsset(), (HasRelationships) transferringAsset)
597: && !localScheduleUpdateRequired(
598: (HasRelationships) at.getAssignee(),
599: (HasRelationships) receivingAsset)) {
600: return false;
601: }
602:
603: //Remove existing relationships
604: removeExistingRelationships(at,
605: (HasRelationships) transferringAsset,
606: (HasRelationships) receivingAsset);
607: }
608:
609: // Add transfer relationships to local assets
610: Collection localRelationships = convertToLocalRelationships(at,
611: transferringAsset, receivingAsset);
612:
613: RelationshipSchedule transferringSchedule = ((HasRelationships) transferringAsset)
614: .getRelationshipSchedule();
615: transferringSchedule.addAll(localRelationships);
616:
617: RelationshipSchedule receivingSchedule = ((HasRelationships) receivingAsset)
618: .getRelationshipSchedule();
619: receivingSchedule.addAll(localRelationships);
620:
621: return true;
622: }
623:
624: private boolean localScheduleUpdateRequired(
625: HasRelationships atAsset, HasRelationships localAsset) {
626:
627: if (!atAsset.equals(localAsset)) {
628: throw new IllegalArgumentException(
629: "AssetTransferLP.localScheduleUpdateRequired()"
630: + " attempt to compare different Assets - "
631: + atAsset + " != " + localAsset);
632: }
633:
634: RelationshipSchedule localRelationshipSchedule = localAsset
635: .getRelationshipSchedule();
636:
637: // Can't iterate over a schedule so pull elements into an ArrayList and
638: // iterate over that
639: for (Iterator iterator = new ArrayList(atAsset
640: .getRelationshipSchedule()).iterator(); iterator
641: .hasNext();) {
642: final Relationship relationship = (Relationship) iterator
643: .next();
644:
645: Collection matching = localRelationshipSchedule
646: .getMatchingRelationships(new UnaryPredicate() {
647: public boolean execute(Object obj) {
648: Relationship matchCandidate = (Relationship) obj;
649: return (relationship.equals(matchCandidate));
650: }
651: });
652:
653: if (matching.isEmpty()) {
654: return true;
655: }
656: }
657: return false;
658: }
659:
660: private void removeExistingRelationships(AssetTransfer at,
661: HasRelationships transferringAsset,
662: HasRelationships receivingAsset) {
663:
664: RelationshipSchedule receivingSchedule = receivingAsset
665: .getRelationshipSchedule();
666: RelationshipSchedule transferringSchedule = transferringAsset
667: .getRelationshipSchedule();
668:
669: RelationshipSchedule atRelationshipSchedule = ((HasRelationships) at
670: .getAsset()).getRelationshipSchedule();
671:
672: for (Iterator atIterator = new ArrayList(atRelationshipSchedule)
673: .iterator(); atIterator.hasNext();) {
674: Relationship relationship = (Relationship) atIterator
675: .next();
676:
677: Role role = (relationship.getA().equals(receivingAsset)) ? relationship
678: .getRoleA()
679: : relationship.getRoleB();
680:
681: Collection remove = transferringSchedule
682: .getMatchingRelationships(role, receivingAsset,
683: ETERNITY);
684: transferringSchedule.removeAll(remove);
685:
686: role = (relationship.getA().equals(transferringAsset)) ? relationship
687: .getRoleA()
688: : relationship.getRoleB();
689: remove = receivingSchedule.getMatchingRelationships(role,
690: transferringAsset, ETERNITY);
691: receivingSchedule.removeAll(remove);
692: }
693: }
694:
695: protected Collection convertToLocalRelationships(AssetTransfer at,
696: Asset localTransferringAsset, Asset receivingAsset) {
697: RelationshipSchedule atRelationshipSchedule = ((HasRelationships) at
698: .getAsset()).getRelationshipSchedule();
699: ArrayList atRelationships = new ArrayList(
700: atRelationshipSchedule);
701:
702: ArrayList localRelationships = new ArrayList(atRelationships
703: .size());
704:
705: for (Iterator iterator = atRelationships.iterator(); iterator
706: .hasNext();) {
707: Relationship atRelationship = (Relationship) iterator
708: .next();
709:
710: Asset A = (atRelationship.getA().equals(at.getAsset())) ? localTransferringAsset
711: : receivingAsset;
712: Asset B = (atRelationship.getB().equals(at.getAsset())) ? localTransferringAsset
713: : receivingAsset;
714: Relationship localRelationship = ldmf.newRelationship(
715: atRelationship.getRoleA(), (HasRelationships) A,
716: (HasRelationships) B,
717: atRelationship.getStartTime(), atRelationship
718: .getEndTime());
719: localRelationships.add(localRelationship);
720: }
721:
722: return localRelationships;
723: }
724:
725: // Clear relationship, role and availble schedules to ensure that there
726: // are no dangling references to other organizations.
727: private void clearSchedule(Asset asset) {
728: if (related(asset)) {
729: ((HasRelationships) asset).setRelationshipSchedule(null);
730: }
731:
732: if (asset.getRoleSchedule() != null) {
733: asset.getRoleSchedule().clear();
734:
735: if (asset.getRoleSchedule().getAvailableSchedule() != null) {
736: asset.getRoleSchedule().getAvailableSchedule().clear();
737: }
738: }
739: }
740:
741: private void publishAsset(Asset asset, boolean newAsset,
742: boolean changeRelationshipRequired,
743: boolean changeAvailabilityRequired) {
744:
745: if (newAsset) {
746: rootplan.add(asset);
747: if (logger.isDebugEnabled()) {
748: logger.debug("publishAsset: publish added " + asset
749: + " uid = " + asset.getUID());
750: }
751: } else {
752: boolean publishRequired = false;
753: Collection changes = null;
754:
755: if (changeRelationshipRequired) {
756: changes = new ArrayList();
757: changes
758: .add(new RelationshipSchedule.RelationshipScheduleChangeReport());
759: publishRequired = true;
760: } else if (changeAvailabilityRequired) {
761: publishRequired = true;
762: }
763:
764: if (publishRequired) {
765: if (logger.isDebugEnabled()) {
766: logger.debug("publishAsset: publish changed "
767: + asset + " uid = " + asset.getUID());
768: }
769: rootplan.change(asset, changes);
770: }
771: }
772: }
773: }
|