View Javadoc
1   /*
2    * Copyright 2009 the original author or authors.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *     
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.openehealth.ipf.commons.xml;
17  
18  import java.io.StringReader;
19  import java.util.Map;
20  
21  import javax.xml.transform.Source;
22  import javax.xml.transform.Templates;
23  import javax.xml.transform.stream.StreamSource;
24  
25  import org.slf4j.Logger;
26  import org.slf4j.LoggerFactory;
27  
28  /**
29   * Converts a XML document into a Schematron validation report by applying
30   * Schematron rules. The rules to be used are passed in with the
31   * {@link #zap(Source, Object...)} call, however, the resulting Xslt Template
32   * object is cached for subsequent transformations using this stylesheet.
33   * <p>
34   * The following standard Schematron parameters can be passed in as Map
35   * parameter:
36   * <ul>
37   * <li>phase : NMTOKEN | "#ALL" (default) Select the phase for validation
38   * <li>allow-foreign : "true" | "false" (default) Pass non-Schematron elements
39   * and rich markup to the generated stylesheet
40   * <li>diagnose : "true" (default) | "false" Add the diagnostics to the
41   * assertion test in reports
42   * <li>property : "true" (default) | "false" Experimental: Add properties to the
43   * assertion test in reports
44   * <li>generate-paths : "true" (default) | "false" Generate the @location
45   * attribute with XPaths
46   * <li>sch.exslt.imports : semi-colon delimited string of filenames for some
47   * EXSLT implementations
48   * <li>optimize : "visit-no-attributes" Use only when the schema has no
49   * attributes as the context nodes
50   * <li>generate-fired-rule: "true" (default) | "false" Generate fired-rule
51   * elements
52   * </ul>
53   * <p>
54   * 
55   * @author Christian Ohr
56   */
57  public class SchematronTransmogrifier<T> extends XsltTransmogrifier<T> {
58  
59      private final static Logger LOG = LoggerFactory.getLogger(SchematronTransmogrifier.class);
60  
61      private final XsltTransmogrifier<String> xsltTransmogrifier;
62  
63      @SuppressWarnings("unchecked")
64      public SchematronTransmogrifier() {
65          this((Class<T>) String.class);
66      }
67  
68      public SchematronTransmogrifier(Class<T> outputFormat) {
69          this(new XsltTransmogrifier<>(String.class), outputFormat);
70      }
71      
72      public SchematronTransmogrifier(Class<T> outputFormat, Map<String, Object> staticParams) {
73          this(new XsltTransmogrifier<>(String.class), outputFormat, staticParams);
74      }
75  
76      public SchematronTransmogrifier(XsltTransmogrifier<String> t, Class<T> outputFormat) {
77          super(outputFormat);
78          xsltTransmogrifier = t;
79      }
80      
81      public SchematronTransmogrifier(XsltTransmogrifier<String> t, Class<T> outputFormat, Map<String, Object> staticParams) {
82          super(outputFormat, staticParams);
83          xsltTransmogrifier = t;
84      }
85  
86      @Override
87      protected String resourceCacheKey(Object... params) {
88          String phase = null;
89          if (params[0] instanceof SchematronProfile) {
90              SchematronProfile schematronProfile = (SchematronProfile) params[0];
91              Map<String, Object> parameters = schematronProfile.getParameters();
92              if (parameters != null) {
93                  phase = (String) parameters.get("phase");
94              }
95          }
96          return (phase != null)
97                  ? resourceLocation(params) + '\n' + phase
98                  : resourceLocation(params);
99      }
100 
101     @Override
102     protected Templates createResource(Object... params) {
103         try {
104             LOG.debug("Creating new Schematron stylesheet");
105             Source rules = resourceContent(params);
106             Map<String, Object> parameters = resourceParameters(params);
107             LOG.debug("step 1 of 3");
108             Source source = step(xsltTransmogrifier, rules,
109                     "/schematron/iso_dsdl_include.xsl", parameters);
110             LOG.debug("step 2 of 3");
111             source = step(xsltTransmogrifier, source,
112                     "/schematron/iso_abstract_expand.xsl", parameters);
113             LOG.debug("step 3 of 3");
114             source = step(xsltTransmogrifier, source,
115                     "/schematron/iso_svrl_for_xslt2.xsl", parameters);
116             Templates template = getFactory().newTemplates(source);
117             LOG.debug("done!");
118             return template;
119         } catch (Exception e) {
120             throw new IllegalArgumentException("The schematron rules resource "
121                     + resourceLocation(params) + " is not valid", e);
122         }
123     }
124 
125     private static Source step(XsltTransmogrifier<String> t, Source input,
126             String stylesheet, Map<String, Object> params) {
127         String s = t.zap(input, stylesheet, params);
128         return new StreamSource(new StringReader(s));
129     }
130 
131 }