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.core.qos.frame;
028:
029: import java.util.Iterator;
030: import java.util.Map;
031:
032: import org.cougaar.core.util.UID;
033: import org.cougaar.core.util.UniqueObject;
034: import org.cougaar.util.log.Logger;
035: import org.cougaar.util.log.Logging;
036:
037: /**
038: * This class represents a kind of visitor pattern that can be used to
039: * find the value of a slot at runtime. It consists of an ordered
040: * series of Forks and a slot. Each Fork refers to a relation and a
041: * role. This allows any given frame to traverse a Path to a related
042: * frame, arbitrarily far away. When the final frame in the path is
043: * reached, the given slot value is retrieved.
044: */
045: public class Path implements UniqueObject {
046: private transient Logger log = Logging.getLogger(getClass()
047: .getName());
048:
049: static class Fork implements java.io.Serializable {
050: private String role;
051: private String relation;
052:
053: Fork(String role, String relation) {
054: this .role = role;
055: this .relation = relation;
056: }
057: }
058:
059: private final UID uid;
060: private String name;
061: private Fork[] forks;
062: private String override_slot;
063:
064: public Path(UID uid, String name, Fork[] forks, String slot) {
065: this .name = name;
066: this .forks = forks;
067: this .override_slot = slot;
068: this .uid = uid;
069: }
070:
071: String getName() {
072: return name;
073: }
074:
075: Object getValue(DataFrame root, String requestor_slot) {
076: synchronized (root.get_rlock()) {
077: root.clearRelationDependencies(requestor_slot);
078: return getNextValue(root, root, 0, requestor_slot);
079: }
080: }
081:
082: private Object getNextValue(DataFrame root, DataFrame frame,
083: int index, String requestor_slot) {
084: String slot = override_slot != null ? override_slot
085: : requestor_slot;
086: if (log.isDebugEnabled())
087: log.debug("Walking path " + name + " index=" + index
088: + " frame=" + frame + " length=" + forks.length);
089:
090: if (index == forks.length) {
091: Object value = frame.getValue(slot);
092: if (log.isDebugEnabled())
093: log.debug("End of path at " + frame + " value of "
094: + slot + " = " + value);
095: return value;
096: }
097:
098: Fork entry = forks[index];
099: Map frames = frame.findRelationshipFrames(entry.role,
100: entry.relation);
101: if (frames == null) {
102: if (log.isDebugEnabled())
103: log.debug(frame + " has no relations of type "
104: + entry.relation + " role=" + entry.role);
105: return null;
106: }
107:
108: if (log.isDebugEnabled())
109: log.debug(frames.size() + " matches for relation "
110: + entry.relation + " role=" + entry.role);
111:
112: Iterator itr = frames.entrySet().iterator();
113: while (itr.hasNext()) {
114: Map.Entry e = (Map.Entry) itr.next();
115: RelationFrame rframe = (RelationFrame) e.getKey();
116: synchronized (rframe) {
117: // Don't allow relationship changes during the lookup.
118: root.addRelationDependency(rframe, requestor_slot);
119: DataFrame next = (DataFrame) e.getValue();
120: Object result = getNextValue(root, next, ++index, slot);
121: if (result != null) {
122: root.addRelationSlotDependency(next,
123: requestor_slot, slot);
124: return result;
125: }
126:
127: // This tree failed
128: root.removeRelationDependency(rframe, requestor_slot);
129: }
130: if (index == forks.length)
131: return null;
132: }
133: return null;
134: }
135:
136: // UniqueObject
137: public UID getUID() {
138: return uid;
139: }
140:
141: public void setUID(UID uid) {
142: if (!uid.equals(this .uid))
143: throw new RuntimeException("UID already set");
144: }
145: }
|