Coverage Report - net.sf.jmatchparser.util.csv.XMLCSVReader
 
Classes in this File Line Coverage Branch Coverage Complexity
XMLCSVReader
100%
37/37
91%
33/36
4
 
 1  
 /*
 2  
  * Copyright (c) 2010 - 2011 Michael Schierl
 3  
  * 
 4  
  * All rights reserved.
 5  
  * 
 6  
  * Redistribution and use in source and binary forms, with or without
 7  
  * modification, are permitted provided that the following conditions
 8  
  * are met:
 9  
  * 
 10  
  * - Redistributions of source code must retain the above copyright notice,
 11  
  *   this list of conditions and the following disclaimer.
 12  
  *   
 13  
  * - Redistributions in binary form must reproduce the above copyright
 14  
  *   notice, this list of conditions and the following disclaimer in the
 15  
  *   documentation and/or other materials provided with the distribution.
 16  
  *   
 17  
  * - Neither name of the copyright holders nor the names of its
 18  
  *   contributors may be used to endorse or promote products derived from
 19  
  *   this software without specific prior written permission.
 20  
  *   
 21  
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND THE CONTRIBUTORS
 22  
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 23  
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 24  
  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 25  
  * HOLDERS OR THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 26  
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 27  
  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 28  
  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 29  
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 30  
  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 31  
  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 32  
  */
 33  
 package net.sf.jmatchparser.util.csv;
 34  
 
 35  
 import java.io.IOException;
 36  
 import java.util.ArrayList;
 37  
 import java.util.List;
 38  
 
 39  
 import org.w3c.dom.Document;
 40  
 import org.w3c.dom.Element;
 41  
 import org.w3c.dom.Node;
 42  
 
 43  
 /**
 44  
  * Class to read data from an XML file as if it was a CSV (Comma Separated
 45  
  * Value) file.
 46  
  */
 47  
 public class XMLCSVReader extends AbstractCSVReader {
 48  
 
 49  
         private Node nextRow;
 50  
         private final String rowTag;
 51  
         private final String[] cellTags;
 52  
 
 53  
         /**
 54  
          * Create a new {@link XMLCSVReader} that reads from the given DOM document.
 55  
          * All child elements of the document element are considered rows, and all
 56  
          * their child elements are considered cells.
 57  
          * 
 58  
          * @param doc
 59  
          *            the {@link Document}
 60  
          */
 61  
         public XMLCSVReader(Document doc) {
 62  2
                 this(doc, "*", "*");
 63  2
         }
 64  
 
 65  
         /**
 66  
          * Create a new {@link XMLCSVReader} that reads from the given DOM document.
 67  
          * All child elements of the document element that have the row tag as name
 68  
          * (or all of them if the row tag is <code>*</code>) are considered rows,
 69  
          * and all their child elements that have one of the cell tags as name are
 70  
          * considered cells. In case there is more than one cell tag, the cell tag
 71  
          * in the list of cell tags is used to determine the position in the result
 72  
          * row. If a cell tag matches more than once in a row, all the fields before
 73  
          * the cell tag are added to the result row, and a complete set of empty
 74  
          * fields is used to parse the rest of the row. Cell tags that are not
 75  
          * matched result in empty strings, unless they would be at the end of the
 76  
          * row in the last run.
 77  
          * 
 78  
          * @param doc
 79  
          *            the {@link Document}
 80  
          * @param rowTag
 81  
          *            the name of row elements
 82  
          * @param cellTags
 83  
          *            the names of cell elements
 84  
          * 
 85  
          */
 86  6
         public XMLCSVReader(Document doc, String rowTag, String... cellTags) {
 87  6
                 this.rowTag = rowTag;
 88  6
                 this.cellTags = cellTags;
 89  6
                 this.nextRow = doc.getDocumentElement().getFirstChild();
 90  6
         }
 91  
 
 92  
         /**
 93  
          * Close this reader. This is a no-op.
 94  
          */
 95  
         @Override
 96  
         public void close() throws IOException {
 97  2
         }
 98  
 
 99  
         /**
 100  
          * Read a row from this XML file.
 101  
          */
 102  
         @Override
 103  
         public String[] read() throws IOException {
 104  13
                 return read(null);
 105  
         }
 106  
 
 107  
         /**
 108  
          * Read a row from this XML file. If the row has a <tt>@file</tt> attribute
 109  
          * and the fileIndex argument is non-null, the value of that file attribute
 110  
          * is stored into the first element of that array.
 111  
          * 
 112  
          * @param fileIndex
 113  
          *            Array to store the file index to, if needed
 114  
          */
 115  
         public String[] read(int[] fileIndex) {
 116  20
                 while (nextRow != null && !nameMatches(nextRow, rowTag))
 117  1
                         nextRow = nextRow.getNextSibling();
 118  19
                 if (nextRow == null)
 119  6
                         return null;
 120  13
                 Element row = (Element) nextRow;
 121  13
                 nextRow = row.getNextSibling();
 122  13
                 if (row.getAttribute("file").length() > 0 && fileIndex != null)
 123  1
                         fileIndex[0] = Integer.parseInt(row.getAttribute("file"));
 124  13
                 List<String> elems = new ArrayList<String>();
 125  13
                 String[] restRecord = new String[cellTags.length];
 126  40
                 for (int i = 0; i < row.getChildNodes().getLength(); i++) {
 127  27
                         Node n = row.getChildNodes().item(i);
 128  44
                         for (int j = 0; j < cellTags.length; j++) {
 129  44
                                 if (nameMatches(n, cellTags[j])) {
 130  27
                                         if (restRecord[j] != null) {
 131  22
                                                 for (int k = 0; k < restRecord.length; k++) {
 132  15
                                                         elems.add(restRecord[k] == null ? "" : restRecord[k]);
 133  15
                                                         restRecord[k] = null;
 134  
                                                 }
 135  
                                         }
 136  27
                                         restRecord[j] = n.getTextContent();
 137  27
                                         break;
 138  
                                 }
 139  
                         }
 140  
                 }
 141  13
                 int lastNonNull = -1;
 142  42
                 for (int i = 0; i < restRecord.length; i++) {
 143  29
                         if (restRecord[i] != null)
 144  17
                                 lastNonNull = i;
 145  
                 }
 146  34
                 for (int i = 0; i <= lastNonNull; i++) {
 147  21
                         elems.add(restRecord[i] == null ? "" : restRecord[i]);
 148  
                 }
 149  13
                 return elems.toArray(new String[elems.size()]);
 150  
         }
 151  
 
 152  
         private boolean nameMatches(Node node, String name) {
 153  58
                 return node instanceof Element && name.equals("*") || node.getNodeName().equals(name);
 154  
         }
 155  
 }