From 9d64f89c449f7a7c6b0971a4ae2517db10034f6f Mon Sep 17 00:00:00 2001 From: Laxmi Narsimha Rao Oruganti Date: Mon, 15 Feb 2016 17:10:23 +0530 Subject: [PATCH] RegEx Validation Using Java Patterns (perf) While using this library we found RhinoHelper takes way too much time for pattern validations using Visual VM CPU Profiling. Here is an observation: - JSON Schema: Roughly 30 fields, 10 fields have one or the other validation, 5 of them have patterns (listed below) - Input Data: An array of 10K messages - Time Taken: -- With out pattern annotation: ~6 seconds -- With Rhino Helper: ~30 seconds -- With Java Patterns: ~7 seconds Patterns used: "pattern": "^(19[7-9][0-9]|[2-9][0-9][0-9][0-9])-", "pattern" : "^[+-][0-1][0-9]:[0-5][0-9]$", "pattern": "^(19[7-9][0-9]|[2-9][0-9][0-9][0-9])-", "pattern": "[^\\s]{1}", "pattern": "[^\\s]{1}", --- .../validator/common/PatternValidator.java | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/fge/jsonschema/keyword/validator/common/PatternValidator.java b/src/main/java/com/github/fge/jsonschema/keyword/validator/common/PatternValidator.java index 653428a27..bad68a787 100644 --- a/src/main/java/com/github/fge/jsonschema/keyword/validator/common/PatternValidator.java +++ b/src/main/java/com/github/fge/jsonschema/keyword/validator/common/PatternValidator.java @@ -19,6 +19,9 @@ package com.github.fge.jsonschema.keyword.validator.common; +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import com.fasterxml.jackson.databind.JsonNode; import com.github.fge.jsonschema.core.exceptions.ProcessingException; import com.github.fge.jsonschema.core.processing.Processor; @@ -31,13 +34,15 @@ /** * Keyword validator for {@code pattern} * - * @see RhinoHelper */ public final class PatternValidator extends AbstractKeywordValidator { + private HashMap _patterns; + public PatternValidator(final JsonNode digest) { + _patterns = new HashMap(); super("pattern"); } @@ -50,7 +55,11 @@ public void validate(final Processor processor, final String regex = data.getSchema().getNode().get(keyword) .textValue(); final String value = data.getInstance().getNode().textValue(); - if (!RhinoHelper.regMatch(regex, value)) + + Pattern pattern = getPattern(regex); + Matcher matches = pattern.matcher(value); + + if (!matches.find()) report.error(newMsg(data, bundle, "err.common.pattern.noMatch") .putArgument("regex", regex).putArgument("string", value)); } @@ -60,4 +69,15 @@ public String toString() { return keyword; } + + private Pattern getPattern(String regex) + { + // If there is not any existing compiled pattern, create one now! + if (!_patterns.containsKey(regex)) + { + _patterns.put(regex, Pattern.compile(regex)); + } + + return _patterns.get(regex); + } }