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 LOGGER = 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 (LOGGER.isDebugEnabled ())
130 LOGGER.debug ("Creating XSLT step 1 template");
131 s_aStep1 = XMLTransformerFactory.newTemplates (SchematronTransformerFactory.getDefaultSaxonFirst (),
132 new ClassPathResource (XSLT2_STEP1,
133 SchematronProviderXSLTFromSCH.class.getClassLoader ()));
134 }
135 if (s_aStep2 == null)
136 {
137 if (LOGGER.isDebugEnabled ())
138 LOGGER.debug ("Creating XSLT step 2 template");
139 s_aStep2 = XMLTransformerFactory.newTemplates (SchematronTransformerFactory.getDefaultSaxonFirst (),
140 new ClassPathResource (XSLT2_STEP2,
141 SchematronProviderXSLTFromSCH.class.getClassLoader ()));
142 }
143 if (s_aStep3 == null)
144 {
145 if (LOGGER.isDebugEnabled ())
146 LOGGER.debug ("Creating XSLT step 3 template");
147 s_aStep3 = XMLTransformerFactory.newTemplates (SchematronTransformerFactory.getDefaultSaxonFirst (),
148 new ClassPathResource (XSLT2_STEP3,
149 SchematronProviderXSLTFromSCH.class.getClassLoader ()));
150 }
151 }
152
153
154
155
156
157
158
159
160
161
162 public SchematronProviderXSLTFromSCH (@Nonnull final IReadableResource aSchematronResource,
163 @Nonnull final SCHTransformerCustomizer aTransformerCustomizer)
164 {
165 m_aSchematronResource = ValueEnforcer.notNull (aSchematronResource, "SchematronResource");
166 ValueEnforcer.notNull (aTransformerCustomizer, "TransformerCustomizer");
167
168 try
169 {
170 cacheXSLTTemplates ();
171
172
173 final DOMResult aResult1 = new DOMResult ();
174 final Transformer aTransformer1 = s_aStep1.newTransformer ();
175 aTransformerCustomizer.customize (EStep.SCH2XSLT_1, aTransformer1);
176 aTransformer1.transform (TransformSourceFactory.create (aSchematronResource), aResult1);
177
178 if (LOGGER.isDebugEnabled ())
179 LOGGER.debug ("Finished applying XSLT step 1 on " + aSchematronResource);
180
181
182 final DOMResult aResult2 = new DOMResult ();
183 final Transformer aTransformer2 = s_aStep2.newTransformer ();
184 aTransformerCustomizer.customize (EStep.SCH2XSLT_2, aTransformer2);
185 aTransformer2.transform (TransformSourceFactory.create (aResult1.getNode ()), aResult2);
186
187 if (LOGGER.isDebugEnabled ())
188 LOGGER.debug ("Finished applying XSLT step 2 on " + aSchematronResource);
189
190 if (SchematronDebug.isSaveIntermediateXSLTFiles ())
191 {
192 final String sXML = XMLWriter.getNodeAsString (aResult2.getNode ());
193 SimpleFileIO.writeFile (new File (SchematronDebug.getIntermediateMinifiedSCHFolder (),
194 FilenameHelper.getWithoutPath (aSchematronResource.getPath ()) +
195 ".min-xslt.sch"),
196 sXML,
197 XMLWriterSettings.DEFAULT_XML_CHARSET_OBJ);
198 }
199
200
201 final DOMResult aResult3 = new DOMResult ();
202 final Transformer aTransformer3 = s_aStep3.newTransformer ();
203 aTransformerCustomizer.customize (EStep.SCH2XSLT_3, aTransformer3);
204 aTransformer3.transform (TransformSourceFactory.create (aResult2.getNode ()), aResult3);
205
206 if (LOGGER.isDebugEnabled ())
207 LOGGER.debug ("Finished applying XSLT step 3 on " + aSchematronResource);
208
209
210
211 m_aSchematronXSLTDoc = (Document) aResult3.getNode ();
212
213 if (SchematronDebug.isSaveIntermediateXSLTFiles ())
214 {
215 final String sXML = XMLWriter.getNodeAsString (m_aSchematronXSLTDoc);
216 SimpleFileIO.writeFile (new File (SchematronDebug.getIntermediateFinalXSLTFolder (),
217 FilenameHelper.getWithoutPath (aSchematronResource.getPath ()) + ".xslt"),
218 sXML,
219 XMLWriterSettings.DEFAULT_XML_CHARSET_OBJ);
220 }
221
222
223 m_aSchematronXSLTTemplates = XMLTransformerFactory.newTemplates (SchematronTransformerFactory.getDefaultSaxonFirst (),
224 TransformSourceFactory.create (m_aSchematronXSLTDoc));
225 }
226 catch (final Throwable t)
227 {
228 LOGGER.error ("Schematron preprocessor error", t);
229 }
230 }
231
232 @Nonnull
233 public IReadableResource getSchematronResource ()
234 {
235 return m_aSchematronResource;
236 }
237
238 public boolean isValidSchematron ()
239 {
240 return m_aSchematronXSLTTemplates != null;
241 }
242
243 @Nullable
244 public Document getXSLTDocument ()
245 {
246 return m_aSchematronXSLTDoc;
247 }
248
249 @Nullable
250 public Transformer getXSLTTransformer () throws TransformerConfigurationException
251 {
252 return m_aSchematronXSLTTemplates == null ? null : m_aSchematronXSLTTemplates.newTransformer ();
253 }
254 }