1
2
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
24
25
26
27 public final class XMLRenderer implements Renderer {
28
29 private final String encoding;
30
31
32
33
34 public XMLRenderer() {
35 this(System.getProperty("file.encoding"));
36 }
37
38
39
40
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 }