Author: jawi
Date: Thu Nov 15 16:48:35 2012
New Revision: 1409877

URL: http://svn.apache.org/viewvc?rev=1409877&view=rev
Log:
Fixed FELIX-3758, FELIX-3757 & FELIX-3756:

- validation of required attributes without min, max or optionValues was not 
performed;
- validation of attributes with cardinality != 0 was not performed correctly;
- added a validation for values of invalid types to ensure they are not 
accepted as-is.


Added:
    
felix/trunk/metatype/src/main/java/org/apache/felix/metatype/ADValidator.java   
(with props)
    
felix/trunk/metatype/src/test/java/org/apache/felix/metatype/ADValidatorTest.java
   (with props)
Modified:
    felix/trunk/metatype/src/main/java/org/apache/felix/metatype/AD.java
    felix/trunk/metatype/src/test/java/org/apache/felix/metatype/ADTest.java

Modified: felix/trunk/metatype/src/main/java/org/apache/felix/metatype/AD.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/metatype/src/main/java/org/apache/felix/metatype/AD.java?rev=1409877&r1=1409876&r2=1409877&view=diff
==============================================================================
--- felix/trunk/metatype/src/main/java/org/apache/felix/metatype/AD.java 
(original)
+++ felix/trunk/metatype/src/main/java/org/apache/felix/metatype/AD.java Thu 
Nov 15 16:48:35 2012
@@ -47,6 +47,12 @@ public class AD extends OptionalAttribut
 
     /**
      * The message returned from the {@link #validate(String)} method if the
+     * value is invalid considering its type (value is "%invalid value").
+     */
+    public static final String VALIDATE_INVALID_VALUE = "%invalid value";
+
+    /**
+     * The message returned from the {@link #validate(String)} method if the
      * value is greater than the specified {@link #getMax() maximum value}
      * (value is "%greater than maximum").
      */
@@ -175,109 +181,7 @@ public class AD extends OptionalAttribut
      */
     public String validate( String valueString )
     {
-        // no validation if no min and max
-        if ( getMin() == null && getMax() == null && getOptionValues() == null 
)
-        {
-            return null;
-        }
-
-        // min/max for strings and passwords indicates the length
-        final Comparable value;
-        if ( getType() == AttributeDefinition.STRING || getType() == 
AttributeDefinition.PASSWORD )
-        {
-            if ( valueString == null )
-            {
-                if ( isRequired() )
-                {
-                    return VALIDATE_MISSING;
-                }
-
-                return ""; // accept null value
-            }
-
-            if ( getMin() != null )
-            {
-                try
-                {
-                    if ( valueString.length() < Integer.parseInt( getMin() ) )
-                    {
-                        return VALIDATE_LESS_THAN_MINIMUM;
-                    }
-                }
-                catch ( NumberFormatException nfe )
-                {
-                    // cannot check min length
-                }
-            }
-
-            if ( getMax() != null )
-            {
-                try
-                {
-                    if ( valueString.length() > Integer.parseInt( getMax() ) )
-                    {
-                        return VALIDATE_GREATER_THAN_MAXIMUM;
-                    }
-                }
-                catch ( NumberFormatException nfe )
-                {
-                    // cannot check min length
-                }
-            }
-
-            value = valueString;
-        }
-        else
-        {
-            value = convertToType( valueString );
-            if ( value == null )
-            {
-                if ( isRequired() )
-                {
-                    return VALIDATE_MISSING;
-                }
-
-                return ""; // accept null value
-            }
-
-            Comparable other = convertToType( getMin() );
-            if ( other != null )
-            {
-                if ( value.compareTo( other ) < 0 )
-                {
-                    return VALIDATE_LESS_THAN_MINIMUM;
-                }
-            }
-
-            other = convertToType( getMax() );
-            if ( other != null )
-            {
-                if ( value.compareTo( other ) > 0 )
-                {
-                    return VALIDATE_GREATER_THAN_MAXIMUM;
-                }
-            }
-        }
-
-        String[] optionValues = getOptionValues();
-        if ( optionValues != null && optionValues.length > 0 )
-        {
-            for ( int i = 0; i < optionValues.length; i++ )
-            {
-                Comparable other = convertToType( optionValues[i] );
-                if ( value.compareTo( other ) == 0 )
-                {
-                    // one of the option values
-                    return "";
-                }
-            }
-
-            // not any of the option values, fail
-            return VALIDATE_NOT_A_VALID_OPTION;
-        }
-
-        // finally, we accept the value
-        return "";
+       return ADValidator.validate(this, valueString);
     }
 
 
@@ -440,59 +344,50 @@ public class AD extends OptionalAttribut
 
     public static String[] splitList( String listString )
     {
-        // check for non-existing or empty lists
-        if ( listString == null )
-        {
-            return null;
-        }
-        else if ( listString.length() == 0 )
-        {
-            return new String[]
-                { "" };
-        }
+               if (listString == null) {
+                       return null;
+               } else if (listString.length() == 0) {
+                       return new String[] { "" };
+               }
+
+               List strings = new ArrayList();
+               StringBuffer sb = new StringBuffer();
+
+               int length = listString.length();
+               boolean escaped = false;
+               
+               for (int i = 0; i < length; i++) {
+                       char ch = listString.charAt(i);
+                       if (ch == '\\') {
+                               if (!escaped) {
+                                       escaped = true;
+                                       continue;
+                               }
+                       } else if (ch == ',') {
+                               if (!escaped) {
+                                       // unescaped comma, this is a string 
delimiter...
+                                       strings.add(sb.toString());
+                                       sb.setLength(0);
+                                       continue;
+                               }
+                       } else if (ch == ' ') {
+                               // we should ignore spaces normally, unless 
they are escaped...
+                               if (!escaped) {
+                                       continue;
+                               }
+                       } else if (Character.isWhitespace(ch)) {
+                               // Other whitespaces are ignored...
+                               continue;
+                       }
+
+                       sb.append(ch);
+                       escaped = false;
+               }
 
-        List values = new ArrayList();
-        boolean escape = false;
-        StringBuffer buf = new StringBuffer();
-        for ( int i = 0; i < listString.length(); i++ )
-        {
-            char c = listString.charAt( i );
-
-            if ( escape )
-            {
-                // just go ahead
-                escape = false;
-            }
-            else if ( c == ',' )
-            {
-                String value = buf.toString().trim();
-                if ( value.length() > 0 )
-                {
-                    values.add( value );
-                }
-                buf.delete( 0, buf.length() );
-                continue;
-            }
-            else if ( c == '\\' )
-            {
-                escape = true;
-                continue;
-            }
-
-            buf.append( c );
-        }
-
-        // add last string
-        if ( buf.length() > 0 )
-        {
-            String value = buf.toString().trim();
-            if ( value.length() > 0 )
-            {
-                values.add( value );
-            }
-        }
+               // Always add the last string, as it contains everything after 
the last comma...
+               strings.add(sb.toString());
 
-        return values.isEmpty() ? null : ( String[] ) values.toArray( new 
String[values.size()] );
+               return (String[]) strings.toArray(new String[strings.size()]);
     }
 
 

Added: 
felix/trunk/metatype/src/main/java/org/apache/felix/metatype/ADValidator.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/metatype/src/main/java/org/apache/felix/metatype/ADValidator.java?rev=1409877&view=auto
==============================================================================
--- 
felix/trunk/metatype/src/main/java/org/apache/felix/metatype/ADValidator.java 
(added)
+++ 
felix/trunk/metatype/src/main/java/org/apache/felix/metatype/ADValidator.java 
Thu Nov 15 16:48:35 2012
@@ -0,0 +1,348 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.metatype;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import org.osgi.service.metatype.AttributeDefinition;
+
+/**
+ * Provides various validation routines used by the {@link AD#validate(String)}
+ * method.
+ * 
+ * @author <a href="mailto:[email protected]";>Felix Project Team</a>
+ */
+final class ADValidator {
+
+       /**
+        * Validates a given input string according to the type specified by the
+        * given attribute definition.
+        * 
+        * @param ad
+        *            the attribute definition to use in the validation;
+        * @param rawInput
+        *            the raw input value to validate.
+        * @return <code>null</code> if no validation is available, <tt>""</tt> 
if
+        *         validation was successful, or any other non-empty string in 
case
+        *         validation fails.
+        */
+       public static String validate(AD ad, String rawInput) {
+               // Handle the case in which the given input is not defined...
+               if (rawInput == null) {
+                       if (ad.isRequired()) {
+                               return AD.VALIDATE_MISSING;
+                       }
+
+                       return ""; // accept null value...
+               }
+
+               // Raw input is defined, validate it further
+               String[] input;
+
+               if (ad.getCardinality() == 0) {
+                       input = new String[] { rawInput.trim() };
+               } else {
+                       input = AD.splitList(rawInput);
+               }
+
+               int type = ad.getType();
+               switch (type) {
+               case AttributeDefinition.BOOLEAN:
+                       return validateBooleanValue(ad, input);
+
+               case AttributeDefinition.CHARACTER:
+                       return validateCharacterValue(ad, input);
+
+               case AttributeDefinition.BIGDECIMAL:
+               case AttributeDefinition.BIGINTEGER:
+               case AttributeDefinition.BYTE:
+               case AttributeDefinition.DOUBLE:
+               case AttributeDefinition.FLOAT:
+               case AttributeDefinition.INTEGER:
+               case AttributeDefinition.LONG:
+               case AttributeDefinition.SHORT:
+                       return validateNumericValue(ad, input);
+
+               case AttributeDefinition.PASSWORD:
+               case AttributeDefinition.STRING:
+                       return validateString(ad, input);
+
+               default:
+                       return null; // no validation present...
+               }
+       }
+
+       /**
+        * Searches for a given search value in a given array of options.
+        * 
+        * @param searchValue
+        *            the value to search for;
+        * @param optionValues
+        *            the values to search in.
+        * @return <code>null</code> if the given search value is not found in 
the
+        *         given options, the searched value if found, or <tt>""</tt> 
if no
+        *         search value or options were given.
+        */
+       private static String findOptionValue(String searchValue, String[] 
optionValues) {
+               if ((searchValue == null) || (optionValues == null) || 
(optionValues.length == 0)) {
+                       // indicates that we've not searched
+                       return "";
+               }
+
+               for (int i = 0; i < optionValues.length; i++) {
+                       if (optionValues[i].equals(searchValue)) {
+                               return optionValues[i];
+                       }
+               }
+
+               return null;
+       }
+
+       /**
+        * Parses a given string value into a numeric type.
+        * 
+        * @param type
+        *            the type to parse;
+        * @param value
+        *            the value to parse.
+        * @return a {@link Number} representation of the given value, or
+        *         <code>null</code> if the input was <code>null</code>, empty, 
or
+        *         not a numeric type.
+        * @throws NumberFormatException
+        *             in case the given value cannot be parsed as numeric 
value.
+        */
+       private static Comparable parseNumber(int type, String value) throws 
NumberFormatException {
+               if ((value != null) && (value.length() > 0)) {
+                       switch (type) {
+                       case AttributeDefinition.BIGDECIMAL:
+                               return new BigDecimal(value);
+                       case AttributeDefinition.BIGINTEGER:
+                               return new BigInteger(value);
+                       case AttributeDefinition.BYTE:
+                               return Byte.valueOf(value);
+                       case AttributeDefinition.SHORT:
+                               return Short.valueOf(value);
+                       case AttributeDefinition.INTEGER:
+                               return Integer.valueOf(value);
+                       case AttributeDefinition.LONG:
+                               return Long.valueOf(value);
+                       case AttributeDefinition.FLOAT:
+                               return Float.valueOf(value);
+                       case AttributeDefinition.DOUBLE:
+                               return Double.valueOf(value);
+                       default:
+                               return null;
+                       }
+               }
+               return null;
+       }
+
+       /**
+        * Parses a given string value as character, allowing <code>null</code>
+        * -values and empty values to be given as input.
+        * 
+        * @param value
+        *            the value to parse as character, can be <code>null</code> 
or
+        *            an empty value.
+        * @return the character value if, and only if, the given input was non-
+        *         <code>null</code> and a non-empty string.
+        */
+       private static Character parseOptionalChar(String value) {
+               if ((value != null) && (value.length() > 0)) {
+                       return Character.valueOf(value.charAt(0));
+               }
+               return null;
+       }
+
+       /**
+        * Parses a given string value as integer, allowing 
<code>null</code>-values
+        * and invalid numeric values to be given as input.
+        * 
+        * @param value
+        *            the value to parse as integer, can be <code>null</code> 
or a
+        *            non-numeric value.
+        * @return the integer value if, and only if, the given input was non-
+        *         <code>null</code> and a valid integer representation.
+        */
+       private static Integer parseOptionalInt(String value) {
+               if (value != null) {
+                       try {
+                               return Integer.valueOf(value);
+                       } catch (NumberFormatException e) {
+                               // Ignore; invalid value...
+                       }
+               }
+               return null;
+       }
+
+       /**
+        * Validates a given input string as boolean value.
+        * 
+        * @param ad
+        *            the attribute definition to use in the validation;
+        * @param input
+        *            the array with input values to validate.
+        * @return <code>null</code> if no validation is available, <tt>""</tt> 
if
+        *         validation was successful, or any other non-empty string in 
case
+        *         validation fails.
+        */
+       private static String validateBooleanValue(AD ad, String[] input) {
+               for (int i = 0; i < input.length; i++) {
+                       int length = input[i].length();
+                       if ((length == 0) && ad.isRequired()) {
+                               return AD.VALIDATE_MISSING;
+                       } else if (length > 0 && 
!"true".equalsIgnoreCase(input[i]) && !"false".equalsIgnoreCase(input[i])) {
+                               return AD.VALIDATE_INVALID_VALUE;
+                       }
+               }
+
+               String[] optionValues = ad.getOptionValues();
+               if (optionValues != null && optionValues.length > 0) {
+                       return null; // no validation possible for this type...
+               }
+
+               return ""; // accept given value...
+       }
+
+       /**
+        * Validates a given input string as character value.
+        * 
+        * @param ad
+        *            the attribute definition to use in the validation;
+        * @param input
+        *            the array with input values to validate.
+        * @return <code>null</code> if no validation is available, <tt>""</tt> 
if
+        *         validation was successful, or any other non-empty string in 
case
+        *         validation fails.
+        */
+       private static String validateCharacterValue(AD ad, String[] input) {
+               Character min = parseOptionalChar(ad.getMin());
+               Character max = parseOptionalChar(ad.getMax());
+               String[] optionValues = ad.getOptionValues();
+
+               for (int i = 0; i < input.length; i++) {
+                       Character ch = null;
+                       int length = input[i].length();
+                       if (length > 1) {
+                               return AD.VALIDATE_GREATER_THAN_MAXIMUM;
+                       } else if ((length == 0) && ad.isRequired()) {
+                               return AD.VALIDATE_MISSING;
+                       } else if (length == 1) {
+                               ch = Character.valueOf(input[i].charAt(0));
+                               // Check whether the minimum value is adhered 
for all values...
+                               if ((min != null) && (ch.compareTo(min) < 0)) {
+                                       return AD.VALIDATE_LESS_THAN_MINIMUM;
+                               }
+                               // Check whether the maximum value is adhered 
for all values...
+                               if ((max != null) && (ch.compareTo(max) > 0)) {
+                                       return AD.VALIDATE_GREATER_THAN_MAXIMUM;
+                               }
+                       }
+
+                       if (findOptionValue(input[i], optionValues) == null) {
+                               return AD.VALIDATE_NOT_A_VALID_OPTION;
+                       }
+               }
+
+               return ""; // accept given value...
+       }
+
+       /**
+        * Validates a given input string as numeric value.
+        * 
+        * @param ad
+        *            the attribute definition to use in the validation;
+        * @param input
+        *            the array with input values to validate.
+        * @return <code>null</code> if no validation is available, <tt>""</tt> 
if
+        *         validation was successful, or any other non-empty string in 
case
+        *         validation fails.
+        */
+       private static String validateNumericValue(AD ad, String[] input) {
+               Integer min = parseOptionalInt(ad.getMin());
+               Integer max = parseOptionalInt(ad.getMax());
+               String[] optionValues = ad.getOptionValues();
+
+               for (int i = 0; i < input.length; i++) {
+                       Comparable value = null;
+                       try {
+                               value = parseNumber(ad.getType(), input[i]);
+                       } catch (NumberFormatException e) {
+                               return AD.VALIDATE_INVALID_VALUE;
+                       }
+
+                       if ((value == null) && ad.isRequired()) {
+                               // Possible if the cardinality != 0 and input 
was something like
+                               // "0,,1"...
+                               return AD.VALIDATE_MISSING;
+                       }
+                       // Check whether the minimum value is adhered for all 
values...
+                       if ((min != null) && (value != null) && 
(value.compareTo(min) < 0)) {
+                               return AD.VALIDATE_LESS_THAN_MINIMUM;
+                       }
+                       // Check whether the maximum value is adhered for all 
values...
+                       if ((max != null) && (value != null) && 
(value.compareTo(max) > 0)) {
+                               return AD.VALIDATE_GREATER_THAN_MAXIMUM;
+                       }
+
+                       if (findOptionValue(input[i], optionValues) == null) {
+                               return AD.VALIDATE_NOT_A_VALID_OPTION;
+                       }
+               }
+
+               return ""; // accept given value...
+       }
+
+       /**
+        * Validates a given input string as string (or password).
+        * 
+        * @param ad
+        *            the attribute definition to use in the validation;
+        * @param input
+        *            the array with input values to validate.
+        * @return <code>null</code> if no validation is available, <tt>""</tt> 
if
+        *         validation was successful, or any other non-empty string in 
case
+        *         validation fails.
+        */
+       private static String validateString(AD ad, String[] input) {
+               Integer min = parseOptionalInt(ad.getMin());
+               Integer max = parseOptionalInt(ad.getMax());
+               String[] optionValues = ad.getOptionValues();
+
+               for (int i = 0; i < input.length; i++) {
+                       int length = input[i].length();
+                       // Check whether the minimum length is adhered for all 
values...
+                       if ((min != null) && (length < min.intValue())) {
+                               return AD.VALIDATE_LESS_THAN_MINIMUM;
+                       }
+                       // Check whether the maximum length is adhered for all 
values...
+                       if ((max != null) && (length > max.intValue())) {
+                               return AD.VALIDATE_GREATER_THAN_MAXIMUM;
+                       }
+
+                       if (findOptionValue(input[i], optionValues) == null) {
+                               return AD.VALIDATE_NOT_A_VALID_OPTION;
+                       }
+               }
+
+               return ""; // accept given value...
+       }
+}

Propchange: 
felix/trunk/metatype/src/main/java/org/apache/felix/metatype/ADValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
felix/trunk/metatype/src/test/java/org/apache/felix/metatype/ADTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/metatype/src/test/java/org/apache/felix/metatype/ADTest.java?rev=1409877&r1=1409876&r2=1409877&view=diff
==============================================================================
--- felix/trunk/metatype/src/test/java/org/apache/felix/metatype/ADTest.java 
(original)
+++ felix/trunk/metatype/src/test/java/org/apache/felix/metatype/ADTest.java 
Thu Nov 15 16:48:35 2012
@@ -78,6 +78,31 @@ public class ADTest extends TestCase
     }
 
 
+    public void testEmptySecond()
+    {
+        String value0 = "value0";
+        String value1 = "";
+        String listString = value0 + ",";
+        String[] list = AD.splitList( listString );
+        assertNotNull( list );
+        assertEquals( 2, list.length );
+        assertEquals( value0, list[0] );
+        assertEquals( value1, list[1] );
+    }
+
+    public void testSpacedSecond()
+    {
+        String value0 = "value0";
+        String value1 = "";
+        String listString = value0 + ", ";
+        String[] list = AD.splitList( listString );
+        assertNotNull( list );
+        assertEquals( 2, list.length );
+        assertEquals( value0, list[0] );
+        assertEquals( value1, list[1] );
+    }
+
+
     public void testSingleBlanks()
     {
         String value0 = "value";
@@ -106,9 +131,9 @@ public class ADTest extends TestCase
     {
         String value0 = "a,b";
         String value1 = "b,c";
-        String value2 = "c\\";
+        String value2 = " c\\";
         String value3 = "d";
-        String listString = "a\\,b,b\\,c, c\\\\,d";
+        String listString = "a\\,b,b\\,c,\\ c\\\\,d";
         String[] list = AD.splitList( listString );
         assertNotNull( list );
         assertEquals( 4, list.length );
@@ -133,4 +158,42 @@ public class ADTest extends TestCase
         assertEquals( AttributeDefinition.PASSWORD, AD.toType( "Password" ) );
         assertEquals( AttributeDefinition.STRING, AD.toType( "JohnDoe" ) );
     }
+    
+    /**
+     * FELIX-3757: if an AD has only its 'required' property set, but no 
+     * min/max or option values defined, the validation still should detect 
+     * empty values. 
+     */
+    public void testValidateRequiredValueWithMinimalOptions() {
+       AD ad = new AD();
+       ad.setType("Integer");
+       ad.setRequired(true);
+
+       assertEquals(AD.VALIDATE_MISSING, ad.validate(null));
+    }
+    
+    /**
+     * FELIX-3756: if an AD is optional, but its validate method is called
+     * with invalid data, the value is regarded missing.
+     */
+    public void testValidateOptionalValueWithInvalidData() {
+       AD ad = new AD();
+       ad.setType("Integer");
+       ad.setRequired(false);
+       
+       assertEquals(AD.VALIDATE_INVALID_VALUE, ad.validate("abc"));
+    }
+    
+    /**
+     * FELIX-3758: if an AD has a cardinality != 0, the validation method
+     * cannot handle a comma-separated input.
+     */
+    public void testValidateValueWithMultiValueCardinality() {
+       AD ad = new AD();
+       ad.setType("Integer");
+       ad.setCardinality(2);
+       ad.setRequired(true);
+       
+       assertEquals("", ad.validate("1,2"));
+    }
 }

Added: 
felix/trunk/metatype/src/test/java/org/apache/felix/metatype/ADValidatorTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/metatype/src/test/java/org/apache/felix/metatype/ADValidatorTest.java?rev=1409877&view=auto
==============================================================================
--- 
felix/trunk/metatype/src/test/java/org/apache/felix/metatype/ADValidatorTest.java
 (added)
+++ 
felix/trunk/metatype/src/test/java/org/apache/felix/metatype/ADValidatorTest.java
 Thu Nov 15 16:48:35 2012
@@ -0,0 +1,269 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.metatype;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+/**
+ * Test cases for {@link ADValidator}.
+ * 
+ * @author <a href="mailto:[email protected]";>Felix Project Team</a>
+ */
+public class ADValidatorTest extends TestCase {
+
+       /**
+        * Tests the validation of boolean is only done minimally.
+        */
+       public void testValidateBoolean() {
+               AD ad = new AD();
+               ad.setType("Boolean");
+               ad.setRequired(false);
+
+               // optional value
+               assertEquals("", ADValidator.validate(ad, null));
+               // adhere minimal value
+               assertEquals("", ADValidator.validate(ad, "true"));
+               // adhere maximal value
+               assertEquals("", ADValidator.validate(ad, "false"));
+               // not a valid value
+               assertEquals(AD.VALIDATE_INVALID_VALUE, 
ADValidator.validate(ad, "foobar"));
+
+               ad.setCardinality(3); // up to three values are allowed...
+               
+               // mandatory value
+               assertEquals("", ADValidator.validate(ad, null));
+               // 2nd value is missing
+               assertEquals("", ADValidator.validate(ad, "true,,false"));
+
+               ad.setRequired(true);
+
+               // mandatory value
+               assertEquals(AD.VALIDATE_MISSING, ADValidator.validate(ad, 
null));
+               // 2nd value is missing
+               assertEquals(AD.VALIDATE_MISSING, ADValidator.validate(ad, 
"false,,true"));
+               assertEquals("", ADValidator.validate(ad, "false, true, 
false"));
+
+               ad.setOptions(Collections.singletonMap("true", "Yes!"));
+
+               assertEquals(null, ADValidator.validate(ad, "false, true, 
false"));
+       }
+
+       /**
+        * Tests the validation of characters with only limited set of options.
+        */
+       public void testValidateCharacterOptionValues() {
+               AD ad = new AD();
+               ad.setType("Char");
+               ad.setRequired(false);
+
+               // optional value
+               assertEquals("", ADValidator.validate(ad, null));
+               // option too long
+               assertEquals(AD.VALIDATE_GREATER_THAN_MAXIMUM, 
ADValidator.validate(ad, "ab"));
+               // adhere first option value
+               assertEquals("", ADValidator.validate(ad, "b"));
+               // adhere last option value
+               assertEquals("", ADValidator.validate(ad, "e"));
+
+               ad.setCardinality(3); // up to three values are allowed...
+
+               // mandatory value
+               assertEquals("", ADValidator.validate(ad, ""));
+               // 2nd value is missing
+               assertEquals("", ADValidator.validate(ad, "b,,c"));
+
+               ad.setRequired(true);
+
+               // mandatory value
+               assertEquals(AD.VALIDATE_MISSING, ADValidator.validate(ad, 
null));
+               // 2nd value is missing
+               assertEquals(AD.VALIDATE_MISSING, ADValidator.validate(ad, 
"b,,c"));
+               // adhere minimal values
+               assertEquals("", ADValidator.validate(ad, "b, c, d"));
+               // adhere maximal values
+               assertEquals("", ADValidator.validate(ad, "c, d, e"));
+
+               Map options = new HashMap();
+               options.put("b", "B");
+               options.put("c", "C");
+               options.put("d", "D");
+               options.put("e", "E");
+
+               ad.setOptions(options);
+               // no option given
+               assertEquals(AD.VALIDATE_MISSING, ADValidator.validate(ad, ""));
+               // invalid option
+               assertEquals(AD.VALIDATE_NOT_A_VALID_OPTION, 
ADValidator.validate(ad, "a"));
+               // too great
+               assertEquals(AD.VALIDATE_NOT_A_VALID_OPTION, 
ADValidator.validate(ad, "f"));
+               // 2nd value is too less
+               assertEquals(AD.VALIDATE_NOT_A_VALID_OPTION, 
ADValidator.validate(ad, "b,a,c"));
+               // 3rd value is too great
+               assertEquals(AD.VALIDATE_NOT_A_VALID_OPTION, 
ADValidator.validate(ad, "d, e, f"));
+
+               ad.setMin("b");
+               ad.setMax("c");
+               ad.setOptions(Collections.emptyMap());
+
+               // adhere minimal values
+               assertEquals("", ADValidator.validate(ad, "b, c, b"));
+               // d is too great
+               assertEquals(AD.VALIDATE_GREATER_THAN_MAXIMUM, 
ADValidator.validate(ad, "b, c, d"));
+               // a is too less
+               assertEquals(AD.VALIDATE_LESS_THAN_MINIMUM, 
ADValidator.validate(ad, "a, b, c"));
+       }
+
+       /**
+        * Tests the validation of characters with only limited set of options.
+        */
+       public void testValidateDoubleOptionValues() {
+               Map options = new HashMap();
+               options.put("1.1", "B");
+               options.put("2.2", "C");
+               options.put("3.3", "D");
+               options.put("4.4", "E");
+
+               AD ad = new AD();
+               ad.setType("Double");
+               ad.setOptions(options);
+               ad.setRequired(false);
+
+               // optional value
+               assertEquals("", ADValidator.validate(ad, null));
+               // invalid option
+               assertEquals(AD.VALIDATE_NOT_A_VALID_OPTION, 
ADValidator.validate(ad, "1.0"));
+               // adhere first option value
+               assertEquals("", ADValidator.validate(ad, "1.1"));
+               // adhere last option value
+               assertEquals("", ADValidator.validate(ad, "4.4"));
+               // too great
+               assertEquals(AD.VALIDATE_NOT_A_VALID_OPTION, 
ADValidator.validate(ad, "4.5"));
+
+               ad.setCardinality(3); // up to three values are allowed...
+               ad.setRequired(true);
+
+               // mandatory value
+               assertEquals(AD.VALIDATE_MISSING, ADValidator.validate(ad, 
null));
+               // 2nd value is too less
+               assertEquals(AD.VALIDATE_NOT_A_VALID_OPTION, 
ADValidator.validate(ad, "1.1,1.0,2.2"));
+               // adhere minimal values
+               assertEquals("", ADValidator.validate(ad, "1.1, 2.2, 3.3"));
+               // adhere maximal values
+               assertEquals("", ADValidator.validate(ad, "2.2, 3.3, 4.4"));
+               // 3rd value is too great
+               assertEquals(AD.VALIDATE_NOT_A_VALID_OPTION, 
ADValidator.validate(ad, "3.3, 4.4, 5.5"));
+       }
+
+       /**
+        * Tests the validation of integers is based on the minimum and maximum 
values.
+        */
+       public void testValidateInteger() {
+               AD ad = new AD();
+               ad.setType("Integer");
+               ad.setMin("3"); // only values greater than 2
+               ad.setMax("6"); // only values less than 7
+               ad.setRequired(false);
+
+               // optional value
+               assertEquals("", ADValidator.validate(ad, null));
+               // too less
+               assertEquals(AD.VALIDATE_LESS_THAN_MINIMUM, 
ADValidator.validate(ad, "2"));
+               // adhere minimal value
+               assertEquals("", ADValidator.validate(ad, "3"));
+               // adhere maximal value
+               assertEquals("", ADValidator.validate(ad, "6"));
+               // too great
+               assertEquals(AD.VALIDATE_GREATER_THAN_MAXIMUM, 
ADValidator.validate(ad, "7"));
+
+               ad.setCardinality(3); // up to three values are allowed...
+               
+               // mandatory value
+               assertEquals("", ADValidator.validate(ad, null));
+               // 2nd value is missing
+               assertEquals("", ADValidator.validate(ad, "3,,3"));
+
+               ad.setRequired(true);
+
+               // mandatory value
+               assertEquals(AD.VALIDATE_MISSING, ADValidator.validate(ad, 
null));
+               // 2nd value is missing
+               assertEquals(AD.VALIDATE_MISSING, ADValidator.validate(ad, 
"3,,3"));
+               // 2nd value is invalid
+               assertEquals(AD.VALIDATE_INVALID_VALUE, 
ADValidator.validate(ad, "3,a,3"));
+               // 2nd value is too less
+               assertEquals(AD.VALIDATE_LESS_THAN_MINIMUM, 
ADValidator.validate(ad, "3,2,3"));
+               // adhere minimal values
+               assertEquals("", ADValidator.validate(ad, "3, 4, 5"));
+               // adhere maximal values
+               assertEquals("", ADValidator.validate(ad, "6, 5, 4"));
+               // 3rd value is too great
+               assertEquals(AD.VALIDATE_GREATER_THAN_MAXIMUM, 
ADValidator.validate(ad, "5, 6, 7"));
+       }
+
+       /**
+        * Tests the validation of strings is based on the minimum and maximum 
lengths.
+        */
+       public void testValidateString() {
+               AD ad = new AD();
+               ad.setType("String");
+               ad.setRequired(false);
+
+               // optional value
+               assertEquals("", ADValidator.validate(ad, null));
+               // any length of input is accepted
+               assertEquals("", ADValidator.validate(ad, "1234567890"));
+
+               ad.setMin("3"); // minimal length == 3
+               ad.setMax("6"); // maximum length == 6
+
+               // too short
+               assertEquals(AD.VALIDATE_LESS_THAN_MINIMUM, 
ADValidator.validate(ad, "12"));
+               // adhere minimum length
+               assertEquals("", ADValidator.validate(ad, "123"));
+               // adhere maximum length
+               assertEquals("", ADValidator.validate(ad, "12356"));
+               // too long
+               assertEquals(AD.VALIDATE_GREATER_THAN_MAXIMUM, 
ADValidator.validate(ad, "1234567"));
+
+               ad.setCardinality(3); // up to three values are allowed...
+               ad.setRequired(true);
+
+               // mandatory value
+               assertEquals(AD.VALIDATE_MISSING, ADValidator.validate(ad, 
null));
+               // 2nd value is too short
+               assertEquals(AD.VALIDATE_LESS_THAN_MINIMUM, 
ADValidator.validate(ad, "321,12,123"));
+               // adhere minimum lengths
+               assertEquals("", ADValidator.validate(ad, "123, 123, 123"));
+               // adhere maximum lengths
+               assertEquals("", ADValidator.validate(ad, "12356, 654321, 
123456"));
+               // 3rd value is too long
+               assertEquals(AD.VALIDATE_GREATER_THAN_MAXIMUM, 
ADValidator.validate(ad, "123, 123, 1234567"));
+               
+               ad.setOptions(Collections.singletonMap("123", "foo"));
+
+               // adhere minimum lengths
+               assertEquals("", ADValidator.validate(ad, "123, 123, 123"));
+               assertEquals(AD.VALIDATE_NOT_A_VALID_OPTION, 
ADValidator.validate(ad, "2134"));
+       }
+}

Propchange: 
felix/trunk/metatype/src/test/java/org/apache/felix/metatype/ADValidatorTest.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to