1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.helger.schematron;
18
19 import java.io.InputStream;
20
21 import javax.annotation.Nonnull;
22 import javax.annotation.Nullable;
23 import javax.annotation.concurrent.NotThreadSafe;
24 import javax.xml.transform.Source;
25 import javax.xml.transform.stream.StreamSource;
26
27 import org.oclc.purl.dsdl.svrl.SchematronOutputType;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30 import org.w3c.dom.Document;
31 import org.w3c.dom.Node;
32 import org.xml.sax.EntityResolver;
33
34 import com.helger.commons.ValueEnforcer;
35 import com.helger.commons.annotation.ReturnsMutableCopy;
36 import com.helger.commons.io.IHasInputStream;
37 import com.helger.commons.io.resource.IReadableResource;
38 import com.helger.commons.state.EValidity;
39 import com.helger.commons.string.ToStringGenerator;
40 import com.helger.xml.EXMLParserFeature;
41 import com.helger.xml.sax.DefaultEntityResolver;
42 import com.helger.xml.serialize.read.DOMReader;
43 import com.helger.xml.serialize.read.DOMReaderSettings;
44 import com.helger.xml.transform.TransformSourceFactory;
45
46
47
48
49
50
51
52 @NotThreadSafe
53 public abstract class AbstractSchematronResource implements ISchematronResource
54 {
55 private static final Logger LOGGER = LoggerFactory.getLogger (AbstractSchematronResource.class);
56
57 private final IReadableResource m_aResource;
58 private final String m_sResourceID;
59 private boolean m_bUseCache = true;
60 private EntityResolver m_aEntityResolver;
61
62
63
64
65
66
67
68 public AbstractSchematronResource (@Nonnull final IReadableResource aResource)
69 {
70 m_aResource = ValueEnforcer.notNull (aResource, "Resource");
71 m_sResourceID = aResource.getResourceID ();
72
73 m_aEntityResolver = DefaultEntityResolver.createOnDemand (aResource);
74 }
75
76 @Nonnull
77 public final String getID ()
78 {
79 return m_sResourceID;
80 }
81
82 @Nonnull
83 public final IReadableResource getResource ()
84 {
85 return m_aResource;
86 }
87
88 public boolean isUseCache ()
89 {
90 return m_bUseCache;
91 }
92
93 public void setUseCache (final boolean bUseCache)
94 {
95 m_bUseCache = bUseCache;
96 }
97
98 @Nullable
99 public EntityResolver getEntityResolver ()
100 {
101 return m_aEntityResolver;
102 }
103
104
105
106
107
108
109
110
111
112
113
114 protected final void internalSetEntityResolver (@Nullable final EntityResolver aEntityResolver)
115 {
116 m_aEntityResolver = aEntityResolver;
117 }
118
119
120
121
122
123
124
125 @Nonnull
126 @ReturnsMutableCopy
127 protected DOMReaderSettings internalCreateDOMReaderSettings ()
128 {
129 final DOMReaderSettings aDRS = new DOMReaderSettings ();
130 if (m_aEntityResolver != null)
131 aDRS.setEntityResolver (m_aEntityResolver);
132 if (false)
133 {
134 final boolean m_bLoadExternalSchemas = false;
135 aDRS.setFeatureValue (EXMLParserFeature.EXTERNAL_GENERAL_ENTITIES, m_bLoadExternalSchemas);
136 aDRS.setFeatureValue (EXMLParserFeature.EXTERNAL_PARAMETER_ENTITIES, m_bLoadExternalSchemas);
137 aDRS.setFeatureValue (EXMLParserFeature.LOAD_EXTERNAL_DTD, m_bLoadExternalSchemas);
138 aDRS.setFeatureValue (EXMLParserFeature.VALIDATION, true);
139 aDRS.setFeatureValue (EXMLParserFeature.NAMESPACES, true);
140 }
141 return aDRS;
142 }
143
144 protected static final class NodeAndBaseURI
145 {
146 private final Document m_aDoc;
147 private final String m_sBaseURI;
148
149 public NodeAndBaseURI (@Nonnull final Document aDoc, @Nullable final String sBaseURI)
150 {
151 m_aDoc = aDoc;
152 m_sBaseURI = sBaseURI;
153 }
154 }
155
156 @Nullable
157 protected NodeAndBaseURI getAsNode (@Nonnull final IHasInputStream aXMLResource) throws Exception
158 {
159 final StreamSource aStreamSrc = TransformSourceFactory.create (aXMLResource);
160 InputStream aIS = null;
161 try
162 {
163 aIS = aStreamSrc.getInputStream ();
164 }
165 catch (final IllegalStateException ex)
166 {
167
168
169 }
170 if (aIS == null)
171 {
172
173 LOGGER.warn ("XML resource " + aXMLResource + " does not exist!");
174 return null;
175 }
176 final Document aDoc = DOMReader.readXMLDOM (aIS, internalCreateDOMReaderSettings ());
177 if (aDoc == null)
178 throw new IllegalArgumentException ("Failed to read resource " + aXMLResource + " as XML");
179
180 LOGGER.info ("Read XML resource " + aXMLResource);
181 return new NodeAndBaseURI (aDoc, aStreamSrc.getSystemId ());
182 }
183
184 @Nullable
185 protected Node getAsNode (@Nonnull final Source aXMLSource) throws Exception
186 {
187
188 final Node aNode = SchematronResourceHelper.getNodeOfSource (aXMLSource, internalCreateDOMReaderSettings ());
189 if (aNode == null)
190 return null;
191 return aNode;
192 }
193
194 @Nonnull
195 public EValidity getSchematronValidity (@Nonnull final IHasInputStream aXMLResource) throws Exception
196 {
197 if (!isValidSchematron ())
198 return EValidity.INVALID;
199
200 final NodeAndBaseURI aXMLNode = getAsNode (aXMLResource);
201 if (aXMLNode == null)
202 return EValidity.INVALID;
203
204 return getSchematronValidity (aXMLNode.m_aDoc, aXMLNode.m_sBaseURI);
205 }
206
207 @Nonnull
208 public EValidity getSchematronValidity (@Nonnull final Source aXMLSource) throws Exception
209 {
210 if (!isValidSchematron ())
211 return EValidity.INVALID;
212
213 final Node aXMLNode = getAsNode (aXMLSource);
214 if (aXMLNode == null)
215 return EValidity.INVALID;
216
217 return getSchematronValidity (aXMLNode, aXMLSource.getSystemId ());
218 }
219
220 @Nullable
221 public Document applySchematronValidation (@Nonnull final IHasInputStream aXMLResource) throws Exception
222 {
223 if (!isValidSchematron ())
224 return null;
225
226 final NodeAndBaseURI aXMLNode = getAsNode (aXMLResource);
227 if (aXMLNode == null)
228 return null;
229
230 return applySchematronValidation (aXMLNode.m_aDoc, aXMLNode.m_sBaseURI);
231 }
232
233 @Nullable
234 public Document applySchematronValidation (@Nonnull final Source aXMLSource) throws Exception
235 {
236 if (!isValidSchematron ())
237 return null;
238
239 final Node aXMLNode = getAsNode (aXMLSource);
240 if (aXMLNode == null)
241 return null;
242
243 return applySchematronValidation (aXMLNode, aXMLSource.getSystemId ());
244 }
245
246 @Nullable
247 public SchematronOutputType applySchematronValidationToSVRL (@Nonnull final IHasInputStream aXMLResource) throws Exception
248 {
249 if (!isValidSchematron ())
250 return null;
251
252 final NodeAndBaseURI aXMLNode = getAsNode (aXMLResource);
253 if (aXMLNode == null)
254 return null;
255
256 return applySchematronValidationToSVRL (aXMLNode.m_aDoc, aXMLNode.m_sBaseURI);
257 }
258
259 @Nullable
260 public SchematronOutputType applySchematronValidationToSVRL (@Nonnull final Source aXMLSource) throws Exception
261 {
262 if (!isValidSchematron ())
263 return null;
264
265 final Node aXMLNode = getAsNode (aXMLSource);
266 if (aXMLNode == null)
267 return null;
268
269 return applySchematronValidationToSVRL (aXMLNode, aXMLSource.getSystemId ());
270 }
271
272 @Override
273 public String toString ()
274 {
275 return new ToStringGenerator (this).append ("Resource", m_aResource)
276 .append ("UseCache", m_bUseCache)
277 .appendIfNotNull ("EntityResolver", m_aEntityResolver)
278 .getToString ();
279 }
280 }