View Javadoc

    1   /**
    2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    3    */
    4   package net.sourceforge.pmd.cpd;
    5
    6   import java.io.StringWriter;
    7   import java.util.Iterator;
    8
    9   import javax.xml.parsers.DocumentBuilder;
    10  import javax.xml.parsers.DocumentBuilderFactory;
    11  import javax.xml.parsers.ParserConfigurationException;
    12  import javax.xml.transform.OutputKeys;
    13  import javax.xml.transform.Transformer;
    14  import javax.xml.transform.TransformerException;
    15  import javax.xml.transform.TransformerFactory;
    16  import javax.xml.transform.dom.DOMSource;
    17  import javax.xml.transform.stream.StreamResult;
    18
    19  import org.w3c.dom.Document;
    20  import org.w3c.dom.Element;
    21
    22  /**
    23   * @author Philippe T'Seyen - original implementation
    24   * @author Romain Pelisse - javax.xml implementation
    25   *
    26   */
    27  public final class XMLRenderer implements Renderer {
    28
    29  	private final String encoding;
    30
    31  	/**
    32  	 * Creates a XML Renderer with the default (platform dependent) encoding.
    33  	 */
    34  	public XMLRenderer() {
    35  		this(System.getProperty("file.encoding"));
    36  	}
    37
    38  	/**
    39  	 * Creates a XML Renderer with a specific output encoding.
    40  	 * @param encoding the encoding to use
    41  	 */
    42  	public XMLRenderer(String encoding) {
    43  		this.encoding = encoding;
    44  	}
    45
    46  	private Document createDocument() {
    47      	try {
    48  			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    49  			DocumentBuilder parser = factory.newDocumentBuilder();
    50  			return parser.newDocument();
    51  		} catch (ParserConfigurationException e) {
    52  			throw new IllegalStateException(e);
    53  		}
    54  	}
    55
    56  	private String xmlDocToString(Document doc) {
    57          try {
    58  	        TransformerFactory tf = TransformerFactory.newInstance();
    59  	        Transformer transformer = tf.newTransformer();
    60  	        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
    61  	        transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
    62  	        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    63  	        transformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, "codefragment");
    64  	        StringWriter writer = new StringWriter();
    65  	        transformer.transform(new DOMSource(doc), new StreamResult(writer));
    66  	        return writer.getBuffer().toString();
    67          }  catch (TransformerException e) {
    68          	throw new IllegalStateException(e);
    69  		}
    70  	}
    71
    72      public String render(Iterator<Match> matches) {
    73      	Document doc = createDocument();
    74  		Element root = doc.createElement("pmd-cpd");
    75  		doc.appendChild(root);
    76
    77          Match match;
    78          while (matches.hasNext()) {
    79              match = matches.next();
    80              root.appendChild( addCodeSnippet(doc, addFilesToDuplicationElement(doc, createDuplicationElement(doc, match), match), match ) );
    81          }
    82          return xmlDocToString(doc);
    83      }
    84
    85      private Element addFilesToDuplicationElement(Document doc, Element duplication, Match match) {
    86      	TokenEntry mark;
    87          for (Iterator<TokenEntry> iterator = match.iterator(); iterator.hasNext();) {
    88              mark = iterator.next();
    89              Element file = doc.createElement("file");
    90              file.setAttribute("line", String.valueOf(mark.getBeginLine()));
    91              file.setAttribute("path", mark.getTokenSrcID());
    92              duplication.appendChild(file);
    93          }
    94          return duplication;
    95      }
    96
    97      private Element addCodeSnippet(Document doc, Element duplication, Match match) {
    98          String codeSnipet = match.getSourceCodeSlice();
    99          if (codeSnipet != null) {
    100         	Element codefragment = doc.createElement("codefragment");
    101             codefragment.appendChild(doc.createCDATASection(codeSnipet));
    102             duplication.appendChild(codefragment);
    103         }
    104         return duplication;
    105     }
    106
    107     private Element createDuplicationElement(Document doc, Match match) {
    108         Element duplication = doc.createElement("duplication");
    109         duplication.setAttribute("lines", String.valueOf(match.getLineCount()));
    110         duplication.setAttribute("tokens", String.valueOf(match.getTokenCount()));
    111         return duplication;
    112     }
    113 }