Home | History | Annotate | Download | only in dom
      1 package org.testng.xml.dom;
      2 
      3 import org.testng.collections.Lists;
      4 import org.testng.collections.Maps;
      5 import org.testng.xml.XmlClass;
      6 import org.testng.xml.XmlSuite;
      7 import org.testng.xml.XmlTest;
      8 import org.w3c.dom.Document;
      9 import org.w3c.dom.Element;
     10 import org.w3c.dom.Node;
     11 import org.w3c.dom.NodeList;
     12 
     13 import javax.xml.xpath.XPath;
     14 import javax.xml.xpath.XPathExpressionException;
     15 import javax.xml.xpath.XPathFactory;
     16 
     17 import java.lang.reflect.InvocationTargetException;
     18 import java.lang.reflect.Method;
     19 import java.util.Iterator;
     20 import java.util.List;
     21 import java.util.Map;
     22 
     23 public class DomUtil {
     24 
     25   private XPath m_xpath;
     26   private Document m_document;
     27 
     28   public DomUtil(Document doc) {
     29     XPathFactory xpathFactory = XPathFactory.newInstance();
     30     m_xpath = xpathFactory.newXPath();
     31     m_document = doc;
     32   }
     33 
     34   public void populate(final XmlSuite xmlSuite) throws XPathExpressionException {
     35     NodeList nodes = m_document.getChildNodes();
     36     final Map<String, String> parameters = Maps.newHashMap();
     37     for (int i = 0; i < nodes.getLength(); i++) {
     38       Node item1 = nodes.item(i);
     39 
     40       Map<String, NodeProcessor> map = Maps.newHashMap();
     41       map.put("parameter", new NodeProcessor() {
     42         @Override
     43         public void process(Node node) {
     44           Element e = (Element) node;
     45           parameters.put(e.getAttribute("name"), e.getAttribute("value"));
     46         }
     47       });
     48       map.put("test", new NodeProcessor() {
     49         @Override
     50         public void process(Node node) {
     51           XmlTest xmlTest = new XmlTest(xmlSuite);
     52           populateTest(xmlTest, node);
     53         }
     54       });
     55       map.put("suite-files", new NodeProcessor() {
     56         @Override
     57         public void process(Node node) {
     58           NodeList item2Children = node.getChildNodes();
     59           List<String> suiteFiles = Lists.newArrayList();
     60           for (int k = 0; k < item2Children.getLength(); k++) {
     61             Node item3 = item2Children.item(k);
     62             if (item3 instanceof Element) {
     63               Element e = (Element) item3;
     64               if ("suite-file".equals(item3.getNodeName())) {
     65                 suiteFiles.add(e.getAttribute("path"));
     66               }
     67             }
     68           }
     69           xmlSuite.setSuiteFiles(suiteFiles);
     70         }
     71       });
     72       parseNodeAndChildren("suite", item1, xmlSuite, map);
     73 
     74 //      if ("suite".equals(item1.getNodeName()) && item1.getAttributes() != null) {
     75 //        populateAttributes(item1, xmlSuite);
     76 //        NodeList item1Children = item1.getChildNodes();
     77 //        for (int j = 0; j < item1Children.getLength(); j++) {
     78 //          Node item2 = item1Children.item(j);
     79 //          if ("parameter".equals(item2.getNodeName())) {
     80 //            Element e = (Element) item2;
     81 //            parameters.put(e.getAttribute("name"), e.getAttribute("value"));
     82 //          } else if ("test".equals(item2.getNodeName())) {
     83 //            XmlTest xmlTest = new XmlTest(xmlSuite);
     84 //            populateTest(xmlTest, item2);
     85 //          } else if ("suite-files".equals(item2.getNodeName())) {
     86 //            NodeList item2Children = item2.getChildNodes();
     87 //            List<String> suiteFiles = Lists.newArrayList();
     88 //            for (int k = 0; k < item2Children.getLength(); k++) {
     89 //              Node item3 = item2Children.item(k);
     90 //              if (item3 instanceof Element) {
     91 //                Element e = (Element) item3;
     92 //                if ("suite-file".equals(item3.getNodeName())) {
     93 //                  suiteFiles.add(e.getAttribute("path"));
     94 //                }
     95 //              }
     96 //            }
     97 //            xmlSuite.setSuiteFiles(suiteFiles);
     98 //          }
     99 //        }
    100 //      }
    101     }
    102 
    103     xmlSuite.setParameters(parameters);
    104 //    XPathExpression expr = m_xpath.compile("//suite/test");
    105 //    NodeList tests = (NodeList) expr.evaluate(m_document, XPathConstants.NODESET);
    106 //    for (int i = 0; i < tests.getLength(); i++) {
    107 //      Node node = tests.item(i);
    108 //      System.out.println("<test>:" + node);
    109 //    }
    110   }
    111 
    112   public static interface NodeProcessor {
    113     void process(Node node);
    114   }
    115 
    116   private void parseNodeAndChildren(String name, Node root, Object object,
    117       Map<String, NodeProcessor> processors) throws XPathExpressionException {
    118     if (name.equals(root.getNodeName()) && root.getAttributes() != null) {
    119       populateAttributes(root, object);
    120       NodeList children = root.getChildNodes();
    121       for (int j = 0; j < children.getLength(); j++) {
    122         Node item2 = children.item(j);
    123         String nodeName = item2.getNodeName();
    124         NodeProcessor proc = processors.get(nodeName);
    125         if (proc != null) {
    126           proc.process(item2);
    127         } else if (! nodeName.startsWith("#")){
    128           throw new RuntimeException("No processor found for " + nodeName);
    129         }
    130 //        if ("parameter".equals(item2.getNodeName())) {
    131 //          Element e = (Element) item2;
    132 //          parameters.put(e.getAttribute("name"), e.getAttribute("value"));
    133 //        }
    134       }
    135     }
    136   }
    137 
    138     public static Iterator<Node> findChildren(Node node, String name) {
    139     List<Node> result = Lists.newArrayList();
    140     NodeList children = node.getChildNodes();
    141     for (int i = 0; i < children.getLength(); i++) {
    142       Node n = children.item(i);
    143       if (name.equals(n.getNodeName())) {
    144         result.add(n);
    145       }
    146     }
    147     return result.iterator();
    148   }
    149 
    150   private void populateTest(XmlTest xmlTest, Node item) {
    151     Map<String, String> testParameters = Maps.newHashMap();
    152     populateAttributes(item, xmlTest);
    153     NodeList itemChildren = item.getChildNodes();
    154     for (int k = 0; k < itemChildren.getLength(); k++) {
    155       Node item2 = itemChildren.item(k);
    156       if ("parameter".equals(item2.getNodeName())) {
    157         Element e = (Element) item2;
    158         testParameters.put(e.getAttribute("name"), e.getAttribute("value"));
    159       } else if ("classes".equals(item2.getNodeName())) {
    160         NodeList item2Children = item2.getChildNodes();
    161         for (int l = 0; l < item2Children.getLength(); l++) {
    162           Node item4 = item2Children.item(l);
    163           if ("class".equals(item4.getNodeName())) {
    164             XmlClass xmlClass = new XmlClass();
    165             populateAttributes(item4, xmlClass);
    166             xmlTest.getClasses().add(xmlClass);
    167 
    168             // TODO: excluded/included methods
    169           }
    170         }
    171       } else if ("groups".equals(item2.getNodeName())) {
    172         NodeList item2Children = item2.getChildNodes();
    173         List<String> includes = Lists.newArrayList();
    174         List<String> excludes = Lists.newArrayList();
    175         for (int l = 0; l < item2Children.getLength(); l++) {
    176           Node item3 = item2Children.item(l);
    177           if ("run".equals(item3.getNodeName())) {
    178             NodeList item3Children = item3.getChildNodes();
    179             for (int m = 0; m < item3Children.getLength(); m++) {
    180               Node item4 = item3Children.item(m);
    181               if ("include".equals(item4.getNodeName())) {
    182                 includes.add(((Element) item4).getAttribute("name"));
    183               } else if ("exclude".equals(item4.getNodeName())) {
    184                 excludes.add(((Element) item4).getAttribute("name"));
    185               }
    186             }
    187           } else if ("dependencies".equals(item3.getNodeName())) {
    188             NodeList item3Children = item3.getChildNodes();
    189             for (int m = 0; m < item3Children.getLength(); m++) {
    190               Node item4 = item3Children.item(m);
    191               if ("group".equals(item4.getNodeName())) {
    192                 Element e = (Element) item4;
    193                 xmlTest.addXmlDependencyGroup(e.getAttribute("name"), e.getAttribute("depends-on"));
    194               }
    195             }
    196           } else if ("define".equals(item3.getNodeName())) {
    197             xmlDefine(xmlTest, item3);
    198           }
    199         }
    200         xmlTest.setIncludedGroups(includes);
    201         xmlTest.setExcludedGroups(excludes);
    202       } // TODO: (method-selectors?,packages?) >
    203     }
    204 
    205     xmlTest.setParameters(testParameters);
    206   }
    207 
    208   /**
    209    * Parse the <define> tag.
    210    */
    211   private void xmlDefine(XmlTest xmlTest, Node item) {
    212     NodeList item3Children = item.getChildNodes();
    213     List<String> groups = Lists.newArrayList();
    214     for (int m = 0; m < item3Children.getLength(); m++) {
    215       Node item4 = item3Children.item(m);
    216       if ("include".equals(item4.getNodeName())) {
    217         Element e = (Element) item4;
    218         groups.add(e.getAttribute("name"));
    219       }
    220     }
    221     xmlTest.addMetaGroup(((Element) item).getAttribute("name"), groups);
    222   }
    223 
    224   private void populateAttributes(Node node, Object object) {
    225     for (int j = 0; j < node.getAttributes().getLength(); j++) {
    226       Node item = node.getAttributes().item(j);
    227       p(node.getAttributes().item(j).toString());
    228       setProperty(object, item.getLocalName(), item.getNodeValue());
    229     }
    230   }
    231 
    232   private void setProperty(Object object, String name, Object value) {
    233     String methodName = toCamelCaseSetter(name);
    234     Method foundMethod = null;
    235     for (Method m : object.getClass().getDeclaredMethods()) {
    236       if (m.getName().equals(methodName)) {
    237         foundMethod = m;
    238         break;
    239       }
    240     }
    241 
    242     if (foundMethod == null) {
    243       p("Warning: couldn't find setter method " + methodName);
    244     } else {
    245       try {
    246         p("Invoking " + methodName + " with " + value);
    247         Class<?> type = foundMethod.getParameterTypes()[0];
    248         if (type == Boolean.class || type == boolean.class) {
    249           foundMethod.invoke(object, Boolean.parseBoolean(value.toString()));
    250         } else if (type == Integer.class || type == int.class) {
    251           foundMethod.invoke(object, Integer.parseInt(value.toString()));
    252         } else {
    253           foundMethod.invoke(object, value.toString());
    254         }
    255       } catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException e) {
    256         e.printStackTrace();
    257       }
    258     }
    259   }
    260 
    261   private void p(String string) {
    262 //    System.out.println("[XPathUtil] " + string);
    263   }
    264 
    265   private String toCamelCaseSetter(String name) {
    266     StringBuilder result = new StringBuilder("set" + name.substring(0, 1).toUpperCase());
    267     for (int i = 1; i < name.length(); i++) {
    268       if (name.charAt(i) == '-') {
    269         result.append(Character.toUpperCase(name.charAt(i + 1)));
    270         i++;
    271       } else {
    272         result.append(name.charAt(i));
    273       }
    274     }
    275     return result.toString();
    276   }
    277 }
    278