Coverage Report - net.objectlab.qalab.exporter.QALabXMLExporter
 
Classes in this File Line Coverage Branch Coverage Complexity
QALabXMLExporter
71%
146/206
79%
34/43
4.056
 
 1  
 ////////////////////////////////////////////////////////////////////////////////
 2  
 //
 3  
 //                  ObjectLab is sponsoring QALab
 4  
 // 
 5  
 // Based in London, we are world leaders in the design and development 
 6  
 // of bespoke applications for the Securities Financing markets.
 7  
 // 
 8  
 // <a href="http://www.objectlab.co.uk/open">Click here to learn more</a>
 9  
 //           ___  _     _           _   _          _
 10  
 //          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
 11  
 //         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
 12  
 //         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
 13  
 //          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
 14  
 //                   |__/
 15  
 //
 16  
 //                   http://www.ObjectLab.co.uk
 17  
 // ---------------------------------------------------------------------------
 18  
 //
 19  
 //QALab is released under the GNU General Public License.
 20  
 //
 21  
 //QALab: Collects QA Statistics from your build over time.
 22  
 //2005+, ObjectLab Ltd
 23  
 //
 24  
 //This library is free software; you can redistribute it and/or
 25  
 //modify it under the terms of the GNU General Public
 26  
 //License as published by the Free Software Foundation; either
 27  
 //version 2.1 of the License, or (at your option) any later version.
 28  
 //
 29  
 //This library is distributed in the hope that it will be useful,
 30  
 //but WITHOUT ANY WARRANTY; without even the implied warranty of
 31  
 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 32  
 //General Public License for more details.
 33  
 //
 34  
 //You should have received a copy of the GNU General Public
 35  
 //License along with this library; if not, write to the Free Software
 36  
 //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 37  
 //
 38  
 ////////////////////////////////////////////////////////////////////////////////
 39  
 package net.objectlab.qalab.exporter;
 40  
 
 41  
 import java.io.File;
 42  
 import java.io.FileInputStream;
 43  
 import java.io.FileWriter;
 44  
 import java.io.IOException;
 45  
 import java.io.InputStream;
 46  
 import java.io.StringWriter;
 47  
 import java.util.Locale;
 48  
 import java.util.Properties;
 49  
 
 50  
 import javax.xml.parsers.DocumentBuilderFactory;
 51  
 import javax.xml.parsers.ParserConfigurationException;
 52  
 
 53  
 import net.objectlab.qalab.interfaces.QALabExporter;
 54  
 import net.objectlab.qalab.util.QALabTags;
 55  
 import net.objectlab.qalab.util.TaskLogger;
 56  
 import net.objectlab.qalab.util.Util;
 57  
 
 58  
 import org.apache.tools.ant.BuildException;
 59  
 import org.apache.xml.serialize.OutputFormat;
 60  
 import org.apache.xml.serialize.XMLSerializer;
 61  
 import org.w3c.dom.Document;
 62  
 import org.w3c.dom.Element;
 63  
 import org.w3c.dom.Node;
 64  
 import org.w3c.dom.NodeList;
 65  
 import org.xml.sax.InputSource;
 66  
 import org.xml.sax.SAXException;
 67  
 
 68  
 /**
 69  
  * This is the main exporter to an XML file following the QALab DTD.
 70  
  * 
 71  
  * @author Benoit Xhenseval
 72  
  * @version $Revision$
 73  
  */
 74  87
 public class QALabXMLExporter implements QALabExporter {
 75  
     private static final String XML_VERSION = "1.1";
 76  
 
 77  
     /**
 78  
      * If no qalab.xml is found, this will be the basis of a new one.
 79  
      */
 80  15
     private static final String DTD_DEFINITION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
 81  
             + System.getProperty("line.separator") + "<!DOCTYPE qalab [" + System.getProperty("line.separator")
 82  
             + "<!ELEMENT qalab (summary, file*)>" + System.getProperty("line.separator")
 83  
             + "<!ATTLIST qalab version CDATA #REQUIRED> " + System.getProperty("line.separator")
 84  
             + "<!ELEMENT summary (summaryresult*)>" + System.getProperty("line.separator") + "<!ELEMENT file (result+)>"
 85  
             + System.getProperty("line.separator") + "<!ATTLIST file id ID #REQUIRED" + System.getProperty("line.separator")
 86  
             + "   path CDATA #REQUIRED>" + System.getProperty("line.separator") + "<!ELEMENT result EMPTY>"
 87  
             + System.getProperty("line.separator") + "<!ATTLIST result date CDATA #REQUIRED"
 88  
             + System.getProperty("line.separator") + "   statvalue CDATA #REQUIRED" + System.getProperty("line.separator")
 89  
             + "   type CDATA #REQUIRED>" + System.getProperty("line.separator") + "<!ELEMENT summaryresult EMPTY>"
 90  
             + System.getProperty("line.separator") + "<!ATTLIST summaryresult date CDATA #REQUIRED"
 91  
             + System.getProperty("line.separator") + "   statvalue CDATA #REQUIRED" + System.getProperty("line.separator")
 92  
             + "   filecount CDATA #REQUIRED" + System.getProperty("line.separator") + "   type CDATA #REQUIRED>"
 93  
             + System.getProperty("line.separator") + "]>" + System.getProperty("line.separator");
 94  
 
 95  15
     private static final String EMPTY_FILE = DTD_DEFINITION + System.getProperty("line.separator") + "<qalab version=\""
 96  
             + XML_VERSION + "\">" + "   <summary/>" + "</qalab>";
 97  
 
 98  
     /** current XML version * */
 99  87
     private String currentXmlVersion = null;
 100  
 
 101  
     /** the compiled stats. */
 102  87
     private Document compiledStats = null;
 103  
 
 104  
     /** given implementation for the logger. * */
 105  87
     private TaskLogger taskLogger = null;
 106  
 
 107  
     /** if true, no debug information is logged. * */
 108  87
     private boolean quiet = true;
 109  
 
 110  
     /** the merged properties file. */
 111  87
     private File outputFile = null;
 112  
 
 113  
     /** the action for same type and timestamp replace (default)| new. */
 114  87
     private String action = "replace";
 115  
 
 116  
     /** timestamp to use. */
 117  87
     private String timestampToUse = null;
 118  
 
 119  
     /** type of stats we are interested in. */
 120  87
     private String typeToUse = null;
 121  
 
 122  
     /**
 123  
      * For instance for the XML Exporter.
 124  
      * <ul>
 125  
      * <li>qalab.outputfile = the output file name and path.</li>
 126  
      * <li>qalab.merge.output.classname = alternatively, the XML could be a
 127  
      * resource for this class</li>
 128  
      * <li>qalab.merge.output.resourcename = the resource name for the
 129  
      * qalab.merge.output.classname given</li>
 130  
      * <li>qalab.merge.timestamp = the timestamp YYYY-MM-dd HH:mm:ss</li>
 131  
      * <li>qalab.merge.type = the type of statistics being merged. (eg
 132  
      * checkstyle,findbugs,simian, pmd)</li>
 133  
      * <li>qalab.merge.action = the action to take in case of clash
 134  
      * type/timetstamp</li>
 135  
      * </ul>
 136  
      * 
 137  
      * @param properties
 138  
      *            the properties.
 139  
      * @see net.objectlab.qalab.interfaces.
 140  
      *      QALabExporter#configure(java.util.Properties)
 141  
      */
 142  
     public final void configure(final Properties properties) {
 143  87
         InputStream stream = null;
 144  
 
 145  
         try {
 146  87
             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 147  87
             factory.setValidating(false);
 148  
 
 149  87
             stream = parseOriginalDocument(properties, factory);
 150  
 
 151  87
             validateXmlVersion(compiledStats);
 152  
 
 153  87
             if (!quiet) {
 154  6
                 getTaskLogger().log("Parsed Statistics.");
 155  
             }
 156  
 
 157  87
             loadActionAndStamp(properties);
 158  
 
 159  87
             if ("replace".equals(action)) {
 160  87
                 clearAll(timestampToUse, typeToUse);
 161  87
                 if (!quiet) {
 162  6
                     getTaskLogger().log("Finished clearing due to " + action);
 163  
                 }
 164  
             }
 165  0
         } catch (IOException e) {
 166  0
             throw new BuildException("Cannot create file ", e);
 167  0
         } catch (SAXException e) {
 168  0
             throw new BuildException("Cannot parse file ", e);
 169  0
         } catch (ClassNotFoundException e) {
 170  0
             throw new BuildException("Cannot find class ", e);
 171  0
         } catch (ParserConfigurationException e) {
 172  0
             throw new BuildException("Issue with ParserConfiguration ", e);
 173  
         } finally {
 174  87
             if (stream != null) {
 175  
                 try {
 176  87
                     stream.close();
 177  0
                 } catch (IOException e) {
 178  0
                     throw new BuildException("Cannot close streams", e);
 179  87
                 }
 180  
             }
 181  87
             if (!quiet) {
 182  6
                 getTaskLogger().log("Finished Configuring XML streams.");
 183  6
             }
 184  0
         }
 185  87
     }
 186  
 
 187  
     /**
 188  
      * @param properties
 189  
      */
 190  
     private void loadActionAndStamp(final Properties properties) {
 191  87
         final String actionToUse = properties.getProperty("qalab.merge.action");
 192  
 
 193  87
         if (actionToUse != null) {
 194  3
             action = actionToUse.toLowerCase(Locale.ENGLISH);
 195  
         }
 196  
 
 197  87
         if (!quiet) {
 198  6
             getTaskLogger().log("ACTION: " + action);
 199  
         }
 200  
 
 201  
         // now check the timeStamp
 202  87
         timestampToUse = properties.getProperty("qalab.merge.output.timestamp");
 203  
 
 204  87
         if (!quiet) {
 205  6
             getTaskLogger().log("Timestamp to use:" + timestampToUse);
 206  
         }
 207  
 
 208  87
         typeToUse = properties.getProperty("qalab.merge.type");
 209  87
     }
 210  
 
 211  
     /**
 212  
      * @param properties
 213  
      * @param factory
 214  
      * @return
 215  
      * @throws IOException
 216  
      * @throws FileNotFoundException
 217  
      * @throws ClassNotFoundException
 218  
      * @throws SAXException
 219  
      * @throws ParserConfigurationException
 220  
      */
 221  
     private InputStream parseOriginalDocument(final Properties properties, DocumentBuilderFactory factory) throws IOException,
 222  
             ClassNotFoundException, SAXException, ParserConfigurationException {
 223  
         InputStream stream;
 224  87
         final String file = properties.getProperty("qalab.merge.output.file");
 225  
 
 226  87
         if (file != null) {
 227  15
             outputFile = new File(file);
 228  
 
 229  15
             if (!quiet) {
 230  0
                 getTaskLogger().log("Parsing " + outputFile);
 231  
             }
 232  
 
 233  15
             if (!outputFile.exists()) {
 234  
                 // create the new file.
 235  15
                 if (outputFile.createNewFile()) {
 236  15
                     FileWriter stringOut = null;
 237  
 
 238  
                     try {
 239  15
                         stringOut = new FileWriter(outputFile);
 240  15
                         stringOut.write(EMPTY_FILE);
 241  15
                         stringOut.flush();
 242  
                     } finally {
 243  15
                         if (stringOut != null) {
 244  15
                             stringOut.close();
 245  15
                         }
 246  0
                     }
 247  15
                 } else {
 248  0
                     throw new BuildException("Cannot create file " + outputFile.getAbsolutePath());
 249  
                 }
 250  
             }
 251  
 
 252  15
             if (!quiet) {
 253  0
                 getTaskLogger().log("Output file: " + outputFile.getAbsolutePath());
 254  
             }
 255  
 
 256  15
             stream = new FileInputStream(outputFile);
 257  15
         } else {
 258  72
             final String resourceName = properties.getProperty("qalab.merge.output.resourcename");
 259  72
             final String className = properties.getProperty("qalab.merge.output.classname");
 260  
 
 261  72
             if (!quiet) {
 262  6
                 getTaskLogger().log("Using Stream: " + resourceName + " for " + className);
 263  
             }
 264  
 
 265  72
             stream = Class.forName(className).getResourceAsStream(resourceName);
 266  
         }
 267  
 
 268  
         // Create the builder and parse the file
 269  87
         compiledStats = factory.newDocumentBuilder().parse(new InputSource(stream));
 270  87
         return stream;
 271  
     }
 272  
 
 273  
     private void validateXmlVersion(Document doc) {
 274  87
         Element qalab = getElement(doc.getElementsByTagName("qalab"));
 275  
 
 276  87
         if (qalab != null) {
 277  87
             currentXmlVersion = qalab.getAttribute("version");
 278  87
             if (currentXmlVersion == null || !currentXmlVersion.equals(XML_VERSION)) {
 279  0
                 getTaskLogger().log("Inadequate DTD, must change it to " + XML_VERSION);
 280  0
                 qalab.setAttribute("version", XML_VERSION);
 281  
                 // now handle the change... from null or whatever to
 282  
                 // XML_VERSION.
 283  0
                 changeXmlToDtdV11(qalab);
 284  
             }
 285  
         }
 286  87
     }
 287  
 
 288  
     /**
 289  
      * @param qalab
 290  
      */
 291  
     private void changeXmlToDtdV11(Element qalab) {
 292  0
         NodeList list = qalab.getChildNodes();
 293  0
         for (int i = 0; i < list.getLength(); i++) {
 294  0
             Node childNode = list.item(i);
 295  0
             if (childNode.getNodeType() == Node.ELEMENT_NODE) {
 296  0
                 if (QALabTags.FILE_TAG.equals(childNode.getNodeName())) {
 297  0
                     Element fileNode = (Element) list.item(i);
 298  0
                     String id = fileNode.getAttribute(QALabTags.ID_ATTRIBUTE);
 299  0
                     fileNode.setAttribute(QALabTags.ID_ATTRIBUTE, id.replace('/', '_'));
 300  0
                     fileNode.setAttribute(QALabTags.PATH_ATTRIBUTE, id);
 301  
                     // now in the results, check the timestamp
 302  0
                     NodeList results = fileNode.getChildNodes();
 303  0
                     for (int u = 0; u < results.getLength(); u++) {
 304  0
                         Node resultNode = results.item(u);
 305  0
                         if (resultNode.getNodeType() == Node.ELEMENT_NODE
 306  
                                 && QALabTags.RESULT_TAG.equals(resultNode.getNodeName())) {
 307  0
                             Element resultElement = (Element) resultNode;
 308  0
                             String timestamp = resultElement.getAttribute(QALabTags.DATE_ATTRIBUTE);
 309  0
                             dropMidnight(resultElement, timestamp);
 310  
                         }
 311  
                     }
 312  0
                 } else if (QALabTags.SUMMARY_TAG.equals(childNode.getNodeName())) {
 313  0
                     Element summaryNode = (Element) list.item(i);
 314  
                     // now in the results, check the timestamp
 315  0
                     NodeList results = summaryNode.getChildNodes();
 316  0
                     for (int u = 0; u < results.getLength(); u++) {
 317  0
                         Node resultNode = results.item(u);
 318  0
                         if (resultNode.getNodeType() == Node.ELEMENT_NODE
 319  
                                 && QALabTags.SUMMARY_RESULT_TAG.equals(resultNode.getNodeName())) {
 320  0
                             Element resultElement = (Element) resultNode;
 321  0
                             String timestamp = resultElement.getAttribute(QALabTags.DATE_ATTRIBUTE);
 322  0
                             dropMidnight(resultElement, timestamp);
 323  
                         }
 324  
                     }
 325  
                 }
 326  
             }
 327  
         }
 328  0
     }
 329  
 
 330  
     /**
 331  
      * Remove the 00:00:00 from timestamp.
 332  
      * 
 333  
      * @param resultElement
 334  
      * @param timestamp
 335  
      */
 336  
     private void dropMidnight(Element resultElement, String timestamp) {
 337  0
         final int indexOf = timestamp.indexOf(" 00:00:00");
 338  0
         if (indexOf > 0) {
 339  0
             resultElement.setAttribute(QALabTags.DATE_ATTRIBUTE, timestamp.substring(0, indexOf));
 340  
         }
 341  0
     }
 342  
 
 343  
     /**
 344  
      * Add summary details for this merger of statistics for this type.
 345  
      * 
 346  
      * @param violationCount
 347  
      *            total number of violations for this type
 348  
      * @param fileCount
 349  
      *            total number of files affected by this type.
 350  
      */
 351  
     public final void addSummary(final int violationCount, final int fileCount) {
 352  57
         NodeList list = compiledStats.getElementsByTagName(QALabTags.SUMMARY_TAG);
 353  
 
 354  57
         for (int i = 0; i < list.getLength(); i++) {
 355  57
             Node childNode = list.item(i);
 356  
 
 357  57
             if (childNode.getNodeType() == Node.ELEMENT_NODE) {
 358  57
                 Element summary = (Element) childNode;
 359  57
                 Element foundSummaryResult = summary.getOwnerDocument().createElement(QALabTags.SUMMARY_RESULT_TAG);
 360  
 
 361  57
                 foundSummaryResult.setAttribute(QALabTags.TYPE_ATTRIBUTE, typeToUse);
 362  57
                 foundSummaryResult.setAttribute(QALabTags.FILECOUNT_ATTRIBUTE, "" + fileCount);
 363  57
                 foundSummaryResult.setAttribute(QALabTags.STATVALUE_ATTRIBUTE, "" + violationCount);
 364  57
                 foundSummaryResult.setAttribute(QALabTags.DATE_ATTRIBUTE, timestampToUse);
 365  
 
 366  57
                 summary.appendChild(foundSummaryResult);
 367  
 
 368  57
                 if (!isQuiet()) {
 369  6
                     getTaskLogger().log("Summary:" + typeToUse + " file:" + fileCount + " issues:" + violationCount);
 370  6
                 }
 371  
 
 372  
                 break;
 373  
             }
 374  
         }
 375  57
     }
 376  
 
 377  
     /**
 378  
      * Add a result entry for a given file name and type.
 379  
      * 
 380  
      * @param violationCount
 381  
      *            total number of violations for this type and file.
 382  
      * @param fileName
 383  
      *            file name
 384  
      * @see net.objectlab.qalab.interfaces.QALabExporter#addFileResult(
 385  
      *      java.util.Date, int, java.lang.String, java.lang.String)
 386  
      */
 387  
     public final void addFileResult(final int violationCount, final String fileName) {
 388  159
         String id = fileName.replace('/', '_');
 389  159
         Element fileElement = compiledStats.getElementById(id);
 390  
 
 391  159
         if (!isQuiet()) {
 392  33
             taskLogger.log("* addNewResults for [" + fileName + "] Element:" + id);
 393  
         }
 394  
 
 395  159
         if (fileElement == null) {
 396  84
             if (!isQuiet()) {
 397  0
                 taskLogger.log("Create file new ENTRY......");
 398  
             }
 399  
 
 400  84
             fileElement = compiledStats.createElement(QALabTags.FILE_TAG);
 401  84
             fileElement.setAttribute(QALabTags.ID_ATTRIBUTE, id);
 402  84
             fileElement.setAttribute(QALabTags.PATH_ATTRIBUTE, fileName);
 403  84
             compiledStats.getDocumentElement().appendChild(fileElement);
 404  
         }
 405  159
         Element newResult = compiledStats.createElement(QALabTags.RESULT_TAG);
 406  
 
 407  159
         newResult.setAttribute(QALabTags.TYPE_ATTRIBUTE, typeToUse);
 408  159
         newResult.setAttribute(QALabTags.STATVALUE_ATTRIBUTE, "" + violationCount);
 409  159
         newResult.setAttribute(QALabTags.DATE_ATTRIBUTE, timestampToUse);
 410  159
         fileElement.appendChild(newResult);
 411  159
     }
 412  
 
 413  
     /**
 414  
      * Find the element in the children that has the same timestamp and type.
 415  
      * 
 416  
      * @param startingElement
 417  
      *            the start element in the DOM
 418  
      * @param timestampStr
 419  
      *            the timestamp
 420  
      * @param type
 421  
      *            the type we are looking for.
 422  
      * @return Element or null if not found
 423  
      */
 424  
     private Element findSameTypeAndTimestamp(final Element startingElement, final String timestampStr, final String type) {
 425  219
         Element newResult = null;
 426  219
         NodeList fileResults = startingElement.getChildNodes();
 427  
 
 428  219
         if ("replace".equals(action)) {
 429  711
             for (int u = 0; u < fileResults.getLength() && newResult == null; u++) {
 430  492
                 Node resultNode = fileResults.item(u);
 431  
 
 432  492
                 if (resultNode.getNodeType() == Node.ELEMENT_NODE) {
 433  171
                     final String stamp = Util.getAttributeValue(resultNode.getAttributes(), "date", isQuiet(), getTaskLogger());
 434  171
                     final String existingType = Util.getAttributeValue(resultNode.getAttributes(), "type", isQuiet(),
 435  
                             getTaskLogger());
 436  171
                     if (timestampStr.equals(stamp) && type.equals(existingType)) {
 437  21
                         newResult = (Element) resultNode;
 438  
                     }
 439  
                 }
 440  
             }
 441  
         }
 442  219
         return newResult;
 443  
     }
 444  
 
 445  
     /**
 446  
      * Save the stats (called when the parsing of input statistics is
 447  
      * completed).
 448  
      * 
 449  
      * @see net.objectlab.qalab.interfaces.QALabExporter#save()
 450  
      */
 451  
     public final void save() throws IOException {
 452  15
         OutputFormat format = new OutputFormat(compiledStats, "UTF-8", true);
 453  15
         FileWriter stringOut = new FileWriter(outputFile);
 454  
 
 455  15
         if (!XML_VERSION.equals(currentXmlVersion)) {
 456  
             // replace DTD!
 457  0
             StringWriter sw = new StringWriter();
 458  0
             XMLSerializer serial = new XMLSerializer(sw, format);
 459  
 
 460  0
             serial.asDOMSerializer(); // As a DOM Serializer
 461  0
             serial.serialize(compiledStats);
 462  0
             sw.flush();
 463  0
             sw.close();
 464  0
             StringBuffer newXml = new StringBuffer(sw.getBuffer().substring(sw.getBuffer().indexOf("<qalab")));
 465  0
             newXml.insert(0, DTD_DEFINITION);
 466  0
             stringOut.write(newXml.toString());
 467  0
         } else {
 468  15
             XMLSerializer serial = new XMLSerializer(stringOut, format);
 469  
 
 470  15
             serial.asDOMSerializer(); // As a DOM Serializer
 471  15
             serial.serialize(compiledStats);
 472  
         }
 473  15
         stringOut.flush();
 474  15
         stringOut.close();
 475  15
     }
 476  
 
 477  
     /**
 478  
      * @return logger to use if not quiet.
 479  
      */
 480  
     protected final TaskLogger getTaskLogger() {
 481  405
         return taskLogger;
 482  
     }
 483  
 
 484  
     /**
 485  
      * set the task logger, ie mechanism to log issues & debug info.
 486  
      * 
 487  
      * @param task
 488  
      *            the logger to use
 489  
      */
 490  
     public final void setTaskLogger(final TaskLogger task) {
 491  87
         taskLogger = task;
 492  87
     }
 493  
 
 494  
     /**
 495  
      * @return true means that no debug info is logged.
 496  
      */
 497  
     public final boolean isQuiet() {
 498  663
         return quiet;
 499  
     }
 500  
 
 501  
     /**
 502  
      * @param noLog
 503  
      *            true if no log required.
 504  
      */
 505  
     public final void setQuiet(final boolean noLog) {
 506  87
         this.quiet = noLog;
 507  87
     }
 508  
 
 509  
     /**
 510  
      * @return the compiled document.
 511  
      */
 512  
     public final Document getDocument() {
 513  282
         return compiledStats;
 514  
     }
 515  
 
 516  
     /**
 517  
      * get rid of the element with same timestamp and type.
 518  
      * 
 519  
      * @param timestampStr
 520  
      *            the timestamp to eliminate
 521  
      * @param type
 522  
      *            the type to eliminate
 523  
      */
 524  
     private void clearAll(final String timestampStr, final String type) {
 525  
         // first get rid of the summary
 526  87
         NodeList list = compiledStats.getElementsByTagName(QALabTags.SUMMARY_TAG);
 527  87
         clearChildren(list, timestampStr, type);
 528  
 
 529  
         // first get rid of the files
 530  87
         NodeList listFiles = compiledStats.getElementsByTagName(QALabTags.FILE_TAG);
 531  87
         clearChildren(listFiles, timestampStr, type);
 532  87
     }
 533  
 
 534  
     /**
 535  
      * get rid of the element with same timestamp and type.
 536  
      * 
 537  
      * @param list
 538  
      *            list of nodes that may contain items with same timestamp and
 539  
      *            type.
 540  
      * @param timestampStr
 541  
      *            the timestamp to eliminate
 542  
      * @param type
 543  
      *            the type to eliminate
 544  
      */
 545  
     private void clearChildren(final NodeList list, final String timestampStr, final String type) {
 546  393
         for (int i = 0; i < list.getLength(); i++) {
 547  219
             Node childNode = list.item(i);
 548  
 
 549  219
             if (childNode.getNodeType() == Node.ELEMENT_NODE) {
 550  219
                 Element summary = (Element) childNode;
 551  
 
 552  219
                 Element foundSummaryResult = findSameTypeAndTimestamp(summary, timestampStr, type);
 553  
 
 554  
                 // get rid of it!
 555  219
                 if (foundSummaryResult != null) {
 556  21
                     if (!isQuiet()) {
 557  21
                         getTaskLogger()
 558  
                                 .log("Removing element due to same type and timestamp " + foundSummaryResult.getNodeName());
 559  
                     }
 560  21
                     childNode.removeChild(foundSummaryResult);
 561  
                 }
 562  
             }
 563  
         }
 564  174
     }
 565  
 
 566  
     private Element getElement(NodeList list) {
 567  87
         for (int i = 0; i < list.getLength(); i++) {
 568  87
             Node childNode = list.item(i);
 569  87
             if (childNode.getNodeType() == Node.ELEMENT_NODE) {
 570  87
                 return (Element) childNode;
 571  
             }
 572  
         }
 573  0
         return null;
 574  
     }
 575  
 }
 576  
 /*
 577  
  *                   ObjectLab is sponsoring QALab
 578  
  * 
 579  
  * Based in London, we are world leaders in the design and development 
 580  
  * of bespoke applications for the securities financing markets.
 581  
  * 
 582  
  * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a>
 583  
  *           ___  _     _           _   _          _
 584  
  *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
 585  
  *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
 586  
  *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
 587  
  *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
 588  
  *                   |__/
 589  
  *
 590  
  *                     www.ObjectLab.co.uk
 591  
  */