private final Pattern pattern;
private final String errorMessage;
+ private final String regEx;
CompiledPatternContext(final PatternConstraint yangConstraint) {
- pattern = Pattern.compile("^" + yangConstraint.getRegularExpression() + "$");
+ pattern = Pattern.compile(yangConstraint.getJavaPatternString());
errorMessage = yangConstraint.getErrorMessage().orElse(null);
+ regEx = errorMessage == null ? yangConstraint.getRegularExpressionString() : null;
}
void validate(final String str) {
throw new IllegalArgumentException(errorMessage);
}
- throw new IllegalArgumentException("Value " + str + "does not match regular expression '"
- + pattern.pattern() + "'");
+ throw new IllegalArgumentException("Value " + str + "does not match regular expression '" + regEx + "'");
}
}
}
package org.opendaylight.yangtools.yang.model.api.type;
import java.util.Optional;
+import java.util.regex.Pattern;
import org.opendaylight.yangtools.yang.model.api.ConstraintMetaDefinition;
/**
- * Contains the method for getting the data from the YANG <code>pattern</code> which is substatement of
- * <code>type</code> statement.
+ * Contains the method for getting the data from the YANG <code>pattern</code> which is substatement
+ * of <code>type</code> statement.
*/
public interface PatternConstraint extends ConstraintMetaDefinition {
/**
- * Returns a java regular expression (pattern).
+ * Returns a Java {@link Pattern}-compatible regular expression (pattern). Returned string performs equivalent
+ * matching in terms of enforcement, but it may have a structure completely different from the one in YANG model.
+ * This string DOES NOT include the effects of the modifier (if present, as indicated by {@link #getModifier()}.
*
- * @return string with java regular expression which is equal to the argument of
- * the YANG <code>pattern</code> substatement
+ * @return string Java Pattern regular expression
*/
- String getRegularExpression();
+ // FIXME: should we be providing a Pattern instance? This, along with the other method is treading the fine
+ // balance between usability of the effective model, the purity of effective view model and memory
+ // overhead. We pick usability and memory footprint and expose both methods from effective model.
+ String getJavaPatternString();
/**
- * Returns a raw regular expression as it was declared in a source.
+ * Returns a raw regular expression as it was declared in a source. This string conforms to XSD regular expression
+ * syntax, which is notably different from Java's Pattern string.
*
- * @return argument of pattern statement as it was declared in a source.
+ * @return argument of pattern statement as it was declared in YANG model.
*/
- // FIXME: version 2.0.0: make this method non-default
- default String getRawRegularExpression() {
- return getRegularExpression();
- }
+ String getRegularExpressionString();
/**
* RFC7950 allows a pattern constraint to be inverted. For this purpose a general modifier concept has been
}
private void emitPatternNode(final PatternConstraint pattern) {
- super.writer.startPatternNode(pattern.getRawRegularExpression());
+ super.writer.startPatternNode(pattern.getRegularExpressionString());
pattern.getErrorMessage().ifPresent(this::emitErrorMessageNode);
pattern.getErrorAppTag().ifPresent(this::emitErrorAppTagNode);
emitDocumentedNode(pattern);
}
@Override
- public String getRegularExpression() {
+ public String getJavaPatternString() {
return regex;
}
+ @Override
+ public String getRegularExpressionString() {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public Optional<ModifierKind> getModifier() {
return Optional.ofNullable(modifier);
assertEquals(Optional.of("invalid-regular-expression"), patternConstraint.getErrorAppTag());
assertTrue(patternConstraint.getErrorMessage().isPresent());
assertEquals(Optional.of("RFC 6020"), patternConstraint.getReference());
- assertEquals("Regular expression should be equls '\\D'.", "\\D", patternConstraint.getRegularExpression());
+ assertEquals("Regular expression should be equls '\\D'.", "\\D", patternConstraint.getJavaPatternString());
assertNotEquals("Hash codes shouldn't be equals.", patternConstraint.hashCode(), patternConstraint2.hashCode());
assertFalse("String representation shouldn't be empty.", patternConstraint.toString().isEmpty());
}
@Override
- public String getRegularExpression() {
+ public String getJavaPatternString() {
return regEx;
}
@Override
- public String getRawRegularExpression() {
+ public String getRegularExpressionString() {
return rawRegEx;
}
return argument;
}
- return new PatternConstraintEffectiveImpl(argument.getRegularExpression(), argument.getRawRegularExpression(),
+ return new PatternConstraintEffectiveImpl(argument.getJavaPatternString(),
+ argument.getRegularExpressionString(),
getDescription().orElse(null), getReference().orElse(null), getErrorAppTag().orElse(null),
getErrorMessage().orElse(null), getModifier());
}
final PatternConstraint pattern = getPatternConstraintOf(context, "leaf-with-pattern");
- final String rawRegex = pattern.getRawRegularExpression();
+ final String rawRegex = pattern.getRegularExpressionString();
final String expectedYangRegex = "$0$.*|$1$[a-zA-Z0-9./]{1,8}$[a-zA-Z0-9./]{22}|$5$(rounds=\\d+$)?"
+ "[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{43}|$6$(rounds=\\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{86}";
assertEquals(expectedYangRegex, rawRegex);
- final String javaRegexFromYang = pattern.getRegularExpression();
+ final String javaRegexFromYang = pattern.getJavaPatternString();
final String expectedJavaRegex = "^\\$0\\$.*|\\$1\\$[a-zA-Z0-9./]{1,8}\\$[a-zA-Z0-9./]{22}|\\$5\\$"
+ "(rounds=\\d+\\$)?[a-zA-Z0-9./]{1,16}\\$[a-zA-Z0-9./]{43}|\\$6\\$(rounds=\\d+\\$)?"
+ "[a-zA-Z0-9./]{1,16}\\$[a-zA-Z0-9./]{86}$";
Assert.assertEquals(Integer.valueOf(10), span.upperEndpoint());
final PatternConstraint patternConstraint = patternConstraints.get(0);
- Assert.assertEquals(patternConstraint.getRegularExpression(), "^[0-9a-fA-F]$");
+ Assert.assertEquals(patternConstraint.getJavaPatternString(), "^[0-9a-fA-F]$");
}
@Test
Assert.assertEquals(Integer.valueOf(10), lengthConstraint.upperEndpoint());
final PatternConstraint patternConstraint = patternConstraints.get(0);
- Assert.assertEquals(patternConstraint.getRegularExpression(), "^[0-9a-fA-F]$");
+ Assert.assertEquals(patternConstraint.getJavaPatternString(), "^[0-9a-fA-F]$");
}
@Test
Assert.assertEquals(Integer.valueOf(10), lengthConstraint.upperEndpoint());
final PatternConstraint patternConstraint = patternConstraints.get(0);
- Assert.assertEquals(patternConstraint.getRegularExpression(), "^[0-9a-fA-F]$");
+ Assert.assertEquals(patternConstraint.getJavaPatternString(), "^[0-9a-fA-F]$");
}
private static Module typesModule(final SchemaContext context) {
final PatternConstraint patternConstraint2 = patternConstraints2.get(0);
final PatternConstraint patternConstraint3 = patternConstraints3.get(0);
- assertEquals("^dp[0-9]+o[0-9]+(d[0-9]+)?$", patternConstraint0.getRegularExpression());
- assertEquals("^dp[0-9]+s[0-9]+(f[0-9]+)?(d[0-9]+)?$", patternConstraint1.getRegularExpression());
+ assertEquals("^dp[0-9]+o[0-9]+(d[0-9]+)?$", patternConstraint0.getJavaPatternString());
+ assertEquals("^dp[0-9]+s[0-9]+(f[0-9]+)?(d[0-9]+)?$", patternConstraint1.getJavaPatternString());
assertEquals("^dp[0-9]+(P[0-9]+)?p[0-9]{1,3}s[0-9]{1,3}(f[0-9]+)?(d[0-9]+)?$",
- patternConstraint2.getRegularExpression());
- assertEquals("^dp[0-9]+p[0-9]+p[0-9]+$", patternConstraint3.getRegularExpression());
+ patternConstraint2.getJavaPatternString());
+ assertEquals("^dp[0-9]+p[0-9]+p[0-9]+$", patternConstraint3.getJavaPatternString());
}
}
final List<PatternConstraint> patternConstraints = ((StringTypeDefinition) type).getPatternConstraints();
assertEquals(1, patternConstraints.size());
final PatternConstraint pattern = patternConstraints.iterator().next();
- assertEquals("^\".*\"$", pattern.getRegularExpression());
- assertTrue(Pattern.compile(pattern.getRegularExpression()).matcher("\"enclosed string in quotes\"").matches());
+ assertEquals("^\".*\"$", pattern.getJavaPatternString());
+ assertTrue(Pattern.compile(pattern.getJavaPatternString()).matcher("\"enclosed string in quotes\"").matches());
}
private static void verifySingleQuotesExpression(final SchemaContext schemaContext) {
final List<PatternConstraint> patternConstraints = ((StringTypeDefinition) type).getPatternConstraints();
assertEquals(1, patternConstraints.size());
final PatternConstraint pattern = patternConstraints.iterator().next();
- assertEquals("^'.*'$", pattern.getRegularExpression());
- assertTrue(Pattern.compile(pattern.getRegularExpression()).matcher("'enclosed string in quotes'").matches());
+ assertEquals("^'.*'$", pattern.getJavaPatternString());
+ assertTrue(Pattern.compile(pattern.getJavaPatternString()).matcher("'enclosed string in quotes'").matches());
}
}
\ No newline at end of file
final PatternConstraintEffectiveImpl patternConstraintSecond = (PatternConstraintEffectiveImpl)
((StringTypeDefinition) currentLeaf.getType()).getPatternConstraints().get(0);
- assertEquals("^[0-9a-fA-F]*$", patternConstraint.getRegularExpression());
+ assertEquals("^[0-9a-fA-F]*$", patternConstraint.getJavaPatternString());
assertFalse(patternConstraint.getReference().isPresent());
assertFalse(patternConstraint.getDescription().isPresent());
assertEquals(Optional.of("Supplied value does not match the regular expression ^[0-9a-fA-F]*$."),
assertNotNull(ipv4.getBaseType());
String expectedPattern = "^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}"
+ "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])" + "(%[\\p{N}\\p{L}]+)?$";
- assertEquals(expectedPattern, ipv4.getPatternConstraints().get(0).getRegularExpression());
+ assertEquals(expectedPattern, ipv4.getPatternConstraints().get(0).getJavaPatternString());
StringTypeDefinition ipv6 = (StringTypeDefinition) unionTypes.get(1);
assertNotNull(ipv6.getBaseType());
expectedPattern = "^((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}"
+ "((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|" + "(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}"
+ "(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))" + "(%[\\p{N}\\p{L}]+)?$";
- assertEquals(expectedPattern, ipv6Patterns.get(0).getRegularExpression());
+ assertEquals(expectedPattern, ipv6Patterns.get(0).getJavaPatternString());
expectedPattern = "^(([^:]+:){6}(([^:]+:[^:]+)|(.*\\..*)))|" + "((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)"
+ "(%.+)?$";
- assertEquals(expectedPattern, ipv6Patterns.get(1).getRegularExpression());
+ assertEquals(expectedPattern, ipv6Patterns.get(1).getJavaPatternString());
}
@Test
assertEquals(1, patterns.size());
String expectedPattern = "^((([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.)*"
+ "([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.?)" + "|\\.$";
- assertEquals(expectedPattern, patterns.get(0).getRegularExpression());
+ assertEquals(expectedPattern, patterns.get(0).getJavaPatternString());
LengthConstraint lengths = type.getLengthConstraint().get();
assertEquals(1, lengths.getAllowedRanges().asRanges().size());
List<PatternConstraint> patterns = testedType.getPatternConstraints();
assertEquals(1, patterns.size());
PatternConstraint pattern = patterns.get(0);
- assertEquals("^\\d*(\\.\\d*){1,127}$", pattern.getRegularExpression());
+ assertEquals("^\\d*(\\.\\d*){1,127}$", pattern.getJavaPatternString());
QName testedTypeQName = testedType.getQName();
assertEquals(URI.create("urn:ietf:params:xml:ns:yang:ietf-yang-types"), testedTypeQName.getNamespace());
pattern = patterns.get(0);
assertEquals("^(([0-1](\\.[1-3]?[0-9]))|(2\\.(0|([1-9]\\d*))))(\\.(0|([1-9]\\d*)))*$",
- pattern.getRegularExpression());
+ pattern.getJavaPatternString());
QName testedTypeBaseQName = testedTypeBase.getQName();
assertEquals(URI.create("urn:ietf:params:xml:ns:yang:ietf-yang-types"), testedTypeBaseQName.getNamespace());
List<PatternConstraint> patterns = type.getPatternConstraints();
assertEquals(1, patterns.size());
PatternConstraint pattern = patterns.iterator().next();
- assertEquals("^[e-z]*$", pattern.getRegularExpression());
+ assertEquals("^[e-z]*$", pattern.getJavaPatternString());
assertEquals(1, type.getLengthConstraint().get().getAllowedRanges().asRanges().size());
final StringTypeDefinition baseType1 = type.getBaseType();
patterns = baseType1.getPatternConstraints();
assertEquals(1, patterns.size());
pattern = patterns.iterator().next();
- assertEquals("^[b-u]*$", pattern.getRegularExpression());
+ assertEquals("^[b-u]*$", pattern.getJavaPatternString());
assertEquals(1, baseType1.getLengthConstraint().get().getAllowedRanges().asRanges().size());
final StringTypeDefinition baseType2 = baseType1.getBaseType();
patterns = baseType3.getPatternConstraints();
assertEquals(1, patterns.size());
pattern = patterns.iterator().next();
- assertEquals("^[a-k]*$", pattern.getRegularExpression());
+ assertEquals("^[a-k]*$", pattern.getJavaPatternString());
final RangeSet<Integer> baseType3Lengths = baseType3.getLengthConstraint().get().getAllowedRanges();
assertEquals(1, baseType3Lengths.asRanges().size());
length = baseType3Lengths.span();
assertTrue(!patterns.isEmpty());
assertEquals(1, patterns.size());
final PatternConstraint pattern = patterns.iterator().next();
- assertEquals("^[e-z]*$", pattern.getRegularExpression());
+ assertEquals("^[e-z]*$", pattern.getJavaPatternString());
assertEquals(1, type.getLengthConstraint().get().getAllowedRanges().asRanges().size());
final LeafSchemaNode multiplePatternDirectStringDefLeaf = (LeafSchemaNode) foo
boolean isEZPattern = false;
boolean isADPattern = false;
for (final PatternConstraint patternConstraint : patterns) {
- if (patternConstraint.getRegularExpression().equals("^[e-z]*$")) {
+ if (patternConstraint.getJavaPatternString().equals("^[e-z]*$")) {
isEZPattern = true;
- } else if (patternConstraint.getRegularExpression().equals("^[a-d]*$")) {
+ } else if (patternConstraint.getJavaPatternString().equals("^[a-d]*$")) {
isADPattern = true;
}
}
final List<PatternConstraint> patterns = baseType2.getPatternConstraints();
assertEquals(1, patterns.size());
final PatternConstraint pattern = patterns.iterator().next();
- assertEquals("^[a-k]*$", pattern.getRegularExpression());
+ assertEquals("^[a-k]*$", pattern.getJavaPatternString());
final RangeSet<Integer> baseType3Lengths = baseType2.getLengthConstraint().get().getAllowedRanges();
assertEquals(1, baseType3Lengths.asRanges().size());
length = baseType3Lengths.span();