Merge "Add NotNull and NotBlank parameter validation"
diff --git a/policy-endpoints/pom.xml b/policy-endpoints/pom.xml
index 1d8ae53..53e2186 100644
--- a/policy-endpoints/pom.xml
+++ b/policy-endpoints/pom.xml
@@ -19,7 +19,8 @@
   ============LICENSE_END=========================================================
 -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
     <modelVersion>4.0.0</modelVersion>
 
@@ -205,6 +206,12 @@
             <artifactId>openpojo</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
     </dependencies>
 
     <build>
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/client/TopicSinkClient.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/client/TopicSinkClient.java
new file mode 100644
index 0000000..3188b8d
--- /dev/null
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/client/TopicSinkClient.java
@@ -0,0 +1,104 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.endpoints.event.comm.client;
+
+
+import java.util.List;
+
+import lombok.Getter;
+
+import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
+import org.onap.policy.common.endpoints.event.comm.TopicSink;
+import org.onap.policy.common.utils.coder.Coder;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Client for sending messages to a Topic using TopicSink.
+ */
+public class TopicSinkClient {
+    private static final Logger logger = LoggerFactory.getLogger(TopicSinkClient.class);
+
+    /**
+     * Coder used to encode messages being sent to the topic.
+     */
+    private static final Coder CODER = new StandardCoder();
+
+    /**
+     * Topic to which messages are published.
+     */
+    @Getter
+    private final String topic;
+
+    /**
+     * Where messages are published.
+     */
+    private final TopicSink sink;
+
+    /**
+     * Constructs the object.
+     *
+     * @param topic topic to which messages should be published
+     * @throws TopicSinkClientException if the topic does not exist
+     */
+    public TopicSinkClient(final String topic) throws TopicSinkClientException {
+        this.topic = topic;
+
+        final List<TopicSink> lst = getTopicSinks(topic);
+        if (lst.isEmpty()) {
+            throw new TopicSinkClientException("no sinks for topic: " + topic);
+        }
+
+        this.sink = lst.get(0);
+    }
+
+    /**
+     * Sends a message to the topic, after encoding the message as json.
+     *
+     * @param message message to be encoded and sent
+     * @return {@code true} if the message was successfully sent/enqueued, {@code false} otherwise
+     */
+    public boolean send(final Object message) {
+        try {
+            final String json = CODER.encode(message);
+            return sink.send(json);
+
+        } catch (RuntimeException | CoderException e) {
+            logger.warn("send to {} failed because of {}", topic, e.getMessage(), e);
+            return false;
+        }
+    }
+
+    // the remaining methods are wrappers that can be overridden by junit tests
+
+    /**
+     * Gets the sinks for a given topic.
+     *
+     * @param topic the topic of interest
+     * @return the sinks for the topic
+     */
+    protected List<TopicSink> getTopicSinks(final String topic) {
+        return TopicEndpoint.manager.getTopicSinks(topic);
+    }
+}
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/client/TopicSinkClientException.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/client/TopicSinkClientException.java
new file mode 100644
index 0000000..608393b
--- /dev/null
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/client/TopicSinkClientException.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.endpoints.event.comm.client;
+
+/**
+ * Exception thrown by TopicSink client classes.
+ */
+public class TopicSinkClientException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    public TopicSinkClientException() {
+        super();
+    }
+
+    public TopicSinkClientException(final String message) {
+        super(message);
+    }
+
+    public TopicSinkClientException(final Throwable cause) {
+        super(cause);
+    }
+
+    public TopicSinkClientException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+
+    public TopicSinkClientException(final String message, final Throwable cause, final boolean enableSuppression,
+            final boolean writableStackTrace) {
+        super(message, cause, enableSuppression, writableStackTrace);
+    }
+
+}
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/client/TopicSinkClientExceptionTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/client/TopicSinkClientExceptionTest.java
new file mode 100644
index 0000000..c081470
--- /dev/null
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/client/TopicSinkClientExceptionTest.java
@@ -0,0 +1,35 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.endpoints.event.comm.client;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.onap.policy.common.utils.test.ExceptionsTester;
+
+public class TopicSinkClientExceptionTest {
+
+    @Test
+    public void test() {
+        assertEquals(5, new ExceptionsTester().test(TopicSinkClientException.class));
+    }
+}
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/client/TopicSinkClientTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/client/TopicSinkClientTest.java
new file mode 100644
index 0000000..725c041
--- /dev/null
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/client/TopicSinkClientTest.java
@@ -0,0 +1,150 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.endpoints.event.comm.client;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.internal.util.reflection.Whitebox;
+import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
+import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
+import org.onap.policy.common.endpoints.event.comm.TopicListener;
+import org.onap.policy.common.endpoints.event.comm.TopicSink;
+
+public class TopicSinkClientTest {
+    private static final String SINK_FIELD_NAME = "sink";
+    private static final String TOPIC = "my-topic";
+
+    private TopicSinkClient client;
+    private TopicSink sink;
+    private List<TopicSink> sinks;
+
+    /**
+     * Creates mocks and an initial client object.
+     *
+     * @throws Exception if an error occurs
+     */
+    @Before
+    public void setUp() throws Exception {
+        sink = mock(TopicSink.class);
+        when(sink.send(anyString())).thenReturn(true);
+
+        sinks = Arrays.asList(sink, null);
+
+        client = new TopicSinkClient2(TOPIC);
+    }
+
+    @AfterClass
+    public static void tearDown() throws Exception {
+        // clear all topics after the tests
+        TopicEndpoint.manager.shutdown();
+    }
+
+    /**
+     * Uses a real NO-OP topic sink.
+     */
+    @Test
+    public void testGetTopicSinks() throws Exception {
+        // clear all topics and then configure one topic
+        TopicEndpoint.manager.shutdown();
+
+        final Properties props = new Properties();
+        props.setProperty("noop.sink.topics", TOPIC);
+        TopicEndpoint.manager.addTopicSinks(props);
+
+        sink = TopicEndpoint.manager.getNoopTopicSink(TOPIC);
+        assertNotNull(sink);
+
+        final AtomicReference<String> evref = new AtomicReference<>(null);
+
+        sink.register(new TopicListener() {
+            @Override
+            public void onTopicEvent(final CommInfrastructure infra, final String topic, final String event) {
+                evref.set(event);
+            }
+        });
+
+        sink.start();
+
+        client = new TopicSinkClient(TOPIC);
+        client.send(100);
+
+        assertEquals("100", evref.get());
+    }
+
+    @Test
+    public void testTopicSinkClient_testGetTopic() {
+        assertEquals(TOPIC, client.getTopic());
+        assertSame(sink, Whitebox.getInternalState(client, SINK_FIELD_NAME));
+
+        // unknown topic -> should throw exception
+        sinks = new LinkedList<>();
+        assertThatThrownBy(() -> new TopicSinkClient2(TOPIC)).isInstanceOf(TopicSinkClientException.class)
+                .hasMessage("no sinks for topic: my-topic");
+    }
+
+    @Test
+    public void testSend() throws Exception {
+        client.send(Arrays.asList("abc", "def"));
+        verify(sink).send("['abc','def']".replace('\'', '"'));
+
+        // sink send fails
+        when(sink.send(anyString())).thenReturn(false);
+        assertFalse(client.send("ghi"));
+
+        // sink send throws an exception
+        final RuntimeException ex = new RuntimeException("expected exception");
+        when(sink.send(anyString())).thenThrow(ex);
+        assertFalse(client.send("jkl"));
+    }
+
+    /**
+     * TopicSinkClient with some overrides.
+     */
+    private class TopicSinkClient2 extends TopicSinkClient {
+
+        public TopicSinkClient2(final String topic) throws TopicSinkClientException {
+            super(topic);
+        }
+
+        @Override
+        protected List<TopicSink> getTopicSinks(final String topic) {
+            return sinks;
+        }
+    }
+}
diff --git a/utils/src/main/java/org/onap/policy/common/utils/properties/PropertyConfiguration.java b/utils/src/main/java/org/onap/policy/common/utils/properties/PropertyConfiguration.java
deleted file mode 100644
index b41f3bc..0000000
--- a/utils/src/main/java/org/onap/policy/common/utils/properties/PropertyConfiguration.java
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP Policy Engine - Common Modules
- * ================================================================================
- * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * 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.
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.policy.common.utils.properties;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.Properties;
-import org.apache.commons.lang3.StringUtils;
-import org.onap.policy.common.utils.properties.exception.PropertyAccessException;
-import org.onap.policy.common.utils.properties.exception.PropertyException;
-import org.onap.policy.common.utils.properties.exception.PropertyInvalidException;
-import org.onap.policy.common.utils.properties.exception.PropertyMissingException;
-
-/**
- * Configuration whose fields are initialized by reading from a set of {@link Properties},
- * as directed by the {@link Property} annotations that appear on fields within the
- * subclass. The values of the fields are set via <i>setXxx()</i> methods. As a result, if
- * a field is annotated and there is no corresponding <i>setXxx()</i> method, then an
- * exception will be thrown.
- *
- * <p>It is possible that an invalid <i>defaultValue</i> is specified via the
- * {@link Property} annotation. This could remain undetected until an optional property is
- * left out of the {@link Properties}. Consequently, this class will always validate a
- * {@link Property}'s default value, if the <i>defaultValue</i> is not empty or if
- * <i>accept</i> includes the "empty" option.
- */
-public class PropertyConfiguration {
-
-    /**
-     * The "empty" option that may appear within the {@link Property}'s <i>accept</i>
-     * attribute.
-     */
-    public static final String ACCEPT_EMPTY = "empty";
-
-    /**
-     * Constructs a configuration, without populating any fields; fields should be
-     * populated later by invoking {@link #setAllFields(Properties)}.
-     */
-    public PropertyConfiguration() {
-        super();
-    }
-
-    /**
-     * Initializes each "@Property" field with its value, as found in the properties.
-     *
-     * @param props properties from which to extract the values
-     * @throws PropertyException if an error occurs
-     */
-    public PropertyConfiguration(Properties props) throws PropertyException {
-        setAllFields(props);
-    }
-
-    /**
-     * Walks the class hierarchy of "this" object, populating fields defined in each
-     * class, using values extracted from the given property set.
-     *
-     * @param props properties from which to extract the values
-     * @throws PropertyException if an error occurs
-     */
-    public void setAllFields(Properties props) throws PropertyException {
-        Class<?> clazz = getClass();
-
-        while (clazz != PropertyConfiguration.class) {
-            for (Field field : clazz.getDeclaredFields()) {
-                setValue(field, props);
-            }
-
-            clazz = clazz.getSuperclass();
-        }
-    }
-
-    /**
-     * Sets a field's value, within an object, based on what's in the properties.
-     *
-     * @param field field whose value is to be set
-     * @param props properties from which to get the value
-     * @return {@code true} if the property's value was set, {@code false} otherwise
-     * @throws PropertyException if an error occurs
-     */
-    protected boolean setValue(Field field, Properties props) throws PropertyException {
-        Property prop = field.getAnnotation(Property.class);
-        if (prop == null) {
-            return false;
-        }
-
-        checkModifiable(field, prop);
-
-        Method setter = getSetter(field, prop);
-        checkSetter(setter, prop);
-
-        if (setValue(setter, field, props, prop)) {
-            return true;
-        }
-
-        throw new PropertyAccessException(prop.name(), field.getName(), "unsupported field type");
-    }
-
-    /**
-     * Sets a field's value from a particular property.
-     *
-     * @param setter method to be used to set the field's value
-     * @param field field whose value is to be set
-     * @param props properties from which to get the value
-     * @param prop property of interest
-     * @return {@code true} if the property's value was set, {@code false} otherwise
-     * @throws PropertyException if an error occurs
-     */
-    protected boolean setValue(Method setter, Field field, Properties props, Property prop) throws PropertyException {
-
-        try {
-            Object val = getValue(field, props, prop);
-            if (val == null) {
-                return false;
-
-            } else {
-                setter.invoke(this, val);
-                return true;
-            }
-
-        } catch (IllegalArgumentException e) {
-            throw new PropertyInvalidException(prop.name(), field.getName(), e);
-
-        } catch (IllegalAccessException | InvocationTargetException e) {
-            throw new PropertyAccessException(prop.name(), setter.getName(), e);
-        }
-    }
-
-    /**
-     * Get the setter.
-     *
-     * @param field field whose value is to be set
-     * @param prop property of interest
-     * @return the method to be used to set the field's value
-     * @throws PropertyAccessException if a "set" method cannot be identified
-     */
-    private Method getSetter(Field field, Property prop) throws PropertyAccessException {
-        String nm = "set" + StringUtils.capitalize(field.getName());
-
-        try {
-            return this.getClass().getMethod(nm, field.getType());
-
-        } catch (NoSuchMethodException | SecurityException e) {
-            throw new PropertyAccessException(prop.name(), nm, e);
-        }
-    }
-
-    /**
-     * Gets a property value, coercing it to the field's type.
-     *
-     * @param field field whose value is to be set
-     * @param props properties from which to get the value
-     * @param prop property of interest
-     * @return the value extracted from the property, or {@code null} if the field type is
-     *         not supported
-     * @throws PropertyException if an error occurs
-     */
-    protected Object getValue(Field field, Properties props, Property prop) throws PropertyException {
-
-        Class<?> clazz = field.getType();
-        String fieldName = field.getName();
-
-        // can still add support for short, float, double, enum
-
-        if (clazz == String.class) {
-            return getStringValue(fieldName, props, prop);
-
-        } else if (clazz == Boolean.class || clazz == boolean.class) {
-            return getBooleanValue(fieldName, props, prop);
-
-        } else if (clazz == Integer.class || clazz == int.class) {
-            return getIntegerValue(fieldName, props, prop);
-
-        } else if (clazz == Long.class || clazz == long.class) {
-            return getLongValue(fieldName, props, prop);
-
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Verifies that the field can be modified, i.e., it's neither <i>static</i>, nor
-     * <i>final</i>.
-     *
-     * @param field field whose value is to be set
-     * @param prop property of interest
-     * @throws PropertyAccessException if the field is not modifiable
-     */
-    protected void checkModifiable(Field field, Property prop) throws PropertyAccessException {
-        int mod = field.getModifiers();
-
-        if (Modifier.isStatic(mod)) {
-            throw new PropertyAccessException(prop.name(), field.getName(), "'static' variable cannot be modified");
-        }
-
-        if (Modifier.isFinal(mod)) {
-            throw new PropertyAccessException(prop.name(), field.getName(), "'final' variable cannot be modified");
-        }
-    }
-
-    /**
-     * Verifies that the setter method is not <i>static</i>.
-     *
-     * @param setter method to be checked
-     * @param prop property of interest
-     * @throws PropertyAccessException if the method is static
-     */
-    private void checkSetter(Method setter, Property prop) throws PropertyAccessException {
-        int mod = setter.getModifiers();
-
-        if (Modifier.isStatic(mod)) {
-            throw new PropertyAccessException(prop.name(), setter.getName(), "method is 'static'");
-        }
-    }
-
-    /**
-     * Gets a property value, coercing it to a String.
-     *
-     * @param fieldName field whose value is to be set
-     * @param props properties from which to get the value
-     * @param prop property of interest
-     * @return the value extracted from the property
-     * @throws PropertyException if an error occurs
-     */
-    protected String getStringValue(String fieldName, Properties props, Property prop) throws PropertyException {
-
-        /*
-         * Note: the default value for a String type is always valid, thus no need to
-         * check it.
-         */
-
-        return getPropValue(fieldName, props, prop);
-    }
-
-    /**
-     * Gets a property value, coercing it to a Boolean.
-     *
-     * @param fieldName field whose value is to be set
-     * @param props properties from which to get the value
-     * @param prop property of interest
-     * @return the value extracted from the property
-     * @throws PropertyException if an error occurs
-     */
-    protected Boolean getBooleanValue(String fieldName, Properties props, Property prop) throws PropertyException {
-        // validate the default value
-        checkDefaultValue(fieldName, prop, xxx -> makeBoolean(fieldName, prop, prop.defaultValue()));
-
-        return makeBoolean(fieldName, prop, getPropValue(fieldName, props, prop));
-    }
-
-    /**
-     * Gets a property value, coercing it to an Integer.
-     *
-     * @param fieldName field whose value is to be set
-     * @param props properties from which to get the value
-     * @param prop property of interest
-     * @return the value extracted from the property
-     * @throws PropertyException if an error occurs
-     */
-    protected Integer getIntegerValue(String fieldName, Properties props, Property prop) throws PropertyException {
-        // validate the default value
-        checkDefaultValue(fieldName, prop, xxx -> makeInteger(fieldName, prop, prop.defaultValue()));
-
-        return makeInteger(fieldName, prop, getPropValue(fieldName, props, prop));
-    }
-
-    /**
-     * Gets a property value, coercing it to a Long.
-     *
-     * @param fieldName field whose value is to be set
-     * @param props properties from which to get the value
-     * @param prop property of interest
-     * @return the value extracted from the property
-     * @throws PropertyException if an error occurs
-     */
-    protected Long getLongValue(String fieldName, Properties props, Property prop) throws PropertyException {
-        // validate the default value
-        checkDefaultValue(fieldName, prop, xxx -> makeLong(fieldName, prop, prop.defaultValue()));
-
-        return makeLong(fieldName, prop, getPropValue(fieldName, props, prop));
-    }
-
-    /**
-     * Gets a value from the property set.
-     *
-     * @param fieldName field whose value is to be set
-     * @param props properties from which to get the value
-     * @param prop property of interest
-     * @return the value extracted from the property, or the <i>defaultValue</i> if the
-     *         value does not exist
-     * @throws PropertyMissingException if the property does not exist and the
-     *         <i>defaultValue</i> is empty and <i>emptyOk</i> is {@code false}
-     */
-    protected String getPropValue(String fieldName, Properties props, Property prop) throws PropertyMissingException {
-        String propnm = prop.name();
-
-        String val = getRawPropertyValue(props, propnm);
-        if (val != null && isEmptyOk(prop, val)) {
-            return val;
-        }
-
-        val = prop.defaultValue();
-        if (val != null && isEmptyOk(prop, val)) {
-            return val;
-        }
-
-        throw new PropertyMissingException(prop.name(), fieldName);
-    }
-
-    /**
-     * Gets the property value, straight from the property set.
-     *
-     * @param props properties from which to get the value
-     * @param propnm name of the property of interest
-     * @return the raw property value
-     */
-    protected String getRawPropertyValue(Properties props, String propnm) {
-        return props.getProperty(propnm);
-    }
-
-    /**
-     * Coerces a String value into a Boolean.
-     *
-     * @param fieldName field whose value is to be set
-     * @param prop property of interest
-     * @param value value to be coerced
-     * @return the Boolean value represented by the String value
-     * @throws PropertyInvalidException if the value does not represent a valid Boolean
-     */
-    private Boolean makeBoolean(String fieldName, Property prop, String value) throws PropertyInvalidException {
-        if ("true".equalsIgnoreCase(value)) {
-            return Boolean.TRUE;
-
-        } else if ("false".equalsIgnoreCase(value)) {
-            return Boolean.FALSE;
-
-        } else {
-            throw new PropertyInvalidException(prop.name(), fieldName, "expecting 'true' or 'false'");
-        }
-    }
-
-    /**
-     * Coerces a String value into an Integer.
-     *
-     * @param fieldName field whose value is to be set
-     * @param prop property of interest
-     * @param value value to be coerced
-     * @return the Integer value represented by the String value
-     * @throws PropertyInvalidException if the value does not represent a valid Integer
-     */
-    private Integer makeInteger(String fieldName, Property prop, String value) throws PropertyInvalidException {
-        try {
-            return Integer.valueOf(value);
-
-        } catch (NumberFormatException e) {
-            throw new PropertyInvalidException(prop.name(), fieldName, e);
-        }
-    }
-
-    /**
-     * Coerces a String value into a Long.
-     *
-     * @param fieldName field whose value is to be set
-     * @param prop property of interest
-     * @param value value to be coerced
-     * @return the Long value represented by the String value
-     * @throws PropertyInvalidException if the value does not represent a valid Long
-     */
-    private Long makeLong(String fieldName, Property prop, String value) throws PropertyInvalidException {
-        try {
-            return Long.valueOf(value);
-
-        } catch (NumberFormatException e) {
-            throw new PropertyInvalidException(prop.name(), fieldName, e);
-        }
-    }
-
-    /**
-     * Applies a function to check a property's default value. If the function throws an
-     * exception about an invalid property, then it's re-thrown as an exception about an
-     * invalid <i>defaultValue</i>.
-     *
-     * @param fieldName name of the field being checked
-     * @param prop property of interest
-     * @param func function to invoke to check the default value
-     */
-    private void checkDefaultValue(String fieldName, Property prop, CheckDefaultValueFunction func)
-                    throws PropertyInvalidException {
-
-        if (isEmptyOk(prop, prop.defaultValue())) {
-            try {
-                func.apply(null);
-
-            } catch (PropertyInvalidException ex) {
-                throw new PropertyInvalidException(ex.getPropertyName(), fieldName, "defaultValue is invalid", ex);
-            }
-        }
-    }
-
-    /**
-     * Determines if a value is OK, even if it's empty.
-     *
-     * @param prop property specifying what's acceptable
-     * @param value value to be checked
-     * @return {@code true} if the value is not empty or empty is allowed, {@code false}
-     *         otherwise
-     */
-    protected boolean isEmptyOk(Property prop, String value) {
-        return !value.isEmpty() || isEmptyOk(prop);
-    }
-
-    /**
-     * Determines if a {@link Property}'s <i>accept</i> attribute includes the "empty"
-     * option.
-     *
-     * @param prop property whose <i>accept</i> attribute is to be examined
-     * @return {@code true} if the <i>accept</i> attribute includes "empty"
-     */
-    protected boolean isEmptyOk(Property prop) {
-        for (String option : prop.accept().split(",")) {
-            if (ACCEPT_EMPTY.equals(option)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * Functions to check a default value.
-     */
-    @FunctionalInterface
-    private static interface CheckDefaultValueFunction {
-
-        /**
-         * Checks the default value.
-         *
-         * @param arg always {@code null}
-         * @throws PropertyInvalidException if an error occurs
-         */
-        public void apply(Void arg) throws PropertyInvalidException;
-    }
-
-    /**
-     * Annotation that declares a variable to be configured via {@link Properties}.
-     */
-    @Target(ElementType.FIELD)
-    @Retention(RetentionPolicy.RUNTIME)
-
-    protected static @interface Property {
-
-        /**
-         * Name of the property.
-         *
-         * @return the property name
-         */
-        public String name();
-
-        /**
-         * Default value, used when the property does not exist.
-         *
-         * @return the default value
-         */
-        public String defaultValue() default "";
-
-        /**
-         * Comma-separated options identifying what's acceptable. The word, "empty",
-         * indicates that an empty string, "", is an acceptable value.
-         *
-         * @return options identifying what's acceptable
-         */
-        public String accept() default "";
-    }
-}
diff --git a/utils/src/test/java/org/onap/policy/common/utils/properties/PropertyConfigurationTest.java b/utils/src/test/java/org/onap/policy/common/utils/properties/PropertyConfigurationTest.java
deleted file mode 100644
index dbe04ae..0000000
--- a/utils/src/test/java/org/onap/policy/common/utils/properties/PropertyConfigurationTest.java
+++ /dev/null
@@ -1,1268 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP Policy Engine - Common Modules
- * ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * 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.
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.policy.common.utils.properties;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import java.lang.reflect.Field;
-import java.util.Properties;
-import org.junit.Before;
-import org.junit.Test;
-import org.onap.policy.common.utils.properties.exception.PropertyAccessException;
-import org.onap.policy.common.utils.properties.exception.PropertyException;
-import org.onap.policy.common.utils.properties.exception.PropertyInvalidException;
-import org.onap.policy.common.utils.properties.exception.PropertyMissingException;
-
-/**
- * Test class for PropertyConfiguration.
- */
-public class PropertyConfigurationTest {
-
-    /**
-     * Property used for most of the simple configuration subclasses.
-     */
-    private static final String THE_VALUE = "the.value";
-
-    /**
-     * String property value.
-     */
-    private static final String STRING_VALUE = "a string";
-
-    /**
-     * Default value for string property.
-     */
-    private static final String STRING_VALUE_DEFAULT = "another string";
-
-    /**
-     * Value that cannot be coerced into any other type.
-     */
-    private static final String INVALID_VALUE = "invalid";
-
-    /**
-     * Properties used when invoking constructors.
-     */
-    private Properties props;
-
-    @Before
-    public void setUp() {
-        props = new Properties();
-    }
-
-    @Test
-    public void testPropertyConfiguration() throws PropertyException {
-        props.setProperty(THE_VALUE, STRING_VALUE);
-
-        PlainStringConfig cfg = new PlainStringConfig();
-        assertEquals(null, cfg.value);
-
-        cfg.setAllFields(props);
-        assertEquals(STRING_VALUE, cfg.value);
-    }
-
-    @Test
-    public void testPropertyConfigurationProperties() throws PropertyException {
-        props.setProperty(THE_VALUE, STRING_VALUE);
-        PlainStringConfig cfg = new PlainStringConfig(props);
-
-        assertEquals(STRING_VALUE, cfg.value);
-    }
-
-    @Test
-    public void testSetAllFields() throws Exception {
-
-        /*
-         * Implements an extra interface, just to see that it doesn't cause issues.
-         */
-        class GrandParentConfig extends PropertyConfiguration implements DoesNothing {
-
-            @Property(name = "grandparent.value")
-            protected boolean grandparentValue;
-
-            @SuppressWarnings("unused")
-            public void setGrandparentValue(boolean grandparentValue) {
-                this.grandparentValue = grandparentValue;
-            }
-        }
-
-        /*
-         * Implements the extra interface, too.
-         */
-        class ParentConfig extends GrandParentConfig implements DoesNothing {
-
-            @Property(name = "parent.value")
-            protected long parentValue;
-
-            @SuppressWarnings("unused")
-            public void setParentValue(long parentValue) {
-                this.parentValue = parentValue;
-            }
-        }
-
-        class Config extends ParentConfig {
-
-            @Property(name = THE_VALUE)
-            private String value;
-
-            @SuppressWarnings("unused")
-            public void setValue(String value) {
-                this.value = value;
-            }
-        }
-
-
-        final Config cfg = new Config();
-
-        // try one set of values
-        props.setProperty(THE_VALUE, STRING_VALUE);
-        props.setProperty("parent.value", "50000");
-        props.setProperty("grandparent.value", "true");
-        cfg.setAllFields(props);
-
-        assertEquals(STRING_VALUE, cfg.value);
-        assertEquals(50000L, cfg.parentValue);
-        assertEquals(true, cfg.grandparentValue);
-
-        // now a different set of values
-        props.setProperty(THE_VALUE, STRING_VALUE + "x");
-        props.setProperty("parent.value", "50001");
-        props.setProperty("grandparent.value", "false");
-        cfg.setAllFields(props);
-
-        assertEquals(STRING_VALUE + "x", cfg.value);
-        assertEquals(50001L, cfg.parentValue);
-        assertEquals(false, cfg.grandparentValue);
-    }
-
-    @Test
-    public void testSetAllFields_NoProperties() throws Exception {
-
-        class Config extends PropertyConfiguration {
-
-            private String value;
-
-            @SuppressWarnings("unused")
-            public void setValue(String value) {
-                this.value = value;
-            }
-        }
-
-
-        Config cfg = new Config();
-
-        props.setProperty(THE_VALUE, STRING_VALUE);
-        cfg.setAllFields(props);
-
-        assertEquals(null, cfg.value);
-    }
-
-    @Test
-    public void testSetValueFieldProperties_FieldSet() throws PropertyException {
-        props.setProperty(THE_VALUE, STRING_VALUE);
-        PlainStringConfig cfg = new PlainStringConfig(props);
-
-        assertEquals(STRING_VALUE, cfg.value);
-    }
-
-    @Test
-    public void testSetValueFieldProperties_NoAnnotation() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            private String value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(String value) {
-                this.value = value;
-            }
-        }
-
-        props.setProperty(THE_VALUE, STRING_VALUE);
-        Config cfg = new Config(props);
-
-        assertNull(cfg.value);
-    }
-
-    @Test(expected = PropertyAccessException.class)
-    public void testSetValueFieldProperties_WrongFieldType() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            // Cannot set a property into an "Exception" field
-            @Property(name = THE_VALUE)
-            private Exception value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(Exception value) {
-                this.value = value;
-            }
-        }
-
-        props.setProperty(THE_VALUE, STRING_VALUE);
-        new Config(props);
-    }
-
-    @Test(expected = PropertyAccessException.class)
-    public void testGetSetter_NoSetter() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE)
-            private String value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-        }
-
-        props.setProperty(THE_VALUE, STRING_VALUE);
-        new Config(props);
-    }
-
-    @Test(expected = PropertyMissingException.class)
-    public void testSetValueMethodFieldPropertiesProperty_NoProperty_NoDefault() throws PropertyException {
-        new PlainStringConfig(props);
-    }
-
-    @Test(expected = PropertyInvalidException.class)
-    public void testSetValueMethodFieldPropertiesProperty_InvalidValue() throws PropertyException {
-        class Config extends PlainPrimIntConfig {
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            /**
-             * This returns a boolean, but the field is an "int", so it should throw an
-             * exception when it tries to stuff the value into the field.
-             */
-            @Override
-            protected Object getValue(Field field, Properties props, Property prop) throws PropertyException {
-                return Boolean.TRUE;
-            }
-        }
-
-        new Config(props);
-    }
-
-    @Test(expected = PropertyAccessException.class)
-    public void testSetValueMethodFieldPropertiesProperty_MethodEx() throws PropertyException {
-        class Config extends PlainStringConfig {
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @Override
-            public void setValue(String value) {
-                throw new IllegalArgumentException("expected exception");
-            }
-        }
-
-        props.setProperty(THE_VALUE, STRING_VALUE);
-        new Config(props);
-    }
-
-    @Test
-    public void testGetValue() throws PropertyException {
-        // this class contains all of the supported field types
-        class Config extends PropertyConfiguration {
-
-            @Property(name = "string")
-            private String stringValue;
-
-            @Property(name = "boolean.true")
-            private Boolean boolTrueValue;
-
-            @Property(name = "boolean.false")
-            private Boolean boolFalseValue;
-
-            @Property(name = "primitive.boolean.true")
-            private boolean primBoolTrueValue;
-
-            @Property(name = "primitive.boolean.false")
-            private boolean primBoolFalseValue;
-
-            @Property(name = "integer")
-            private Integer intValue;
-
-            @Property(name = "primitive.integer")
-            private int primIntValue;
-
-            @Property(name = "long")
-            private Long longValue;
-
-            @Property(name = "primitive.long")
-            private long primLongValue;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public String getStringValue() {
-                return stringValue;
-            }
-
-            @SuppressWarnings("unused")
-            public void setStringValue(String stringValue) {
-                this.stringValue = stringValue;
-            }
-
-            @SuppressWarnings("unused")
-            public Boolean getBoolTrueValue() {
-                return boolTrueValue;
-            }
-
-            @SuppressWarnings("unused")
-            public void setBoolTrueValue(Boolean boolTrueValue) {
-                this.boolTrueValue = boolTrueValue;
-            }
-
-            @SuppressWarnings("unused")
-            public Boolean getBoolFalseValue() {
-                return boolFalseValue;
-            }
-
-            @SuppressWarnings("unused")
-            public void setBoolFalseValue(Boolean boolFalseValue) {
-                this.boolFalseValue = boolFalseValue;
-            }
-
-            @SuppressWarnings("unused")
-            public boolean isPrimBoolTrueValue() {
-                return primBoolTrueValue;
-            }
-
-            @SuppressWarnings("unused")
-            public void setPrimBoolTrueValue(boolean primBoolTrueValue) {
-                this.primBoolTrueValue = primBoolTrueValue;
-            }
-
-            @SuppressWarnings("unused")
-            public boolean isPrimBoolFalseValue() {
-                return primBoolFalseValue;
-            }
-
-            @SuppressWarnings("unused")
-            public void setPrimBoolFalseValue(boolean primBoolFalseValue) {
-                this.primBoolFalseValue = primBoolFalseValue;
-            }
-
-            @SuppressWarnings("unused")
-            public Integer getIntValue() {
-                return intValue;
-            }
-
-            @SuppressWarnings("unused")
-            public void setIntValue(Integer intValue) {
-                this.intValue = intValue;
-            }
-
-            @SuppressWarnings("unused")
-            public int getPrimIntValue() {
-                return primIntValue;
-            }
-
-            @SuppressWarnings("unused")
-            public void setPrimIntValue(int primIntValue) {
-                this.primIntValue = primIntValue;
-            }
-
-            @SuppressWarnings("unused")
-            public Long getLongValue() {
-                return longValue;
-            }
-
-            @SuppressWarnings("unused")
-            public void setLongValue(Long longValue) {
-                this.longValue = longValue;
-            }
-
-            @SuppressWarnings("unused")
-            public long getPrimLongValue() {
-                return primLongValue;
-            }
-
-            @SuppressWarnings("unused")
-            public void setPrimLongValue(long primLongValue) {
-                this.primLongValue = primLongValue;
-            }
-        }
-
-        props.setProperty("string", "a string");
-        props.setProperty("boolean.true", "true");
-        props.setProperty("boolean.false", "false");
-        props.setProperty("primitive.boolean.true", "true");
-        props.setProperty("primitive.boolean.false", "false");
-        props.setProperty("integer", "100");
-        props.setProperty("primitive.integer", "101");
-        props.setProperty("long", "10000");
-        props.setProperty("primitive.long", "10001");
-
-        Config cfg = new Config(props);
-
-        assertEquals("a string", cfg.stringValue);
-        assertEquals(true, cfg.boolTrueValue);
-        assertEquals(false, cfg.boolFalseValue);
-        assertEquals(true, cfg.primBoolTrueValue);
-        assertEquals(false, cfg.primBoolFalseValue);
-        assertEquals(100, cfg.intValue.intValue());
-        assertEquals(101, cfg.primIntValue);
-        assertEquals(10000, cfg.longValue.longValue());
-        assertEquals(10001, cfg.primLongValue);
-    }
-
-    @Test(expected = PropertyAccessException.class)
-    public void testGetValue_UnsupportedType() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            // Cannot set a property into an "Exception" field
-            @Property(name = THE_VALUE)
-            private Exception value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(Exception value) {
-                this.value = value;
-            }
-        }
-
-        props.setProperty(THE_VALUE, STRING_VALUE);
-        new Config(props);
-    }
-
-    @Test
-    public void testCheckModifiable_OtherModifiers() throws PropertyException {
-        // this class contains all of the supported field types
-        class Config extends PropertyConfiguration {
-
-            @Property(name = "public")
-            public String publicString;
-
-            @Property(name = "private")
-            private String privateString;
-
-            @Property(name = "protected")
-            protected String protectedString;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setPublicString(String publicString) {
-                this.publicString = publicString;
-            }
-
-            @SuppressWarnings("unused")
-            public void setPrivateString(String privateString) {
-                this.privateString = privateString;
-            }
-
-            @SuppressWarnings("unused")
-            public void setProtectedString(String protectedString) {
-                this.protectedString = protectedString;
-            }
-        }
-
-        props.setProperty("public", "a public string");
-        props.setProperty("private", "a private string");
-        props.setProperty("protected", "a protected string");
-
-        Config cfg = new Config(props);
-
-        assertEquals("a public string", cfg.publicString);
-        assertEquals("a private string", cfg.privateString);
-        assertEquals("a protected string", cfg.protectedString);
-    }
-
-    @Test(expected = PropertyAccessException.class)
-    public void testCheckModifiable_Static() throws PropertyException {
-        props.setProperty(THE_VALUE, STRING_VALUE);
-        new StaticPropConfig(props);
-    }
-
-    @Test(expected = PropertyAccessException.class)
-    public void testCheckModifiable_Final() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            // Cannot set a property into an "final" field
-            @Property(name = THE_VALUE)
-            private final String value = "";
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-        }
-
-        props.setProperty(THE_VALUE, STRING_VALUE);
-        new Config(props);
-    }
-
-    @Test(expected = PropertyAccessException.class)
-    public void testCheckSetter_Static() throws PropertyException {
-        props.setProperty(THE_VALUE, STRING_VALUE);
-        new StaticMethodConfig(props);
-    }
-
-    @Test
-    public void testGetStringValue() throws PropertyException {
-        props.setProperty(THE_VALUE, STRING_VALUE);
-        PlainStringConfig cfg = new PlainStringConfig(props);
-
-        assertEquals(STRING_VALUE, cfg.value);
-    }
-
-    @Test
-    public void testGetBooleanValue_NoDefault() throws PropertyException {
-        props.setProperty(THE_VALUE, "true");
-        PlainBooleanConfig cfg = new PlainBooleanConfig(props);
-
-        assertEquals(true, cfg.value);
-    }
-
-    @Test(expected = PropertyInvalidException.class)
-    public void testGetBooleanValue_InvalidDefault() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = INVALID_VALUE)
-            private Boolean value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(Boolean value) {
-                this.value = value;
-            }
-        }
-
-        props.setProperty(THE_VALUE, "true");
-        new Config(props);
-    }
-
-    @Test
-    public void testGetBooleanValue_ValidDefault_True() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = "true")
-            private Boolean value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(Boolean value) {
-                this.value = value;
-            }
-        }
-
-        // property not defined
-        Config cfg = new Config(props);
-        assertEquals(true, cfg.value);
-
-        // try again, with the property defined as true
-        props.setProperty(THE_VALUE, "true");
-        cfg = new Config(props);
-        assertEquals(true, cfg.value);
-
-        // try again, with the property defined as false
-        props.setProperty(THE_VALUE, "false");
-        cfg = new Config(props);
-        assertEquals(false, cfg.value);
-    }
-
-    @Test
-    public void testGetBooleanValue_ValidDefault_False() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = "false")
-            private Boolean value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(Boolean value) {
-                this.value = value;
-            }
-        }
-
-        // property not defined
-        Config cfg = new Config(props);
-        assertEquals(false, cfg.value);
-
-        // try again, with the property defined as true
-        props.setProperty(THE_VALUE, "true");
-        cfg = new Config(props);
-        assertEquals(true, cfg.value);
-
-        // try again, with the property defined as false
-        props.setProperty(THE_VALUE, "false");
-        cfg = new Config(props);
-        assertEquals(false, cfg.value);
-    }
-
-    @Test
-    public void testGetIntegerValue_NoDefault() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE)
-            private Integer value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(Integer value) {
-                this.value = value;
-            }
-        }
-
-        props.setProperty(THE_VALUE, "200");
-        Config cfg = new Config(props);
-
-        assertEquals(200, cfg.value.intValue());
-    }
-
-    @Test(expected = PropertyInvalidException.class)
-    public void testGetIntegerValue_InvalidDefault() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = INVALID_VALUE)
-            private Integer value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(Integer value) {
-                this.value = value;
-            }
-        }
-
-        props.setProperty(THE_VALUE, "200");
-        new Config(props);
-    }
-
-    @Test
-    public void testGetIntegerValue_ValidDefault() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = "201")
-            private Integer value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(Integer value) {
-                this.value = value;
-            }
-        }
-
-        // property not defined
-        Config cfg = new Config(props);
-        assertEquals(201, cfg.value.intValue());
-
-        // try again, with the property defined
-        props.setProperty(THE_VALUE, "200");
-        cfg = new Config(props);
-        assertEquals(200, cfg.value.intValue());
-    }
-
-    @Test
-    public void testGetLongValue_NoDefault() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE)
-            private Long value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(Long value) {
-                this.value = value;
-            }
-        }
-
-        props.setProperty(THE_VALUE, "20000");
-        Config cfg = new Config(props);
-
-        assertEquals(20000L, cfg.value.longValue());
-    }
-
-    @Test(expected = PropertyInvalidException.class)
-    public void testGetLongValue_InvalidDefault() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = INVALID_VALUE)
-            private Long value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(Long value) {
-                this.value = value;
-            }
-        }
-
-        props.setProperty(THE_VALUE, "20000");
-        new Config(props);
-    }
-
-    @Test
-    public void testGetLongValue_ValidDefault() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = "20001")
-            private Long value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(Long value) {
-                this.value = value;
-            }
-        }
-
-        // property not defined
-        Config cfg = new Config(props);
-        assertEquals(20001L, cfg.value.longValue());
-
-        // try again, with the property defined
-        props.setProperty(THE_VALUE, "20000");
-        cfg = new Config(props);
-        assertEquals(20000L, cfg.value.longValue());
-    }
-
-    @Test
-    public void testGetPropValue_Prop_NoDefault() throws PropertyException {
-        props.setProperty(THE_VALUE, STRING_VALUE);
-        PlainStringConfig cfg = new PlainStringConfig(props);
-
-        assertEquals(STRING_VALUE, cfg.value);
-    }
-
-    @Test
-    public void testGetPropValue_Prop_Default() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = STRING_VALUE_DEFAULT)
-            private String value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(String value) {
-                this.value = value;
-            }
-        }
-
-        props.setProperty(THE_VALUE, STRING_VALUE);
-        Config cfg = new Config(props);
-
-        assertEquals(STRING_VALUE, cfg.value);
-    }
-
-    @Test
-    public void testGetPropValue_EmptyProp_EmptyOk() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, accept = "empty")
-            private String value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(String value) {
-                this.value = value;
-            }
-        }
-
-        props.setProperty(THE_VALUE, "");
-        Config cfg = new Config(props);
-
-        assertEquals("", cfg.value);
-    }
-
-    @Test
-    public void testGetPropValue_EmptyDefault_EmptyOk() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = "", accept = "empty")
-            private String value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(String value) {
-                this.value = value;
-            }
-        }
-
-        Config cfg = new Config(props);
-
-        assertEquals("", cfg.value);
-    }
-
-    @Test
-    public void testGetPropValue_Default_EmptyOk() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = STRING_VALUE, accept = "empty")
-            private String value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(String value) {
-                this.value = value;
-            }
-        }
-
-        Config cfg = new Config(props);
-
-        assertEquals(STRING_VALUE, cfg.value);
-    }
-
-    @Test(expected = PropertyMissingException.class)
-    public void testGetPropValue_EmptyDefault_EmptyNotOk() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = "")
-            private String value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(String value) {
-                this.value = value;
-            }
-        }
-
-        new Config(props);
-    }
-
-    @Test
-    public void testGetPropValue_Default_EmptyNotOk() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = STRING_VALUE, accept = "")
-            private String value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(String value) {
-                this.value = value;
-            }
-        }
-
-        Config cfg = new Config(props);
-
-        assertEquals(STRING_VALUE, cfg.value);
-    }
-
-    @Test
-    public void testGetRawPropertyValue() throws PropertyException {
-        class Config extends PlainStringConfig {
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @Override
-            protected String getRawPropertyValue(Properties props, String propnm) {
-                return STRING_VALUE;
-            }
-        }
-
-        Config cfg = new Config(props);
-
-        assertEquals(STRING_VALUE, cfg.getValue());
-
-    }
-
-    @Test
-    public void testMakeBoolean_True() throws PropertyException {
-        props.setProperty(THE_VALUE, "true");
-        PlainBooleanConfig cfg = new PlainBooleanConfig(props);
-
-        assertEquals(true, cfg.value);
-    }
-
-    @Test
-    public void testMakeBoolean_False() throws PropertyException {
-        props.setProperty(THE_VALUE, "false");
-        PlainBooleanConfig cfg = new PlainBooleanConfig(props);
-
-        assertEquals(false, cfg.value);
-    }
-
-    @Test(expected = PropertyInvalidException.class)
-    public void testMakeBoolean_Invalid() throws PropertyException {
-        props.setProperty(THE_VALUE, INVALID_VALUE);
-        new PlainBooleanConfig(props);
-    }
-
-    @Test
-    public void testMakeInteger_Valid() throws PropertyException {
-        props.setProperty(THE_VALUE, "300");
-        PlainPrimIntConfig cfg = new PlainPrimIntConfig(props);
-
-        assertEquals(300, cfg.value);
-    }
-
-    @Test(expected = PropertyInvalidException.class)
-    public void testMakeInteger_Invalid() throws PropertyException {
-        props.setProperty(THE_VALUE, INVALID_VALUE);
-        new PlainPrimIntConfig(props);
-    }
-
-    @Test(expected = PropertyInvalidException.class)
-    public void testMakeInteger_TooBig() throws PropertyException {
-        props.setProperty(THE_VALUE, String.valueOf(Integer.MAX_VALUE + 10L));
-        new PlainPrimIntConfig(props);
-    }
-
-    @Test
-    public void testMakeLong_Valid() throws PropertyException {
-        props.setProperty(THE_VALUE, "30000");
-        PlainPrimLongConfig cfg = new PlainPrimLongConfig(props);
-
-        assertEquals(30000L, cfg.value);
-    }
-
-    @Test(expected = PropertyInvalidException.class)
-    public void testMakeLong_Invalid() throws PropertyException {
-        props.setProperty(THE_VALUE, INVALID_VALUE);
-        new PlainPrimLongConfig(props);
-    }
-
-    @Test
-    public void testCheckDefaultValue_NotEmpty_Valid() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = "700")
-            private long value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(long value) {
-                this.value = value;
-            }
-        }
-
-        Config cfg = new Config(props);
-
-        assertEquals(700L, cfg.value);
-    }
-
-    @Test(expected = PropertyInvalidException.class)
-    public void testCheckDefaultValue_NotEmpty_Invalid() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = INVALID_VALUE)
-            private long value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(long value) {
-                this.value = value;
-            }
-        }
-
-        new Config(props);
-    }
-
-    @Test(expected = PropertyInvalidException.class)
-    public void testCheckDefaultValue_Empty_EmptyOk_Invalid() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = "", accept = "empty")
-            private long value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(long value) {
-                this.value = value;
-            }
-        }
-
-        new Config(props);
-    }
-
-    @Test
-    public void testIsEmptyOkPropertyString_True() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = "", accept = "empty")
-            private String value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(String value) {
-                this.value = value;
-            }
-        }
-
-        // missing property - should default to ""
-        Config cfg = new Config(props);
-        assertEquals("", cfg.value);
-
-        // add an empty property - should take the property's value
-        props.setProperty(THE_VALUE, "");
-        cfg.setAllFields(props);
-        assertEquals("", cfg.value);
-        
-        // add the property - should take the property's value
-        props.setProperty(THE_VALUE, STRING_VALUE);
-        cfg.setAllFields(props);
-        assertEquals(STRING_VALUE, cfg.value);
-    }
-
-    @Test(expected = PropertyMissingException.class)
-    public void testIsEmptyOkPropertyString_False() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = "", accept = "")
-            private long value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(long value) {
-                this.value = value;
-            }
-        }
-
-        new Config(props);
-    }
-
-    @Test
-    public void testIsEmptyOkProperty_True() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = "", accept = "empty")
-            private String value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(String value) {
-                this.value = value;
-            }
-        }
-
-        Config cfg = new Config(props);
-
-        assertEquals("", cfg.value);
-    }
-
-    @Test(expected = PropertyMissingException.class)
-    public void testIsEmptyOkProperty_False() throws PropertyException {
-        class Config extends PropertyConfiguration {
-
-            @Property(name = THE_VALUE, defaultValue = "", accept = "")
-            private long value;
-
-            public Config(Properties props) throws PropertyException {
-                super(props);
-            }
-
-            @SuppressWarnings("unused")
-            public void setValue(long value) {
-                this.value = value;
-            }
-        }
-
-        new Config(props);
-    }
-
-    /**
-     * Config with a String value having no qualifiers.
-     */
-    public class PlainStringConfig extends PropertyConfiguration {
-
-        @Property(name = THE_VALUE)
-        private String value;
-        
-        public PlainStringConfig() {
-            
-        }
-        
-        public PlainStringConfig(Properties props) throws PropertyException {
-            super(props);
-        }
-
-        public String getValue() {
-            return value;
-        }
-
-        public void setValue(String value) {
-            this.value = value;
-        }
-    }
-
-    /**
-     * Config with a Boolean value having no qualifiers.
-     */
-    public class PlainBooleanConfig extends PropertyConfiguration {
-
-        @Property(name = THE_VALUE)
-        private Boolean value;
-        
-        public PlainBooleanConfig(Properties props) throws PropertyException {
-            super(props);
-        }
-
-        public void setValue(Boolean value) {
-            this.value = value;
-        }
-    }
-
-    /**
-     * Config with an int value having no qualifiers.
-     */
-    public class PlainPrimIntConfig extends PropertyConfiguration {
-
-        @Property(name = THE_VALUE)
-        private int value;
-
-        public PlainPrimIntConfig(Properties props) throws PropertyException {
-            super(props);
-        }
-
-        public void setValue(int value) {
-            this.value = value;
-        }
-    }
-
-    /**
-     * Config with a long value having no qualifiers.
-     */
-    public class PlainPrimLongConfig extends PropertyConfiguration {
-
-        @Property(name = THE_VALUE)
-        private long value;
-
-        public PlainPrimLongConfig(Properties props) throws PropertyException {
-            super(props);
-        }
-
-        public void setValue(long value) {
-            this.value = value;
-        }
-    }
-
-    /**
-     * A config whose field is "static".
-     */
-    public static class StaticPropConfig extends PropertyConfiguration {
-
-        // "static" field cannot be set
-        @Property(name = THE_VALUE)
-        private static String value;
-
-        public StaticPropConfig(Properties props) throws PropertyException {
-            super(props);
-        }
-
-        public static void setValue(String value) {
-            StaticPropConfig.value = value;
-        }
-    }
-
-    /**
-     * A config whose method is "static".
-     */
-    public static class StaticMethodConfig extends PropertyConfiguration {
-
-        // "static" field cannot be set
-        @Property(name = THE_VALUE)
-        private String value;
-
-        public StaticMethodConfig(Properties props) throws PropertyException {
-            super(props);
-        }
-
-        public static void setValue(String value) {
-            
-        }
-    }
-
-    /**
-     * This is just used as a mix-in to ensure that the configuration ignores interfaces.
-     */
-    public static interface DoesNothing {
-
-    }
-}