001: /*
002: * <copyright>
003: *
004: * Copyright 2002-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.servicediscovery.description;
028:
029: import java.util.Iterator;
030:
031: import org.cougaar.planning.ldm.plan.Role;
032: import org.cougaar.servicediscovery.Constants;
033: import org.cougaar.servicediscovery.description.Lineage;
034: import org.cougaar.servicediscovery.description.ProviderCapabilities;
035: import org.cougaar.servicediscovery.description.ProviderCapability;
036: import org.cougaar.servicediscovery.description.ServiceInfo;
037: import org.cougaar.servicediscovery.util.UDDIConstants;
038:
039: import org.cougaar.util.log.Logger;
040: import org.cougaar.util.log.Logging;
041:
042: public class LineageEchelonScorer implements ServiceInfoScorer,
043: java.io.Serializable {
044: private static Logger logger = Logging
045: .getLogger(LineageEchelonScorer.class);
046: String myMinimumEchelon = null;
047: Role myRole;
048: Lineage myCommandLineage;
049: String myAgentName = null;
050:
051: public static String getMinimumEchelonOfSupport(
052: ProviderCapabilities capabilities, Role role) {
053: int providedEchelonIndex = -1;
054:
055: if (capabilities != null) {
056: ProviderCapability providerCapability = capabilities
057: .getCapability(role);
058:
059: if (providerCapability != null) {
060: providedEchelonIndex = Constants.MilitaryEchelon
061: .echelonOrder(providerCapability.getEchelon());
062: }
063: }
064:
065: return Constants.MilitaryEchelon.ECHELON_ORDER[providedEchelonIndex + 1];
066: }
067:
068: public LineageEchelonScorer(Lineage lineage, String minimumEchelon,
069: Role role) {
070: setLineage(lineage);
071: myMinimumEchelon = minimumEchelon;
072: myRole = role;
073: }
074:
075: public LineageEchelonScorer() {
076: myCommandLineage = null;
077: myRole = null;
078: myMinimumEchelon = null;
079: }
080:
081: public void setLineage(Lineage lineage) {
082: if (myCommandLineage != null) {
083: logger
084: .warn("setLineage: ignoring attempt to change lineage from "
085: + myCommandLineage + " to " + lineage);
086: } else if (lineage.getType() == Lineage.OPCON) {
087: myCommandLineage = lineage;
088: myAgentName = myCommandLineage.getLeaf();
089: } else {
090: logger.warn("setLineage: ignoring " + lineage
091: + ". Must be OPCON lineage.");
092: }
093: }
094:
095: public Lineage getLineage() {
096: return myCommandLineage;
097: }
098:
099: public void setRole(Role role) {
100: if (myRole != null) {
101: logger
102: .warn("setRole: ignoring attempt to change Role from "
103: + myRole + " to " + role);
104: } else {
105: myRole = role;
106: }
107: }
108:
109: public Role getRole() {
110: return myRole;
111: }
112:
113: public void setMinimumEchelon(String echelon) {
114: if (myMinimumEchelon != null) {
115: logger
116: .warn("setMinimum: ignoring attempt to change minimum echelon from "
117: + myMinimumEchelon + " to " + echelon);
118: } else {
119: String verifiedEchelon = Constants.MilitaryEchelon
120: .mapToMilitaryEchelon(echelon);
121:
122: if (verifiedEchelon == Constants.MilitaryEchelon.UNDEFINED) {
123: logger
124: .warn("setMinimumEchelonOfSupport: unrecognized echelon "
125: + echelon
126: + ". Ignoring attempt to change minimum echelon from "
127: + myMinimumEchelon + " to " + echelon);
128: } else {
129: myMinimumEchelon = verifiedEchelon;
130: }
131: }
132: }
133:
134: public String getMinimumEchelon() {
135: return myMinimumEchelon;
136: }
137:
138: /**
139: * Will be called by Matchmaker for each ServiceInfo. Returned score will
140: * be added to the ScoredServiceDescription associated with the Service.
141: *
142: * @return int representing score. Client responsible for
143: * understanding the precise value. Current usage assumes lowest value >= 0
144: * is the best. Values less than 0 are not suitable.
145: *
146: */
147: public int scoreServiceInfo(ServiceInfo serviceInfo) {
148: int echelonScore = getEchelonScore(serviceInfo,
149: getMinimumEchelon());
150:
151: if (logger.isDebugEnabled()) {
152: logger.debug("scoreServiceProvider: echelon score "
153: + echelonScore);
154: }
155: if (echelonScore < 0) {
156: return -1;
157: }
158:
159: int lineageScore = getLineageScore(serviceInfo);
160: if (logger.isDebugEnabled()) {
161: logger.debug("scoreServiceProvider: lineage score "
162: + lineageScore);
163: }
164: if (lineageScore < 0) {
165: return -1;
166: } else {
167: lineageScore = 100 * lineageScore;
168: }
169:
170: return echelonScore + lineageScore;
171: }
172:
173: protected int getEchelonScore(ServiceInfo serviceInfo,
174: String requestedEchelonOfSupport) {
175: int requestedEchelonOrder = Constants.MilitaryEchelon
176: .echelonOrder(requestedEchelonOfSupport);
177:
178: if (requestedEchelonOrder == -1) {
179: if (logger.isWarnEnabled())
180: logger.warn(myAgentName
181: + " getEchelonScore() - invalid echelon "
182: + requestedEchelonOfSupport);
183: return 0;
184: }
185:
186: int serviceEchelonOrder = -1;
187:
188: for (Iterator iterator = serviceInfo
189: .getServiceClassifications().iterator(); iterator
190: .hasNext();) {
191: ServiceClassification classification = (ServiceClassification) iterator
192: .next();
193: if (classification.getClassificationSchemeName().equals(
194: UDDIConstants.MILITARY_ECHELON_SCHEME)) {
195:
196: String serviceEchelon = classification
197: .getClassificationCode();
198: serviceEchelonOrder = Constants.MilitaryEchelon
199: .echelonOrder(serviceEchelon);
200: break;
201: }
202: }
203:
204: if (serviceEchelonOrder == -1) {
205: if (logger.isInfoEnabled()) {
206: logger
207: .info(myAgentName
208: + ": Ignoring service with a bad echelon of support: "
209: + serviceEchelonOrder
210: + " for provider: "
211: + serviceInfo.getProviderName());
212: }
213: return -1;
214: }
215: if (serviceEchelonOrder < requestedEchelonOrder) {
216: if (logger.isInfoEnabled()) {
217: logger
218: .info(myAgentName
219: + ": Ignoring service with a lower echelon of support: "
220: + serviceEchelonOrder
221: + " for provider: "
222: + serviceInfo.getProviderName());
223: }
224: return -1;
225: } else {
226: return (serviceEchelonOrder - requestedEchelonOrder);
227: }
228: }
229:
230: protected int getLineageScore(ServiceInfo serviceInfo) {
231: if (myCommandLineage == null) {
232: if (logger.isWarnEnabled()) {
233: logger
234: .warn(myAgentName
235: + ": in getLineageScore, has no command lineage");
236: }
237: return -1;
238: }
239:
240: //if there are multiple SCAs, return the minimum distance
241: //among them
242: int minHops = Integer.MAX_VALUE;
243:
244: for (Iterator iterator = serviceInfo
245: .getServiceClassifications().iterator(); iterator
246: .hasNext();) {
247: ServiceClassification classification = (ServiceClassification) iterator
248: .next();
249: if (classification.getClassificationSchemeName().equals(
250: UDDIConstants.SUPPORT_COMMAND_ASSIGNMENT)) {
251: int hops = myCommandLineage.countHops(myAgentName,
252: classification.getClassificationName());
253: if (hops != -1) {
254: minHops = Math.min(minHops, hops);
255: }
256: }
257: }
258:
259: if (minHops == Integer.MAX_VALUE) {
260: if (logger.isInfoEnabled()) {
261: logger.info(myAgentName
262: + ": in getLineageScore, local lineage "
263: + myCommandLineage
264: + " does not intersect with provider's SCA "
265: + " for provider "
266: + serviceInfo.getProviderName());
267: }
268: return -1;
269: } else
270: return minHops;
271: }
272:
273: public boolean equals(Object o) {
274: if (o instanceof LineageEchelonScorer) {
275: LineageEchelonScorer scorer = (LineageEchelonScorer) o;
276:
277: return ((scorer.getMinimumEchelon()
278: .equals(getMinimumEchelon()))
279: && (scorer.getRole().equals(getRole())) && (scorer
280: .getLineage().equals(getLineage())));
281: } else {
282: return false;
283: }
284: }
285:
286: public String toString() {
287: return "Role: " + myRole + " MinimumEchelon: "
288: + myMinimumEchelon + " CommandLineage: "
289: + myCommandLineage;
290: }
291:
292: }
|