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: package org.cougaar.core.qos.frame;
027:
028: import java.util.Collection;
029: import java.util.HashSet;
030: import java.util.Set;
031:
032: import org.cougaar.core.blackboard.IncrementalSubscription;
033: import org.cougaar.core.qos.frame.aggregator.SlotAggregator;
034: import org.cougaar.core.service.BlackboardService;
035: import org.cougaar.util.UnaryPredicate;
036:
037: /**
038: * If a child frame is added or removed, redo all relevant calculations on
039: * related parents. Similary if childSlot was given and that slot was changed in
040: * a child frame.
041: *
042: * For now ignore the relation frames, though if they're changing that will have
043: * to be taken into account.
044: *
045: */
046: public class SlotAggregation {
047: private final String slot;
048: private final String relatedSlot;
049: private final String relation;
050: private final SlotAggregator aggregator;
051: private final FrameSet frameset;
052: private final String role;
053: private final String otherRole;
054: private IncrementalSubscription frameSub, relationshipSub;
055:
056: public SlotAggregation(FrameSet frameset, String slot,
057: String relatedSlot, String relation, String role,
058: String className) throws Exception {
059: // Assume "parent" role for now
060: this .role = role == null ? "parent" : role;
061: this .otherRole = this .role.equals("parent") ? "child"
062: : "parent";
063:
064: Class aggregatorClass = null;
065: if (className.indexOf('.') < 0) {
066: // No package, check the frameset's
067: String cname = frameset.getPackageName() + "." + className;
068: try {
069: aggregatorClass = Class.forName(cname);
070: } catch (ClassNotFoundException ex) {
071: // Not in the frameset's package, try our package
072: cname = getClass().getPackage().getName()
073: + ".aggregator." + className;
074: try {
075: aggregatorClass = Class.forName(cname);
076: } catch (ClassNotFoundException ex2) {
077: // ignore
078: }
079: }
080: }
081: if (aggregatorClass == null) {
082: // fully qualified name: allow this one to throw an Exception out of the call
083: aggregatorClass = Class.forName(className);
084: }
085: this .aggregator = (SlotAggregator) aggregatorClass
086: .newInstance();
087: this .slot = slot;
088: this .relatedSlot = relatedSlot;
089: this .relation = relation;
090: this .frameset = frameset;
091: }
092:
093: public String getRelatedSlot() {
094: return relatedSlot;
095: }
096:
097: public String getSlot() {
098: return slot;
099: }
100:
101: public String getRelation() {
102: return relation;
103: }
104:
105: public String getRole() {
106: return role;
107: }
108:
109: private void addToUpdateSet(Object x, Set<DataFrame> framesToUpdate) {
110: DataFrame frame = (DataFrame) x;
111: Set<DataFrame> parents = frame.findRelations(role, relation);
112: if (parents != null) {
113: framesToUpdate.addAll(parents);
114: }
115: }
116:
117: /**
118: * Collect the set of changed parent frames and invoke
119: * the updater on each.
120: */
121: public void execute(BlackboardService bbs) {
122: if (frameSub == null) {
123: setupSubscriptions(bbs);
124: }
125: Set<DataFrame> framesToUpdate = new HashSet<DataFrame>();
126: if (frameSub.hasChanged()) {
127: Collection addedFrames = frameSub.getAddedCollection();
128: for (Object x : addedFrames) {
129: addToUpdateSet(x, framesToUpdate);
130: }
131:
132: Collection removedFrames = frameSub.getRemovedCollection();
133: for (Object x : removedFrames) {
134: addToUpdateSet(x, framesToUpdate);
135: }
136:
137: if (relatedSlot != null) {
138: Collection changedFrames = frameSub
139: .getChangedCollection();
140: for (Object x : changedFrames) {
141: Set changeReports = frameSub.getChangeReports(x);
142: boolean relevant = false;
143: for (Frame.Change change : (Set<Frame.Change>) changeReports) {
144: if (change.getSlotName().equals(relatedSlot)) {
145: relevant = true;
146: break;
147: }
148: }
149: if (relevant)
150: addToUpdateSet(x, framesToUpdate);
151: }
152: }
153: }
154:
155: if (relationshipSub.hasChanged()) {
156: Collection addedFrames = relationshipSub
157: .getAddedCollection();
158: for (Object x : addedFrames) {
159: RelationFrame rframe = (RelationFrame) x;
160: if (role.equals("parent")) {
161: framesToUpdate.add(frameset
162: .getRelationshipParent(rframe));
163: } else {
164: framesToUpdate.add(frameset
165: .getRelationshipChild(rframe));
166: }
167: }
168:
169: Collection removedFrames = relationshipSub
170: .getRemovedCollection();
171: for (Object x : removedFrames) {
172: RelationFrame rframe = (RelationFrame) x;
173: if (role.equals(FrameSet.PARENT)) {
174: framesToUpdate.add(frameset
175: .getRelationshipParent(rframe));
176: } else {
177: framesToUpdate.add(frameset
178: .getRelationshipChild(rframe));
179: }
180: }
181: }
182:
183: for (DataFrame frame : framesToUpdate) {
184: if (frame == null)
185: continue;
186: Set<DataFrame> children = frame.findRelations(otherRole,
187: relation);
188: aggregator.updateSlotValue(frame, children, this );
189: }
190: }
191:
192: public void setupSubscriptions(BlackboardService bbs) {
193: if (frameSub == null) {
194: frameSub = (IncrementalSubscription) bbs
195: .subscribe(new FramePredicate());
196: }
197: if (relationshipSub == null) {
198: relationshipSub = (IncrementalSubscription) bbs
199: .subscribe(new RelationPredicate());
200: }
201: }
202:
203: private class FramePredicate implements UnaryPredicate {
204: private final String attribute = otherRole + "-prototype";
205: private Class relatedFrameClass;
206:
207: public boolean execute(Object o) {
208: if (!(o instanceof DataFrame))
209: return false;
210: DataFrame frame = (DataFrame) o;
211: if (frameset != frame.getFrameSet())
212: return false;
213:
214: if (relatedFrameClass == null) {
215: PrototypeFrame relationProto = frameset
216: .findPrototypeFrame(relation);
217: String type = relationProto.getAttribute(attribute);
218: relatedFrameClass = frameset.classForPrototype(type);
219: }
220: Class frameClass = frame.getClass();
221: return relatedFrameClass.isAssignableFrom(frameClass);
222: }
223: }
224:
225: private class RelationPredicate implements UnaryPredicate {
226: private Class relationshipClass;
227:
228: public boolean execute(Object o) {
229: if (!(o instanceof DataFrame))
230: return false;
231: DataFrame frame = (DataFrame) o;
232: if (frameset != frame.getFrameSet())
233: return false;
234:
235: if (relationshipClass == null) {
236: PrototypeFrame relationProto = frameset
237: .findPrototypeFrame(relation);
238: relationshipClass = frameset
239: .classForPrototype(relationProto);
240: }
241: Class frameClass = frame.getClass();
242: return relationshipClass.isAssignableFrom(frameClass);
243: }
244: }
245: }
|