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: */package org.cougaar.tools.csmart.core.cdata;
026:
027: import org.cougaar.planning.plugin.asset.AssetDataCallback;
028: import org.cougaar.planning.ldm.asset.NewPropertyGroup;
029: import org.cougaar.planning.ldm.asset.PropertyGroup;
030: import org.cougaar.tools.csmart.ui.viewer.CSMART;
031: import org.cougaar.util.ConfigFinder;
032: import org.cougaar.util.TimeSpan;
033: import org.cougaar.util.log.Logger;
034:
035: import java.text.DateFormat;
036: import java.text.ParseException;
037: import java.util.ArrayList;
038: import java.util.Collection;
039: import java.util.Iterator;
040: import java.util.List;
041:
042: /**
043: * AssetDataCallbackImpl.java
044: *
045: * Implements {@link AssetDataCallback}. This class is
046: * the guts behind parsing a prototype-dat.ini file. Some
047: * of the methods are implemented to do what we need, meaning
048: * the original callback was for actually creating a valid
049: * asset object where we just want to parse the data. Because
050: * of that, some methods may look to be named weird, based on
051: * their actual function.
052: * <br><br>
053: * Created: Fri Mar 8 12:40:31 2002
054: *
055: */
056:
057: public class AssetDataCallbackImpl implements AssetDataCallback {
058: private AgentAssetData assetData = null;
059: private DateFormat myDateFormat = DateFormat.getInstance();
060: private transient Logger log = null;
061: private String agentName;
062:
063: /**
064: * Creates a new <code>AssetDataCallbackImpl</code> instance.
065: *
066: */
067: public AssetDataCallbackImpl(String agentName) {
068: this .agentName = agentName;
069: log = CSMART.createLogger(this .getClass().getName());
070: }
071:
072: // implementation of org.cougaar.planning.plugin.asset.AssetDataCallback interface
073:
074: /**
075: * Parses out the correct type. Collections
076: * are enclosed in '< >' and Measures start with '/'
077: *
078: * @param type String with type to be parsed
079: * @return a parsed type as a <code>String</code> value
080: */
081: public String getType(String type) {
082: return type;
083: // int i;
084: // if ((i = type.indexOf("<")) > -1) { // deal with collections
085: // int j = type.lastIndexOf(">");
086: // return getType(type.substring(0, i).trim()); // deal with measures
087: // } else if ((i = type.indexOf("/")) > -1) {
088: // return getType(type.substring(0, i).trim());
089: // } else {
090: // return type;
091: // }
092: }
093:
094: /**
095: * Gets the <code>AgentAssetData</code> created with this callback.
096: * If the <code>AgentAssetData</code> has not been
097: * created yet, null is returned.
098: *
099: * @return a current <code>AgentAssetData</code> object
100: */
101: public AgentAssetData getAgentAssetData() {
102: if (log.isWarnEnabled() && assetData == null) {
103: log.warn("Warning: assetData is null");
104: }
105: return assetData;
106: }
107:
108: /**
109: * Gets an instance of the <code>ConfigFinder</code> for the CSMART module
110: *
111: * @return a valid <code>ConfigFinder</code> instance
112: */
113: public ConfigFinder getConfigFinder() {
114: return ConfigFinder.getInstance("csmart");
115: }
116:
117: /**
118: * Creates an <code>AgentAssetData</code> and assigns
119: * its class name.
120: *
121: * @param assetClassName - Name of the Asset Class
122: */
123: public void createMyLocalAsset(String assetClassName) {
124: if (log.isDebugEnabled()) {
125: log.debug("Creating Asset of class: " + assetClassName);
126: }
127: assetData = new AgentAssetData(null);
128: assetData.setAssetClass(assetClassName);
129: assetData.setIniFormat(AgentAssetData.NEW_FORMAT);
130: }
131:
132: /**
133: * Checks if a local asset exists.
134: *
135: * @return a <code>boolean</code> value
136: */
137: public boolean hasMyLocalAsset() {
138: return (assetData != null);
139: }
140:
141: /**
142: * Creates a <code>PropGroupData</code> with the given name
143: *
144: * @param propGroupName Name of the new property group
145: * @exception Exception if an error occurs
146: */
147: public NewPropertyGroup createPropertyGroup(String propGroupName)
148: throws Exception {
149: if (log.isDebugEnabled()) {
150: log.debug("Create PropertyGroup: " + propGroupName);
151: }
152: return new PropGroupData(propGroupName);
153: }
154:
155: /**
156: * Parses the given expression.
157: *
158: * @param type Unparsed Type(s)
159: * @param arg Unparsed Argument(s)
160: * @return an <code>Object</code> value
161: */
162: public Object parseExpr(String type, String arg) {
163: int i;
164:
165: type = type.trim();
166: arg = arg.trim();
167:
168: if ((i = type.indexOf("<")) >= 0) {
169: int j = type.lastIndexOf(">");
170: String ctype = type.substring(0, i).trim();
171: String etype = type.substring(i + 1, j).trim();
172: Collection c = null;
173: if (ctype.equals("Collection") || ctype.equals("List")) {
174: c = new ArrayList();
175: } else {
176: throw new RuntimeException(
177: "Unparsable collection type: " + type);
178: }
179:
180: List coll = org.cougaar.util.CSVUtility.parseToList(arg);
181: for (Iterator iterator = coll.iterator(); iterator
182: .hasNext();) {
183: String str = (String) iterator.next();
184: c.add(parseE(etype, str));
185: }
186:
187: return c;
188: } else if ((i = type.indexOf("/")) >= 0) {
189: // Handle Measure Object Here.
190: return arg;
191: } else {
192: return arg;
193: }
194: }
195:
196: private Object parseE(String type, String arg) {
197: int i;
198:
199: type = type.trim();
200: arg = arg.trim();
201:
202: if ((i = type.indexOf("<")) >= 0) {
203: int j = type.lastIndexOf(">");
204: String ctype = type.substring(0, i).trim();
205: String etype = type.substring(i + 1, j).trim();
206: Collection c = null;
207: if (ctype.equals("Collection") || ctype.equals("List")) {
208: c = new ArrayList();
209: } else {
210: throw new RuntimeException(
211: "Unparsable collection type: " + type);
212: }
213:
214: List coll = org.cougaar.util.CSVUtility.parseToList(arg);
215: for (Iterator iterator = coll.iterator(); iterator
216: .hasNext();) {
217: String o = (String) iterator.next();
218: c.add(parseE(etype, o));
219: }
220: return c;
221: } else if ((i = type.indexOf("/")) >= 0) {
222: // Measure Object. How should we handle this?
223: return arg;
224: } else {
225: return arg;
226: }
227: }
228:
229: /**
230: * Parses a Date
231: *
232: * @param dateString Date string to parse
233: * @return a <code>long</code> value
234: * @exception ParseException if an error occurs
235: */
236: public long parseDate(String dateString) throws ParseException {
237: if (log.isDebugEnabled()) {
238: log.debug("Parsing Date: " + dateString);
239: }
240: return myDateFormat.parse(dateString).getTime();
241: }
242:
243: /**
244: * This is a "creative interpretation" of the callSetter method.
245: * This implementation Creates the PGPropData for the passed in
246: * name.
247: *
248: * @param setterName Not used
249: * @param type Type of <code>PGPropData</code>
250: * @param arguments Arguments for the <code>PGPropData</code>
251: */
252: public void callSetter(NewPropertyGroup propertyGroup,
253: String setterName, String type, Object[] arguments) {
254: PropGroupData propGroup = (PropGroupData) propertyGroup;
255: String name = setterName.substring(3);
256:
257: if (log.isWarnEnabled() && arguments.length > 1) {
258: log.warn("Arguments is greater than one!");
259: }
260:
261: PGPropData data = new PGPropData();
262: data.setName(name);
263:
264: int i;
265: if ((i = type.indexOf("<")) >= 0) {
266: int j = type.lastIndexOf(">");
267: data.setType(type.substring(0, i).trim());
268: data.setSubType(type.substring(i + 1, j).trim());
269: } else {
270: data.setType(type);
271: }
272:
273: // HACK 10.0 ClusterIdentifier->MessageAddress
274: if (name.equals("ClusterIdentifier")) {
275: if (log.isWarnEnabled()) {
276: log
277: .warn("ClusterIdentifier obsolete. Replacing with MessageAddress.");
278: }
279: data.setName("MessageAddress");
280: data.setType("MessageAddress");
281: }
282:
283: if (data.getName().equals("HomeLocation")) {
284: data.setValue(parseHomeLocation((String) arguments[0]));
285: // This is a serious hack! For now, can not see any way around it.
286: // The bug this is trying to fix is that in the INI files,
287: // the ItemIdentification is not always the Agent name.
288: // We need to correct this or there will be runtime issues.
289: } else if (name.equals("ItemIdentification")
290: && !arguments[0].equals(agentName)) {
291: data.setValue(agentName);
292: } else {
293: if (arguments[0] instanceof Collection) {
294: Iterator iter = ((Collection) arguments[0]).iterator();
295: PGPropMultiVal multi = new PGPropMultiVal();
296: while (iter.hasNext()) {
297: multi.addValue((String) iter.next());
298: }
299: data.setValue(multi);
300: } else {
301: data.setValue(arguments[0]);
302: }
303: }
304: propGroup.addProperty(data);
305: }
306:
307: private String parseHomeLocation(String argument) {
308: return argument.substring(0, argument.indexOf(","));
309: }
310:
311: /**
312: * Not implemented
313: *
314: * @param latStr
315: * @param lonStr
316: */
317: public void setLocationSchedule(String latStr, String lonStr) {
318: // Not really sure what to do here.
319: }
320:
321: /**
322: * Returns the default start time
323: * {@link TimeSpan#MIN_VALUE}
324: *
325: * @return a <code>long</code> value
326: */
327: public long getDefaultStartTime() {
328: return TimeSpan.MIN_VALUE;
329: }
330:
331: /**
332: * Returns the default end time
333: * {@link TimeSpan#MAX_VALUE}
334: *
335: * @return a <code>long</code> value
336: */
337: public long getDefaultEndTime() {
338: return TimeSpan.MAX_VALUE;
339: }
340:
341: /**
342: * Adds a new Property to the asset.
343: * This method is required by the callback
344: *
345: */
346: public void addPropertyToAsset(PropertyGroup propertyGroup) {
347: PropGroupData propGroup = (PropGroupData) propertyGroup;
348: if (log.isDebugEnabled()) {
349: log.debug("Adding Property group: " + propGroup.getName()
350: + " to asset");
351: }
352: assetData.addPropertyGroup(propGroup);
353: }
354:
355: /**
356: * Adds a new Relationship to the asset.
357: *
358: * @param typeId Type Id for the new Relationship
359: * @param itemId Item Id for the new Relationship
360: * @param supportedAgent Agent supported in this relationship
361: * @param type Type of Relationship
362: * @param start Start time for new Relationship
363: * @param end Stop time for new Relationship
364: */
365: public void addRelationship(String typeId, String itemId,
366: String supportedAgent, String type, long start, long end) {
367:
368: RelationshipData rd = new RelationshipData();
369: rd.setItemId(itemId);
370: rd.setTypeId(typeId);
371: rd.setType(type);
372: rd.setStartTime(start);
373: rd.setEndTime(end);
374: rd.setSupported(supportedAgent);
375: assetData.addRelationship(rd);
376: }
377:
378: }// AssetDataCallbackImpl
|