1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 package org.apache.qetest.dtm;
  21 
  22 import com.sun.org.apache.xml.internal.dtm.Axis;
  23 import com.sun.org.apache.xml.internal.dtm.DTM;
  24 import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
  25 import com.sun.org.apache.xml.internal.dtm.DTMManager;
  26 import com.sun.org.apache.xml.internal.dtm.DTMWSFilter;
  27 import com.sun.org.apache.xml.internal.dtm.ref.DTMManagerDefault;
  28 import com.sun.org.apache.xpath.internal.objects.XMLStringFactoryImpl;
  29 import java.io.IOException;
  30 import java.io.PrintWriter;
  31 import java.io.StringReader;
  32 import javax.xml.transform.Source;
  33 import javax.xml.transform.stream.StreamSource;
  34 import jaxp.library.JAXPFileBaseTest;
  35 import static jaxp.library.JAXPTestUtilities.compareWithGold;
  36 import static jaxp.library.JAXPTestUtilities.getNextFile;
  37 import static org.apache.qetest.dtm.QeDtmConst.GOLDEN_DIR;
  38 import static org.apache.qetest.dtm.QeDtmConst.TYPENAME;
  39 import static org.testng.Assert.assertTrue;
  40 import org.testng.annotations.Test;
  41 
  42 /**
  43  *
  44  * Loads an XML document from a file (or, if no filename is supplied,
  45  * an internal string), then dumps its contents. Replaces the old
  46  * version, which was specific to the ultra-compressed implementation.
  47  */
  48 public class TestDTMIterator extends JAXPFileBaseTest {
  49     /**
  50      * Test DTMIterator on a well-formed XML string. Checking on expected output.
  51      * @throws IOException if any error on File I/O operation.
  52      */
  53     @Test
  54     public void test() throws IOException { 
  55         setPermissions(new RuntimePermission("accessClassInPackage.com.sun.org.apache.xml.internal.utils"),
  56                 new RuntimePermission("accessClassInPackage.com.sun.org.apache.xpath.internal.objects"));
  57         String goldFile  = GOLDEN_DIR + "TestDTMIterator.out";
  58         
  59         String defaultSource = "<?xml version=\"1.0\"?>\n"
  60                 + "<Document xmlns:d=\"www.d.com\" a1=\"hello\" a2=\"goodbye\">"
  61                 + "<!-- Default test document -->"
  62                 + "<?api a1=\"yes\" a2=\"no\"?>"
  63                 + "<A><!-- A Subtree --><B><C><D><E>"
  64                 + "<F xmlns:f=\"www.f.com\" a1=\"down\" a2=\"up\"/>"
  65                 + "</E></D></C></B></A>"
  66                 + "<Aa/><Ab/><Ac><Ac1/></Ac>"
  67                 + "<Ad xmlns:Ad=\"www.Ad.com\" xmlns:y=\"www.y.com\" xmlns:z=\"www.z.com\">"
  68                 + "<Ad1/></Ad>"
  69                 + "</Document>";
  70 
  71         try(StringReader sw = new StringReader(defaultSource)) {
  72             Source source = new StreamSource(sw);
  73 
  74                 // Get a DTM manager, and ask it to load the DTM "uniquely",
  75             // with no whitespace filtering, nonincremental, but _with_
  76             // indexing (a fairly common case, and avoids the special
  77             // mode used for RTF DTMs).
  78             // For testing with some of David Marston's files I do want to strip whitespace.
  79             DTMManager manager = DTMManagerDefault.newInstance(new XMLStringFactoryImpl());
  80             DTM dtm = manager.getDTM(source, true, (e, d) -> DTMWSFilter.STRIP, false, true);
  81 
  82             // Get various nodes to use as context nodes.
  83             int dtmRoot = dtm.getDocument();                  // #document
  84             int DNode = dtm.getFirstChild(dtmRoot);           // <Document>
  85             int CNode = dtm.getFirstChild(DNode);             // <Comment>
  86             int PINode = dtm.getNextSibling(CNode);           // <PI>
  87             int ANode = dtm.getNextSibling(PINode);           // <A>
  88             int lastNode = 0;
  89 
  90             // Get a Iterator for CHILD:: axis.
  91             DTMAxisIterator iter = dtm.getAxisIterator(Axis.CHILD);
  92             iter.setStartNode(DNode);
  93 
  94             String outputFile = getNextFile(this.getClass());
  95 
  96             try(PrintWriter pw = new PrintWriter(outputFile)) {
  97                 // Iterate the axis and print out node info.
  98                 for (int itNode = iter.next(); DTM.NULL != itNode;
  99                         itNode = iter.next()) {
 100                     printNode(dtm, itNode, " ", pw);
 101                     lastNode = itNode;
 102                 }
 103 
 104                 // Get iterator for PARENT:: Axis
 105                 iter = dtm.getAxisIterator(Axis.PARENT);
 106                 iter.setStartNode(lastNode);
 107 
 108                 // Iterate the axis and print out node info.
 109                 for (int itNode = iter.next(); DTM.NULL != itNode;
 110                         itNode = iter.next()) {
 111                     printNode(dtm, itNode, " ", pw);
 112                 }
 113 
 114                 // Get iterator for SELF:: Axis
 115                 iter = dtm.getAxisIterator(Axis.SELF);
 116                 iter.setStartNode(lastNode);
 117 
 118                 // Iterate the axis and print out node info.
 119                 for (int itNode = iter.next(); DTM.NULL != itNode;
 120                         itNode = iter.next()) {
 121                     printNode(dtm, itNode, " ", pw);
 122                 }
 123 
 124                 // Get iterator for NAMESPACE:: Axis
 125                 iter = dtm.getAxisIterator(Axis.NAMESPACE);
 126                 iter.setStartNode(lastNode);
 127 
 128                 // Iterate the axis and print out node info.
 129                 for (int itNode = iter.next(); DTM.NULL != itNode;
 130                         itNode = iter.next()) {
 131                     printNode(dtm, itNode, " ", pw);
 132                 }
 133 
 134                 // Get iterator for PRECEDING:: Axis
 135                 iter = dtm.getAxisIterator(Axis.PRECEDING);
 136                 iter.setStartNode(lastNode);
 137 
 138                 // Iterate the axis and print out node info.
 139                 for (int itNode = iter.next(); DTM.NULL != itNode;
 140                         itNode = iter.next()) {
 141                     printNode(dtm, itNode, " ", pw);
 142                 }
 143 
 144                 // Get iterator for PRECEDINGSIBLING:: Axis
 145                 iter = dtm.getAxisIterator(Axis.PRECEDINGSIBLING);
 146                 iter.setStartNode(lastNode);
 147 
 148                 // Iterate the axis and print out node info.
 149                 for (int itNode = iter.next(); DTM.NULL != itNode;
 150                         itNode = iter.next()) {
 151                     printNode(dtm, itNode, " ", pw);
 152                 }
 153 
 154                 // Get iterator for FOLLOWING:: Axis
 155                 iter = dtm.getAxisIterator(Axis.FOLLOWING);
 156                 iter.setStartNode(ANode);
 157 
 158                 // Iterate the axis and print out node info.
 159                 for (int itNode = iter.next(); DTM.NULL != itNode;
 160                         itNode = iter.next()) {
 161                     printNode(dtm, itNode, " ", pw);
 162                 }
 163 
 164                 // Get iterator for FOLLOWINGSIBLING:: Axis
 165                 iter = dtm.getAxisIterator(Axis.FOLLOWINGSIBLING);
 166                 iter.setStartNode(ANode);
 167 
 168                 // Iterate the axis and print out node info.
 169                 for (int itNode = iter.next(); DTM.NULL != itNode;
 170                         itNode = iter.next()) {
 171                     printNode(dtm, itNode, " ", pw);
 172                 }
 173 
 174                 // Get a iterator for  DESCENDANT:: axis.
 175                 iter = dtm.getAxisIterator(Axis.DESCENDANT);
 176                 iter.setStartNode(ANode);
 177 
 178                 // Iterate the axis and print out node info.
 179                 for (int itNode = iter.next(); DTM.NULL != itNode;
 180                         itNode = iter.next()) {
 181                     printNode(dtm, itNode, " ", pw);
 182                     lastNode = itNode;
 183                 }
 184 
 185                 // Get iterator for DESCENDANTORSELF:: Axis
 186                 iter = dtm.getAxisIterator(Axis.DESCENDANTORSELF);
 187                 iter.setStartNode(ANode);
 188 
 189                 // Iterate the axis and print out node info.
 190                 for (int itNode = iter.next(); DTM.NULL != itNode;
 191                         itNode = iter.next()) {
 192                     printNode(dtm, itNode, " ", pw);
 193                     lastNode = itNode;
 194                 }
 195 
 196                     // The output from Ancestor and Ancestor-or-self is the topic
 197                 // of Bugzilla 7886
 198                 // Get iterator for ANCESTOR:: Axis
 199                 iter = dtm.getAxisIterator(Axis.ANCESTOR);
 200                 iter.setStartNode(lastNode);
 201 
 202                 // Iterate the axis and print out node info.
 203                 for (int itNode = iter.next(); DTM.NULL != itNode;
 204                         itNode = iter.next()) {
 205                     printNode(dtm, itNode, " ", pw);
 206                 }
 207 
 208                 // Get iterator for ANCESTORORSELF:: Axis
 209                 iter = dtm.getAxisIterator(Axis.ANCESTORORSELF);
 210                 iter.setStartNode(lastNode);
 211 
 212                 // Iterate the axis and print out node info.
 213                 for (int itNode = iter.next(); DTM.NULL != itNode;
 214                         itNode = iter.next()) {
 215                     printNode(dtm, itNode, " ", pw);
 216                 }
 217             }
 218             assertTrue(compareWithGold(goldFile, outputFile));
 219         }   
 220     }
 221 
 222     /**
 223      * Print a node info by given node handle.
 224      * @param dtm DTM instance.
 225      * @param nodeHandle node handle.
 226      * @param indent a format indention.
 227      */
 228     private void printNode(DTM dtm, int nodeHandle, String indent, PrintWriter pw) {
 229         // Briefly display this node
 230         // Don't bother displaying namespaces or attrs; we do that at the
 231         // next level up.
 232         // %REVIEW% Add namespace info, type info, ...
 233 
 234         // Formatting hack -- suppress quotes when value is null, to distinguish
 235         // it from "null".
 236         String value = dtm.getNodeValue(nodeHandle);
 237         String vq = (value == null) ? "" : "\"";
 238 
 239         // Skip outputing of text nodes. In most cases they clutter the output,
 240         // besides I'm only interested in the elemental structure of the dtm.
 241         if (!"TEXT".equals(TYPENAME[dtm.getNodeType(nodeHandle)])) {
 242             pw.println(indent
 243                     + +nodeHandle + ": "
 244                     + TYPENAME[dtm.getNodeType(nodeHandle)] + " "
 245                     + dtm.getNodeName(nodeHandle) + " "
 246                     + " Level=" + dtm.getLevel(nodeHandle) + " "
 247                     + "\tValue=" + vq + value + vq
 248             );
 249         }
 250     }
 251 }