1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.helger.schematron.pure;
18
19 import java.io.File;
20 import java.io.InputStream;
21 import java.net.MalformedURLException;
22 import java.net.URL;
23 import java.nio.charset.Charset;
24
25 import javax.annotation.Nonnull;
26 import javax.annotation.Nullable;
27 import javax.annotation.concurrent.NotThreadSafe;
28 import javax.xml.transform.Source;
29 import javax.xml.xpath.XPathFunctionResolver;
30 import javax.xml.xpath.XPathVariableResolver;
31
32 import org.oclc.purl.dsdl.svrl.SchematronOutputType;
33 import org.w3c.dom.Document;
34 import org.w3c.dom.Node;
35
36 import com.helger.commons.ValueEnforcer;
37 import com.helger.commons.annotations.Nonempty;
38 import com.helger.commons.charset.CharsetManager;
39 import com.helger.commons.io.IInputStreamProvider;
40 import com.helger.commons.io.IReadableResource;
41 import com.helger.commons.io.resource.ClassPathResource;
42 import com.helger.commons.io.resource.FileSystemResource;
43 import com.helger.commons.io.resource.URLResource;
44 import com.helger.commons.io.resource.inmemory.AbstractMemoryReadableResource;
45 import com.helger.commons.io.resource.inmemory.ReadableResourceByteArray;
46 import com.helger.commons.io.resource.inmemory.ReadableResourceInputStream;
47 import com.helger.commons.state.EValidity;
48 import com.helger.commons.xml.serialize.DOMReader;
49 import com.helger.commons.xml.serialize.XMLWriterSettings;
50 import com.helger.schematron.AbstractSchematronResource;
51 import com.helger.schematron.SchematronException;
52 import com.helger.schematron.SchematronUtils;
53 import com.helger.schematron.pure.bound.IPSBoundSchema;
54 import com.helger.schematron.pure.bound.PSBoundSchemaCache;
55 import com.helger.schematron.pure.bound.PSBoundSchemaCacheKey;
56 import com.helger.schematron.pure.errorhandler.DoNothingPSErrorHandler;
57 import com.helger.schematron.pure.errorhandler.IPSErrorHandler;
58 import com.helger.schematron.pure.exchange.PSWriter;
59 import com.helger.schematron.pure.model.PSSchema;
60 import com.helger.schematron.svrl.SVRLWriter;
61
62
63
64
65
66
67
68
69
70
71
72 @NotThreadSafe
73 public class SchematronResourcePure extends AbstractSchematronResource
74 {
75 private String m_sPhase;
76 private IPSErrorHandler m_aErrorHandler;
77 private XPathVariableResolver m_aVariableResolver;
78 private XPathFunctionResolver m_aFunctionResolver;
79
80 private IPSBoundSchema m_aBoundSchema;
81
82 public SchematronResourcePure (@Nonnull final IReadableResource aResource)
83 {
84 this (aResource, (String) null, (IPSErrorHandler) null);
85 }
86
87 public SchematronResourcePure (@Nonnull final IReadableResource aResource,
88 @Nullable final String sPhase,
89 @Nullable final IPSErrorHandler aErrorHandler)
90 {
91 super (aResource);
92 setPhase (sPhase);
93 setErrorHandler (aErrorHandler);
94 }
95
96
97
98
99 @Nullable
100 public String getPhase ()
101 {
102 return m_sPhase;
103 }
104
105
106
107
108
109
110
111
112
113
114 @Nonnull
115 public SchematronResourcePure setPhase (@Nullable final String sPhase)
116 {
117 if (m_aBoundSchema != null)
118 throw new IllegalStateException ("Schematron was already bound and can therefore not be altered!");
119 m_sPhase = sPhase;
120 return this;
121 }
122
123
124
125
126
127 @Nullable
128 public IPSErrorHandler getErrorHandler ()
129 {
130 return m_aErrorHandler;
131 }
132
133
134
135
136
137
138
139
140 @Nonnull
141 public SchematronResourcePure setErrorHandler (@Nullable final IPSErrorHandler aErrorHandler)
142 {
143 if (m_aBoundSchema != null)
144 throw new IllegalStateException ("Schematron was already bound and can therefore not be altered!");
145 m_aErrorHandler = aErrorHandler;
146 return this;
147 }
148
149
150
151
152 @Nullable
153 public XPathVariableResolver getVariableResolver ()
154 {
155 return m_aVariableResolver;
156 }
157
158
159
160
161
162
163
164
165
166
167 @Nonnull
168 public SchematronResourcePure setVariableResolver (@Nullable final XPathVariableResolver aVariableResolver)
169 {
170 if (m_aBoundSchema != null)
171 throw new IllegalStateException ("Schematron was already bound and can therefore not be altered!");
172 m_aVariableResolver = aVariableResolver;
173 return this;
174 }
175
176
177
178
179 @Nullable
180 public XPathFunctionResolver getFunctionResolver ()
181 {
182 return m_aFunctionResolver;
183 }
184
185
186
187
188
189
190
191
192
193
194 @Nonnull
195 public SchematronResourcePure setFunctionResolver (@Nullable final XPathFunctionResolver aFunctionResolver)
196 {
197 if (m_aBoundSchema != null)
198 throw new IllegalStateException ("Schematron was already bound and can therefore not be altered!");
199 m_aFunctionResolver = aFunctionResolver;
200 return this;
201 }
202
203 @Nonnull
204 protected IPSBoundSchema createBoundSchema ()
205 {
206 final IReadableResource aResource = getResource ();
207 final IPSErrorHandler aErrorHandler = getErrorHandler ();
208 final PSBoundSchemaCacheKey aCacheKey = new PSBoundSchemaCacheKey (aResource,
209 getPhase (),
210 aErrorHandler,
211 getVariableResolver (),
212 getFunctionResolver ());
213 if (aResource instanceof AbstractMemoryReadableResource)
214 {
215
216 try
217 {
218 return aCacheKey.createBoundSchema ();
219 }
220 catch (final SchematronException ex)
221 {
222
223 throw new IllegalStateException ("Failed to bind Schematron", ex);
224 }
225 }
226
227
228
229 return PSBoundSchemaCache.getInstance ().getFromCache (aCacheKey);
230 }
231
232 @Nonnull
233 protected IPSBoundSchema getOrCreateBoundSchema ()
234 {
235 if (m_aBoundSchema == null)
236 m_aBoundSchema = createBoundSchema ();
237 return m_aBoundSchema;
238 }
239
240 public boolean isValidSchematron ()
241 {
242 try
243 {
244
245 final IPSErrorHandler aErrorHandler = m_aErrorHandler != null ? m_aErrorHandler
246 : DoNothingPSErrorHandler.getInstance ();
247 return getOrCreateBoundSchema ().getOriginalSchema ().isValid (aErrorHandler);
248 }
249 catch (final RuntimeException ex)
250 {
251
252 return false;
253 }
254 }
255
256
257
258
259
260 public void validateCompletely ()
261 {
262
263 final IPSErrorHandler aErrorHandler = m_aErrorHandler != null ? m_aErrorHandler
264 : DoNothingPSErrorHandler.getInstance ();
265 validateCompletely (aErrorHandler);
266 }
267
268
269
270
271
272
273
274
275 public void validateCompletely (@Nonnull final IPSErrorHandler aErrorHandler)
276 {
277 ValueEnforcer.notNull (aErrorHandler, "ErrorHandler");
278
279 try
280 {
281 getOrCreateBoundSchema ().getOriginalSchema ().validateCompletely (aErrorHandler);
282 }
283 catch (final RuntimeException ex)
284 {
285
286 }
287 }
288
289
290
291
292
293
294
295
296
297
298
299 @Deprecated
300 @Nonnull
301 public SchematronOutputType applySchematronValidation (@Nonnull final Node aXMLNode) throws SchematronException
302 {
303 return applySchematronValidationToSVRL (aXMLNode);
304 }
305
306
307
308
309
310
311
312
313
314
315 @Nonnull
316 public SchematronOutputType applySchematronValidationToSVRL (@Nonnull final Node aXMLNode) throws SchematronException
317 {
318 return getOrCreateBoundSchema ().validateComplete (aXMLNode);
319 }
320
321 @Nonnull
322 public EValidity getSchematronValidity (@Nonnull final IInputStreamProvider aXMLResource) throws Exception
323 {
324 if (!isValidSchematron ())
325 return EValidity.INVALID;
326
327 final Document aDoc = DOMReader.readXMLDOM (aXMLResource.getInputStream ());
328 if (aDoc == null)
329 throw new IllegalArgumentException ("Failed to read resource " + aXMLResource + " as XML");
330
331 return getOrCreateBoundSchema ().validatePartially (aDoc);
332 }
333
334 @Nonnull
335 public EValidity getSchematronValidity (@Nonnull final Source aXMLSource) throws Exception
336 {
337 if (!isValidSchematron ())
338 return EValidity.INVALID;
339
340
341 final Node aNode = SchematronUtils.getNodeOfSource (aXMLSource);
342 if (aNode == null)
343 return EValidity.INVALID;
344
345 return getOrCreateBoundSchema ().validatePartially (aNode);
346 }
347
348 @Nullable
349 public Document applySchematronValidation (@Nonnull final IInputStreamProvider aXMLResource) throws Exception
350 {
351 final SchematronOutputType aSO = applySchematronValidationToSVRL (aXMLResource);
352 return aSO == null ? null : SVRLWriter.createXML (aSO);
353 }
354
355 @Nullable
356 public Document applySchematronValidation (@Nonnull final Source aXMLSource) throws Exception
357 {
358 final SchematronOutputType aSO = applySchematronValidationToSVRL (aXMLSource);
359 return aSO == null ? null : SVRLWriter.createXML (aSO);
360 }
361
362 @Nullable
363 public SchematronOutputType applySchematronValidationToSVRL (@Nonnull final IInputStreamProvider aXMLResource) throws Exception
364 {
365 ValueEnforcer.notNull (aXMLResource, "XMLResource");
366
367 if (!isValidSchematron ())
368 return null;
369
370 final InputStream aIS = aXMLResource.getInputStream ();
371 if (aIS == null)
372 return null;
373
374 final Document aDoc = DOMReader.readXMLDOM (aIS);
375 if (aDoc == null)
376 throw new IllegalArgumentException ("Failed to read resource " + aXMLResource + " as XML");
377
378 return applySchematronValidationToSVRL (aDoc);
379 }
380
381 @Nullable
382 public SchematronOutputType applySchematronValidationToSVRL (@Nonnull final Source aXMLSource) throws Exception
383 {
384 ValueEnforcer.notNull (aXMLSource, "XMLSource");
385
386 if (!isValidSchematron ())
387 return null;
388
389
390 final Node aNode = SchematronUtils.getNodeOfSource (aXMLSource);
391 if (aNode == null)
392 return null;
393
394 return applySchematronValidationToSVRL (aNode);
395 }
396
397
398
399
400
401
402
403
404
405 @Nonnull
406 public static SchematronResourcePure fromClassPath (@Nonnull @Nonempty final String sSCHPath)
407 {
408 return new SchematronResourcePure (new ClassPathResource (sSCHPath));
409 }
410
411
412
413
414
415
416
417
418
419 @Nonnull
420 public static SchematronResourcePure fromFile (@Nonnull @Nonempty final String sSCHPath)
421 {
422 return new SchematronResourcePure (new FileSystemResource (sSCHPath));
423 }
424
425
426
427
428
429
430
431
432
433 @Nonnull
434 public static SchematronResourcePure fromFile (@Nonnull final File aSCHFile)
435 {
436 return new SchematronResourcePure (new FileSystemResource (aSCHFile));
437 }
438
439
440
441
442
443
444
445
446
447
448
449
450 @Nonnull
451 public static SchematronResourcePure fromURL (@Nonnull @Nonempty final String sSCHURL) throws MalformedURLException
452 {
453 return new SchematronResourcePure (new URLResource (sSCHURL));
454 }
455
456
457
458
459
460
461
462
463
464 @Nonnull
465 public static SchematronResourcePure fromURL (@Nonnull final URL aSCHURL)
466 {
467 return new SchematronResourcePure (new URLResource (aSCHURL));
468 }
469
470
471
472
473
474
475
476
477
478
479
480 @Nonnull
481 public static SchematronResourcePure fromInputStream (@Nonnull final InputStream aSchematronIS)
482 {
483 return new SchematronResourcePure (new ReadableResourceInputStream (aSchematronIS));
484 }
485
486
487
488
489
490
491
492
493
494
495
496 @Nonnull
497 public static SchematronResourcePure fromByteArray (@Nonnull final byte [] aSchematron)
498 {
499 return new SchematronResourcePure (new ReadableResourceByteArray (aSchematron));
500 }
501
502
503
504
505
506
507
508
509
510
511
512
513
514 @Nonnull
515 public static SchematronResourcePure fromString (@Nonnull final String sSchematron, @Nonnull final Charset aCharset)
516 {
517 return fromByteArray (CharsetManager.getAsBytes (sSchematron, aCharset));
518 }
519
520
521
522
523
524
525
526
527
528
529 @Nonnull
530 public static SchematronResourcePure fromSchema (@Nonnull final PSSchema aSchematron)
531 {
532 return fromString (new PSWriter ().getXMLString (aSchematron), XMLWriterSettings.DEFAULT_XML_CHARSET_OBJ);
533 }
534 }