001/* 002 * Copyright (c) 2010-2011 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * 006 * Permission is hereby granted, without written agreement and without 007 * license or royalty fees, to use, copy, modify, and distribute this 008 * software and its documentation for any purpose, provided that the above 009 * copyright notice and the following two paragraphs appear in all copies 010 * of this software. 011 * 012 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 013 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 014 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 015 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 016 * SUCH DAMAGE. 017 * 018 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 019 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 020 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 021 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 022 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 023 * ENHANCEMENTS, OR MODIFICATIONS. 024 * 025 */ 026 027package org.kepler.kar.karxml; 028 029import java.io.ByteArrayInputStream; 030import java.io.File; 031import java.io.FileInputStream; 032import java.io.FileNotFoundException; 033import java.io.FileWriter; 034import java.io.IOException; 035import java.io.InputStream; 036import java.io.Reader; 037import java.io.StringWriter; 038import java.io.Writer; 039import java.util.ArrayList; 040import java.util.Arrays; 041import java.util.Collections; 042import java.util.List; 043 044import javax.xml.XMLConstants; 045import javax.xml.parsers.DocumentBuilder; 046import javax.xml.parsers.DocumentBuilderFactory; 047import javax.xml.parsers.ParserConfigurationException; 048import javax.xml.transform.OutputKeys; 049import javax.xml.transform.Source; 050import javax.xml.transform.Transformer; 051import javax.xml.transform.TransformerException; 052import javax.xml.transform.TransformerFactory; 053import javax.xml.transform.dom.DOMSource; 054import javax.xml.transform.stream.StreamResult; 055import javax.xml.transform.stream.StreamSource; 056import javax.xml.validation.Schema; 057import javax.xml.validation.SchemaFactory; 058import javax.xml.validation.Validator; 059import javax.xml.xpath.XPath; 060import javax.xml.xpath.XPathConstants; 061import javax.xml.xpath.XPathExpression; 062import javax.xml.xpath.XPathExpressionException; 063import javax.xml.xpath.XPathFactory; 064 065import org.apache.commons.logging.Log; 066import org.apache.commons.logging.LogFactory; 067import org.kepler.kar.KARFile; 068import org.kepler.moml.CompositeClassEntity; 069import org.w3c.dom.Document; 070import org.w3c.dom.Node; 071import org.w3c.dom.NodeList; 072import org.xml.sax.InputSource; 073import org.xml.sax.SAXException; 074 075import ptolemy.actor.TypedCompositeActor; 076 077/** 078 * Created by IntelliJ IDEA. 079 * User: sean 080 * Date: Feb 16, 2010 081 * Time: 1:53:33 PM 082 */ 083public class KarXml { 084 085 private Document document; 086 private String name; 087 private long size; 088 private String karVersion; 089 private String manifestVersion; 090 private List<String> moduleDependencies; 091 private String lsid; 092 private List<KarEntry> karEntries; 093 094 private boolean valid = false; 095 096 097 098 public static final String COMPOSITEACTORTYPE = TypedCompositeActor.class.getName(); 099 public static final String COMPOSITECLASSENTITYTYPE = CompositeClassEntity.class.getName(); 100 private static final String DIRECTOR = "director"; 101 public static final String REPORTLAYOUT = "ReportLayout"; 102 private static XPathExpression GET_KAR_VERSION_EXPRESSION = null; 103 private static XPathExpression GET_NAME_EXPRESSION = null; 104 private static XPathExpression GET_SIZE_EXPRESSION = null; 105 private static XPathExpression GET_MANIFEST_VERSION_EXPRESSION = null; 106 private static XPathExpression GET_MODULE_DEPENDENCIES_EXPRESSION = null; 107 private static XPathExpression GET_LSID_EXPRESSION = null; 108 private static XPathExpression GET_KAR_ENTRIES = null; 109 private static XPathExpression GKE_NAME_EXPRESSION = null; 110 private static XPathExpression GKE_DEPENDS_ON_EXPRESSION = null; 111 private static XPathExpression GKE_TYPE_EXPRESSION = null; 112 private static XPathExpression GKE_LSID_EXPRESSION = null; 113 private static XPathExpression GKE_HANDLER_EXPRESSION = null; 114 //only used by 2.0.0: 115 private static XPathExpression GKE_DEPENDS_ON_MODULE_EXPRESSION = null; 116 private static XPathExpression GKE_XML_EXPRESSION = null; 117 private static XPathExpression GKE_GET_SEMANTIC_TYPES = null; 118 private static XPathExpression GKE_GET_WORKFLOW_NAME = null; 119 private static XPathExpression GKE_GET_DIRECTOR = null; 120 private static XPathExpression GKE_GET_DERIVEDFROM = null; 121 private String repositoryName; 122 private boolean hasReportLayoutInKarEntry = false; 123 124 // accessors 125 public String getKarVersion() { 126 return karVersion; 127 } 128 129 public String getManifestVersion() { 130 return manifestVersion; 131 } 132 133 public List<String> getModuleDependencies() { 134 return moduleDependencies; 135 } 136 137 public String getLsid() { 138 return lsid; 139 } 140 141 142 public Document getDocument() { 143 return document; 144 } 145 146 public List<KarEntry> getKarEntries() { 147 return karEntries; 148 } 149 // accessors end 150 151 private KarXml() { 152 if (GET_KAR_VERSION_EXPRESSION == null) { 153 setupXPathExpressions(); 154 } 155 } 156 157 private static void setupXPathExpressions() { 158 XPathFactory factory = XPathFactory.newInstance(); 159 XPath xpath = factory.newXPath(); 160 try { 161 GET_KAR_VERSION_EXPRESSION = xpath.compile("/*[local-name() = 'kar']/mainAttributes/KAR-Version/text()"); 162 GET_NAME_EXPRESSION = xpath.compile("/*[local-name() = 'kar']/karFileName/text()"); 163 GET_SIZE_EXPRESSION = xpath.compile("/*[local-name() = 'kar']/karFileSize/text()"); 164 GET_MANIFEST_VERSION_EXPRESSION = xpath.compile("/*[local-name() = 'kar']/mainAttributes/Manifest-Version/text()"); 165 GET_MODULE_DEPENDENCIES_EXPRESSION = xpath.compile("/*[local-name() = 'kar']/mainAttributes/module-dependencies/text()"); 166 GET_LSID_EXPRESSION = xpath.compile("/*[local-name() = 'kar']/mainAttributes/lsid/text()"); 167 168 GET_KAR_ENTRIES = xpath.compile("/*[local-name() = 'kar']/karEntry"); 169 GKE_NAME_EXPRESSION = xpath.compile("karEntryAttributes/Name/text()"); 170 GKE_DEPENDS_ON_EXPRESSION = xpath.compile("karEntryAttributes/dependsOn/text()"); 171 GKE_TYPE_EXPRESSION = xpath.compile("karEntryAttributes/type/text()"); 172 GKE_LSID_EXPRESSION = xpath.compile("karEntryAttributes/lsid/text()"); 173 GKE_HANDLER_EXPRESSION = xpath.compile("karEntryAttributes/handler/text()"); 174 //only used by 2.0.0: 175 GKE_DEPENDS_ON_MODULE_EXPRESSION = xpath.compile("karEntryAttributes/dependsOnModule/text()"); 176 GKE_XML_EXPRESSION = xpath.compile("karEntryXML"); 177 GKE_GET_SEMANTIC_TYPES = xpath.compile("karEntryXML/entity/property[@class=\"org.kepler.sms.SemanticType\"]/@value"); 178 GKE_GET_WORKFLOW_NAME = xpath.compile("karEntryXML/entity/@name"); 179 GKE_GET_DIRECTOR = xpath.compile("karEntryXML/entity/property/property[@name=\"entityId\"]/@value"); 180 GKE_GET_DERIVEDFROM =xpath.compile("karEntryXML/entity/property/property[@name=\"derivedFrom\"]/@value"); 181 } catch(XPathExpressionException ex) { 182 log.error("Exception", ex); 183 // Make sure all expression are in a mutually consistent state 184 GET_KAR_VERSION_EXPRESSION = null; 185 GET_NAME_EXPRESSION = null; 186 GET_SIZE_EXPRESSION = null; 187 GET_MANIFEST_VERSION_EXPRESSION = null; 188 GET_MODULE_DEPENDENCIES_EXPRESSION = null; 189 GET_LSID_EXPRESSION = null; 190 191 GET_KAR_ENTRIES = null; 192 GKE_DEPENDS_ON_EXPRESSION = null; 193 GKE_TYPE_EXPRESSION = null; 194 GKE_LSID_EXPRESSION = null; 195 GKE_HANDLER_EXPRESSION = null; 196 //only used by 2.0.0: 197 GKE_DEPENDS_ON_MODULE_EXPRESSION = null; 198 GKE_XML_EXPRESSION = null; 199 GKE_GET_SEMANTIC_TYPES = null; 200 GKE_GET_WORKFLOW_NAME = null; 201 GKE_GET_DIRECTOR = null; 202 GKE_GET_DERIVEDFROM = null; 203 } 204 } 205 206 public static KarXml of(File file) { 207 try { 208 return of(new FileInputStream(file)); 209 } 210 catch(FileNotFoundException ex) { 211 return null; 212 } 213 } 214 public static KarXml of(InputStream is) { 215 Document document = parseXmlStream(is); 216 if (document == null) { 217 return null; 218 } 219 // Validate document 220 boolean valid = validateDocument(document); 221 if (!valid) { 222 System.out.println("Invalid document."); 223 return null; 224 } 225 KarXml kx = new KarXml(); 226 kx.document = document; 227 kx.parse(); 228 kx.fixSemanticTypes(); 229 return kx; 230 } 231 232 private void fixSemanticTypes() { 233 234 List<String> semanticTypes = null; 235 236 // Go through each of the KAR XML entries in this object 237 238 // Find a TypedCompositeActor with at least one semantic type on it 239 for (KarEntry entry : this.getKarEntries()) { 240 if (entry.getType().endsWith(".TypedCompositeActor") && !entry.getSemanticTypes().isEmpty()) { 241 semanticTypes = entry.getSemanticTypes(); 242 break; 243 } 244 } 245 if (semanticTypes == null) { 246 // Nothing has a semantic type. So nothing is going to be visible, sorry. 247 log.warn("This KAR has no semantically-tagged composites, cannot determine semantic types to assign"); 248 return; 249 } 250 251 // Assign that/those semantic type(s) to all entries without a semantic type already 252 for (KarEntry entry : this.getKarEntries()) { 253 if (entry.getSemanticTypes().isEmpty()) { 254 entry.semanticTypes = new ArrayList<String>(semanticTypes); 255 } 256 } 257 } 258 259 260 /** 261 * Validate the document against the schema. Currently we only validate against 262 * kar xml 2.0.0 and 2.1.0. If it is not a kar xml 2.0.0 or 2.1.0 xml, this method will return true. 263 * @param document the document need to be validate 264 * @return true if it is a valid document 265 */ 266 public static boolean validateDocument(Document document) { 267 if(document == null){ 268 return false; 269 } 270 try { 271 Node docElement = document.getDocumentElement(); 272 String nameSpace = docElement.getNamespaceURI(); 273 log.debug("The name space is ===== "+nameSpace); 274 275 if(nameSpace == null || !nameSpace.equals(KARFile.KAR_VERSION_200_NAMESPACE_DEFAULT)|| 276 !nameSpace.equals(KARFile.KAR_VERSION_210_NAMESPACE_DEFAULT)){ 277 return true; 278 } 279 SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 280 String resourceDir = KARFile.getResourceDir(nameSpace); 281 String resourceFileName = KARFile.getResourceFileName(nameSpace); 282 // ClassLoader.getResource javadoc says: 283 // The name of a resource is a '/'-separated path name that identifies the resource. 284 // so I am using a hardcode / in this path: 285 Source schemaFile = new StreamSource(KarXml.class.getClassLoader().getResourceAsStream(resourceDir + 286 "/" + resourceFileName)); 287 Schema schema = factory.newSchema(schemaFile); 288 Validator validator = schema.newValidator(); 289 validator.validate(new DOMSource(document)); 290 } 291 catch(SAXException ex) { 292 ex.printStackTrace(); 293 return false; 294 } 295 catch(IOException ex) { 296 ex.printStackTrace(); 297 return false; 298 } 299 log.debug("return true"); 300 return true; 301 } 302 303 private void parse() { 304 try { 305 NodeList nodes = (NodeList) GET_KAR_VERSION_EXPRESSION.evaluate(document, XPathConstants.NODESET); 306 if (nodes.getLength() == 0) { 307 log.warn("No KAR version found"); 308 } 309 else { 310 valid = true; // NOTE: At present, this is what is used to 311 // determine if the file is a valid KAR XML 312 // file. 313 karVersion = nodes.item(0).getNodeValue().trim(); 314 } 315 316 nodes = (NodeList) GET_NAME_EXPRESSION.evaluate(document, XPathConstants.NODESET); 317 if (nodes.getLength() == 0) { 318 log.warn("No KAR name found"); 319 } 320 else { 321 name = nodes.item(0).getNodeValue().trim(); 322 } 323 324 //System.out.println("The kar name is ================ "+name); 325 326 nodes = (NodeList) GET_SIZE_EXPRESSION.evaluate(document, XPathConstants.NODESET); 327 if (nodes.getLength() == 0) { 328 log.warn("No KAR size found"); 329 size = -1; 330 } 331 else { 332 size = Long.valueOf(nodes.item(0).getNodeValue().trim()); 333 } 334 335 nodes = (NodeList) GET_MANIFEST_VERSION_EXPRESSION.evaluate(document, XPathConstants.NODESET); 336 if (nodes.getLength() == 0) { 337 log.warn("No manifest version found"); 338 } 339 else { 340 manifestVersion = nodes.item(0).getNodeValue().trim(); 341 } 342 343 nodes = (NodeList) GET_LSID_EXPRESSION.evaluate(document, XPathConstants.NODESET); 344 if (nodes.getLength() == 0) { 345 log.warn("No LSID found"); 346 } 347 else { 348 lsid = nodes.item(0).getNodeValue().trim(); 349 } 350 //System.out.println("The kar file lisd is ============== "+lsid); 351 352 nodes = (NodeList) GET_MODULE_DEPENDENCIES_EXPRESSION.evaluate(document, XPathConstants.NODESET); 353 if (nodes.getLength() == 0) { 354 log.warn("No module dependencies found"); 355 } 356 else { 357 String moduleDependenciesString = nodes.item(0).getNodeValue().trim(); 358 String[] dependencies = moduleDependenciesString.split(";"); 359 moduleDependencies = new ArrayList<String>(Arrays.asList((String[]) dependencies)); 360 } 361 362 nodes = (NodeList) GET_KAR_ENTRIES.evaluate(document, XPathConstants.NODESET); 363 if (nodes.getLength() == 0) { 364 log.warn("No KAR entries found"); 365 } 366 else { 367 List<KarEntry> entries = new ArrayList<KarEntry>(); 368 for (int i = 0; i < nodes.getLength(); i++) { 369 Node node = nodes.item(i); 370 KarEntry entry = KarEntry.of(node, karVersion); 371 //System.out.println("kar entry name ==================="+entry.getName()); 372 entry.setParent(this); 373 entries.add(entry); 374 if(entry.hasReportingLayout()) 375 { 376 hasReportLayoutInKarEntry = true; 377 } 378 } 379 karEntries = entries; 380 } 381 } 382 catch(XPathExpressionException ex) { 383 log.error("Exception", ex); 384 } 385 386 // Get the karEntry nodes 387 388 } 389 390 public static Document parseXmlStream(InputStream is) { 391 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 392 factory.setNamespaceAware(true); 393 try { 394 DocumentBuilder builder = factory.newDocumentBuilder(); 395 return builder.parse(is); 396 // TODO: Have the document parser validate against the KAR XML DTD 397 // (in progress) 398 } 399 catch(ParserConfigurationException ex) { 400 log.error("Exception", ex); 401 } 402 catch(SAXException ex) { 403 log.error("Exception", ex); 404 } 405 catch(IOException ex) { 406 log.error("Exception", ex); 407 } 408 return null; 409 } 410 411 public static Document parseXml(Reader reader) { 412 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 413 factory.setNamespaceAware(true); 414 try { 415 InputSource source = new InputSource(reader); 416 DocumentBuilder builder = factory.newDocumentBuilder(); 417 return builder.parse(source); 418 // TODO: Have the document parser validate against the KAR XML DTD 419 // (in progress) 420 } 421 catch(ParserConfigurationException ex) { 422 log.error("Exception", ex); 423 } 424 catch(SAXException ex) { 425 log.error("Exception", ex); 426 } 427 catch(IOException ex) { 428 log.error("Exception", ex); 429 } 430 return null; 431 } 432 433 // toString 434 @Override 435 public String toString() { 436 return "KarXml{" + 437 "karVersion='" + getKarVersion() + '\'' + 438 ", manifestVersion='" + getManifestVersion() + '\'' + 439 ", moduleDependencies=" + getModuleDependencies() + 440 ", lsid='" + getLsid() + '\'' + 441 '}'; 442 } 443 444 public boolean isValid() { 445 return valid; 446 } 447 448 public String getId() { 449 return this.getLsid(); 450 } 451 452 public String getName() { 453 if (name == null) { 454 // On some searches, this really floods stdout. 455// log.warn("No explicit name, using LSID instead"); 456 return this.getId(); 457 } 458 else { 459 return name; 460 } 461 } 462 463 /** 464 * @return The size of the KAR file in bytes, if available. -1, if not available. 465 */ 466 public long getSize() { 467 return size; 468 } 469 470 public String getRepositoryName() { 471 return repositoryName; 472 } 473 474 public void setRepositoryName(String repositoryName) { 475 this.repositoryName = repositoryName; 476 } 477 478 public boolean hasReportLayout() 479 { 480 return hasReportLayoutInKarEntry; 481 } 482 483 public static class KarEntry { 484 // disallow the default constructor 485 private KarEntry() {} 486 487 private KarEntry(Node karEntryNode, String karVersion) { 488 this(); 489 try { 490 NodeList nodes = (NodeList) GKE_DEPENDS_ON_EXPRESSION.evaluate(karEntryNode, XPathConstants.NODESET); 491 if (nodes.getLength() == 0) { 492 log.warn("No dependsOn found"); 493 } 494 else { 495 dependsOn = nodes.item(0).getNodeValue().trim(); 496 } 497 498 nodes = (NodeList) GKE_NAME_EXPRESSION.evaluate(karEntryNode, XPathConstants.NODESET); 499 if (nodes.getLength() == 0) { 500 log.warn("No name found"); 501 } 502 else { 503 name = nodes.item(0).getNodeValue().trim(); 504 } 505 506 nodes = (NodeList) GKE_TYPE_EXPRESSION.evaluate(karEntryNode, XPathConstants.NODESET); 507 if (nodes.getLength() == 0) { 508 log.warn("No type found"); 509 } 510 else { 511 type = nodes.item(0).getNodeValue().trim(); 512 if(type != null) 513 { 514 type = type.trim(); 515 //System.out.println("type is ==================== "+type); 516 if(type.equals(COMPOSITEACTORTYPE) || type.equals(COMPOSITECLASSENTITYTYPE)) 517 { 518 //System.out.println("================it is a composite actor"); 519 isCompositeActor = true; 520 //System.out.println("is a compoiste Actor ================ "); 521 } 522 else if(type.contains(REPORTLAYOUT)) 523 { 524 hasReportingLayout = true; 525 } 526 } 527 } 528 529 nodes = (NodeList) GKE_LSID_EXPRESSION.evaluate(karEntryNode, XPathConstants.NODESET); 530 if (nodes.getLength() == 0) { 531 log.warn("No LSID found"); 532 } 533 else { 534 lsid = nodes.item(0).getNodeValue().trim(); 535 } 536 537 nodes = (NodeList) GKE_HANDLER_EXPRESSION.evaluate(karEntryNode, XPathConstants.NODESET); 538 if (nodes.getLength() == 0) { 539 log.warn("No handler found"); 540 } 541 else { 542 handler = nodes.item(0).getNodeValue().trim(); 543 } 544 545 //not used in 2.1: 546 if (!karVersion.equals(KARFile.VERSION_2_1)){ 547 nodes = (NodeList) GKE_DEPENDS_ON_MODULE_EXPRESSION.evaluate(karEntryNode, XPathConstants.NODESET); 548 if (nodes.getLength() == 0) { 549 log.warn("No dependsOnModule found"); 550 } 551 else { 552 dependsOnModule = nodes.item(0).getNodeValue().trim(); 553 } 554 } 555 556 // if this composite actor type, we need to figure out if it has director 557 if(isCompositeActor) 558 { 559 nodes = (NodeList) GKE_GET_DIRECTOR.evaluate(karEntryNode, XPathConstants.NODESET); 560 if(nodes.getLength() >0) 561 { 562 563 if(hasDirector(nodes)) 564 { 565 //System.out.println("find a directory, this is workflow ============="); 566 hasDirector = true; 567 //System.out.println("has director========"); 568 isWorkflow = true; 569 } 570 else 571 { 572 //check derivedForm 573 if(isDerivedFromDirector(karEntryNode)) 574 { 575 hasDirector = true; 576 //System.out.println("has derived director========"); 577 isWorkflow = true; 578 } 579 } 580 581 } 582 } 583 //if this workflow, we need to get workflow name. 584 //(getName method will get the name of the workflow xml file.) 585 if(isWorkflow) 586 { 587 nodes = (NodeList)GKE_GET_WORKFLOW_NAME.evaluate(karEntryNode, XPathConstants.NODESET); 588 if(nodes.getLength() == 0) 589 { 590 //System.out.println("Couldn't find workflow name, use the name of kar entry to replace it"); 591 workflowName = name; 592 } 593 else 594 { 595 596 workflowName = nodes.item(0).getNodeValue().trim(); 597 //System.out.println("get the workflow name "+workflowName); 598 } 599 } 600 601 602 nodes = (NodeList) GKE_XML_EXPRESSION.evaluate(karEntryNode, XPathConstants.NODESET); 603 if (nodes.getLength() == 0) { 604 log.warn("No XML found"); 605 } 606 else { 607 xml = nodes.item(0); 608 } 609 610 nodes = (NodeList) GKE_GET_SEMANTIC_TYPES.evaluate(karEntryNode, XPathConstants.NODESET); 611 if (nodes.getLength() == 0) { 612 log.warn("No semantic types found"); 613 } 614 else { 615 List<String> semanticTypes = new ArrayList<String>(); 616 for (int i = 0; i < nodes.getLength(); i++) { 617 Node node = nodes.item(i); 618 semanticTypes.add(node.getNodeValue()); 619 } 620 this.semanticTypes = semanticTypes; 621 } 622 } 623 catch(XPathExpressionException ex) { 624 log.warn("Exception", ex); 625 } 626 } 627 628 629 /* 630 * Determine if the entity has a director 631 */ 632 private boolean hasDirector(NodeList directorNodeList) 633 { 634 boolean hasDirector = false; 635 if(directorNodeList != null) 636 { 637 for(int i=0 ; i<directorNodeList.getLength(); i++) 638 { 639 Node node = directorNodeList.item(i); 640 String value = node.getNodeValue().trim(); 641 if(value != null && value.indexOf(DIRECTOR) != -1) 642 { 643 hasDirector = true; 644 break; 645 } 646 } 647 } 648 return hasDirector; 649 650 } 651 652 653 /* 654 * Determine if the entity is derived from a director 655 */ 656 private boolean isDerivedFromDirector(Node karEntryNode){ 657 boolean fromDirector = false; 658 if(karEntryNode != null){ 659 try{ 660 NodeList nodeList = (NodeList)GKE_GET_DERIVEDFROM.evaluate(karEntryNode, XPathConstants.NODESET); 661 if(nodeList != null){ 662 for(int i=0; i<nodeList.getLength(); i++){ 663 Node node = nodeList.item(i); 664 if(node != null){ 665 String value = node.getNodeValue(); 666 if(value != null && value.contains(DIRECTOR)){ 667 fromDirector = true; 668 break; 669 } 670 } 671 } 672 } 673 } 674 catch(Exception e){ 675 log.warn("Exception", e); 676 } 677 } 678 return fromDirector; 679 } 680 681 public String getName() { 682 return name; 683 } 684 685 public List<String> getSemanticTypes() { 686 return semanticTypes == null ? getDefaultSemanticTypes() : semanticTypes; 687 } 688 689 private List<String> getDefaultSemanticTypes() { 690 return Collections.emptyList(); 691 } 692 693 public String getDependsOn() { 694 return dependsOn; 695 } 696 697 public String getType() { 698 return type; 699 } 700 701 public String getLsid() { 702 return lsid; 703 } 704 705 public String getHandler() { 706 return handler; 707 } 708 709 //only used by 2.0.0: 710 public String getDependsOnModule() { 711 return dependsOnModule; 712 } 713 714 public Node getXml() { 715 return xml; 716 } 717 718 public String getWorkflowName(){ 719 return workflowName; 720 } 721 722 public boolean isWorkflow(){ 723 return isWorkflow; 724 } 725 726 public boolean hasReportingLayout(){ 727 return hasReportingLayout; 728 } 729 730 private String _asString() { 731 return nodeToString(xml); 732 } 733 734 735 // Used for debugging 736 @SuppressWarnings({"UnusedDeclaration"}) 737 public File asLocalFile() { 738 Writer writer = null; 739 String data = this._asString(); 740 File file = null; 741 try { 742 file = File.createTempFile("dump", ".xml"); 743 writer = new FileWriter(file); 744 writer.write(data); 745 System.out.println("Wrote fragment: " + file.getAbsolutePath()); 746 } 747 catch(IOException ex) { 748 System.out.println("Error dumping fragment"); 749 } 750 finally { 751 if (writer != null) { 752 try { 753 writer.close(); 754 } 755 catch(IOException ignored) {} 756 } 757 } 758 759 return file; 760 } 761 762 public InputStream asInputStream() { 763 return new ByteArrayInputStream(this._asString().getBytes()); 764 } 765 766 // toString 767 @Override 768 public String toString() { 769 770 String KARVersion = getParent().getKarVersion(); 771 772 if (!KARVersion.equals(KARFile.VERSION_2_1)) 773 { 774 return "KarEntry{" + 775 "name='" + getName() + '\'' + 776 ", dependsOn='" + getDependsOn() + '\'' + 777 ", type='" + getType() + '\'' + 778 ", lsid='" + getLsid() + '\'' + 779 ", handler='" + getHandler() + '\'' + 780 ", dependsOnModule='" + getDependsOnModule() + '\'' + 781 ", xml=" + (getXml() == null ? "null" : "non-null") + 782 '}'; 783 } 784 else{ 785 return "KarEntry{" + 786 "name='" + getName() + '\'' + 787 ", dependsOn='" + getDependsOn() + '\'' + 788 ", type='" + getType() + '\'' + 789 ", lsid='" + getLsid() + '\'' + 790 ", handler='" + getHandler() + '\'' + 791 //", dependsOnModule='" + getDependsOnModule() + '\'' + 792 ", xml=" + (getXml() == null ? "null" : "non-null") + 793 '}'; 794 } 795 } 796 797 public static KarEntry of(Node karEntryNode, String karVersion) { 798 return new KarEntry(karEntryNode, karVersion); 799 } 800 801 private String name = null; 802 private List<String> semanticTypes = null; 803 private String dependsOn = null; 804 private String type = null; 805 private String lsid = null; 806 private String handler = null; 807 //only used by 2.0.0: 808 private String dependsOnModule = null; 809 private Node xml = null; 810 private KarXml parent; 811 private boolean isCompositeActor = false; 812 private boolean hasReportingLayout = false; 813 private boolean hasDirector = false; 814 private boolean isWorkflow = false; 815 private String workflowName = null; 816 817 public void setParent(KarXml parent) { 818 this.parent = parent; 819 } 820 821 public KarXml getParent() { 822 return parent; 823 } 824 } 825 826 private static final Log log = LogFactory.getLog(KarXml.class); 827 828 public static String nodeToString(Node node) { 829 StringWriter sw = new StringWriter(); 830 try { 831 Transformer t = TransformerFactory.newInstance().newTransformer(); 832 t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 833 NodeList nodes = node.getChildNodes(); 834 for (int i = 0; i < nodes.getLength(); i++) { 835 t.transform(new DOMSource(nodes.item(i)), new StreamResult(sw)); 836 } 837 } 838 catch(TransformerException ex) { 839 System.out.println("Transformer exception"); 840 } 841 return sw.toString(); 842 } 843}