Introduce XSLT report generation
authorMathieu Baudier <mbaudier@argeo.org>
Mon, 5 May 2008 13:22:20 +0000 (13:22 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Mon, 5 May 2008 13:22:20 +0000 (13:22 +0000)
git-svn-id: https://svn.argeo.org/slc/trunk@1126 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

org.argeo.slc.core/pom.xml
org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/tree/AsynchronousTreeTestResultListener.java [deleted file]
org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/tree/TreeTestResultLogger.java
org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/tree/XsltReportGenerator.java [new file with mode: 0644]
org.argeo.slc.core/src/main/resources/org/argeo/slc/core/test/tree/basicReport.xslt [new file with mode: 0644]
org.argeo.slc.core/src/test/resources/org/argeo/slc/ws/result.xml

index 6959e7708bf9cdacd578a5efc117fde752e6bf93..cab5eb90e36310b11d6f4e22d23446cfe9d99c2d 100644 (file)
                        <groupId>hsqldb</groupId>\r
                        <artifactId>hsqldb</artifactId>\r
                </dependency>\r
+               <dependency>\r
+                       <groupId>xalan</groupId>\r
+                       <artifactId>xalan</artifactId>\r
+               </dependency>\r
        </dependencies>\r
 </project>
\ No newline at end of file
diff --git a/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/tree/AsynchronousTreeTestResultListener.java b/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/tree/AsynchronousTreeTestResultListener.java
deleted file mode 100644 (file)
index a3dc33f..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-package org.argeo.slc.core.test.tree;\r
-\r
-import java.util.Vector;\r
-\r
-import org.argeo.slc.core.structure.tree.TreeSPath;\r
-import org.argeo.slc.core.test.TestResult;\r
-import org.argeo.slc.core.test.TestResultListener;\r
-import org.argeo.slc.core.test.TestResultPart;\r
-\r
-/**\r
- * Abstract asynchronous implementation of a listener listening to a\r
- * <code>TreeTestResult</code>.\r
- * \r
- * @deprecated listeners should be called synchronously\r
- * @see TreeTestResult\r
- */\r
-public abstract class AsynchronousTreeTestResultListener implements\r
-               TestResultListener, Runnable {\r
-       private Vector<PartStruct> partStructs = new Vector<PartStruct>();\r
-       private Thread thread;\r
-\r
-       private Boolean synchronous = true;\r
-\r
-       protected AsynchronousTreeTestResultListener() {\r
-               this(true);\r
-       }\r
-\r
-       protected AsynchronousTreeTestResultListener(Boolean synchronousByDefault) {\r
-               synchronous = synchronousByDefault;\r
-       }\r
-\r
-       /** Starts the underlying thread. */\r
-       public void init() {\r
-               if (!synchronous) {\r
-                       thread = new Thread(this);\r
-                       thread.start();\r
-               }\r
-       }\r
-\r
-       /** Finish the remaining and destroy */\r
-       public void close(TestResult testResult) {\r
-               // FIXME: make behavior more robust when multiple results are\r
-               // registering this listener.\r
-               synchronized (partStructs) {\r
-                       // TODO: put a timeout\r
-                       while (partStructs.size() != 0) {\r
-                               try {\r
-                                       partStructs.wait(500);\r
-                               } catch (InterruptedException e) {\r
-                                       // silent\r
-                               }\r
-                       }\r
-                       thread = null;\r
-                       partStructs.notifyAll();\r
-               }\r
-               postClose((TreeTestResult) testResult);\r
-       }\r
-\r
-       public final void resultPartAdded(TestResult testResult,\r
-                       TestResultPart testResultPart) {\r
-               TreeTestResult result = (TreeTestResult) testResult;\r
-               PartStruct partStruct = new PartStruct(result.getCurrentPath(), result\r
-                               .getUuid(), testResultPart, result);\r
-\r
-               if (!synchronous) {\r
-                       synchronized (partStructs) {\r
-                               partStructs.add(partStruct);\r
-                               partStructs.notifyAll();\r
-                       }\r
-               } else {\r
-                       resultPartAdded(partStruct);\r
-               }\r
-       }\r
-\r
-       /** Called when a result part has been added. */\r
-       protected abstract void resultPartAdded(PartStruct partStruct);\r
-\r
-       /**\r
-        * Called at the end of close. Default implementation is empty. To be\r
-        * overridden.\r
-        */\r
-       protected void postClose(TreeTestResult testResult) {\r
-\r
-       }\r
-\r
-       public void run() {\r
-               while (thread != null) {\r
-                       synchronized (partStructs) {\r
-                               for (PartStruct partStruct : partStructs) {\r
-                                       resultPartAdded(partStruct);\r
-                               }\r
-\r
-                               partStructs.clear();\r
-                               partStructs.notifyAll();\r
-                               while (partStructs.size() == 0) {\r
-                                       try {\r
-                                               partStructs.wait();\r
-                                       } catch (InterruptedException e) {\r
-                                               // silent\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       /** Structure used to pass tree specific information to subclasses. */\r
-       protected static class PartStruct {\r
-               /** The tree path of this part. */\r
-               public final TreeSPath path;\r
-               /** The test result id of the related test result */\r
-               public final String uuid;\r
-               /** The part itself */\r
-               public final TestResultPart part;\r
-               /** The tree test result itself. */\r
-               public final TreeTestResult result;\r
-\r
-               /** Constructor */\r
-               public PartStruct(TreeSPath path, String uuid, TestResultPart part,\r
-                               TreeTestResult result) {\r
-                       super();\r
-                       this.path = path;\r
-                       this.uuid = uuid;\r
-                       this.part = part;\r
-                       this.result = result;\r
-               }\r
-\r
-       }\r
-\r
-       public Boolean getSynchronous() {\r
-               return synchronous;\r
-       }\r
-\r
-       public void setSynchronous(Boolean synchronous) {\r
-               this.synchronous = synchronous;\r
-       }\r
-\r
-}\r
index e20614f905f59f3a1fd7e3f34c97eb159c377c47..2246e18b0ef23d4b450c129df73f62fb27df6195 100644 (file)
@@ -3,12 +3,9 @@ package org.argeo.slc.core.test.tree;
 import org.apache.commons.logging.Log;\r
 import org.apache.commons.logging.LogFactory;\r
 \r
-import org.argeo.slc.core.test.SimpleResultPart;\r
-import org.argeo.slc.core.test.TestResult;\r
 import org.argeo.slc.core.test.TestResultListener;\r
 import org.argeo.slc.core.test.TestResultPart;\r
 import org.argeo.slc.core.test.TestStatus;\r
-import org.argeo.slc.core.test.tree.AsynchronousTreeTestResultListener.PartStruct;\r
 \r
 /**\r
  * Listener logging tree-based test results to the underlying logging system.\r
diff --git a/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/tree/XsltReportGenerator.java b/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/tree/XsltReportGenerator.java
new file mode 100644 (file)
index 0000000..059c209
--- /dev/null
@@ -0,0 +1,156 @@
+package org.argeo.slc.core.test.tree;\r
+\r
+import java.io.File;\r
+import java.io.FileOutputStream;\r
+import java.io.InputStream;\r
+import java.io.OutputStream;\r
+\r
+import javax.xml.parsers.DocumentBuilder;\r
+import javax.xml.parsers.DocumentBuilderFactory;\r
+import javax.xml.transform.Templates;\r
+import javax.xml.transform.Transformer;\r
+import javax.xml.transform.TransformerFactory;\r
+import javax.xml.transform.dom.DOMResult;\r
+import javax.xml.transform.dom.DOMSource;\r
+import javax.xml.transform.stream.StreamResult;\r
+import javax.xml.transform.stream.StreamSource;\r
+\r
+import org.springframework.core.io.Resource;\r
+import org.springframework.oxm.Marshaller;\r
+import org.springframework.xml.transform.StringResult;\r
+import org.w3c.dom.Document;\r
+\r
+import org.apache.commons.io.IOUtils;\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+\r
+import org.argeo.slc.core.SlcException;\r
+import org.argeo.slc.core.test.TestResultListener;\r
+import org.argeo.slc.core.test.TestResultPart;\r
+\r
+public class XsltReportGenerator implements TestResultListener<TreeTestResult> {\r
+       private Log log = LogFactory.getLog(getClass());\r
+\r
+       private DocumentBuilder documentBuilder = null;\r
+\r
+       private Resource xsltStyleSheet;\r
+\r
+       private Templates templates;\r
+\r
+       private Marshaller marshaller;\r
+\r
+       private String outputDir;\r
+       private String outputFileExtension = "html";\r
+\r
+       private Boolean logXml = false;\r
+\r
+       public void init() {\r
+               if (templates != null)\r
+                       return;\r
+\r
+               if (xsltStyleSheet == null)\r
+                       throw new SlcException("XSLT style sheet not specified.");\r
+\r
+               InputStream in = null;\r
+               try {\r
+                       TransformerFactory transformerFactory = TransformerFactory\r
+                                       .newInstance();\r
+                       in = xsltStyleSheet.getInputStream();\r
+                       StreamSource xsltSource = new StreamSource(in);\r
+                       templates = transformerFactory.newTemplates(xsltSource);\r
+               } catch (Exception e) {\r
+                       throw new SlcException("Could not initialize templates", e);\r
+               } finally {\r
+                       IOUtils.closeQuietly(in);\r
+               }\r
+       }\r
+\r
+       public void resultPartAdded(TreeTestResult testResult,\r
+                       TestResultPart testResultPart) {\r
+\r
+       }\r
+\r
+       public void close(TreeTestResult testResult) {\r
+               if (templates == null)\r
+                       throw new SlcException("XSLT template not initialized");\r
+\r
+               File file = getFile(testResult);\r
+               OutputStream out = null;\r
+\r
+               try {\r
+                       Transformer transformer = templates.newTransformer();\r
+\r
+                       if (documentBuilder == null)\r
+                               documentBuilder = DocumentBuilderFactory.newInstance()\r
+                                               .newDocumentBuilder();\r
+\r
+                       Document document = documentBuilder.newDocument();\r
+                       DOMResult marshallResult = new DOMResult(document);\r
+                       marshaller.marshal(testResult, marshallResult);\r
+\r
+                       if (logXml) {\r
+                               Transformer identityTransformer = TransformerFactory\r
+                                               .newInstance().newTransformer();\r
+                               StringResult xmlResult = new StringResult();\r
+                               identityTransformer.transform(new DOMSource(marshallResult\r
+                                               .getNode()), xmlResult);\r
+                               log.info("Marshalled XML:\n" + xmlResult);\r
+                       }\r
+\r
+                       DOMSource transfoSource = new DOMSource(marshallResult.getNode());\r
+\r
+                       if (outputDir != null) {\r
+                               File dir = new File(outputDir);\r
+                               dir.mkdirs();\r
+                               out = new FileOutputStream(file);\r
+                               StreamResult outputResult = new StreamResult(out);\r
+                               transformer.transform(transfoSource, outputResult);\r
+                       } else {\r
+                               // print on console if no output dir\r
+                               StringResult result = new StringResult();\r
+                               transformer.transform(transfoSource, result);\r
+                               log.info("Generated report:\n" + result);\r
+                       }\r
+               } catch (Exception e) {\r
+                       throw new SlcException(\r
+                                       "Could not transform test result to " + file, e);\r
+               } finally {\r
+                       IOUtils.closeQuietly(out);\r
+               }\r
+       }\r
+\r
+       public Resource getXsltStyleSheet() {\r
+               return xsltStyleSheet;\r
+       }\r
+\r
+       public void setXsltStyleSheet(Resource xsltStyleSheet) {\r
+               this.xsltStyleSheet = xsltStyleSheet;\r
+       }\r
+\r
+       public void setTemplates(Templates templates) {\r
+               this.templates = templates;\r
+       }\r
+\r
+       public void setMarshaller(Marshaller marshaller) {\r
+               this.marshaller = marshaller;\r
+       }\r
+\r
+       public void setOutputDir(String outputDir) {\r
+               this.outputDir = outputDir;\r
+       }\r
+\r
+       public void setOutputFileExtension(String outputFileExtension) {\r
+               this.outputFileExtension = outputFileExtension;\r
+       }\r
+\r
+       protected File getFile(TreeTestResult result) {\r
+               Long time = System.currentTimeMillis();\r
+               return new File(outputDir + File.separator + time + "-"\r
+                               + result.getUuid() + "." + outputFileExtension);\r
+       }\r
+\r
+       public void setLogXml(Boolean logXml) {\r
+               this.logXml = logXml;\r
+       }\r
+\r
+}\r
diff --git a/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/test/tree/basicReport.xslt b/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/test/tree/basicReport.xslt
new file mode 100644 (file)
index 0000000..947cef0
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<xsl:stylesheet version="1.0"\r
+       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"\r
+       xmlns:slc="http://argeo.org/projects/slc/schemas"\r
+       exclude-result-prefixes="slc">\r
+\r
+       <xsl:output method="html" omit-xml-declaration="yes" />\r
+\r
+       <xsl:template match="/">\r
+               <html>\r
+                       <head>\r
+                               <title>Result</title>\r
+                       </head>\r
+                       <body style="font-family: sans-serif">\r
+                               <h1>\r
+                                       Result\r
+                                       <xsl:value-of select="slc:tree-test-result/@uuid" />\r
+                               </h1>\r
+                               <xsl:for-each\r
+                                       select="slc:tree-test-result/slc:result-parts/slc:result-part">\r
+                                       <h2>\r
+                                               <xsl:value-of select="@path" />\r
+                                       </h2>\r
+                                       <table>\r
+                                               <xsl:for-each\r
+                                                       select="slc:part-sub-list/slc:parts/slc:simple-result-part">\r
+                                                       <tr>\r
+                                                               <xsl:choose>\r
+                                                                       <xsl:when\r
+                                                                               test="slc:status = 'PASSED' ">\r
+                                                                               <td style="color:green">\r
+                                                                                       <xsl:value-of\r
+                                                                                               select="slc:message" />\r
+                                                                               </td>\r
+                                                                       </xsl:when>\r
+                                                                       <xsl:otherwise>\r
+                                                                               <td style="color:red">\r
+                                                                                       <xsl:value-of\r
+                                                                                               select="slc:message" />\r
+                                                                               </td>\r
+                                                                       </xsl:otherwise>\r
+                                                               </xsl:choose>\r
+                                                       </tr>\r
+                                               </xsl:for-each>\r
+                                       </table>\r
+                               </xsl:for-each>\r
+                       </body>\r
+               </html>\r
+       </xsl:template>\r
+</xsl:stylesheet>
\ No newline at end of file
index 36733d18f3233f534b79453cb9a53cf7e4a4c1d2..f2d660caceb4e2dda24ec4ab8eeb3df170aeff9d 100644 (file)
                parent="slcDefault.test.basicTreeTestResult">\r
                <property name="listeners">\r
                        <list merge="true">\r
-                               <ref bean="slcDefault.ws.client.treeTestResultWsNotfier" />\r
+                               <ref\r
+                                       bean="slcDefault.ws.client.treeTestResultWsNotfier" />\r
+                               <ref bean="xsltReportGenerator" />\r
                        </list>\r
                </property>\r
        </bean>\r
+\r
+       <bean id="xsltReportGenerator"\r
+               class="org.argeo.slc.core.test.tree.XsltReportGenerator"\r
+               init-method="init">\r
+               <property name="xsltStyleSheet"\r
+                       value="classpath:/org/argeo/slc/core/test/tree/basicReport.xslt" />\r
+               <property name="marshaller" ref="slcDefault.castor.marshaller" />\r
+               <property name="logXml" value="false" />\r
+               <!-- \r
+               <property name="outputDir" value="D:\dev\test\SLC\SlcReports" />\r
+               -->\r
+       </bean>\r
 </beans>
\ No newline at end of file