Coverage Report - org.jtheque.core.utils.file.XMLOverReader
 
Classes in this File Line Coverage Branch Coverage Complexity
XMLOverReader
0 %
0/85
0 %
0/12
3.062
XMLOverReader$1
N/A
N/A
3.062
XMLOverReader$Entry
0 %
0/7
N/A
3.062
 
 1  
 package org.jtheque.core.utils.file;
 2  
 
 3  
 /*
 4  
  * This file is part of JTheque.
 5  
  *            
 6  
  * JTheque is free software: you can redistribute it and/or modify
 7  
  * it under the terms of the GNU General Public License as published by
 8  
  * the Free Software Foundation, either version 3 of the License. 
 9  
  *
 10  
  * JTheque is distributed in the hope that it will be useful,
 11  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13  
  * GNU General Public License for more details.
 14  
  *
 15  
  * You should have received a copy of the GNU General Public License
 16  
  * along with JTheque.  If not, see <http://www.gnu.org/licenses/>.
 17  
  */
 18  
 
 19  
 import org.jdom.Document;
 20  
 import org.jdom.Element;
 21  
 import org.jdom.JDOMException;
 22  
 import org.jdom.input.SAXBuilder;
 23  
 import org.jdom.xpath.XPath;
 24  
 
 25  
 import java.io.Closeable;
 26  
 import java.io.File;
 27  
 import java.io.FileInputStream;
 28  
 import java.io.IOException;
 29  
 import java.io.InputStream;
 30  
 import java.net.MalformedURLException;
 31  
 import java.net.URL;
 32  
 import java.net.URLConnection;
 33  
 import java.util.ArrayDeque;
 34  
 import java.util.Deque;
 35  
 import java.util.Iterator;
 36  
 
 37  
 /**
 38  
  * A reader for XML files. This reader keep a current element so it's easier to read.
 39  
  *
 40  
  * @author Baptiste Wicht
 41  
  */
 42  0
 public final class XMLOverReader implements Closeable {
 43  
     private InputStream stream;
 44  
     private Document document;
 45  
 
 46  
     private static final String OPEN_ERROR = "Error opening the file";
 47  
     private static final String READING_ERROR = "Error reading the file";
 48  
 
 49  
     private Element current;
 50  
 
 51  0
     private final Deque<Entry> elements = new ArrayDeque<Entry>();
 52  
 
 53  
     /**
 54  
      * Open the file a the URL.
 55  
      *
 56  
      * @param strUrl The URL of the XML file.
 57  
      * @throws XMLException If an error occurs during the open process.
 58  
      */
 59  
     public void openURL(String strUrl) throws XMLException {
 60  
         URL url;
 61  
         try {
 62  0
             url = new URL(strUrl);
 63  0
         } catch (MalformedURLException e) {
 64  0
             throw new XMLException("Invalid URL", e);
 65  0
         }
 66  
 
 67  0
         openURL(url);
 68  0
     }
 69  
 
 70  
     /**
 71  
      * Open the file a the URL.
 72  
      *
 73  
      * @param url The URL of the XML file.
 74  
      * @throws XMLException If an error occurs during the open process.
 75  
      */
 76  
     public void openURL(URL url) throws XMLException {
 77  
         try {
 78  0
             URLConnection urlConnection = url.openConnection();
 79  0
             urlConnection.setUseCaches(false);
 80  
 
 81  0
             urlConnection.connect();
 82  
 
 83  0
             stream = urlConnection.getInputStream();
 84  
 
 85  0
             SAXBuilder sxb = new SAXBuilder("org.apache.xerces.parsers.SAXParser");
 86  
 
 87  
             try {
 88  0
                 document = sxb.build(stream);
 89  
 
 90  0
                 current = document.getRootElement();
 91  0
             } catch (JDOMException e) {
 92  0
                 throw new XMLException(OPEN_ERROR, e);
 93  0
             }
 94  0
         } catch (IOException e) {
 95  0
             throw new XMLException(OPEN_ERROR, e);
 96  0
         }
 97  0
     }
 98  
 
 99  
     /**
 100  
      * Open the file.
 101  
      *
 102  
      * @param strFile The path to the file to open.
 103  
      * @throws XMLException If an error occurs during the open process.
 104  
      */
 105  
     public void openFile(String strFile) throws XMLException {
 106  0
         openFile(new File(strFile));
 107  0
     }
 108  
 
 109  
     /**
 110  
      * Open the file.
 111  
      *
 112  
      * @param file The file to open.
 113  
      * @throws XMLException If an error occurs during the open process.
 114  
      */
 115  
     public void openFile(File file) throws XMLException {
 116  
         try {
 117  0
             stream = new FileInputStream(file);
 118  
 
 119  0
             SAXBuilder sxb = new SAXBuilder();
 120  
 
 121  0
             document = sxb.build(stream);
 122  
 
 123  0
             current = document.getRootElement();
 124  0
         } catch (JDOMException e) {
 125  0
             throw new XMLException(OPEN_ERROR, e);
 126  0
         } catch (IOException e) {
 127  0
             throw new XMLException(OPEN_ERROR, e);
 128  0
         }
 129  0
     }
 130  
 
 131  
     @Override
 132  
     public void close() throws IOException {
 133  0
         if (stream != null) {
 134  0
             stream.close();
 135  
         }
 136  0
     }
 137  
 
 138  
     /**
 139  
      * Read a node from the current element. The current element become the read node if there is one.
 140  
      *
 141  
      * @param path The path of the node.
 142  
      * @return if the node exists.
 143  
      * @throws XMLException If an error occurs during XML Processing.
 144  
      */
 145  
     public boolean readNode(String path) throws XMLException {
 146  
         try {
 147  0
             Element n = (Element) XPath.newInstance(path).selectSingleNode(current);
 148  
 
 149  0
             if (n != null) {
 150  0
                 current = n;
 151  
 
 152  0
                 return true;
 153  
             }
 154  0
         } catch (JDOMException e) {
 155  0
             throw new XMLException("Error selecting nodes", e);
 156  0
         }
 157  
 
 158  0
         return false;
 159  
     }
 160  
 
 161  
     /**
 162  
      * Change the current element for the parent of current element.
 163  
      */
 164  
     public void switchToParent() {
 165  0
         if (current == null) {
 166  0
             throw new IllegalArgumentException("No current element");
 167  
         }
 168  
 
 169  0
         current = current.getParentElement();
 170  0
     }
 171  
 
 172  
     /**
 173  
      * Go to the next element of the request. The first time this method is called on a specific path, the request is executed and
 174  
      * the elements enqueued. The next time, we only use the enqueued iterator to retrieve the next element.
 175  
      *
 176  
      * @param path The XPath request.
 177  
      * @return <code>true</code> if there is a next element else <code>false</code>.
 178  
      * @throws XMLException If an error occurs during XML Processing.
 179  
      */
 180  
     public boolean next(String path) throws XMLException {
 181  0
         if (elements.isEmpty() || !elements.peek().getPath().equals(path)) {
 182  
             try {
 183  0
                 elements.addFirst(new Entry(path, XPath.newInstance(path).selectNodes(current).iterator()));
 184  0
             } catch (JDOMException e) {
 185  0
                 throw new XMLException("Error selecting nodes", e);
 186  0
             }
 187  
         }
 188  
 
 189  0
         if (elements.peek().getElements().hasNext()) {
 190  0
             current = elements.peek().getElements().next();
 191  
 
 192  0
             return true;
 193  
         } else {
 194  0
             elements.poll();
 195  
 
 196  0
             return false;
 197  
         }
 198  
     }
 199  
 
 200  
     /**
 201  
      * Read a String value from the node.
 202  
      *
 203  
      * @param path The XPath request.
 204  
      * @return The string value of the request.
 205  
      * @throws XMLException If an errors occurs during the reading process.
 206  
      */
 207  
     public String readString(String path) throws XMLException {
 208  
         String value;
 209  
 
 210  
         try {
 211  0
             value = XPath.newInstance(path).valueOf(current);
 212  0
         } catch (JDOMException e) {
 213  0
             throw new XMLException(READING_ERROR, e);
 214  0
         }
 215  
 
 216  0
         return value;
 217  
     }
 218  
 
 219  
     /**
 220  
      * Read a int value from the node.
 221  
      *
 222  
      * @param path The XPath request.
 223  
      * @return The int value of the request.
 224  
      * @throws XMLException If an errors occurs during the reading process.
 225  
      */
 226  
     public int readInt(String path) throws XMLException {
 227  
         String value;
 228  
 
 229  
         try {
 230  0
             value = XPath.newInstance(path).valueOf(current);
 231  0
         } catch (JDOMException e) {
 232  0
             throw new XMLException(READING_ERROR, e);
 233  0
         }
 234  
 
 235  0
         return Integer.parseInt(value);
 236  
     }
 237  
 
 238  
     /**
 239  
      * Read a double value from the node.
 240  
      *
 241  
      * @param path The XPath request.
 242  
      * @return The double value of the request.
 243  
      * @throws XMLException If an errors occurs during the reading process.
 244  
      */
 245  
     public double readDouble(String path) throws XMLException {
 246  
         String value;
 247  
 
 248  
         try {
 249  0
             value = XPath.newInstance(path).valueOf(current);
 250  0
         } catch (JDOMException e) {
 251  0
             throw new XMLException(READING_ERROR, e);
 252  0
         }
 253  
 
 254  0
         return Double.parseDouble(value);
 255  
     }
 256  
 
 257  
     /**
 258  
      * Read a boolean value from the node.
 259  
      *
 260  
      * @param path The XPath request.
 261  
      * @return The boolean value of the request.
 262  
      * @throws XMLException If an errors occurs during the reading process.
 263  
      */
 264  
     public boolean readBoolean(String path) throws XMLException {
 265  
         String value;
 266  
 
 267  
         try {
 268  0
             value = XPath.newInstance(path).valueOf(current);
 269  0
         } catch (JDOMException e) {
 270  0
             throw new XMLException(READING_ERROR, e);
 271  0
         }
 272  
 
 273  0
         return Boolean.parseBoolean(value);
 274  
     }
 275  
 
 276  
     /**
 277  
      * Read a long value from the node.
 278  
      *
 279  
      * @param path The XPath request.
 280  
      * @return The double value of the request.
 281  
      * @throws XMLException If an errors occurs during the reading process.
 282  
      */
 283  
     public long readLong(String path) throws XMLException {
 284  
         String value;
 285  
 
 286  
         try {
 287  0
             value = XPath.newInstance(path).valueOf(current);
 288  0
         } catch (JDOMException e) {
 289  0
             throw new XMLException(READING_ERROR, e);
 290  0
         }
 291  
 
 292  0
         return Long.parseLong(value);
 293  
     }
 294  
 
 295  
     /**
 296  
      * An entry of the elements stack.
 297  
      *
 298  
      * @author Baptiste Wicht
 299  
      */
 300  0
     private static final class Entry {
 301  
         private final String path;
 302  
         private final Iterator<Element> elements;
 303  
 
 304  
         /**
 305  
          * Construct a new Entry.
 306  
          *
 307  
          * @param path     The XPath request.
 308  
          * @param elements The iterator on the found elements.
 309  
          */
 310  
         private Entry(String path, Iterator<Element> elements) {
 311  0
             super();
 312  
 
 313  0
             this.path = path;
 314  0
             this.elements = elements;
 315  0
         }
 316  
 
 317  
         /**
 318  
          * Return the XPath request.
 319  
          *
 320  
          * @return The XPath request.
 321  
          */
 322  
         public String getPath() {
 323  0
             return path;
 324  
         }
 325  
 
 326  
         /**
 327  
          * Return the iterator on the results of the request.
 328  
          *
 329  
          * @return The iterator on the results of the request.
 330  
          */
 331  
         public Iterator<Element> getElements() {
 332  0
             return elements;
 333  
         }
 334  
     }
 335  
 }