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.logistics.servlet;
028:
029: import javax.servlet.*;
030: import javax.servlet.http.*;
031:
032: import java.util.Collection;
033: import java.util.Iterator;
034: import java.util.Vector;
035: import java.util.Date;
036:
037: import org.cougaar.core.mts.MessageAddress;
038: import org.cougaar.core.blackboard.CollectionSubscription;
039: import org.cougaar.core.blackboard.Subscription;
040: import org.cougaar.planning.ldm.asset.Asset;
041: import org.cougaar.planning.ldm.asset.ItemIdentificationPG;
042: import org.cougaar.planning.ldm.asset.TypeIdentificationPG;
043: import org.cougaar.logistics.ldm.Constants.Verb;
044: import org.cougaar.glm.ldm.asset.SupplyClassPG;
045: import org.cougaar.logistics.ldm.Constants;
046: import org.cougaar.glm.ldm.asset.Inventory;
047: import org.cougaar.planning.ldm.plan.Task;
048: import org.cougaar.util.UnaryPredicate;
049: import org.cougaar.util.TimeSpanSet;
050:
051: import java.io.*;
052: import java.nio.charset.Charset;
053:
054: import javax.servlet.ServletException;
055: import javax.servlet.ServletOutputStream;
056: import javax.servlet.ServletInputStream;
057: import javax.servlet.http.HttpServlet;
058: import javax.servlet.http.HttpServletRequest;
059: import javax.servlet.http.HttpServletResponse;
060:
061: import org.cougaar.glm.ldm.oplan.Oplan;
062: import org.cougaar.glm.ldm.oplan.OrgActivity;
063: import org.cougaar.glm.ldm.asset.Organization;
064:
065: import org.cougaar.core.servlet.SimpleServletSupport;
066: import org.cougaar.core.util.UID;
067: import org.cougaar.planning.ldm.asset.Asset;
068:
069: import org.cougaar.core.service.AlarmService;
070: import org.cougaar.core.service.LoggingService;
071:
072: import org.cougaar.logistics.plugin.inventory.LogisticsInventoryFormatter;
073: import org.cougaar.logistics.plugin.inventory.LogisticsInventoryPG;
074:
075: public class LogisticsInventoryServlet extends HttpServlet {
076:
077: private SimpleServletSupport support;
078: private AlarmService alarmService;
079: private LoggingService logger;
080: private boolean printOrgActs;
081:
082: public void setSimpleServletSupport(SimpleServletSupport support) {
083: this .support = support;
084: }
085:
086: public void setLoggingService(LoggingService loggingService) {
087: this .logger = loggingService;
088: }
089:
090: public void setAlarmService(AlarmService anAlarmService) {
091: this .alarmService = anAlarmService;
092: }
093:
094: public void setPrintOrgActs(boolean enableOrgActs) {
095: this .printOrgActs = enableOrgActs;
096: }
097:
098: public void doGet(HttpServletRequest request,
099: HttpServletResponse response) throws IOException,
100: ServletException {
101: // create a new "InventoryGetter" context per request
102: InventoryGetter ig = new InventoryGetter(support, alarmService,
103: logger, printOrgActs);
104: ig.execute(request, response);
105: }
106:
107: public void doPut(HttpServletRequest request,
108: HttpServletResponse response) throws IOException,
109: ServletException {
110: // create a new "InventoryGetter" context per request
111: InventoryGetter ig = new InventoryGetter(support, alarmService,
112: logger, printOrgActs);
113: try {
114: ig.execute(request, response);
115: } catch (Exception e) {
116: e.printStackTrace();
117: }
118: }
119:
120: public static String getNomenclature(Inventory inv) {
121: LogisticsInventoryPG logInvPG = null;
122: logInvPG = (LogisticsInventoryPG) inv
123: .searchForPropertyGroup(LogisticsInventoryPG.class);
124: TypeIdentificationPG typeIdPG = logInvPG.getResource()
125: .getTypeIdentificationPG();
126: String nomenclature = typeIdPG.getNomenclature();
127: // String typeId = typeIdPG.getTypeIdentification();
128: String typeId = inv.getItemIdentificationPG()
129: .getItemIdentification();
130: int idx = typeId.indexOf(':');
131: typeId = typeId.substring(idx + 1);
132: if (nomenclature != null) {
133: nomenclature = nomenclature + ":" + typeId;
134: } else {
135: nomenclature = typeId;
136: }
137: if (logInvPG.getIsLevel2()) {
138: nomenclature = typeId;
139: }
140:
141: return nomenclature;
142:
143: }
144:
145: /**
146: * This inner class does all the work.
147: * <p>
148: * A new class is created per request, to keep all the
149: * instance fields separate. If there was only one
150: * instance then multiple simultaneous requests would
151: * corrupt the instance fields (e.g. the "out" stream).
152: * <p>
153: * This acts as a <b>context</b> per request.
154: */
155: private static class InventoryGetter {
156:
157: public String desiredAssetName = "";
158: ServletOutputStream out;
159:
160: /* since "InventoryGetter" is a static inner class, here
161: * we hold onto the support API.
162: *
163: * this makes it clear that InventoryGetter only uses
164: * the "support" from the outer class.
165: */
166: SimpleServletSupport support;
167: AlarmService alarmService;
168: LoggingService logger;
169: boolean printOrgActs;
170:
171: final public static String ASSET = "ASSET";
172: final public static String ASSET_AND_CLASSTYPE = ASSET + ":"
173: + "CLASS_TYPE:";
174:
175: public InventoryGetter(SimpleServletSupport aSupport,
176: AlarmService anAlarmService,
177: LoggingService aLoggingService, boolean enableOrgActs) {
178: this .support = aSupport;
179: this .alarmService = anAlarmService;
180: this .logger = aLoggingService;
181: this .printOrgActs = enableOrgActs;
182: }
183:
184: /*
185: Called when a request is received from a client.
186: Either gets the command ASSET to return the names of all the assets
187: that contain a ScheduledContentPG or
188: gets the name of the asset to plot from the client request.
189: */
190: public void execute(HttpServletRequest req,
191: HttpServletResponse res) throws IOException {
192:
193: LogisticsInventoryPG logInvPG = null;
194: this .out = res.getOutputStream();
195:
196: int len = req.getContentLength();
197: if (len > 0) {
198: //logger.debug("READ from content-length["+len+"]");
199: InputStream in = req.getInputStream();
200: BufferedReader bin = new BufferedReader(
201: new InputStreamReader(in));
202: desiredAssetName = bin.readLine();
203: bin.close();
204: desiredAssetName = desiredAssetName.trim();
205: logger.info("POST DATA: " + desiredAssetName);
206: } else {
207: logger.warn(" No asset to plot");
208: return;
209: }
210:
211: // return list of asset names
212: if (desiredAssetName.equals(ASSET)
213: || desiredAssetName.startsWith(ASSET_AND_CLASSTYPE)) {
214:
215: //DemandObjectPredicate assetNamePredicate;
216: AssetPredicate assetNamePredicate;
217:
218: if (desiredAssetName.startsWith(ASSET_AND_CLASSTYPE)) {
219: String desiredClassType = desiredAssetName
220: .substring(ASSET_AND_CLASSTYPE.length());
221: //assetNamePredicate = new DemandObjectPredicate(desiredClassType);
222: assetNamePredicate = new AssetPredicate(
223: desiredClassType, logger);
224: } else {
225: //assetNamePredicate = new DemandObjectPredicate();
226: assetNamePredicate = new AssetPredicate(logger);
227: }
228:
229: // Asset no demand type handling
230: /***
231: **
232: */
233:
234: Vector assetNames = new Vector();
235: Collection container = support
236: .queryBlackboard(assetNamePredicate);
237: for (Iterator i = container.iterator(); i.hasNext();) {
238: Inventory inv = (Inventory) (i.next());
239:
240: String nomenclature = getNomenclature(inv);
241:
242: /***
243: logInvPG=null;
244: logInvPG = (LogisticsInventoryPG)inv.searchForPropertyGroup(LogisticsInventoryPG.class);
245: TypeIdentificationPG typeIdPG = logInvPG.getResource().getTypeIdentificationPG();
246: String nomenclature = typeIdPG.getNomenclature();
247: // String typeId = typeIdPG.getTypeIdentification();
248: String typeId = inv.getItemIdentificationPG().getItemIdentification();
249: int idx = typeId.indexOf(':');
250: typeId = typeId.substring(idx+1);
251: if (nomenclature != null) {
252: nomenclature = nomenclature + ":" + typeId;
253: }
254: else {
255: nomenclature = typeId;
256: }
257: if(logInvPG.getIsLevel2()) {
258: nomenclature = typeId;
259: }
260: ***/
261:
262: assetNames.addElement(nomenclature);
263: }
264:
265: /***
266: * Below is for Demand Object Predicate
267: * MWD fix and try this out -below
268: * MWD get rid of old commented out above replaced by below
269: * to get demand even where no inventories.
270: ***
271:
272: HashSet assetNamesSet = new HashSet();
273: Collection container = support.queryBlackboard(assetNamePredicate);
274:
275: for (Iterator i = container.iterator(); i.hasNext(); ) {
276: Asset asset = ((Task)(i.next())).getDirectObject();
277: TypeIdentificationPG typeIdPG = asset.getTypeIdentificationPG();
278: String nomenclature = typeIdPG.getNomenclature();
279: String typeId = typeIdPG.getTypeIdentification();
280: if (nomenclature != null)
281: nomenclature = nomenclature + ":" + typeId;
282: else
283: nomenclature = typeId;
284: assetNamesSet.add(nomenclature);
285: }
286:
287: Vector assetNames = new Vector(assetNamesSet);
288: ****/
289:
290: // send the results
291: ObjectOutputStream p = new ObjectOutputStream(out);
292: p.writeObject(assetNames);
293: logger.info("Sent asset names");
294: return;
295: } // end returning list of asset names
296:
297: if (desiredAssetName.startsWith("UID:")) {
298: String desiredAssetUID = desiredAssetName.substring(4);
299: Collection collection = support
300: .queryBlackboard(new AssetUIDPredicate(
301: desiredAssetUID, logger));
302:
303: for (Iterator i = collection.iterator(); i.hasNext();) {
304: Inventory inv = (Inventory) (i.next());
305: logInvPG = null;
306: logInvPG = (LogisticsInventoryPG) inv
307: .searchForPropertyGroup(LogisticsInventoryPG.class);
308: TypeIdentificationPG typeIdPG = logInvPG
309: .getResource().getTypeIdentificationPG();
310: String nomenclature = typeIdPG.getNomenclature();
311: String typeId = typeIdPG.getTypeIdentification();
312: if (nomenclature == null)
313: return;
314: desiredAssetName = nomenclature + ":" + typeId;
315: }
316: } // end getting asset name from UID
317:
318: Date startDay = getStartDate();
319:
320: // get roles and determine if this cluster is a provider (or consumer)
321: //logger.debug("\n****** look for roles for agent \""+support.getEncodedAgentName()+"\"");
322: /**** MWD do we still need to know if we are a provider or not?
323: ** all the role predicate code below
324: RolePredicate rolePred = new RolePredicate(support.getEncodedAgentName());
325: Collection roleCollection = support.queryBlackboard(rolePred);
326:
327: boolean provider = false;
328: if (!roleCollection.isEmpty()) {
329: Organization asset = (Organization) roleCollection.iterator().next();
330:
331: Collection roles = asset.getOrganizationPG().getRoles();
332: if (roles != null) {
333: Iterator i = roles.iterator();
334: while (i.hasNext()) {
335: Role role = (Role)i.next();
336: if (role.getName().endsWith("Provider")) {
337: provider = true;
338: break;
339: }
340: }
341: }
342: }
343:
344: *****/
345:
346: // get asset and tasks we need to create the inventory
347: logger.debug("Getting Inventory w/InventoryPredicate for "
348: + desiredAssetName);
349:
350: InventoryPredicate inventoryPredicate = new InventoryPredicate(
351: desiredAssetName, support.getEncodedAgentName(),
352: logger);
353: Collection collection = support
354: .queryBlackboard(inventoryPredicate);
355:
356: if (collection.isEmpty()) {
357: logger
358: .warn("\n\n ************* collection is empty; return no response!");
359: return;
360: }
361:
362: // create UIInventory data object from the log plan objects
363: String xmlStr = getXMLFromLogPlan(collection, startDay);
364:
365: // set values in UISimpleInventory, a serializable object
366: //UISimpleInventory simpleInventory =
367: //getInventoryForClient(inventory, provider, startDay);
368:
369: // send the String object
370: if ((xmlStr != null) && (!(xmlStr.trim().equals("")))) {
371: //ObjectOutputStream p = new ObjectOutputStream(out);
372: //logger.debug("\n\n\n\n sending back a non-null inventory:\n"+simpleInventory);
373: //p.writeObject(xmlStr);
374: BufferedWriter p = new BufferedWriter(
375: new OutputStreamWriter(out, Charset
376: .forName("ASCII")));
377: p.write(xmlStr);
378: p.flush();
379: p.close();
380: logger.info("Sent XML document");
381: } else {
382: logger
383: .error("XML string is null or empty. returning null response.");
384: }
385: }
386:
387: protected String getXMLFromLogPlan(Collection collection,
388: Date startDay) {
389: Inventory inv = null;
390: int ctr = 0;
391: for (Iterator i = collection.iterator(); i.hasNext();) {
392: Object o = (Object) (i.next());
393: if (o instanceof Inventory) {
394: inv = (Inventory) o;
395: ctr++;
396: }
397: }
398: if (ctr > 1) {
399: logger
400: .error("More than one inventory at this cluster with asset match");
401: }
402: if (inv == null) {
403: logger
404: .error("No Inventory Match. Can't send any data");
405: return null;
406: } else {
407: StringWriter strWriter = new StringWriter();
408: BufferedWriter buffWriter = new BufferedWriter(
409: strWriter);
410: LogisticsInventoryFormatter formatter = null;
411: formatter = new LogisticsInventoryFormatter(buffWriter,
412: logger, startDay);
413: formatter.logToXMLOutput(inv, getOrgActivities(),
414: alarmService.currentTimeMillis());
415: try {
416: buffWriter.flush();
417: strWriter.flush();
418: buffWriter.close();
419: } catch (IOException ioe) {
420: throw new RuntimeException(
421: "Unable to create Servlet support: ", ioe);
422: }
423: return strWriter.toString();
424: }
425:
426: }
427:
428: protected Date getStartDate() {
429: Date startingCDay = null;
430:
431: // get oplan
432:
433: Collection oplanCollection = support
434: .queryBlackboard(oplanPredicate());
435:
436: if (!(oplanCollection.isEmpty())) {
437: Iterator iter = oplanCollection.iterator();
438: Oplan plan = (Oplan) iter.next();
439: startingCDay = plan.getCday();
440: }
441: return startingCDay;
442: }
443:
444: protected TimeSpanSet getOrgActivities() {
445: TimeSpanSet orgActivities = null;
446: if (printOrgActs) {
447: Collection orgActCollect = support
448: .queryBlackboard(orgActivityPred());
449: orgActivities = new TimeSpanSet(orgActCollect);
450: } else {
451: orgActivities = new TimeSpanSet();
452: }
453: return orgActivities;
454: }
455:
456: private static UnaryPredicate oplanPredicate() {
457: return new UnaryPredicate() {
458: public boolean execute(Object o) {
459: return (o instanceof Oplan);
460: }
461: };
462: }
463:
464: private static UnaryPredicate orgActivityPred() {
465: return new UnaryPredicate() {
466: public boolean execute(Object o) {
467: return (o instanceof OrgActivity);
468: }
469: };
470:
471: }
472: }
473: }
474:
475: /** Get asset which represents this cluster.
476: */
477:
478: class RolePredicate implements UnaryPredicate {
479: String myCluster;
480:
481: public RolePredicate(String myCluster) {
482: this .myCluster = myCluster;
483: }
484:
485: public boolean execute(Object o) {
486: if (o instanceof Organization) {
487: Organization asset = (Organization) o;
488: String s = asset.getItemIdentificationPG()
489: .getNomenclature();
490: if (s != null)
491: if (s.equals(myCluster))
492: return true;
493: }
494: return false;
495: }
496:
497: }
498:
499: /** Subscribes to Logistics type inventories where the BG contains
500: Buffered lists of information for each cycle.
501: */
502:
503: class InventoryPredicate implements UnaryPredicate {
504: String desiredAssetName; // nomenclature:type id
505: MessageAddress myClusterId;
506: LoggingService logger;
507:
508: public InventoryPredicate(String desiredAssetName,
509: String myCluster, LoggingService aLogger) {
510: this .desiredAssetName = desiredAssetName;
511: myClusterId = MessageAddress.getMessageAddress(myCluster);
512: logger = aLogger;
513: }
514:
515: private boolean assetMatch(Asset asset, Asset resource,
516: boolean level2) {
517: ItemIdentificationPG itemIdPG = asset.getItemIdentificationPG();
518: TypeIdentificationPG typeIdPG = resource
519: .getTypeIdentificationPG();
520: if (itemIdPG == null) {
521: logger.warn("No typeIdentificationPG for asset");
522: return false;
523: }
524: String nomenclature = typeIdPG.getNomenclature();
525: String itemId = itemIdPG.getItemIdentification();
526: int idx = itemId.indexOf(':');
527: itemId = itemId.substring(idx + 1);
528: if (level2) {
529: nomenclature = itemId;
530: } else if (nomenclature != null) {
531: nomenclature = nomenclature + ":" + itemId;
532: } else {
533: nomenclature = itemId;
534: }
535: return nomenclature.equals(desiredAssetName);
536: }
537:
538: /** Get Inventories at this cluster such that
539: LogisticsInventoryPG().getResource().getTypeIdentificationPG().getNomenclature
540: equals desiredAssetName.
541: Also matches if asset uid is equal to desiredAssetName -- i.e.
542: the client can pass in a UID instead of the asset name.
543: */
544:
545: public boolean execute(Object o) {
546: if (o instanceof Inventory) {
547: // looking for Inventory Assets
548: Inventory inv = (Inventory) o;
549: LogisticsInventoryPG logInvPG = null;
550: logInvPG = (LogisticsInventoryPG) inv
551: .searchForPropertyGroup(LogisticsInventoryPG.class);
552: if (logInvPG == null)
553: return false;
554: Asset a1 = logInvPG.getResource();
555: if (a1 == null) {
556: logger
557: .warn("no asset in Inventory in InventoryPredicate");
558: return false;
559: }
560: return assetMatch(inv, a1, logInvPG.getIsLevel2());
561: }
562: return false;
563: }
564: }
565:
566: class AssetPredicate implements UnaryPredicate {
567:
568: private String supplyType;
569: private LoggingService logger;
570:
571: public AssetPredicate(LoggingService aLogger) {
572: super ();
573: supplyType = null;
574: logger = aLogger;
575: }
576:
577: public AssetPredicate(String theSupplyType, LoggingService aLogger) {
578: super ();
579: supplyType = theSupplyType;
580: logger = aLogger;
581: }
582:
583: public boolean execute(Object o) {
584: if (!(o instanceof Inventory))
585: return false;
586: Inventory inv = (Inventory) o;
587: LogisticsInventoryPG logInvPG = null;
588: logInvPG = (LogisticsInventoryPG) inv
589: .searchForPropertyGroup(LogisticsInventoryPG.class);
590: if (logInvPG == null)
591: return false;
592: Asset a1 = logInvPG.getResource();
593: if (a1 == null) {
594: if (logger != null)
595: logger
596: .warn("no asset in Inventory in InventoryPredicate");
597: return false;
598: }
599: TypeIdentificationPG typeIdPG = a1.getTypeIdentificationPG();
600: if (typeIdPG == null) {
601: if (logger != null)
602: logger.warn(" No typeIdentificationPG for asset");
603: return false;
604: }
605: //If we care about supply type make sure direct object matches supply type
606: if (supplyType != null) {
607: SupplyClassPG pg = (SupplyClassPG) a1
608: .searchForPropertyGroup(SupplyClassPG.class);
609: if ((pg == null)
610: || (!(supplyType.equals(pg.getSupplyType())))) {
611: return false;
612: }
613: /***
614: if (pg == null) {
615: logger.warn(" Null Supply type");
616: return false;
617: }
618: else if (!(supplyType.equals(pg.getSupplyType()))){
619: if(logger != null)
620: logger.warn(" The Supply type is: " + pg.getSupplyType());
621: return false;
622: }
623: logger.debug("NO WARNING: SUCCESS got Asset of right type");
624: ***/
625: }
626: return true;
627: }
628: }
629:
630: class DemandObjectPredicate implements UnaryPredicate {
631:
632: private String supplyType;
633: private LoggingService logger;
634:
635: public DemandObjectPredicate(LoggingService aLogger) {
636: super ();
637: supplyType = null;
638: logger = aLogger;
639: }
640:
641: public DemandObjectPredicate(String theSupplyType,
642: LoggingService aLogger) {
643: super ();
644: supplyType = theSupplyType;
645: logger = aLogger;
646: }
647:
648: public boolean execute(Object o) {
649: if (!(o instanceof Task))
650: return false;
651: Task task = (Task) o;
652: if (!((task.getVerb().equals(Constants.Verb.PROJECTSUPPLY)) || (task
653: .getVerb().equals(Constants.Verb.SUPPLY))))
654: return false;
655: Asset asset = task.getDirectObject();
656: if (asset == null)
657: return false;
658: TypeIdentificationPG typeIdPG = asset.getTypeIdentificationPG();
659: if (typeIdPG == null) {
660: if (logger != null)
661: logger.warn(" No typeIdentificationPG for asset");
662: return false;
663: }
664: //If we care about supply type make sure direct object matches supply type
665: if (supplyType != null) {
666: SupplyClassPG pg = (SupplyClassPG) asset
667: .searchForPropertyGroup(SupplyClassPG.class);
668: if ((pg == null)
669: || (!(supplyType.equals(pg.getSupplyType())))) {
670: return false;
671: }
672: }
673: return true;
674: }
675: }
676:
677: class AssetUIDPredicate implements UnaryPredicate {
678: String desiredAssetUID;
679: private LoggingService logger;
680:
681: public AssetUIDPredicate(String desiredAssetUID,
682: LoggingService aLogger) {
683: this .desiredAssetUID = desiredAssetUID;
684: logger = aLogger;
685: }
686:
687: public boolean execute(Object o) {
688: if (!(o instanceof Inventory))
689: return false;
690: Inventory inv = (Inventory) o;
691: if (inv.getUID() == null)
692: return false;
693: if (!inv.getUID().toString().equals(desiredAssetUID))
694: return false;
695: LogisticsInventoryPG logInvPG = null;
696: logInvPG = (LogisticsInventoryPG) inv
697: .searchForPropertyGroup(LogisticsInventoryPG.class);
698: if (logInvPG == null)
699: return false;
700: Asset a1 = logInvPG.getResource();
701: if (a1 == null) {
702: logger.warn("no asset in Inventory in InventoryPredicate");
703: return false;
704: }
705: TypeIdentificationPG typeIdPG = a1.getTypeIdentificationPG();
706: if (typeIdPG == null) {
707: logger.warn(" No typeIdentificationPG for asset");
708: return false;
709: }
710: return true;
711: }
712:
713: }
|