1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package gov.nist.secauto.decima.xml.assessment.schematron;
28
29 import gov.nist.secauto.decima.core.assessment.AbstractAssessment;
30 import gov.nist.secauto.decima.core.assessment.Assessment;
31 import gov.nist.secauto.decima.core.assessment.AssessmentException;
32 import gov.nist.secauto.decima.core.assessment.result.AssessmentResultBuilder;
33 import gov.nist.secauto.decima.xml.document.XMLDocument;
34 import gov.nist.secauto.decima.xml.schematron.Schematron;
35 import gov.nist.secauto.decima.xml.schematron.SchematronCompilationException;
36 import gov.nist.secauto.decima.xml.schematron.SchematronEvaluationException;
37
38 import org.apache.logging.log4j.LogManager;
39 import org.apache.logging.log4j.Logger;
40 import org.jdom2.Document;
41 import org.jdom2.JDOMException;
42 import org.jdom2.input.SAXBuilder;
43 import org.jdom2.input.sax.SAXEngine;
44 import org.jdom2.output.XMLOutputter;
45 import org.jdom2.transform.JDOMResult;
46
47 import java.io.BufferedOutputStream;
48 import java.io.File;
49 import java.io.FileOutputStream;
50 import java.io.IOException;
51 import java.io.OutputStream;
52 import java.util.Collections;
53 import java.util.HashMap;
54 import java.util.Map;
55 import java.util.Objects;
56
57 import javax.xml.transform.Result;
58 import javax.xml.transform.stream.StreamResult;
59
60 public class SchematronAssessment
61 extends AbstractAssessment<XMLDocument> {
62 private static final Logger log = LogManager.getLogger(SchematronAssessment.class);
63 public static final String ASSESSMENT_TYPE = "Schematron";
64 private static final XMLOutputter DEFAULT_XML_OUTPUTTER = new XMLOutputter();
65
66 private final Schematron schematron;
67 private final String phase;
68 private final SchematronHandler schematronHandler;
69
70 private final Map<String, String> parameters = new HashMap<>();
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 public SchematronAssessment(Schematron schematron, String phase, SchematronHandler schematronHandler) {
87 Objects.requireNonNull(schematron, "schematron");
88 Objects.requireNonNull(schematronHandler, "schematronHandler");
89 this.schematron = schematron;
90 this.phase = phase;
91 this.schematronHandler = schematronHandler;
92
93 if (log.isInfoEnabled()) {
94 StringBuilder sb = new StringBuilder();
95 sb.append('[');
96 sb.append(getId());
97 sb.append(']');
98 sb.append("Creating a Schematron assessment using schematron '");
99 sb.append(schematron.getPath());
100 sb.append("'");
101
102 if (phase != null) {
103 sb.append(" with phase '");
104 sb.append(phase);
105 sb.append("'");
106 }
107 log.info(sb.toString());
108 }
109 }
110
111 public Schematron getSchematron() {
112 return schematron;
113 }
114
115 public String getPhase() {
116 return phase;
117 }
118
119 protected SchematronHandler getSchematronHandler() {
120 return schematronHandler;
121 }
122
123 public Map<String, String> getParameters() {
124 return Collections.unmodifiableMap(this.parameters);
125 }
126
127 @Override
128 protected void executeInternal(XMLDocument doc, AssessmentResultBuilder builder) throws AssessmentException {
129
130 File resultDir = getResultDirectory();
131 if (resultDir != null) {
132 Document compiledSchematron;
133 try {
134 compiledSchematron = getSchematron().getCompiledSchematron(getPhase());
135 } catch (SchematronCompilationException e) {
136 throw new AssessmentException("Unable to get compiled schematron", e);
137 }
138
139 File schematronXslFile = new File(resultDir, "schematron.xsl");
140 try (OutputStream os = new BufferedOutputStream(new FileOutputStream(schematronXslFile))) {
141 DEFAULT_XML_OUTPUTTER.output(compiledSchematron, os);
142 } catch (IOException e) {
143 throw new AssessmentException("Unable to output the compiled schematron to: " + schematronXslFile.getPath(), e);
144 }
145 }
146
147 File svrlFile;
148 if (resultDir != null) {
149 svrlFile = new File(resultDir, "svrl.xml");
150 } else {
151
152
153
154
155
156
157 svrlFile = null;
158 }
159 if (log.isDebugEnabled()) {
160 log.debug("[{}]Processing schematron: {}", getId(), getSchematron().getPath());
161 }
162 process(doc, builder, svrlFile);
163 if (log.isDebugEnabled()) {
164 log.debug("[{}]Schematron assessment complete", getId());
165 }
166 }
167
168 protected void process(XMLDocument document, AssessmentResultBuilder builder, File svrlFile)
169 throws AssessmentException {
170
171 Result svrlResult2;
172 if (svrlFile == null) {
173 log.debug("Transforming SVRL results");
174 svrlResult2 = new JDOMResult();
175 } else {
176 log.debug("Transforming SVRL results to: " + svrlFile);
177 svrlResult2 = new StreamResult(svrlFile);
178 }
179
180 try {
181 schematron.transform(document.getSource(), svrlResult2, getPhase(), getParameters());
182 } catch (SchematronEvaluationException ex) {
183 throw new AssessmentException(ex);
184 }
185
186 Document svrlDocument;
187 if (svrlFile == null) {
188 log.debug("Analyzing SVRL results");
189 svrlDocument = ((JDOMResult) svrlResult2).getDocument();
190 } else {
191 try {
192 log.debug("Analyzing SVRL results from: " + svrlFile);
193 SAXEngine saxEngine = new SAXBuilder();
194 svrlDocument = saxEngine.build(svrlFile);
195 } catch (JDOMException | IOException e) {
196 throw new AssessmentException(e);
197 }
198 }
199
200 SVRLHandler svrlHandler = getSchematronHandler().newSVRLHandler(this, document, builder);
201 SVRLParser.parse(svrlHandler, svrlDocument);
202 log.debug("SVRL result analysis completed");
203 }
204
205 @Override
206 public String getAssessmentType() {
207 return ASSESSMENT_TYPE;
208 }
209
210 public void addParameter(String name, String value) {
211 parameters.put(name, value);
212 }
213
214 public void addParameters(Map<String, String> params) {
215 parameters.putAll(params);
216 }
217
218 @Override
219 protected String getNameDetails() {
220 StringBuilder builder = new StringBuilder();
221 builder.append(getSchematron().getPath());
222 String phase = getPhase();
223 if (phase != null) {
224 builder.append("(").append(phase).append(")");
225 }
226 return builder.toString();
227 }
228
229 }