Merge pull request #12 from myrle-krantz/develop

@ValidIdentiifiers (plural)
diff --git a/src/main/java/io/mifos/core/lang/validation/CheckIdentifier.java b/src/main/java/io/mifos/core/lang/validation/CheckIdentifier.java
index bda4042..4e54320 100644
--- a/src/main/java/io/mifos/core/lang/validation/CheckIdentifier.java
+++ b/src/main/java/io/mifos/core/lang/validation/CheckIdentifier.java
@@ -39,6 +39,10 @@
       if (obj == null)
          return optional;
 
+      return validate(obj, maximumLength);
+   }
+
+   static boolean validate(final String obj, final int maximumLength) {
       if (obj.length() < 2)
          return false;
 
@@ -53,7 +57,7 @@
       }
    }
 
-   private String encode(String identifier) throws UnsupportedEncodingException {
+   static private String encode(String identifier) throws UnsupportedEncodingException {
       return URLEncoder.encode(identifier, "UTF-8");
    }
 }
diff --git a/src/main/java/io/mifos/core/lang/validation/CheckIdentifiers.java b/src/main/java/io/mifos/core/lang/validation/CheckIdentifiers.java
new file mode 100644
index 0000000..183b6ac
--- /dev/null
+++ b/src/main/java/io/mifos/core/lang/validation/CheckIdentifiers.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2017 The Mifos Initiative
+ *
+ * Licensed 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 io.mifos.core.lang.validation;
+
+import io.mifos.core.lang.validation.constraints.ValidIdentifiers;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import java.util.List;
+
+/**
+ * @author Myrle Krantz
+ */
+public class CheckIdentifiers implements ConstraintValidator<ValidIdentifiers, List<String>> {
+  private int maximumLength = 32;
+  @Override
+  public void initialize(final ValidIdentifiers constraintAnnotation) {
+    maximumLength = constraintAnnotation.maxLength();
+
+  }
+
+  @Override
+  public boolean isValid(final List<String> value, final ConstraintValidatorContext context) {
+    return value != null && value.stream().allMatch(x -> x != null && CheckIdentifier.validate(x, maximumLength));
+  }
+}
diff --git a/src/main/java/io/mifos/core/lang/validation/constraints/ValidIdentifiers.java b/src/main/java/io/mifos/core/lang/validation/constraints/ValidIdentifiers.java
new file mode 100644
index 0000000..899f536
--- /dev/null
+++ b/src/main/java/io/mifos/core/lang/validation/constraints/ValidIdentifiers.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2017 The Mifos Initiative
+ *
+ * Licensed 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 io.mifos.core.lang.validation.constraints;
+
+import io.mifos.core.lang.validation.CheckIdentifier;
+import io.mifos.core.lang.validation.CheckIdentifiers;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Checks that a list of identifiers is valid, in the same way that ValidIdentifier checks if a single identifier is
+ * valid.
+ *
+ * @author Myrle Krantz
+ */
+@SuppressWarnings("unused")
+@Target({ FIELD, METHOD, PARAMETER})
+@Retention(RUNTIME)
+@Documented
+@Constraint(validatedBy = CheckIdentifiers.class)
+public @interface ValidIdentifiers {
+  String message() default "One or more invalid fineract identifiers.";
+  Class<?>[] groups() default { };
+  Class<? extends Payload>[] payload() default { };
+
+  int maxLength() default 32;
+}
\ No newline at end of file
diff --git a/src/test/java/io/mifos/core/lang/validation/TestHelper.java b/src/test/java/io/mifos/core/lang/validation/TestHelper.java
new file mode 100644
index 0000000..e89a7f8
--- /dev/null
+++ b/src/test/java/io/mifos/core/lang/validation/TestHelper.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2017 The Mifos Initiative
+ *
+ * Licensed 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 io.mifos.core.lang.validation;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+import java.util.Set;
+
+/**
+ * @author Myrle Krantz
+ */
+public class TestHelper {
+
+  static <T> boolean isValid(final T annotatedInstance)
+  {
+    final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
+    final Validator validator = factory.getValidator();
+    final Set<ConstraintViolation<T>> errors = validator.validate(annotatedInstance);
+
+    return errors.size() == 0;
+  }
+}
diff --git a/src/test/java/io/mifos/core/lang/validation/ValidIdentifierTest.java b/src/test/java/io/mifos/core/lang/validation/ValidIdentifierTest.java
index 2f8c36f..a1ad204 100644
--- a/src/test/java/io/mifos/core/lang/validation/ValidIdentifierTest.java
+++ b/src/test/java/io/mifos/core/lang/validation/ValidIdentifierTest.java
@@ -19,11 +19,7 @@
 import org.junit.Assert;
 import org.junit.Test;
 
-import javax.validation.ConstraintViolation;
-import javax.validation.Validation;
-import javax.validation.Validator;
-import javax.validation.ValidatorFactory;
-import java.util.Set;
+import static io.mifos.core.lang.validation.TestHelper.isValid;
 
 /**
  * @author Myrle Krantz
@@ -99,15 +95,6 @@
     Assert.assertFalse(isValid(annotatedInstance));
   }
 
-  private boolean isValid(final AnnotatedClass annotatedInstance)
-  {
-    final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
-    final Validator validator = factory.getValidator();
-    final Set<ConstraintViolation<AnnotatedClass>> errors = validator.validate(annotatedInstance);
-
-    return errors.size() == 0;
-  }
-
   private static class AnnotatedClass {
     @ValidIdentifier(maxLength = 5)
     String applicationName;
diff --git a/src/test/java/io/mifos/core/lang/validation/ValidIdentifiersTest.java b/src/test/java/io/mifos/core/lang/validation/ValidIdentifiersTest.java
new file mode 100644
index 0000000..5f110ca
--- /dev/null
+++ b/src/test/java/io/mifos/core/lang/validation/ValidIdentifiersTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2017 The Mifos Initiative
+ *
+ * Licensed 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 io.mifos.core.lang.validation;
+
+import io.mifos.core.lang.validation.constraints.ValidIdentifiers;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static io.mifos.core.lang.validation.TestHelper.isValid;
+
+/**
+ * @author Myrle Krantz
+ */
+public class ValidIdentifiersTest {
+
+  @Test
+  public void valid()
+  {
+    final AnnotatedClass annotatedInstance = new AnnotatedClass(Collections.singletonList("xxxx"));
+    Assert.assertTrue(isValid(annotatedInstance));
+  }
+
+  @Test
+  public void toolong()
+  {
+    final AnnotatedClass annotatedInstance = new AnnotatedClass(Collections.singletonList("xxxxxx"));
+    Assert.assertFalse(isValid(annotatedInstance));
+  }
+
+  @Test
+  public void nullList()
+  {
+    final AnnotatedClass annotatedInstance = new AnnotatedClass(null);
+    Assert.assertFalse(isValid(annotatedInstance));
+  }
+
+  @Test
+  public void nullInList()
+  {
+    final AnnotatedClass annotatedInstance = new AnnotatedClass(Collections.singletonList(null));
+    Assert.assertFalse(isValid(annotatedInstance));
+  }
+
+  @Test
+  public void badApple()
+  {
+    final AnnotatedClass annotatedInstance = new AnnotatedClass(Arrays.asList("xxxx", null));
+    Assert.assertFalse(isValid(annotatedInstance));
+  }
+
+  private static class AnnotatedClass {
+    @ValidIdentifiers(maxLength = 5)
+    List<String> identifiers;
+
+    AnnotatedClass(final List<String> identifiers) {
+      this.identifiers= identifiers;
+    }
+  }
+}