mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

matthew_swift
23.50.2007 ec6408fb14ac5d8f3c5d889e4ccce289db08e498
Fix for issue 1523 - Implement String property definition regex support.

It is now possible to constrain the set of valid values for a string property using regular expressions.
1 files added
2 files modified
193 ■■■■■ changed files
opends/resource/admin/property-types/string.xsl 5 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/StringPropertyDefinition.java 80 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/StringPropertyDefinitionTest.java 108 ●●●●● patch | view | raw | blame | history
opends/resource/admin/property-types/string.xsl
@@ -41,5 +41,10 @@
        select="concat('      builder.setCaseInsensitive(',
                       @case-insensitive, ');
')" />
    </xsl:if>
    <xsl:if test="adm:pattern/adm:regex">
      <xsl:value-of
        select="concat('      builder.setPattern(&quot;',
                       normalize-space(adm:pattern/adm:regex), '&quot;);&#xa;')" />
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>
opends/src/server/org/opends/server/admin/StringPropertyDefinition.java
@@ -34,13 +34,14 @@
import java.util.EnumSet;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
/**
 * String property definition.
 * <p>
 * TODO: pattern matching.
 */
public final class StringPropertyDefinition extends
    AbstractPropertyDefinition<String> {
@@ -54,10 +55,14 @@
  // case-insensitive.
  private final boolean isCaseInsensitive;
  // Optional pattern which values of this property must match.
  private final Pattern pattern;
  /**
   * An interface for incrementally constructing string property definitions.
   * An interface for incrementally constructing string property
   * definitions.
   */
  public static class Builder extends
      AbstractBuilder<String, StringPropertyDefinition> {
@@ -66,11 +71,14 @@
    // case-insensitive.
    private boolean isCaseInsensitive = true;
    // Optional pattern which values of this property must match.
    private Pattern pattern = null;
    // Private constructor
    private Builder(
        AbstractManagedObjectDefinition<?, ?> d, String propertyName) {
    private Builder(AbstractManagedObjectDefinition<?, ?> d,
        String propertyName) {
      super(d, propertyName);
    }
@@ -91,6 +99,28 @@
    /**
     * Set the regular expression pattern which values of this
     * property must match. By default there is no pattern defined.
     *
     * @param pattern
     *          The regular expression pattern string, or
     *          <code>null</code> if there is no pattern.
     * @throws PatternSyntaxException
     *           If the provided regular expression pattern has an
     *           invalid syntax.
     */
    public final void setPattern(String pattern)
        throws PatternSyntaxException {
      if (pattern == null) {
        this.pattern = null;
      } else {
        this.pattern = Pattern.compile(pattern);
      }
    }
    /**
     * {@inheritDoc}
     */
    @Override
@@ -99,7 +129,7 @@
        EnumSet<PropertyOption> options,
        DefaultBehaviorProvider<String> defaultBehavior) {
      return new StringPropertyDefinition(d, propertyName, options,
          defaultBehavior, isCaseInsensitive);
          defaultBehavior, isCaseInsensitive, pattern);
    }
  }
@@ -128,9 +158,24 @@
      AbstractManagedObjectDefinition<?, ?> d, String propertyName,
      EnumSet<PropertyOption> options,
      DefaultBehaviorProvider<String> defaultBehavior,
      boolean isCaseInsensitive) {
      boolean isCaseInsensitive, Pattern pattern) {
    super(d, String.class, propertyName, options, defaultBehavior);
    this.isCaseInsensitive = isCaseInsensitive;
    this.pattern = pattern;
  }
  /**
   * Gets the optional regular expression pattern which values of this
   * property must match.
   *
   * @return Returns the optional regular expression pattern which
   *         values of this property must match, or <code>null</code>
   *         if there is no pattern.
   */
  public Pattern getPattern() {
    return pattern;
  }
@@ -181,8 +226,8 @@
  /**
   * Query whether values of this property are case-insensitive.
   *
   * @return Returns <code>true</code> if values are case-insensitive, or
   *         <code>false</code> otherwise.
   * @return Returns <code>true</code> if values are
   *         case-insensitive, or <code>false</code> otherwise.
   */
  public boolean isCaseInsensitive() {
    return isCaseInsensitive;
@@ -211,11 +256,16 @@
   * {@inheritDoc}
   */
  @Override
  public void validateValue(String value) throws IllegalPropertyValueException {
  public void validateValue(String value)
      throws IllegalPropertyValueException {
    ensureNotNull(value);
    // No additional validation required for now (might do pattern
    // matching in future).
    if (pattern != null) {
      Matcher matcher = pattern.matcher(value);
      if (!matcher.matches()) {
        throw new IllegalPropertyValueException(this, value);
      }
    }
  }
@@ -228,6 +278,12 @@
      throws IllegalPropertyValueStringException {
    ensureNotNull(value);
    try {
      validateValue(value);
    } catch (IllegalPropertyValueException e) {
      throw new IllegalPropertyValueStringException(this, value);
    }
    return value;
  }
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/StringPropertyDefinitionTest.java
New file
@@ -0,0 +1,108 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.server.admin;
import static org.testng.Assert.assertEquals;
import org.opends.server.admin.std.meta.RootCfgDefn;
import org.testng.annotations.Test;
/**
 * StringPropertyDefinition Tester.
 */
public class StringPropertyDefinitionTest {
  /**
   * Tests validateValue() with valid data and no pattern.
   */
  @Test
  public void testValidateValue1() {
    StringPropertyDefinition d = getDefinition(true, null);
    d.validateValue("abc");
  }
  /**
   * Tests validateValue() with valid data and a pattern.
   */
  @Test
  public void testValidateValue2() {
    StringPropertyDefinition d = getDefinition(true, "^[a-z]+$");
    d.validateValue("abc");
  }
  /**
   * Tests validateValue() with invalid data and a pattern.
   */
  @Test(expectedExceptions = IllegalPropertyValueException.class)
  public void testValidateValue3() {
    StringPropertyDefinition d = getDefinition(true, "^[a-z]+$");
    d.validateValue("abc123");
  }
  /**
   * Tests decodeValue() with valid data and a pattern.
   */
  @Test
  public void testDecodeValue1() {
    StringPropertyDefinition d = getDefinition(true, "^[a-z]+$");
    assertEquals(d.decodeValue("abc"), "abc");
  }
  /**
   * Tests decodeValue() with invalid data and a pattern.
   */
  @Test(expectedExceptions = IllegalPropertyValueStringException.class)
  public void testDecodeValue2() {
    StringPropertyDefinition d = getDefinition(true, "^[a-z]+$");
    d.decodeValue("abc123");
  }
  // Create a string property definition.
  private StringPropertyDefinition getDefinition(
      boolean isCaseInsensitive, String pattern) {
    StringPropertyDefinition.Builder builder = StringPropertyDefinition
        .createBuilder(RootCfgDefn.getInstance(), "test-property");
    builder.setCaseInsensitive(isCaseInsensitive);
    builder.setPattern(pattern);
    return builder.getInstance();
  }
}