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.custom;
027:
028: import com.bbn.vishnu.scheduling.Resource;
029: import com.bbn.vishnu.scheduling.SchedulingData;
030: import org.apache.xerces.dom.DocumentImpl;
031: import org.apache.xml.serialize.OutputFormat;
032: import org.apache.xml.serialize.XMLSerializer;
033: import org.cougaar.lib.vishnu.client.XMLizer;
034: import org.cougaar.planning.ldm.asset.Asset;
035: import org.cougaar.planning.ldm.plan.Task;
036: import org.cougaar.planning.ldm.plan.Verb;
037: import org.cougaar.util.log.Logger;
038: import org.w3c.dom.Document;
039: import org.w3c.dom.Element;
040:
041: import java.io.FileNotFoundException;
042: import java.io.FileOutputStream;
043: import java.io.IOException;
044: import java.io.OutputStream;
045: import java.util.Collection;
046: import java.util.Iterator;
047: import java.util.List;
048:
049: /**
050: * Create either an XML document in the Vishnu Data format or Vishnu objects from ALP objects. <p>
051: *
052: * <p>
053: */
054: public class CustomDataXMLize implements XMLizer, DirectTranslator {
055: /**
056: * Chooses whether to use an XMLDataHelper or a DirectDataHelper depending on the setting of
057: * <code>direct</code>.
058: *
059: * @param direct - do direct Cougaar->Vishnu Object translation, no XML
060: */
061: public CustomDataXMLize(boolean direct, Logger logger) {
062: this .direct = direct;
063:
064: if (!direct)
065: dataHelper = new XMLDataHelper(logger);
066: this .logger = logger;
067: }
068:
069: /**
070: * Called from prepareVishnuObjects, creates DirectDataHelper
071: *
072: * @see CustomVishnuAllocatorPlugin#prepareVishnuObjects
073: * @param formatDoc - given to DirectDataHelper, so that it can figure out field attributes
074: * @param schedData - allows creation of Vishnu date fields
075: */
076: public void setFormatDoc(Document formatDoc,
077: SchedulingData schedData) {
078: this .schedData = schedData;
079: dataHelper = new DirectDataHelper(formatDoc, schedData, logger);
080: }
081:
082: /**
083: * Create an XML document from the set of input tasks and resources. <p>
084: *
085: * Called by XMLProcessor.getDataDoc, used in the preparing of the data document. <p>
086: *
087: * @see org.cougaar.lib.vishnu.client.XMLProcessor#getDataDoc
088: * @param items to translate into XML
089: * @param ignoredAssetClassName - ignored
090: **/
091: public Document createDoc(Collection items,
092: Collection changedAssets, String ignoredAssetClassName) {
093: doc = new DocumentImpl();
094: ((XMLDataHelper) dataHelper).setDoc(doc);
095:
096: Element newobjects = createHeader(doc);
097:
098: Element changedobjects = doc.createElement("CHANGEDOBJECTS");
099: Element df = (Element) doc.getElementsByTagName("DATA").item(0);
100: df.appendChild(changedobjects);
101:
102: if (logger.isDebugEnabled())
103: logger.debug("CustomDataXMLize.createDoc - got "
104: + items.size() + " items, " + changedAssets.size()
105: + " changed assets.");
106: if (logger.isDebugEnabled())
107: logger
108: .debug("CustomDataXMLize.createDoc - initially, NEWOBJECTS tag has "
109: + newobjects.getChildNodes().getLength()
110: + " children.");
111:
112: for (Iterator iter = items.iterator(); iter.hasNext();) {
113: Object taskOrAsset = iter.next();
114: Element object = doc.createElement("OBJECT");
115:
116: if (taskOrAsset instanceof Asset) {
117: if (processAsset(object, taskOrAsset)) {
118: boolean changed = changedAssets
119: .contains(taskOrAsset);
120: if (changed) {
121: if (logger.isDebugEnabled())
122: logger
123: .debug("CustomDataXMLize.createDoc - appending "
124: + taskOrAsset
125: + " to changed.");
126: changedobjects.appendChild(object);
127: } else {
128: if (logger.isDebugEnabled())
129: logger
130: .debug("CustomDataXMLize.createDoc - appending "
131: + taskOrAsset + " to new.");
132: newobjects.appendChild(object);
133: }
134: } else if (logger.isDebugEnabled())
135: logger
136: .debug("CustomDataXMLize.createDoc - ignoring asset "
137: + taskOrAsset);
138: } else { // it's a task
139: if (processTask(object, taskOrAsset)) {
140: newobjects.appendChild(object);
141: } else if (logger.isDebugEnabled())
142: logger
143: .debug("CustomDataXMLize.createDoc - ignoring task "
144: + taskOrAsset);
145: }
146: }
147:
148: if (logger.isDebugEnabled())
149: logger.debug("CustomDataXMLize.createDoc - sending "
150: + newobjects.getChildNodes().getLength()
151: + " NEWOBJECTS.");
152:
153: if (writeXMLToFile) {
154: String fileName = "Custom_data_" + numFilesWritten++
155: + ".xml";
156: logger
157: .info("CustomDataXMLize.createDoc - Writing document to file "
158: + fileName);
159: try {
160: FileOutputStream temp = new FileOutputStream(fileName);
161: writeDocToStream(doc, temp);
162: } catch (FileNotFoundException fnfe) { /* never happen */
163: } catch (IOException ioe) { /* never happen */
164: }
165: }
166:
167: return doc;
168: }
169:
170: /** serialize doc to stream */
171: protected void writeDocToStream(Document doc, OutputStream os) {
172: OutputFormat of = new OutputFormat(doc, "UTF-8", true);
173: of.setLineWidth(150);
174:
175: XMLSerializer serializer = new XMLSerializer(os, of);
176:
177: try {
178: serializer.serialize(doc);
179: } catch (IOException ioe) {
180: logger.error("Exception " + ioe, ioe);
181: }
182: }
183:
184: /**
185: * Populate <tt>vishnuTasks/Resources</tt> lists from Cougaar <tt>items</tt>. <p>
186: *
187: * Calls both processTask and processAsset.
188: *
189: * @see #processTask
190: * @see #processAsset
191: */
192: public void createVishnuObjects(List items, Collection changed,
193: List vishnuTasks, List vishnuResources,
194: List changedVishnuResources) {
195:
196: if (logger.isDebugEnabled())
197: logger.debug("CustomDataXMLize.createVishnuObjects - got "
198: + items.size() + " items, " + changed.size()
199: + " changed.");
200:
201: items.addAll(changed);
202:
203: for (Iterator iter = items.iterator(); iter.hasNext();) {
204: Object taskOrAsset = iter.next();
205:
206: if (taskOrAsset instanceof Asset) {
207: Object vishnuObject = new Resource("Asset", schedData);
208: if (processAsset(vishnuObject, taskOrAsset)) {
209: if (changed.contains(taskOrAsset))
210: changedVishnuResources.add(vishnuObject);
211: else
212: vishnuResources.add(vishnuObject);
213: } else if (logger.isDebugEnabled())
214: logger
215: .debug("CustomDataXMLize.createVishnuObjects - ignoring asset "
216: + taskOrAsset);
217: } else { // it's a task
218: Verb verb = ((Task) taskOrAsset).getVerb();
219: // Object vishnuObject = new com.bbn.vishnu.scheduling.Task(verb.toString(), schedData);
220: Object vishnuObject = schedData
221: .newTask(verb.toString());
222: if (processTask(vishnuObject, taskOrAsset)) {
223: vishnuTasks.add(vishnuObject);
224: } else if (logger.isDebugEnabled())
225: logger
226: .debug("CustomDataXMLize.createVishnuObjects - ignoring task "
227: + taskOrAsset);
228: }
229: }
230: }
231:
232: /**
233: * Attach standard header - problem, data, window, and newobjects tags. <p>
234: *
235: * @param doc to add header to
236: * @return the new objects tag to attach all the new objects to
237: */
238: protected Element createHeader(Document doc) {
239: Element root = doc.createElement("PROBLEM");
240: doc.appendChild(root);
241:
242: Element data = doc.createElement("DATA");
243: root.appendChild(data);
244: Element window = doc.createElement("WINDOW");
245: window.setAttribute("starttime", "2000-01-01 00:00:00");
246: window.setAttribute("endtime", "2002-01-01 00:00:00");
247: data.appendChild(window);
248:
249: Element newobjects = doc.createElement("NEWOBJECTS");
250: data.appendChild(newobjects);
251:
252: return newobjects;
253: }
254:
255: /**
256: * Create XML for asset, subclass to add fields
257: *
258: * @param object node representing asset
259: * @param taskOrAsset asset being translated
260: * @return true if should add object to list of new objects
261: */
262: protected boolean processAsset(Object object, Object taskOrAsset) {
263: setType(object, "Asset");
264: return true;
265: }
266:
267: /** if not doing direct translation, set the type of the Element */
268: protected void setType(Object object, String type) {
269: if (!direct)
270: ((Element) object).setAttribute("type", type);
271: }
272:
273: /** set the type, name, and id of the object */
274: protected String setName(String parentType, Object object,
275: Asset asset) {
276: String type = getAssetType(asset);
277: String name = getAssetName(asset);
278:
279: dataHelper.createField(object, parentType, "id", asset.getUID()
280: .toString());
281: dataHelper.createField(object, parentType, "type", type);
282: dataHelper.createField(object, parentType, "name", name);
283:
284: if (logger.isDebugEnabled())
285: logger.debug("CustomDataXMLize.processAsset - asset "
286: + asset.getUID() + " type " + type + " name "
287: + name);
288:
289: return type;
290: }
291:
292: /**
293: * Create XML for task, subclass to add fields
294: *
295: * @param object node representing task
296: * @param taskOrAsset task being translated
297: * @return true if should add object to list of new objects
298: */
299: protected boolean processTask(Object object, Object taskOrAsset) {
300: Task task = (Task) taskOrAsset;
301: String taskName = getTaskName();
302:
303: setType(object, taskName);
304:
305: dataHelper.createField(object, taskName, "id", task.getUID()
306: .toString());
307:
308: return true;
309: }
310:
311: /** Transport by default -- override to use a different name for the task */
312: protected String getTaskName() {
313: return "Transport";
314: }
315:
316: /**
317: * Get the name of the asset <p>
318: *
319: * This will be the item PG's item id. But if this is null, then it will
320: * be the type PG nomenclature + identification.
321: *
322: * @param asset to get name from
323: * @return the name
324: */
325: protected String getAssetName(Asset asset) {
326: String name = "";
327:
328: try {
329: name = //asset.getItemIdentificationPG().getNomenclature() + "-" +
330: asset.getItemIdentificationPG().getItemIdentification();
331: } catch (Exception e) {
332: logger
333: .error("CustomDataXMLize.createDoc - ERROR - no item id pg on "
334: + asset);
335: }
336:
337: if (name == null || name.length() == 0) {
338: try {
339: name = asset.getTypeIdentificationPG()
340: .getNomenclature()
341: + "-"
342: + asset.getTypeIdentificationPG()
343: .getTypeIdentification();
344: } catch (Exception e) {
345: logger
346: .error("CustomDataXMLize.createDoc - ERROR - no type id pg on "
347: + asset);
348: }
349: }
350:
351: return fixName(name);
352: }
353:
354: /**
355: * Get the type of the asset <p>
356: *
357: * If the type PG nomenclature is null, use the type identification.
358: * @param asset to get name from
359: * @return the type
360: */
361: protected String getAssetType(Asset asset) {
362: String name = "";
363:
364: try {
365: name = asset.getTypeIdentificationPG().getNomenclature();
366: } catch (Exception e) {
367: logger
368: .error("CustomDataXMLize.createDoc - ERROR - no type id pg on "
369: + asset);
370: }
371:
372: if (name == null) {
373: try {
374: name = asset.getTypeIdentificationPG()
375: .getTypeIdentification();
376: } catch (Exception e) {
377: logger
378: .error("CustomDataXMLize.createDoc - ERROR - no type id pg on "
379: + asset);
380: }
381: }
382: if (name == null)
383: name = "";
384:
385: return fixName(name);
386: }
387:
388: /** remove XML tags from name -- confuses parsing... */
389: protected String fixName(String name) {
390: if (name.indexOf('<') != -1)
391: name = name.replace('<', '_');
392: if (name.indexOf('>') != -1)
393: name = name.replace('>', '_');
394:
395: return name;
396: }
397:
398: /** document that is created, if producing XML = not direct mode */
399: protected Document doc;
400:
401: protected SchedulingData schedData;
402: protected boolean direct = false;
403: /** the data helper -- comes in two flavors : XML and direct translation */
404: protected DataHelper dataHelper;
405: /** used to form file names when writing XML to a file */
406: protected static int numFilesWritten;
407: /** write XML that's posted to a file */
408: protected boolean writeXMLToFile = false;
409:
410: protected Logger logger;
411: }
|