Changeset 5056
- Timestamp:
- 04/25/14 00:43:18 (10 years ago)
- Location:
- CMDIValidator/trunk/src/main
- Files:
-
- 16 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
CMDIValidator/trunk/src/main/java/eu/clarin/cmdi/validator/CMDIValidator.java
r5052 r5056 12 12 import javax.xml.transform.dom.DOMSource; 13 13 14 import net.sf.saxon.s9api.Axis; 14 15 import net.sf.saxon.s9api.DocumentBuilder; 15 16 import net.sf.saxon.s9api.Processor; 17 import net.sf.saxon.s9api.QName; 16 18 import net.sf.saxon.s9api.SaxonApiException; 17 19 import net.sf.saxon.s9api.WhitespaceStrippingPolicy; 20 import net.sf.saxon.s9api.XPathCompiler; 21 import net.sf.saxon.s9api.XPathExecutable; 22 import net.sf.saxon.s9api.XPathSelector; 23 import net.sf.saxon.s9api.XdmDestination; 24 import net.sf.saxon.s9api.XdmItem; 18 25 import net.sf.saxon.s9api.XdmNode; 26 import net.sf.saxon.s9api.XdmSequenceIterator; 27 import net.sf.saxon.s9api.XsltExecutable; 28 import net.sf.saxon.s9api.XsltTransformer; 19 29 20 30 import org.apache.xerces.impl.xs.XMLSchemaLoader; … … 61 71 "http://apache.org/xml/features/honour-all-schemaLocations"; 62 72 private static final int INITAL_SYMBOL_TABLE_SIZE = 16141; 73 private static final String SVRL_NAMESPACE_URI = "http://purl.oclc.org/dsdl/svrl"; 74 private static final String SVRL_NAMESPACE_PREFIX = "svrl"; 75 private static final QName SVRL_TEXT = 76 new QName(SVRL_NAMESPACE_URI, "text"); 77 private static final QName SVRL_FAILED_ASSERT = 78 new QName(SVRL_NAMESPACE_URI, "failed-assert"); 63 79 private final Processor processor; 80 private final XPathExecutable xpath1; 81 private final XPathExecutable xpath2; 82 private final XsltTransformer schematronValidator; 64 83 private final XML11Configuration config; 65 84 private final DocumentBuilder builder; … … 67 86 68 87 69 CMDIValidator(final Processor processor, final SchemaLoader schemaLoader) 88 CMDIValidator(final Processor processor, final SchemaLoader schemaLoader, 89 XsltExecutable schematronExecutable) 70 90 throws CMDIValidatorInitException { 71 91 if (processor == null) { 72 throw new NullPointerException(" validator == null");92 throw new NullPointerException("processor == null"); 73 93 } 74 94 this.processor = processor; 95 if (schematronExecutable != null) { 96 try { 97 final XPathCompiler compiler = processor.newXPathCompiler(); 98 compiler.declareNamespace(SVRL_NAMESPACE_PREFIX, SVRL_NAMESPACE_URI); 99 this.xpath1 = compiler.compile("//(svrl:failed-assert|svrl:successful-report)"); 100 this.xpath2 = compiler.compile("preceding-sibling::svrl:fired-rule/@role"); 101 this.schematronValidator = schematronExecutable.load(); 102 } catch (SaxonApiException e) { 103 throw new CMDIValidatorInitException( 104 "error initializing validator", e); 105 } 106 } else { 107 this.xpath1 = null; 108 this.xpath2 = null; 109 this.schematronValidator = null; 110 } 75 111 76 112 try { … … 172 208 173 209 /* 174 * initialize Saxon 210 * initialize Saxon document builder 175 211 */ 176 212 this.builder = this.processor.newDocumentBuilder(); 177 this.builder.setWhitespaceStrippingPolicy(WhitespaceStrippingPolicy.IGNORABLE); 213 this.builder.setWhitespaceStrippingPolicy( 214 WhitespaceStrippingPolicy.IGNORABLE); 178 215 179 216 /* … … 184 221 throw new CMDIValidatorInitException("initialization failed", e); 185 222 } 186 }223 } 187 224 188 225 … … 205 242 */ 206 243 if (document != null) { 207 logger.debug("document = {}", document.getNodeName()); 244 if (schematronValidator != null) { 245 validateSchematron(document); 246 } 208 247 } else { 209 248 logger.debug("parseInstance() returned no result"); … … 260 299 261 300 262 // private void validateSchematron(XdmNode document) 263 // throws CMDIValidatorException { 264 // try { 265 // logger.debug("performing schematron validation ..."); 266 // schematronValidator.setSource(document.asSource()); 267 // final XdmDestination destination = new XdmDestination(); 268 // schematronValidator.setDestination(destination); 269 // schematronValidator.transform(); 270 // 271 //// XdmNode validationReport = destination.getXdmNode(); 272 // 273 // // return ((net.sf.saxon.value.BooleanValue) 274 // // Saxon.evaluateXPath(validationReport, 275 // // "empty(//svrl:failed-assert[(preceding-sibling::svrl:fired-rule)[last()][empty(@role) or @role!='warning']])").evaluateSingle().getUnderlyingValue()).getBooleanValue(); 276 // } catch (SaxonApiException e) { 277 // throw new CMDIValidatorException( 278 // "error performing schematron validation", e); 279 // } 280 // } 301 private void validateSchematron(XdmNode document) 302 throws CMDIValidatorException { 303 try { 304 logger.debug("performing schematron validation ..."); 305 schematronValidator.setSource(document.asSource()); 306 final XdmDestination destination = new XdmDestination(); 307 schematronValidator.setDestination(destination); 308 schematronValidator.transform(); 309 310 311 XPathSelector selector = xpath1.load(); 312 selector.setContextItem(destination.getXdmNode()); 313 for (XdmItem item : selector) { 314 final XdmNode node = (XdmNode) item; 315 final XdmNode text = getFirstChild(node, SVRL_TEXT); 316 String msg = (text != null) ? text.getStringValue().trim() : null; 317 if (SVRL_FAILED_ASSERT.equals(node.getNodeName())) { 318 XPathSelector selector2 = xpath2.load(); 319 String role = null; 320 selector2.setContextItem(node); 321 XdmItem evaluateSingle = selector2.evaluateSingle(); 322 if (evaluateSingle != null) { 323 role = evaluateSingle.getStringValue().trim(); 324 } 325 if ("warning".equalsIgnoreCase(role)) { 326 result.reportWarning(-1, -1, msg); 327 } else { 328 result.reportError(-1, -1, msg); 329 } 330 } else { 331 result.reportInfo(-1, -1, msg); 332 } 333 } 334 } catch (SaxonApiException e) { 335 throw new CMDIValidatorException( 336 "error performing schematron validation", e); 337 } 338 } 339 340 341 private static XdmNode getFirstChild(XdmNode parent, QName name) { 342 XdmSequenceIterator i = parent.axisIterator(Axis.CHILD, name); 343 if (i.hasNext()) { 344 return (XdmNode) i.next(); 345 } else { 346 return null; 347 } 348 } 281 349 282 350 -
CMDIValidator/trunk/src/main/java/eu/clarin/cmdi/validator/CMDIValidatorFactory.java
r5052 r5056 2 2 3 3 import java.io.File; 4 import java.net.URL; 4 5 6 import javax.xml.transform.stream.StreamSource; 7 8 import net.sf.saxon.s9api.DocumentBuilder; 5 9 import net.sf.saxon.s9api.Processor; 10 import net.sf.saxon.s9api.SaxonApiException; 11 import net.sf.saxon.s9api.XdmDestination; 12 import net.sf.saxon.s9api.XdmNode; 13 import net.sf.saxon.s9api.XsltCompiler; 14 import net.sf.saxon.s9api.XsltExecutable; 15 import net.sf.saxon.s9api.XsltTransformer; 6 16 7 17 import org.apache.commons.lang3.SystemUtils; 18 import org.slf4j.Logger; 19 import org.slf4j.LoggerFactory; 20 8 21 9 22 public class CMDIValidatorFactory { 10 private final Processor processor = new Processor(true); 23 private static final String SCHEMATATRON_STAGE_1 = 24 "/schematron/iso_dsdl_include.xsl"; 25 private static final String SCHEMATATRON_STAGE_2 = 26 "/schematron/iso_abstract_expand.xsl"; 27 private static final String SCHEMATATRON_STAGE_3 = 28 "/schematron/iso_svrl_for_xslt2.xsl"; 29 private static final String DEFAULT_SCHEMATRON_SCHEMA = 30 "/default.sch"; 31 private static final Logger logger = 32 LoggerFactory.getLogger(CMDIValidatorFactory.class); 33 private final Processor processor; 11 34 private final SchemaLoader schemaLoader; 35 private final XsltExecutable schematronValidator; 12 36 13 37 14 private CMDIValidatorFactory(File cacheDirectory )38 private CMDIValidatorFactory(File cacheDirectory, boolean disableSchematron) 15 39 throws CMDIValidatorInitException { 40 /* 41 * initialize custom schema loader 42 */ 43 logger.debug("initializing schema loader ..."); 16 44 if (cacheDirectory == null) { 17 45 if (SystemUtils.IS_OS_WINDOWS && … … 53 81 schemaLoader = new SchemaLoader(cacheDirectory, 54 82 SchemaLoader.DISABLE_CACHE_AGING); 83 84 /* 85 * initialize Saxon processor 86 */ 87 logger.debug("initializing Saxon ..."); 88 this.processor = new Processor(true); 89 90 /* 91 * initialize Schematron validator 92 */ 93 if (!disableSchematron) { 94 logger.debug("initializing Schematron validator ..."); 95 URL schema = this.getClass().getResource(DEFAULT_SCHEMATRON_SCHEMA); 96 if (schema == null) { 97 throw new CMDIValidatorInitException( 98 "cannot locate schematron schema"); 99 } 100 final XsltCompiler compiler = processor.newXsltCompiler(); 101 XsltTransformer stage1 = 102 loadStylesheet(compiler, SCHEMATATRON_STAGE_1); 103 XsltTransformer stage2 = 104 loadStylesheet(compiler, SCHEMATATRON_STAGE_2); 105 XsltTransformer stage3 = 106 loadStylesheet(compiler, SCHEMATATRON_STAGE_3); 107 try { 108 XdmDestination destination = new XdmDestination(); 109 stage1.setSource(new StreamSource(schema.toExternalForm())); 110 stage1.setDestination(stage2); 111 stage2.setDestination(stage3); 112 stage3.setDestination(destination); 113 stage1.transform(); 114 schematronValidator = 115 compiler.compile(destination.getXdmNode().asSource()); 116 logger.debug("Schematron validator successfully initializied"); 117 } catch (SaxonApiException e) { 118 throw new CMDIValidatorInitException( 119 "error compiling schematron rules", e); 120 } 121 } else { 122 logger.debug("disabling Schematron validator"); 123 this.schematronValidator = null; 124 } 55 125 } 56 126 57 127 58 128 public CMDIValidator newValidator() throws CMDIValidatorInitException { 59 return new CMDIValidator(processor, schemaLoader );129 return new CMDIValidator(processor, schemaLoader, schematronValidator); 60 130 } 61 131 62 132 63 public static CMDIValidatorFactory newInstance(File cacheDircetory )64 throws CMDIValidatorInitException {65 return new CMDIValidatorFactory(cacheDircetory );133 public static CMDIValidatorFactory newInstance(File cacheDircetory, 134 boolean disableSchematron) throws CMDIValidatorInitException { 135 return new CMDIValidatorFactory(cacheDircetory, disableSchematron); 66 136 } 67 137 … … 69 139 public static CMDIValidatorFactory newInstance() 70 140 throws CMDIValidatorInitException { 71 return new CMDIValidatorFactory(null); 141 return new CMDIValidatorFactory(null, false); 142 } 143 144 145 private XsltTransformer loadStylesheet(XsltCompiler compiler, String name) 146 throws CMDIValidatorInitException { 147 try { 148 logger.debug("loading stylesheet '{}'", name); 149 final URL uri = this.getClass().getResource(name); 150 if (uri != null) { 151 DocumentBuilder builder = processor.newDocumentBuilder(); 152 XdmNode source = 153 builder.build(new StreamSource(uri.toExternalForm())); 154 XsltExecutable stylesheet = compiler.compile(source.asSource()); 155 return stylesheet.load(); 156 } else { 157 throw new CMDIValidatorInitException("cannot find resource '" + 158 name + "'"); 159 } 160 } catch (SaxonApiException e) { 161 throw new CMDIValidatorInitException( 162 "error loading schematron stylesheet '" + name + "'", e); 163 } 72 164 } 73 165 -
CMDIValidator/trunk/src/main/java/eu/clarin/cmdi/validator/tool/CMDIValidatorTool.java
r5054 r5056 46 46 private static final char OPT_NO_ESTIMATE = 'E'; 47 47 private static final char OPT_SCHEMA_CACHE_DIR = 'C'; 48 private static final char OPT_NO_SCHEMATRON = 'S'; 49 private static final char OPT_SCHEMATRON_FILE = 's'; 48 50 private static final Logger logger = 49 51 LoggerFactory.getLogger(CMDIValidatorTool.class); … … 55 57 * application defaults 56 58 */ 57 boolean debugging = false; 58 boolean quiet = false; 59 boolean verbose = false; 60 int threadCount = Runtime.getRuntime().availableProcessors(); 61 boolean estimate = true; 62 long progressInterval = DEFAULT_PROGRESS_INTERVAL; 63 File schemaCacheDir = null; 59 boolean debugging = false; 60 boolean quiet = false; 61 boolean verbose = false; 62 int threadCount = Runtime.getRuntime().availableProcessors(); 63 boolean estimate = true; 64 long progressInterval = DEFAULT_PROGRESS_INTERVAL; 65 File schemaCacheDir = null; 66 boolean disableSchematron = false; 64 67 65 68 /* … … 72 75 // check incompatible combinations 73 76 if (line.hasOption(OPT_THREAD_COUNT) && line.hasOption(OPT_NO_THREADS)) { 74 throw new ParseException("The -t and -T option are mutually exclusive");77 throw new ParseException("The -t and -T options are mutually exclusive"); 75 78 } 76 79 if (line.hasOption(OPT_DEBUG) && line.hasOption(OPT_QUIET)) { 77 throw new ParseException("The -d and -q switch are mutually exclusive");80 throw new ParseException("The -d and -q switches are mutually exclusive"); 78 81 } 79 82 if (line.hasOption(OPT_VERBOSE) && line.hasOption(OPT_QUIET)) { 80 throw new ParseException("The -v and -q switch are mutually exclusive"); 83 throw new ParseException("The -v and -q switches are mutually exclusive"); 84 } 85 if (line.hasOption(OPT_NO_SCHEMATRON) && line.hasOption(OPT_SCHEMATRON_FILE)) { 86 throw new ParseException("The -s and -T options are mutually exclusive"); 81 87 } 82 88 // extract options … … 117 123 } 118 124 schemaCacheDir = new File(dir); 125 } 126 if (line.hasOption(OPT_NO_SCHEMATRON)) { 127 disableSchematron = true; 119 128 } 120 129 … … 149 158 } 150 159 final CMDIValidatorFactory factory = 151 CMDIValidatorFactory.newInstance(schemaCacheDir); 160 CMDIValidatorFactory.newInstance(schemaCacheDir, 161 disableSchematron); 152 162 153 163 /* … … 325 335 .withLongOpt("schema-cache-dir") 326 336 .create(OPT_SCHEMA_CACHE_DIR)); 337 OptionGroup g3 = new OptionGroup(); 338 g3.addOption(OptionBuilder 339 .withDescription("disable Schematron validator") 340 .withLongOpt("no-schematron") 341 .create(OPT_NO_SCHEMATRON)); 342 // g3.addOption(OptionBuilder 343 // .withDescription("load Schematron validator rules from file") 344 // .hasArg() 345 // .withArgName("FILE") 346 // .withLongOpt("schematron-file") 347 // .create(OPT_SCHEMATRON_FILE)); 348 options.addOptionGroup(g3); 327 349 return options; 328 350 } … … 442 464 logger.warn("file '{}' is valid (with warnings):", file); 443 465 for (Message msg : result.getMessages()) { 444 logger.warn(" ({}) {} [line={}, column={}]", 445 msg.getSeverity().getShortcut(), 446 msg.getMessage(), 447 msg.getLineNumber(), 448 msg.getColumnNumber()); 466 if ((msg.getLineNumber() != -1) && 467 (msg.getColumnNumber() != -1)) { 468 logger.warn(" ({}) {} [line={}, column={}]", 469 msg.getSeverity().getShortcut(), 470 msg.getMessage(), 471 msg.getLineNumber(), 472 msg.getColumnNumber()); 473 } else { 474 logger.warn(" ({}) {}", 475 msg.getSeverity().getShortcut(), 476 msg.getMessage()); 477 } 449 478 } 450 479 } else { 451 480 Message msg = result.getFirstMessage(Severity.WARNING); 452 int count = result.getMessageCount(Severity.WARNING);481 int count = result.getMessageCount(Severity.WARNING); 453 482 if (count > 1) { 454 483 logger.warn("file '{}' is valid (with warnings): {} ({} more warnings)", 455 file, msg , (count - 1));484 file, msg.getMessage(), (count - 1)); 456 485 } else { 457 486 logger.warn("file '{}' is valid (with warnings): {}", 458 file, msg );487 file, msg.getMessage()); 459 488 } 460 489 } … … 479 508 logger.error("file '{}' is invalid:", file); 480 509 for (Message msg : result.getMessages()) { 481 logger.error(" ({}) {} [line={}, column={}]", 482 msg.getSeverity().getShortcut(), 483 msg.getMessage(), 484 msg.getLineNumber(), 485 msg.getColumnNumber()); 510 if ((msg.getLineNumber() != -1) && 511 (msg.getColumnNumber() != -1)) { 512 logger.error(" ({}) {} [line={}, column={}]", 513 msg.getSeverity().getShortcut(), 514 msg.getMessage(), 515 msg.getLineNumber(), 516 msg.getColumnNumber()); 517 } else { 518 logger.error(" ({}) {}", 519 msg.getSeverity().getShortcut(), 520 msg.getMessage()); 521 } 486 522 } 487 523 } else { 488 524 Message msg = result.getFirstMessage(Severity.ERROR); 489 int count = result.getMessageCount(Severity.ERROR);525 int count = result.getMessageCount(Severity.ERROR); 490 526 if (count > 1) { 491 527 logger.error("file '{}' is invalid: {} ({} more errors)",
Note: See TracChangeset
for help on using the changeset viewer.