1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.helger.schematron.xslt;
18
19 import java.io.File;
20
21 import javax.annotation.Nonnull;
22 import javax.annotation.Nullable;
23 import javax.annotation.concurrent.NotThreadSafe;
24 import javax.xml.transform.Templates;
25 import javax.xml.transform.Transformer;
26 import javax.xml.transform.TransformerConfigurationException;
27 import javax.xml.transform.dom.DOMResult;
28
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31 import org.w3c.dom.Document;
32
33 import com.helger.commons.ValueEnforcer;
34 import com.helger.commons.io.file.FilenameHelper;
35 import com.helger.commons.io.file.SimpleFileIO;
36 import com.helger.commons.io.resource.ClassPathResource;
37 import com.helger.commons.io.resource.IReadableResource;
38 import com.helger.schematron.SchematronDebug;
39 import com.helger.schematron.saxon.SchematronTransformerFactory;
40 import com.helger.schematron.xslt.SCHTransformerCustomizer.EStep;
41 import com.helger.xml.serialize.write.XMLWriter;
42 import com.helger.xml.serialize.write.XMLWriterSettings;
43 import com.helger.xml.transform.TransformSourceFactory;
44 import com.helger.xml.transform.XMLTransformerFactory;
45
46
47
48
49
50
51
52
53 @NotThreadSafe
54 public class SchematronProviderXSLTFromSCH implements ISchematronXSLTBasedProvider
55 {
56 private static final Logger s_aLogger = LoggerFactory.getLogger (SchematronProviderXSLTFromSCH.class);
57
58
59
60
61 public static final String SCHEMATRON_DIRECTORY_XSLT2 = "schematron/20100710-xslt2/";
62
63
64
65
66 public static final String XSLT2_STEP1 = SCHEMATRON_DIRECTORY_XSLT2 + "iso_dsdl_include.xsl";
67
68
69
70
71 public static final String XSLT2_STEP2 = SCHEMATRON_DIRECTORY_XSLT2 + "iso_abstract_expand.xsl";
72
73
74
75
76 public static final String XSLT2_STEP3 = SCHEMATRON_DIRECTORY_XSLT2 + "iso_svrl_for_xslt2.xsl";
77
78 private static volatile Templates s_aStep1;
79 private static volatile Templates s_aStep2;
80 private static volatile Templates s_aStep3;
81
82 private final IReadableResource m_aSchematronResource;
83 private Document m_aSchematronXSLTDoc;
84 private Templates m_aSchematronXSLTTemplates;
85
86 @Deprecated
87 public static final boolean isSaveIntermediateFiles ()
88 {
89 return SchematronDebug.isSaveIntermediateXSLTFiles ();
90 }
91
92 @Deprecated
93 public static final void setSaveIntermediateFiles (final boolean bSaveIntermediateFiles)
94 {
95 SchematronDebug.setSaveIntermediateXSLTFiles (bSaveIntermediateFiles);
96 }
97
98 @Nonnull
99 @Deprecated
100 public static final File getIntermediateMinifiedSCHFolder ()
101 {
102 return SchematronDebug.getIntermediateMinifiedSCHFolder ();
103 }
104
105 @Deprecated
106 public static final void setIntermediateMinifiedSCHFolder (@Nonnull final File aIntermediateMinifiedSCHFolder)
107 {
108 SchematronDebug.setIntermediateMinifiedSCHFolder (aIntermediateMinifiedSCHFolder);
109 }
110
111 @Nonnull
112 @Deprecated
113 public static final File getIntermediateFinalXSLTFolder ()
114 {
115 return SchematronDebug.getIntermediateFinalXSLTFolder ();
116 }
117
118 @Deprecated
119 public static final void setIntermediateFinalXSLTFolder (@Nonnull final File aIntermediateFinalXSLTFolder)
120 {
121 SchematronDebug.setIntermediateFinalXSLTFolder (aIntermediateFinalXSLTFolder);
122 }
123
124 public static void cacheXSLTTemplates ()
125 {
126
127 if (s_aStep1 == null)
128 {
129 if (s_aLogger.isDebugEnabled ())
130 s_aLogger.debug ("Creating XSLT step 1 template");
131 s_aStep1 = XMLTransformerFactory.newTemplates (SchematronTransformerFactory.getDefaultSaxonFirst (),
132 new ClassPathResource (XSLT2_STEP1));
133 }
134 if (s_aStep2 == null)
135 {
136 if (s_aLogger.isDebugEnabled ())
137 s_aLogger.debug ("Creating XSLT step 2 template");
138 s_aStep2 = XMLTransformerFactory.newTemplates (SchematronTransformerFactory.getDefaultSaxonFirst (),
139 new ClassPathResource (XSLT2_STEP2));
140 }
141 if (s_aStep3 == null)
142 {
143 if (s_aLogger.isDebugEnabled ())
144 s_aLogger.debug ("Creating XSLT step 3 template");
145 s_aStep3 = XMLTransformerFactory.newTemplates (SchematronTransformerFactory.getDefaultSaxonFirst (),
146 new ClassPathResource (XSLT2_STEP3));
147 }
148 }
149
150
151
152
153
154
155
156
157
158
159 public SchematronProviderXSLTFromSCH (@Nonnull final IReadableResource aSchematronResource,
160 @Nonnull final SCHTransformerCustomizer aTransformerCustomizer)
161 {
162 m_aSchematronResource = ValueEnforcer.notNull (aSchematronResource, "SchematronResource");
163 ValueEnforcer.notNull (aTransformerCustomizer, "TransformerCustomizer");
164
165 try
166 {
167 cacheXSLTTemplates ();
168
169
170 final DOMResult aResult1 = new DOMResult ();
171 final Transformer aTransformer1 = s_aStep1.newTransformer ();
172 aTransformerCustomizer.customize (EStep.SCH2XSLT_1, aTransformer1);
173 aTransformer1.transform (TransformSourceFactory.create (aSchematronResource), aResult1);
174
175 if (s_aLogger.isDebugEnabled ())
176 s_aLogger.debug ("Finished applying XSLT step 1 on " + aSchematronResource);
177
178
179 final DOMResult aResult2 = new DOMResult ();
180 final Transformer aTransformer2 = s_aStep2.newTransformer ();
181 aTransformerCustomizer.customize (EStep.SCH2XSLT_2, aTransformer2);
182 aTransformer2.transform (TransformSourceFactory.create (aResult1.getNode ()), aResult2);
183
184 if (s_aLogger.isDebugEnabled ())
185 s_aLogger.debug ("Finished applying XSLT step 2 on " + aSchematronResource);
186
187 if (SchematronDebug.isSaveIntermediateXSLTFiles ())
188 {
189 final String sXML = XMLWriter.getNodeAsString (aResult2.getNode ());
190 SimpleFileIO.writeFile (new File (SchematronDebug.getIntermediateMinifiedSCHFolder (),
191 FilenameHelper.getWithoutPath (aSchematronResource.getPath ()) +
192 ".min-xslt.sch"),
193 sXML,
194 XMLWriterSettings.DEFAULT_XML_CHARSET_OBJ);
195 }
196
197
198 final DOMResult aResult3 = new DOMResult ();
199 final Transformer aTransformer3 = s_aStep3.newTransformer ();
200 aTransformerCustomizer.customize (EStep.SCH2XSLT_3, aTransformer3);
201 aTransformer3.transform (TransformSourceFactory.create (aResult2.getNode ()), aResult3);
202
203 if (s_aLogger.isDebugEnabled ())
204 s_aLogger.debug ("Finished applying XSLT step 3 on " + aSchematronResource);
205
206
207
208 m_aSchematronXSLTDoc = (Document) aResult3.getNode ();
209
210 if (SchematronDebug.isSaveIntermediateXSLTFiles ())
211 {
212 final String sXML = XMLWriter.getNodeAsString (m_aSchematronXSLTDoc);
213 SimpleFileIO.writeFile (new File (SchematronDebug.getIntermediateFinalXSLTFolder (),
214 FilenameHelper.getWithoutPath (aSchematronResource.getPath ()) + ".xslt"),
215 sXML,
216 XMLWriterSettings.DEFAULT_XML_CHARSET_OBJ);
217 }
218
219
220 m_aSchematronXSLTTemplates = XMLTransformerFactory.newTemplates (SchematronTransformerFactory.getDefaultSaxonFirst (),
221 TransformSourceFactory.create (m_aSchematronXSLTDoc));
222 }
223 catch (final Throwable t)
224 {
225 s_aLogger.error ("Schematron preprocessor error", t);
226 }
227 }
228
229 @Nonnull
230 public IReadableResource getSchematronResource ()
231 {
232 return m_aSchematronResource;
233 }
234
235 public boolean isValidSchematron ()
236 {
237 return m_aSchematronXSLTTemplates != null;
238 }
239
240 @Nullable
241 public Document getXSLTDocument ()
242 {
243 return m_aSchematronXSLTDoc;
244 }
245
246 @Nullable
247 public Transformer getXSLTTransformer () throws TransformerConfigurationException
248 {
249 return m_aSchematronXSLTTemplates == null ? null : m_aSchematronXSLTTemplates.newTransformer ();
250 }
251 }