001: /*
002: * <copyright>
003: *
004: * Copyright 2001-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.lib.vishnu.client;
027:
028: import org.cougaar.lib.param.ParamMap;
029: import org.cougaar.planning.ldm.asset.Asset;
030: import org.cougaar.util.StringKey;
031: import org.cougaar.util.log.Logger;
032:
033: import java.util.ArrayList;
034: import java.util.Collection;
035: import java.util.HashMap;
036: import java.util.HashSet;
037: import java.util.Iterator;
038: import java.util.List;
039: import java.util.Map;
040: import java.util.Set;
041: import java.util.Stack;
042:
043: /**
044: * Keeps track of configuration files <p>
045: * Also has methods for dealing with template tasks and prototypical resources for when in introspective mode.
046: */
047: public class VishnuConfig {
048: private static String SPECS_SUFFIX = ".vsh.xml";
049: private static String GA_SUFFIX = ".ga.xml";
050: private static String OTHER_FORMAT_SUFFIX = ".odf.xml";
051: private static String OTHER_DATA_SUFFIX = ".odd.xml";
052: private static String DFF_SUFFIX = ".dff.xml";
053:
054: public VishnuConfig(ParamMap myParamTable, String pluginName,
055: String clusterName, Logger logger) {
056: this .myParamTable = myParamTable;
057: this .clusterName = clusterName;
058: this .name = pluginName;
059: this .logger = logger;
060: }
061:
062: protected String getClusterName() {
063: return clusterName;
064: }
065:
066: protected ParamMap getMyParams() {
067: return myParamTable;
068: }
069:
070: protected String getName() {
071: return name;
072: }
073:
074: /**
075: * <pre>
076: * Sets the set of template tasks. Template tasks are examined
077: * to create the ObjectFormat for the tasks used in the problem.
078: *
079: * Say 2 tasks are sent to the vishnu bridge, but only one is
080: * used as the template task. If the second task has an indirect
081: * object with an object of a type that is not in the first task,
082: * Vishnu will reject this object when the task is sent as data AND
083: * the specs will not be able to reference the field.
084: *
085: * So it's imperative that the template tasks have all the fields
086: * and all the types that should be used in the problem.
087: *
088: * This may not be that big of a deal in practice, but this function
089: * may have to be overridden.
090: *
091: * </pre>
092: * By default looks at the parameter <code>firstTemplateTasks</code>
093: * to determine how many of the tasks should be sent as templates.
094: */
095: protected List getTemplateTasks(List tasks, int firstTemplateTasks) {
096: List templateTasks = new ArrayList();
097: int size = (tasks.size() < firstTemplateTasks) ? tasks.size()
098: : firstTemplateTasks;
099:
100: for (int i = 0; i < size; i++)
101: templateTasks.add(tasks.get(i));
102: return templateTasks;
103: }
104:
105: /**
106: * <pre>
107: * Using the task list, figure out which assets are relevant to
108: * the problem and return them. For example, if there is a
109: * prep "WITH CargoShip#5" on a task, and you only want decks for that ship,
110: * you could subclass this function and select those decks here.
111: *
112: * NOTE that this could also be achieved by the Vishnu CAPABILITY CRITERION.
113: * In general, that will be a more flexible way to go, if less efficient.
114: *
115: * If you want to do :
116: * getAssetCallback().getSubscription ().getCollection();
117: * instead do :
118: * new HashSet( getAssetCallback().getSubscription ().getCollection());
119: *
120: * </pre>
121: * @param tasks of tasks to use to filter out relevant assets
122: * @return Collection of assets to send to Vishnu
123: */
124: protected Collection getAssetTemplatesForTasks(List tasks,
125: List assetClassName, Collection assetCollection) {
126: return getDistinctAssetTypes(assetClassName, assetCollection);
127: }
128:
129: /**
130: * <pre>
131: * Looks through all assets and finds prototypical instances
132: * of distinct classes.
133: *
134: * Conceptually, if the cluster has 10 trucks and 10 railcars
135: * as assets, we want to return a list of one truck and
136: * one railcar to be used as templates.
137: *
138: * Uses type identification PG to find distinct types.
139: *
140: * </pre>
141: * @return Collection of the asset instances
142: */
143: protected Collection getDistinctAssetTypes(List assetClassName,
144: Collection assetCollection) {
145: Map typeIDToAsset = new HashMap();
146:
147: for (Iterator iter = assetCollection.iterator(); iter.hasNext();) {
148: Asset asset = (Asset) iter.next();
149: String typeID = asset.getTypeIdentificationPG()
150: .getTypeIdentification();
151: StringKey typeKey = new StringKey(typeID);
152:
153: if (!typeIDToAsset.containsKey(typeKey))
154: typeIDToAsset.put(typeKey, asset);
155: }
156:
157: Set distinctAssets = new HashSet(typeIDToAsset.values());
158:
159: // find most-derived common descendant of all assets
160:
161: Object first = distinctAssets.iterator().next();
162: Class firstClass = first.getClass();
163: Class currentClass = firstClass;
164: Stack currentClasses = new Stack();
165: currentClasses.push(currentClass);
166:
167: while ((currentClass = currentClass.getSuperclass()) != java.lang.Object.class) {
168: if (logger.isDebugEnabled())
169: logger.debug(getName()
170: + ".getDistinctAssetTypes : super "
171: + currentClass);
172: currentClasses.push(currentClass);
173: }
174:
175: for (Iterator iter = distinctAssets.iterator(); iter.hasNext();) {
176: Class assetClass = iter.next().getClass();
177:
178: if (assetClass != firstClass) {
179: currentClass = assetClass;
180: Stack otherClasses = new Stack();
181:
182: otherClasses.push(currentClass);
183:
184: while ((currentClass = currentClass.getSuperclass()) != java.lang.Object.class) {
185: if (logger.isDebugEnabled())
186: logger.debug(getName()
187: + ".getDistinctAssetTypes : super "
188: + currentClass);
189: otherClasses.push(currentClass);
190: }
191:
192: currentClasses.retainAll(otherClasses);
193:
194: if (logger.isInfoEnabled()) {
195: for (int i = 0; i < currentClasses.size(); i++)
196: logger
197: .info(getName()
198: + ".getDistinctAssetTypes : shared class "
199: + currentClasses.get(i));
200: }
201: }
202:
203: }
204:
205: // return final name in complete class name, e.g. from org.cougaar.something.ldm.asset.Truck, Truck
206: String classname = "" + currentClasses.get(0);
207: int index = classname.lastIndexOf(".");
208: classname = classname.substring(index + 1, classname.length());
209:
210: assetClassName.add(classname);
211:
212: if (logger.isInfoEnabled()) {
213: for (int i = 0; i < currentClasses.size(); i++)
214: logger.info(getName()
215: + ".getDistinctAssetTypes : result class "
216: + currentClasses.get(i));
217: }
218:
219: if (distinctAssets.isEmpty())
220: logger
221: .error(getName()
222: + ".getDistinctAssetTypes - ERROR? no templates assets?");
223:
224: return distinctAssets;
225: }
226:
227: /**
228: *<pre>
229: * get the file containing the other data object format
230: *
231: * If the parameter "otherDataFormatFile" is set, it will look
232: * for a file in the data directory with a name equal to the
233: * value of the parameter.
234: * Otherwise, looks for a file called <ClusterName>.odf.xml.
235: *
236: * </pre>
237: * @see #getNeededFile
238: * @return filename of other data object format file
239: */
240: protected String getOtherDataFormat() {
241: return getNeededFile("otherDataFormatFile", OTHER_FORMAT_SUFFIX);
242: }
243:
244: /**
245: *<pre>
246: * get the file containing the other data
247: *
248: * If the parameter "otherDataFile" is set, it will look
249: * for a file in the data directory with a name equal to the
250: * value of the parameter.
251: * Otherwise, looks for a file called <ClusterName>.odd.xml.
252: *
253: * </pre>
254: * @see #getNeededFile
255: * @return filename of other data object(s)
256: */
257: protected String getOtherData() {
258: return getNeededFile("otherDataFile", OTHER_DATA_SUFFIX);
259: }
260:
261: /**
262: *<pre>
263: * get the file containing the vishnu scheduling specs
264: *
265: * If the parameter "specsFile" is set, it will look
266: * for a file in the data directory with a name equal to the
267: * value of the parameter.
268: * Otherwise, looks for a file called <ClusterName>.vsh.xml.
269: *
270: * </pre>
271: * @see #getNeededFile
272: * @return filename of specs file
273: */
274: protected String getSpecsFile() {
275: return getNeededFile("specsFile", SPECS_SUFFIX);
276: }
277:
278: /**
279: * <pre>
280: * get the file containing the ga parameters for VISHNU
281: *
282: * If the parameter "gaFile" is set, it will look
283: * for a file in the data directory with a name equal to the
284: * value of the parameter.
285: * Otherwise, looks for a file called <ClusterName>.ga.xml.
286: *
287: * return relative path of env file with which to start the
288: * Vishnu Scheduler.
289: * </pre>
290: * @see #getNeededFile
291: * @return relative path to specs parameters
292: */
293: protected String getGASpecsFile() {
294: return getNeededFile("gaFile", GA_SUFFIX);
295: }
296:
297: protected String getFormatFile() {
298: return getNeededFile("defaultFormat", DFF_SUFFIX);
299: }
300:
301: /**
302: * <pre>
303: * Get file name for input file. If the parameter exists, use it,
304: * otherwise append the defaultSuffix to the cluster name and use that.
305: *
306: * If there are more than one vishnu plugins in a cluster, one should
307: * set the parameter to the name of the file.
308: * </pre>
309: */
310: public String getNeededFile(String paramName, String defaultSuffix) {
311: String envFile = null;
312:
313: try {
314: if (getMyParams().hasParam(paramName)) {
315: envFile = getMyParams().getStringParam(paramName);
316: if (logger.isInfoEnabled())
317: logger
318: .info("VishnuConfig.getNeededFile - envFile = "
319: + envFile
320: + " - paramName - "
321: + paramName);
322: } else
323: envFile = getClusterName() + defaultSuffix; // no parameter, try default
324: } catch (Exception pe) {
325: }
326:
327: return envFile;
328: }
329:
330: protected ParamMap myParamTable;
331: protected String clusterName;
332: protected String name;
333: protected Logger logger;
334: }
|