This is an automated email from the ASF dual-hosted git repository.

cziegeler pushed a commit to branch SLING-9867
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-extension-apiregions.git


The following commit(s) were added to refs/heads/SLING-9867 by this push:
     new 6947bbd  Add more tests
6947bbd is described below

commit 6947bbd00a9d792e0eff70f99d979c5351ba51a4
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Thu Nov 5 07:37:35 2020 +0100

    Add more tests
---
 .../apiregions/api/config/AttributeableEntity.java |  28 +++--
 .../apiregions/api/config/ConfigurableEntity.java  |   4 +-
 .../apiregions/api/config/ConfigurationApi.java    |  24 ++--
 .../apiregions/api/config/DescribableEntity.java   |  12 +-
 .../api/config/FactoryConfiguration.java           |  12 +-
 .../{Constants.java => InternalConstants.java}     |   6 +-
 .../extension/apiregions/api/config/Option.java    |  46 +++----
 .../extension/apiregions/api/config/Property.java  |  74 +++++++----
 .../extension/apiregions/api/config/Range.java     |  26 ++--
 .../extension/apiregions/api/config/Validator.java |  36 ++++--
 .../apiregions/api/config/package-info.java        |   2 +-
 .../api/config/AttributeableEntityTest.java        |  18 +++
 .../api/config/ConfigurableEntityTest.java         |  75 ++++++++++++
 .../api/config/ConfigurationApiTest.java           |  71 +++++++++++
 ...eEntityTest.java => DescribableEntityTest.java} |  71 ++++-------
 .../api/config/FactoryConfigurationTest.java       |  77 ++++++++++++
 ...ttributeableEntityTest.java => OptionTest.java} |  73 ++++-------
 .../apiregions/api/config/PropertyTest.java        | 136 +++++++++++++++++++++
 .../extension/apiregions/api/config/RangeTest.java |  65 ++++++++++
 19 files changed, 645 insertions(+), 211 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/AttributeableEntity.java
 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/AttributeableEntity.java
index e1dc59e..7ca4b67 100644
--- 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/AttributeableEntity.java
+++ 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/AttributeableEntity.java
@@ -32,13 +32,6 @@ public abstract class AttributeableEntity {
        
        /** The additional attributes */
        private final Map<String, JsonValue> attributes = new LinkedHashMap<>();
-       
-       /**
-        * Create a new instance and set defaults.
-        */
-       public AttributeableEntity() {
-               this.clear();
-       }
 
     /**
      * Clear the object and remove all metadata
@@ -128,7 +121,25 @@ public abstract class AttributeableEntity {
                return null;
        }
 
-       void setString(final JsonObjectBuilder builder, final String 
attributeName, final String value) {
+       /**
+        * Helper method to get a number value from an attribute
+        * @param attributeName The attribute name
+        * @return The string value or {@code null}.
+     * @throws IOException If the attribute value is not of type boolean
+        */
+       Number getNumber(final String attributeName) throws IOException {
+               final JsonValue val = 
this.getAttributes().remove(attributeName);
+               if ( val != null ) {
+                       final Object obj = Configurations.convertToObject(val);
+                       if ( obj instanceof Number ) {
+                               return (Number)obj;
+                       }
+                       throw new IOException("Invalid type for number value " 
+ attributeName + " : " + val.getValueType().name());
+               }
+               return null;
+       }
+
+    void setString(final JsonObjectBuilder builder, final String 
attributeName, final String value) {
                if ( value != null ) {
                        builder.add(attributeName, value);
                }
@@ -153,6 +164,7 @@ public abstract class AttributeableEntity {
         * @param attributeName The attribute name
         * @param defaultValue default value
         * @return The boolean value or the default value
+     * @throws IOException If the attribute value is not of type boolean
         */
        boolean getBoolean(final String attributeName, final boolean 
defaultValue) throws IOException {
                final JsonValue val = 
this.getAttributes().remove(attributeName);
diff --git 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurableEntity.java
 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurableEntity.java
index 936ea1c..b7edfe6 100644
--- 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurableEntity.java
+++ 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurableEntity.java
@@ -51,7 +51,7 @@ public abstract class ConfigurableEntity extends 
DescribableEntity {
        public void fromJSONObject(final JsonObject jsonObj) throws IOException 
{
         super.fromJSONObject(jsonObj);
         try {
-            final JsonValue val = 
this.getAttributes().remove(Constants.KEY_PROPERTIES);
+            final JsonValue val = 
this.getAttributes().remove(InternalConstants.KEY_PROPERTIES);
             if ( val != null ) {
                 for(final Map.Entry<String, JsonValue> innerEntry : 
val.asJsonObject().entrySet()) {
                                        final Property prop = new Property();
@@ -86,7 +86,7 @@ public abstract class ConfigurableEntity extends 
DescribableEntity {
                        for(final Map.Entry<String, Property> entry : 
this.getProperties().entrySet()) {
                                propBuilder.add(entry.getKey(), 
entry.getValue().createJson());
                        }
-                       objBuilder.add(Constants.KEY_PROPERTIES, propBuilder);
+                       objBuilder.add(InternalConstants.KEY_PROPERTIES, 
propBuilder);
                }
 
                return objBuilder;
diff --git 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurationApi.java
 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurationApi.java
index b6ce23f..c97040a 100644
--- 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurationApi.java
+++ 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurationApi.java
@@ -119,7 +119,7 @@ public class ConfigurationApi extends AttributeableEntity {
         super.fromJSONObject(jsonObj);
         try {
             JsonValue val;
-            val = this.getAttributes().remove(Constants.KEY_CONFIGURATIONS);
+            val = 
this.getAttributes().remove(InternalConstants.KEY_CONFIGURATIONS);
             if ( val != null ) {
                 for(final Map.Entry<String, JsonValue> innerEntry : 
val.asJsonObject().entrySet()) {
                     final Configuration cfg = new Configuration();
@@ -128,7 +128,7 @@ public class ConfigurationApi extends AttributeableEntity {
                 }
             }
             
-            val = this.getAttributes().remove(Constants.KEY_FACTORIES);
+            val = this.getAttributes().remove(InternalConstants.KEY_FACTORIES);
             if ( val != null ) {
                 for(final Map.Entry<String, JsonValue> innerEntry : 
val.asJsonObject().entrySet()) {
                     final FactoryConfiguration cfg = new 
FactoryConfiguration();
@@ -137,7 +137,7 @@ public class ConfigurationApi extends AttributeableEntity {
                 }
             }
 
-            val = this.getAttributes().remove(Constants.KEY_FWK_PROPERTIES);
+            val = 
this.getAttributes().remove(InternalConstants.KEY_FWK_PROPERTIES);
             if ( val != null ) {
                 for(final Map.Entry<String, JsonValue> innerEntry : 
val.asJsonObject().entrySet()) {
                     final FrameworkProperty cfg = new FrameworkProperty();
@@ -146,21 +146,21 @@ public class ConfigurationApi extends AttributeableEntity 
{
                 }
             }
 
-            val = 
this.getAttributes().remove(Constants.KEY_INTERNAL_CONFIGURATIONS);
+            val = 
this.getAttributes().remove(InternalConstants.KEY_INTERNAL_CONFIGURATIONS);
             if ( val != null ) {
                 for(final JsonValue innerVal : val.asJsonArray()) {
                     this.getInternalConfigurations().add(getString(innerVal));
                 }
             }
 
-            val = 
this.getAttributes().remove(Constants.KEY_INTERNAL_FACTORIES);
+            val = 
this.getAttributes().remove(InternalConstants.KEY_INTERNAL_FACTORIES);
             if ( val != null ) {
                 for(final JsonValue innerVal : val.asJsonArray()) {
                     this.getInternalFactories().add(getString(innerVal));
                 }
             }
 
-            val = 
this.getAttributes().remove(Constants.KEY_INTERNAL_FWK_PROPERTIES);
+            val = 
this.getAttributes().remove(InternalConstants.KEY_INTERNAL_FWK_PROPERTIES);
             if ( val != null ) {
                 for(final JsonValue innerVal : val.asJsonArray()) {
                     
this.getInternalFrameworkProperties().add(getString(innerVal));
@@ -233,42 +233,42 @@ public class ConfigurationApi extends AttributeableEntity 
{
             for(final Map.Entry<String, Configuration> entry : 
this.getConfigurations().entrySet()) {
                 propBuilder.add(entry.getKey(), entry.getValue().createJson());
             }
-            objBuilder.add(Constants.KEY_CONFIGURATIONS, propBuilder);
+            objBuilder.add(InternalConstants.KEY_CONFIGURATIONS, propBuilder);
         }
         if ( !this.getFactories().isEmpty() ) {
             final JsonObjectBuilder propBuilder = Json.createObjectBuilder();
             for(final Map.Entry<String, FactoryConfiguration> entry : 
this.getFactories().entrySet()) {
                 propBuilder.add(entry.getKey(), entry.getValue().createJson());
             }
-            objBuilder.add(Constants.KEY_FACTORIES, propBuilder);
+            objBuilder.add(InternalConstants.KEY_FACTORIES, propBuilder);
         }
         if ( !this.getFrameworkProperties().isEmpty() ) {
             final JsonObjectBuilder propBuilder = Json.createObjectBuilder();
             for(final Map.Entry<String, FrameworkProperty> entry : 
this.getFrameworkProperties().entrySet()) {
                 propBuilder.add(entry.getKey(), entry.getValue().createJson());
             }
-            objBuilder.add(Constants.KEY_FWK_PROPERTIES, propBuilder);
+            objBuilder.add(InternalConstants.KEY_FWK_PROPERTIES, propBuilder);
         }
         if ( !this.getInternalConfigurations().isEmpty() ) {
             final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
             for(final String n : this.getInternalConfigurations()) {
                 arrayBuilder.add(n);
             }
-                       objBuilder.add(Constants.KEY_INTERNAL_CONFIGURATIONS, 
arrayBuilder);
+                       
objBuilder.add(InternalConstants.KEY_INTERNAL_CONFIGURATIONS, arrayBuilder);
                }
                if ( !this.getInternalFactories().isEmpty() ) {
             final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
             for(final String n : this.getInternalFactories()) {
                 arrayBuilder.add(n);
             }
-                       objBuilder.add(Constants.KEY_INTERNAL_FACTORIES, 
arrayBuilder);
+                       
objBuilder.add(InternalConstants.KEY_INTERNAL_FACTORIES, arrayBuilder);
                }
                if ( !this.getInternalFrameworkProperties().isEmpty() ) {
             final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
             for(final String n : this.getInternalFrameworkProperties()) {
                 arrayBuilder.add(n);
             }
-                       objBuilder.add(Constants.KEY_INTERNAL_FWK_PROPERTIES, 
arrayBuilder);
+                       
objBuilder.add(InternalConstants.KEY_INTERNAL_FWK_PROPERTIES, arrayBuilder);
                }
 
                return objBuilder;
diff --git 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/DescribableEntity.java
 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/DescribableEntity.java
index 69c9e3a..0f36d8a 100644
--- 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/DescribableEntity.java
+++ 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/DescribableEntity.java
@@ -52,9 +52,9 @@ public abstract class DescribableEntity extends 
AttributeableEntity {
        public void fromJSONObject(final JsonObject jsonObj) throws IOException 
{
                super.fromJSONObject(jsonObj);
         try {
-                       this.setTitle(this.getString(Constants.KEY_TITLE));
-                       
this.setDescription(this.getString(Constants.KEY_DESCRIPTION));
-                       
this.setDeprecated(this.getString(Constants.KEY_DEPRECATED));
+                       
this.setTitle(this.getString(InternalConstants.KEY_TITLE));
+                       
this.setDescription(this.getString(InternalConstants.KEY_DESCRIPTION));
+                       
this.setDeprecated(this.getString(InternalConstants.KEY_DEPRECATED));
         } catch (final JsonException | IllegalArgumentException e) {
             throw new IOException(e);
                }
@@ -117,9 +117,9 @@ public abstract class DescribableEntity extends 
AttributeableEntity {
     JsonObjectBuilder createJson() throws IOException {
                final JsonObjectBuilder objectBuilder = super.createJson();
 
-               this.setString(objectBuilder, Constants.KEY_TITLE, 
this.getTitle());
-               this.setString(objectBuilder, Constants.KEY_DESCRIPTION, 
this.getDescription());
-               this.setString(objectBuilder, Constants.KEY_DEPRECATED, 
this.getDeprecated());
+               this.setString(objectBuilder, InternalConstants.KEY_TITLE, 
this.getTitle());
+               this.setString(objectBuilder, 
InternalConstants.KEY_DESCRIPTION, this.getDescription());
+               this.setString(objectBuilder, InternalConstants.KEY_DEPRECATED, 
this.getDeprecated());
 
                return objectBuilder;
        }
diff --git 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/FactoryConfiguration.java
 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/FactoryConfiguration.java
index c2345bb..ea41555 100644
--- 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/FactoryConfiguration.java
+++ 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/FactoryConfiguration.java
@@ -31,10 +31,6 @@ import javax.json.JsonValue;
 
 public class FactoryConfiguration extends ConfigurableEntity {
     
-    private static final String KEY_OPERATIONS = "operations";
-
-    private static final String KEY_INTERNAL_NAMES = "internal-names";
-    
     private final Set<Operation> operations = new HashSet<>();
 
     private final List<String> internalNames = new ArrayList<>();
@@ -58,7 +54,7 @@ public class FactoryConfiguration extends ConfigurableEntity {
         super.fromJSONObject(jsonObj);
         try {
             JsonValue val;
-            val = this.getAttributes().remove(KEY_OPERATIONS);
+            val = 
this.getAttributes().remove(InternalConstants.KEY_OPERATIONS);
             if ( val != null ) {
                 for(final JsonValue innerVal : val.asJsonArray()) {
                     final String v = getString(innerVal).toUpperCase();
@@ -66,7 +62,7 @@ public class FactoryConfiguration extends ConfigurableEntity {
                 }
             }
             
-            val = this.getAttributes().remove(KEY_INTERNAL_NAMES);
+            val = 
this.getAttributes().remove(InternalConstants.KEY_INTERNAL_NAMES);
             if ( val != null ) {
                 for(final JsonValue innerVal : val.asJsonArray()) {
                     this.getInternalNames().add(getString(innerVal));
@@ -106,14 +102,14 @@ public class FactoryConfiguration extends 
ConfigurableEntity {
             for(final Operation op : this.getOperations()) {
                 arrayBuilder.add(op.name());
             }
-                       objBuilder.add(KEY_OPERATIONS, arrayBuilder);
+                       objBuilder.add(InternalConstants.KEY_OPERATIONS, 
arrayBuilder);
                }
                if ( !this.getInternalNames().isEmpty() ) {
             final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
             for(final String n : this.getInternalNames()) {
                 arrayBuilder.add(n);
             }
-                       objBuilder.add(KEY_INTERNAL_NAMES, arrayBuilder);
+                       objBuilder.add(InternalConstants.KEY_INTERNAL_NAMES, 
arrayBuilder);
                }
                return objBuilder;
    }
diff --git 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Constants.java
 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/InternalConstants.java
similarity index 93%
rename from 
src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Constants.java
rename to 
src/main/java/org/apache/sling/feature/extension/apiregions/api/config/InternalConstants.java
index d253419..5ba22ec 100644
--- 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Constants.java
+++ 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/InternalConstants.java
@@ -19,7 +19,7 @@ package 
org.apache.sling.feature.extension.apiregions.api.config;
 /**
  * Constants used in this implementation
  */
-public abstract class Constants {
+abstract class InternalConstants {
     
     static final String KEY_TITLE = "title";
 
@@ -64,4 +64,8 @@ public abstract class Constants {
     static final String KEY_VALUE = "value";
 
     static final String KEY_REQUIRED = "required";
+
+    static final String KEY_OPERATIONS = "operations";
+
+    static final String KEY_INTERNAL_NAMES = "internal-names";
 }
diff --git 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Option.java
 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Option.java
index 9ebd153..4efeecf 100644
--- 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Option.java
+++ 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Option.java
@@ -30,22 +30,22 @@ public class Option extends DescribableEntity {
     /**
      * Clear the object and remove all metadata
      */
-         public void clear() {
+    public void clear() {
         super.clear();
-                   this.setValue(null);
+        this.setValue(null);
     }
 
-         /**
-          * Extract the metadata from the JSON object.
-          * This method first calls {@link #clear()}
-          * @param jsonObj The JSON Object
-          * @throws IOException If JSON parsing fails
-          */
-         public void fromJSONObject(final JsonObject jsonObj) throws 
IOException {
+    /**
+     * Extract the metadata from the JSON object.
+     * This method first calls {@link #clear()}
+     * @param jsonObj The JSON Object
+     * @throws IOException If JSON parsing fails
+     */
+    public void fromJSONObject(final JsonObject jsonObj) throws IOException {
         super.fromJSONObject(jsonObj);
         try {
-                       this.setValue(this.getString(Constants.KEY_VALUE));
-                   } catch (final JsonException | IllegalArgumentException e) {
+               this.setValue(this.getString(InternalConstants.KEY_VALUE));
+        } catch (final JsonException | IllegalArgumentException e) {
             throw new IOException(e);
         }
     }
@@ -53,17 +53,17 @@ public class Option extends DescribableEntity {
     /**
      * Get the value for the option
         * @return the value
-          */
-         public String getValue() {
-                   return value;
-         }
+     */
+    public String getValue() {
+        return value;
+    }
 
-         /**
+    /**
      * Set the value for the option
-          * @param value the value to set
-          */
-         public void setValue(final String value) {
-                   this.value = value;
+     * @param value the value to set
+     */
+    public void setValue(final String value) {
+        this.value = value;
     }
 
     /**
@@ -73,10 +73,10 @@ public class Option extends DescribableEntity {
      * @throws IOException If generating the JSON fails
      */
     JsonObjectBuilder createJson() throws IOException {
-                   final JsonObjectBuilder objectBuilder = super.createJson();
+        final JsonObjectBuilder objectBuilder = super.createJson();
 
-                   this.setString(objectBuilder, Constants.KEY_VALUE, 
this.getValue());
+        this.setString(objectBuilder, InternalConstants.KEY_VALUE, 
this.getValue());
 
-                   return objectBuilder;
+        return objectBuilder;
     }
 }
diff --git 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Property.java
 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Property.java
index 3579029..bebccfd 100644
--- 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Property.java
+++ 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Property.java
@@ -19,6 +19,7 @@ package 
org.apache.sling.feature.extension.apiregions.api.config;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.regex.Pattern;
 
 import javax.json.Json;
 import javax.json.JsonArrayBuilder;
@@ -54,19 +55,27 @@ public class Property extends DescribableEntity {
        private List<Option> options;
        
        /** The optional regex */
-       private String regex;
+       private Pattern pattern;
 
        /** Required? */
        private boolean required;
-       
+    
+    public Property() {
+        this.setDefaults();
+    }
+
+    void setDefaults() {
+               this.setType(PropertyType.STRING);
+        this.setCardinality(1);
+        this.setRequired(false);
+    }
+
     /**
      * Clear the object and remove all metadata
      */
        public void clear() {
         super.clear();
-               this.setType(PropertyType.STRING);
-               this.setCardinality(1);
-               this.setRequired(false);
+        this.setDefaults();
                this.setVariable(null);
                this.setRange(null);
                this.setIncludes(null);
@@ -84,21 +93,21 @@ public class Property extends DescribableEntity {
        public void fromJSONObject(final JsonObject jsonObj) throws IOException 
{
         super.fromJSONObject(jsonObj);
         try {
-                       
this.setVariable(this.getString(Constants.KEY_VARIABLE));
-                       
this.setCardinality(this.getInteger(Constants.KEY_CARDINALITY, 
this.getCardinality()));
-                       
this.setRequired(this.getBoolean(Constants.KEY_REQUIRED, this.isRequired()));
+                       
this.setVariable(this.getString(InternalConstants.KEY_VARIABLE));
+                       
this.setCardinality(this.getInteger(InternalConstants.KEY_CARDINALITY, 
this.getCardinality()));
+                       
this.setRequired(this.getBoolean(InternalConstants.KEY_REQUIRED, 
this.isRequired()));
                        
-                       final String typeVal = 
this.getString(Constants.KEY_TYPE);
+                       final String typeVal = 
this.getString(InternalConstants.KEY_TYPE);
                        if ( typeVal != null ) {
                 this.setType(PropertyType.valueOf(typeVal.toUpperCase()));     
                        
                        }
-                       final JsonValue rangeVal = 
this.getAttributes().remove(Constants.KEY_RANGE);
+                       final JsonValue rangeVal = 
this.getAttributes().remove(InternalConstants.KEY_RANGE);
                        if ( rangeVal != null ) {
                                final Range range = new Range();
                                range.fromJSONObject(rangeVal.asJsonObject());
                                this.setRange(range);
                        }
-                       final JsonValue incs = 
this.getAttributes().remove(Constants.KEY_INCLUDES);
+                       final JsonValue incs = 
this.getAttributes().remove(InternalConstants.KEY_INCLUDES);
                        if ( incs != null ) {
                                final List<String> list = new ArrayList<>();
                                for(final JsonValue innerVal : 
incs.asJsonArray()) {
@@ -106,7 +115,7 @@ public class Property extends DescribableEntity {
                 }
                 this.setIncludes(list.toArray(new String[list.size()]));
                        }
-                       final JsonValue excs = 
this.getAttributes().remove(Constants.KEY_EXCLUDES);
+                       final JsonValue excs = 
this.getAttributes().remove(InternalConstants.KEY_EXCLUDES);
                        if ( excs != null ) {
                                final List<String> list = new ArrayList<>();
                                for(final JsonValue innerVal : 
excs.asJsonArray()) {
@@ -114,7 +123,7 @@ public class Property extends DescribableEntity {
                 }
                 this.setExcludes(list.toArray(new String[list.size()]));
                        }
-                       final JsonValue opts = 
this.getAttributes().remove(Constants.KEY_OPTIONS);
+                       final JsonValue opts = 
this.getAttributes().remove(InternalConstants.KEY_OPTIONS);
                        if ( opts != null ) {
                                final List<Option> list = new ArrayList<>();
                                for(final JsonValue innerVal : 
opts.asJsonArray()) {
@@ -124,7 +133,7 @@ public class Property extends DescribableEntity {
                 }
                                this.setOptions(list);
                        }
-                       this.setRegex(this.getString(Constants.KEY_REGEX));
+                       
this.setRegex(this.getString(InternalConstants.KEY_REGEX));
                } catch (final JsonException | IllegalArgumentException e) {
             throw new IOException(e);
         }
@@ -140,41 +149,41 @@ public class Property extends DescribableEntity {
                final JsonObjectBuilder objectBuilder = super.createJson();
 
                if ( this.getType() != null ) {
-                       this.setString(objectBuilder, Constants.KEY_TYPE, 
this.getType().name());
+                       this.setString(objectBuilder, 
InternalConstants.KEY_TYPE, this.getType().name());
            }
                if ( this.getCardinality() != 1 ) {
-                       objectBuilder.add(Constants.KEY_CARDINALITY, 
this.getCardinality());
+                       objectBuilder.add(InternalConstants.KEY_CARDINALITY, 
this.getCardinality());
                }
                if ( this.isRequired() ) {
-                       objectBuilder.add(Constants.KEY_REQUIRED, 
this.isRequired());
+                       objectBuilder.add(InternalConstants.KEY_REQUIRED, 
this.isRequired());
                }
-           this.setString(objectBuilder, Constants.KEY_VARIABLE, 
this.getVariable());
+           this.setString(objectBuilder, InternalConstants.KEY_VARIABLE, 
this.getVariable());
                
                if ( this.range != null ) {
-                       objectBuilder.add(Constants.KEY_RANGE, 
this.range.toJSONObject());
+                       objectBuilder.add(InternalConstants.KEY_RANGE, 
this.range.toJSONObject());
                }
                if ( this.includes != null && this.includes.length > 0 ) {
                        final JsonArrayBuilder arrayBuilder = 
Json.createArrayBuilder();
                        for(final String v : this.includes) {
                                arrayBuilder.add(v);
                        }
-                       objectBuilder.add(Constants.KEY_INCLUDES, arrayBuilder);
+                       objectBuilder.add(InternalConstants.KEY_INCLUDES, 
arrayBuilder);
                }
                if ( this.excludes != null && this.excludes.length > 0 ) {
                        final JsonArrayBuilder arrayBuilder = 
Json.createArrayBuilder();
                        for(final String v : this.excludes) {
                                arrayBuilder.add(v);
                        }
-                       objectBuilder.add(Constants.KEY_EXCLUDES, arrayBuilder);
+                       objectBuilder.add(InternalConstants.KEY_EXCLUDES, 
arrayBuilder);
                }
                if ( this.options != null && !this.options.isEmpty()) {
                        final JsonArrayBuilder arrayBuilder = 
Json.createArrayBuilder();
             for(final Option o : this.options) {
                                arrayBuilder.add(o.toJSONObject());
                        }
-                       objectBuilder.add(Constants.KEY_OPTIONS, arrayBuilder);
+                       objectBuilder.add(InternalConstants.KEY_OPTIONS, 
arrayBuilder);
                }
-               this.setString(objectBuilder, Constants.KEY_REGEX, 
this.getRegex());
+               this.setString(objectBuilder, InternalConstants.KEY_REGEX, 
this.getRegex());
                
                return objectBuilder;
        }
@@ -192,7 +201,7 @@ public class Property extends DescribableEntity {
         * @param type the type to set
         */
        public void setType(final PropertyType type) {
-               this.type = type;
+               this.type = type == null ? PropertyType.STRING : type;
        }
 
        /**
@@ -296,17 +305,30 @@ public class Property extends DescribableEntity {
         * @return the regex
         */
        public String getRegex() {
-               return regex;
+               return pattern == null ? null : pattern.pattern();
        }
 
        /**
         * Set the regex
         * @param regex the regex to set
+     * @throws IllegalArgumentException If the pattern is not valid
         */
        public void setRegex(final String regex) {
-               this.regex = regex;
+        if ( regex == null ) {
+            this.pattern = null;
+        } else {
+           this.pattern = Pattern.compile(regex);
+        }
        }
 
+    /**
+     * Get the regex pattern
+     * @return The pattern or {@code null}
+     */
+    public Pattern getRegexPattern() {
+        return this.pattern;
+    }
+
        /**
         * Is this property required?
         * @return {@code true} if it is required
diff --git 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Range.java
 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Range.java
index 01a474f..3acac02 100644
--- 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Range.java
+++ 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Range.java
@@ -22,13 +22,15 @@ import javax.json.JsonException;
 import javax.json.JsonObject;
 import javax.json.JsonObjectBuilder;
 
+import org.apache.felix.cm.json.Configurations;
+
 public class Range extends AttributeableEntity {
 
     /** The optional min value */
-    private String min;
+    private Number min;
 
     /** The optional max value */
-    private String max;
+    private Number max;
 
     /**
      * Clear the object and remove all metadata
@@ -48,8 +50,8 @@ public class Range extends AttributeableEntity {
        public void fromJSONObject(final JsonObject jsonObj) throws IOException 
{
         super.fromJSONObject(jsonObj);
         try {
-                       this.setMin(this.getString(Constants.KEY_MIN));
-                       this.setMax(this.getString(Constants.KEY_MAX));
+                       this.setMin(this.getNumber(InternalConstants.KEY_MIN));
+                       this.setMax(this.getNumber(InternalConstants.KEY_MAX));
                } catch (final JsonException | IllegalArgumentException e) {
             throw new IOException(e);
         }
@@ -59,7 +61,7 @@ public class Range extends AttributeableEntity {
      * Get the min value
         * @return the min
         */
-       public String getMin() {
+       public Number getMin() {
                return min;
        }
 
@@ -67,7 +69,7 @@ public class Range extends AttributeableEntity {
      * Set the min value
         * @param min the min to set
         */
-       public void setMin(final String min) {
+       public void setMin(final Number min) {
                this.min = min;
        }
 
@@ -75,7 +77,7 @@ public class Range extends AttributeableEntity {
      * Get the max value
         * @return the max
         */
-       public String getMax() {
+       public Number getMax() {
                return max;
        }
 
@@ -83,7 +85,7 @@ public class Range extends AttributeableEntity {
      * Set the max value
         * @param max the max to set
         */
-       public void setMax(final String max) {
+       public void setMax(final Number max) {
                this.max = max;
     }
 
@@ -96,8 +98,12 @@ public class Range extends AttributeableEntity {
     JsonObjectBuilder createJson() throws IOException {
                final JsonObjectBuilder objectBuilder = super.createJson();
 
-               this.setString(objectBuilder, Constants.KEY_MIN, this.getMin());
-               this.setString(objectBuilder, Constants.KEY_MAX, this.getMax());
+        if ( this.getMin() != null ) {
+            objectBuilder.add(InternalConstants.KEY_MIN, 
Configurations.convertToJsonValue(this.getMin()));
+        }
+        if ( this.getMax() != null ) {
+            objectBuilder.add(InternalConstants.KEY_MAX, 
Configurations.convertToJsonValue(this.getMax()));
+        }
 
                return objectBuilder;
        }
diff --git 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Validator.java
 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Validator.java
index 546fa1c..6a3eda6 100644
--- 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Validator.java
+++ 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/Validator.java
@@ -22,7 +22,6 @@ import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
-import java.util.regex.Pattern;
 
 /**
  * Validate values
@@ -144,9 +143,8 @@ public class Validator {
                                                        break;
                                default : messages.add("Unable to validate 
value - unknown property type : " + prop.getType());
                        }
-                       if ( prop.getRegex() != null ) {
-                               final Pattern p = 
Pattern.compile(prop.getRegex());
-                               if ( !p.matcher(value.toString()).matches() ) {
+                       if ( prop.getRegexPattern() != null ) {
+                               if ( 
!prop.getRegexPattern().matcher(value.toString()).matches() ) {
                     messages.add("Value " + value + " does not match regex " + 
prop.getRegex());
                                }
                        }
@@ -321,16 +319,30 @@ public class Validator {
            if ( prop.getRange() != null ) {
                        try {
                 if ( prop.getRange().getMin() != null ) {
-                                       final long min = 
Long.valueOf(prop.getRange().getMin());
-                                       if ( value.longValue() < min ) {
-                         messages.add("Value " + value + " is too low; should 
not be lower than " + prop.getRange().getMin());
-                                       }
+                    if ( value instanceof Float || value instanceof Double ) {
+                        final double min = 
prop.getRange().getMin().doubleValue();
+                        if ( value.doubleValue() < min ) {
+                             messages.add("Value " + value + " is too low; 
should not be lower than " + prop.getRange().getMin());
+                        }    
+                    } else {
+                        final long min = prop.getRange().getMin().longValue();
+                        if ( value.longValue() < min ) {
+                             messages.add("Value " + value + " is too low; 
should not be lower than " + prop.getRange().getMin());
+                        }    
+                    }
                                }
                 if ( prop.getRange().getMax() != null ) {
-                                       final long max = 
Long.valueOf(prop.getRange().getMax());
-                                       if ( value.longValue() > max ) {
-                         messages.add("Value " + value + " is too high; should 
not be higher than " + prop.getRange().getMax());
-                                       }
+                    if ( value instanceof Float || value instanceof Double ) {
+                        final double max = 
prop.getRange().getMax().doubleValue();
+                        if ( value.doubleValue() > max ) {
+                            messages.add("Value " + value + " is too high; 
should not be higher than " + prop.getRange().getMax());
+                        }    
+                    } else {
+                        final long max = prop.getRange().getMax().longValue();
+                        if ( value.longValue() > max ) {
+                            messages.add("Value " + value + " is too high; 
should not be higher than " + prop.getRange().getMax());
+                        }    
+                    }
                                }
                        } catch ( final NumberFormatException nfe) {
                                messages.add("Invalid range specified in " + 
prop.getRange());
diff --git 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/package-info.java
 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/package-info.java
index f2582d7..b67f74d 100644
--- 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/package-info.java
+++ 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/package-info.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
[email protected]("1.ΓΌ.0")
[email protected]("1.0.0")
 package org.apache.sling.feature.extension.apiregions.api.config;
 
 
diff --git 
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/AttributeableEntityTest.java
 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/AttributeableEntityTest.java
index 5152867..165a5ed 100644
--- 
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/AttributeableEntityTest.java
+++ 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/AttributeableEntityTest.java
@@ -104,4 +104,22 @@ public class AttributeableEntityTest {
         assertEquals(9, entity.getInteger("foo", 7));
         assertTrue(entity.getAttributes().isEmpty());
     }
+
+    @Test public void testGetNumber() throws IOException {
+        final AE entity = new AE();
+        assertNull(entity.getNumber("foo"));
+
+        entity.getAttributes().put("foo", Json.createValue(5));
+        assertEquals(5L, entity.getNumber("foo"));
+        assertTrue(entity.getAttributes().isEmpty());
+
+
+        try {
+            entity.getAttributes().put("foo", Json.createValue("a"));
+            entity.getNumber("foo");
+            fail();
+        } catch ( final IOException expected) {
+            // this is expected
+        }
+    }
 }
\ No newline at end of file
diff --git 
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurableEntityTest.java
 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurableEntityTest.java
new file mode 100644
index 0000000..79efb74
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurableEntityTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.sling.feature.extension.apiregions.api.config;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import javax.json.Json;
+
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionState;
+import org.apache.sling.feature.ExtensionType;
+import org.junit.Test;
+
+public class ConfigurableEntityTest {
+
+    public static class CE extends ConfigurableEntity {
+        // ConfigurableEntity is abstract, therefore subclassing for testing
+    }
+
+    @Test public void testClear() {
+        final CE entity = new CE();
+        entity.getAttributes().put("a", Json.createValue(5));
+        entity.setDeprecated("d");
+        entity.setTitle("t");
+        entity.setDescription("x");
+        entity.getProperties().put("a", new Property());
+        entity.clear();
+        assertTrue(entity.getAttributes().isEmpty());
+        assertNull(entity.getDeprecated());
+        assertNull(entity.getTitle());
+        assertNull(entity.getDescription());
+        assertTrue(entity.getProperties().isEmpty());
+    }
+
+    @Test public void testFromJSONObject() throws IOException {
+        final Extension ext = new Extension(ExtensionType.JSON, "a", 
ExtensionState.OPTIONAL);
+        ext.setJSON("{ \"properties\" : { \"a\" : {}, \"b\" : {}}}");
+
+        final CE entity = new CE();
+        entity.fromJSONObject(ext.getJSONStructure().asJsonObject());
+        assertEquals(2, entity.getProperties().size());
+        assertNotNull(entity.getProperties().get("a"));
+        assertNotNull(entity.getProperties().get("b"));
+    }
+
+    @Test public void testToJSONObject() throws IOException {
+        final CE entity = new CE();
+        entity.getProperties().put("a", new Property());
+        entity.getProperties().put("b", new Property());
+
+        final Extension ext = new Extension(ExtensionType.JSON, "a", 
ExtensionState.OPTIONAL);
+        ext.setJSON("{ \"properties\" : { \"a\" : {\"type\":\"STRING\"}, \"b\" 
: {\"type\":\"STRING\"}}}");
+
+        assertEquals(ext.getJSONStructure().asJsonObject(), 
entity.toJSONObject());
+    }
+}
\ No newline at end of file
diff --git 
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurationApiTest.java
 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurationApiTest.java
index 525797e..cdb2f94 100644
--- 
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurationApiTest.java
+++ 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurationApiTest.java
@@ -16,7 +16,13 @@
  */
 package org.apache.sling.feature.extension.apiregions.api.config;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import javax.json.Json;
 
 import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Extension;
@@ -44,4 +50,69 @@ public class ConfigurationApiTest {
         f.getExtensions().add(e);
         ConfigurationApi.getConfigurationApi(f);
     }
+
+    @Test public void testClear() {
+        final ConfigurationApi entity = new ConfigurationApi();
+        entity.getAttributes().put("a", Json.createValue(5));
+        entity.getConfigurations().put("pid", new Configuration());
+        entity.getFactories().put("factory", new FactoryConfiguration());
+        entity.getFrameworkProperties().put("prop", new FrameworkProperty());
+        entity.getInternalConfigurations().add("ipid");
+        entity.getInternalFactories().add("ifactory");
+        entity.getInternalFrameworkProperties().add("iprop");
+        entity.clear();
+        assertTrue(entity.getAttributes().isEmpty());
+        assertTrue(entity.getConfigurations().isEmpty());
+        assertTrue(entity.getFactories().isEmpty());
+        assertTrue(entity.getFrameworkProperties().isEmpty());
+        assertTrue(entity.getInternalConfigurations().isEmpty());
+        assertTrue(entity.getInternalFactories().isEmpty());
+        assertTrue(entity.getInternalFrameworkProperties().isEmpty());
+    }
+
+    @Test public void testFromJSONObject() throws IOException {
+        final Extension ext = new Extension(ExtensionType.JSON, "a", 
ExtensionState.OPTIONAL);
+        ext.setJSON("{ \"a\" : 5, \"configurations\" : { \"pid\": {}}, " +
+            "\"factories\" : { \"factory\" : {}}," +
+            "\"framework-properties\" : { \"prop\" : { \"type\" : 
\"STRING\"}}," +
+            "\"internal-configurations\" : [\"ipid\"],"+
+            "\"internal-factories\" : [\"ifactory\"],"+
+            "\"internal-framework-properties\" : [\"iprop\"]}");
+
+        final ConfigurationApi entity = new ConfigurationApi();
+        entity.fromJSONObject(ext.getJSONStructure().asJsonObject());
+        assertEquals(1, entity.getConfigurations().size());
+        assertEquals(1, entity.getFactories().size());
+        assertEquals(1, entity.getFrameworkProperties().size());
+        assertEquals(1, entity.getInternalConfigurations().size());
+        assertEquals(1, entity.getInternalFactories().size());
+        assertEquals(1, entity.getInternalFrameworkProperties().size());
+        assertTrue(entity.getConfigurations().containsKey("pid"));
+        assertTrue(entity.getFactories().containsKey("factory"));
+        assertTrue(entity.getFrameworkProperties().containsKey("prop"));
+        assertTrue(entity.getInternalConfigurations().contains("ipid"));
+        assertTrue(entity.getInternalFactories().contains("ifactory"));
+        assertTrue(entity.getInternalFrameworkProperties().contains("iprop"));
+    }
+
+    @Test public void testToJSONObject() throws IOException {
+        final ConfigurationApi entity = new ConfigurationApi();
+        entity.getAttributes().put("a", Json.createValue(5));
+        entity.getConfigurations().put("pid", new Configuration());
+        entity.getFactories().put("factory", new FactoryConfiguration());
+        entity.getFrameworkProperties().put("prop", new FrameworkProperty());
+        entity.getInternalConfigurations().add("ipid");
+        entity.getInternalFactories().add("ifactory");
+        entity.getInternalFrameworkProperties().add("iprop");
+
+        final Extension ext = new Extension(ExtensionType.JSON, "a", 
ExtensionState.OPTIONAL);
+        ext.setJSON("{ \"a\" : 5, \"configurations\" : { \"pid\": {}}, " +
+            "\"factories\" : { \"factory\" : {}}," +
+            "\"framework-properties\" : { \"prop\" : { \"type\" : 
\"STRING\"}}," +
+            "\"internal-configurations\" : [\"ipid\"],"+
+            "\"internal-factories\" : [\"ifactory\"],"+
+            "\"internal-framework-properties\" : [\"iprop\"]}");
+
+        assertEquals(ext.getJSONStructure().asJsonObject(), 
entity.toJSONObject());
+    }
 }
diff --git 
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/AttributeableEntityTest.java
 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/DescribableEntityTest.java
similarity index 54%
copy from 
src/test/java/org/apache/sling/feature/extension/apiregions/api/config/AttributeableEntityTest.java
copy to 
src/test/java/org/apache/sling/feature/extension/apiregions/api/config/DescribableEntityTest.java
index 5152867..f2ad633 100644
--- 
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/AttributeableEntityTest.java
+++ 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/DescribableEntityTest.java
@@ -19,89 +19,60 @@ package 
org.apache.sling.feature.extension.apiregions.api.config;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 import java.io.IOException;
 
 import javax.json.Json;
-import javax.json.JsonValue;
 
 import org.apache.sling.feature.Extension;
 import org.apache.sling.feature.ExtensionState;
 import org.apache.sling.feature.ExtensionType;
 import org.junit.Test;
 
-public class AttributeableEntityTest {
+public class DescribableEntityTest {
 
-    public static class AE extends AttributeableEntity {
-        // AttributeableEntity is abstract, therefore subclassing for testing
+    public static class DE extends DescribableEntity {
+        // DescribableEntity is abstract, therefore subclassing for testing
     }
 
     @Test public void testClear() {
-        final AE entity = new AE();
+        final DE entity = new DE();
         entity.getAttributes().put("a", Json.createValue(5));
+        entity.setDeprecated("d");
+        entity.setTitle("t");
+        entity.setDescription("x");
         entity.clear();
         assertTrue(entity.getAttributes().isEmpty());
+        assertNull(entity.getDeprecated());
+        assertNull(entity.getTitle());
+        assertNull(entity.getDescription());
     }
 
     @Test public void testFromJSONObject() throws IOException {
         final Extension ext = new Extension(ExtensionType.JSON, "a", 
ExtensionState.OPTIONAL);
-        ext.setJSON("{ \"a\" : 1, \"b\" : \"2\"}");
+        ext.setJSON("{ \"a\" : 1, \"b\" : \"2\", \"title\" : \"t\", 
\"description\" : \"desc\", \"deprecated\" : \"depr\"}");
 
-        final AE entity = new AE();
+        final DE entity = new DE();
         entity.fromJSONObject(ext.getJSONStructure().asJsonObject());
         assertEquals(2, entity.getAttributes().size());
         assertEquals(Json.createValue(1), entity.getAttributes().get("a"));
         assertEquals(Json.createValue("2"), entity.getAttributes().get("b"));
+        assertEquals("t", entity.getTitle());
+        assertEquals("desc", entity.getDescription());
+        assertEquals("depr", entity.getDeprecated());
     }
 
     @Test public void testToJSONObject() throws IOException {
-        final AE entity = new AE();
+        final DE entity = new DE();
         entity.getAttributes().put("a", Json.createValue(1));
         entity.getAttributes().put("b", Json.createValue("2"));
-        
+        entity.setTitle("t");
+        entity.setDescription("desc");
+        entity.setDeprecated("depr");
+
         final Extension ext = new Extension(ExtensionType.JSON, "a", 
ExtensionState.OPTIONAL);
-        ext.setJSON("{ \"a\" : 1, \"b\" : \"2\"}");
+        ext.setJSON("{ \"a\" : 1, \"b\" : \"2\", \"title\" : \"t\", 
\"description\" : \"desc\", \"deprecated\" : \"depr\"}");
 
         assertEquals(ext.getJSONStructure().asJsonObject(), 
entity.toJSONObject());
     }
-
-    @Test public void testGetString() {
-        final AE entity = new AE();
-        assertNull(entity.getString("foo"));
-        entity.getAttributes().put("foo", Json.createValue("bar"));
-        assertEquals("bar", entity.getString("foo"));
-        assertTrue(entity.getAttributes().isEmpty());
-    }
-
-    @Test public void testGetBoolean() throws IOException {
-        final AE entity = new AE();
-        assertTrue(entity.getBoolean("foo", true));
-
-        entity.getAttributes().put("foo", JsonValue.FALSE);
-        assertEquals(false, entity.getBoolean("foo", true));
-        assertTrue(entity.getAttributes().isEmpty());
-
-
-        try {
-            entity.getAttributes().put("foo", Json.createValue(1.0));
-            entity.getBoolean("foo", false);
-            fail();
-        } catch ( final IOException expected) {
-            // this is expected
-        }
-    }
-
-    @Test public void testGetInteger() throws IOException {
-        final AE entity = new AE();
-        assertEquals(7, entity.getInteger("foo", 7));
-
-        entity.getAttributes().put("foo", Json.createValue(9));
-        assertEquals(9, entity.getInteger("foo", 7));
-        assertTrue(entity.getAttributes().isEmpty());
-
-        entity.getAttributes().put("foo", Json.createValue("9"));
-        assertEquals(9, entity.getInteger("foo", 7));
-        assertTrue(entity.getAttributes().isEmpty());
-    }
 }
\ No newline at end of file
diff --git 
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/FactoryConfigurationTest.java
 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/FactoryConfigurationTest.java
new file mode 100644
index 0000000..37f09bf
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/FactoryConfigurationTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.sling.feature.extension.apiregions.api.config;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import javax.json.Json;
+
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionState;
+import org.apache.sling.feature.ExtensionType;
+import org.junit.Test;
+
+public class FactoryConfigurationTest {
+
+    @Test public void testClear() {
+        final FactoryConfiguration entity = new FactoryConfiguration();
+        entity.getAttributes().put("a", Json.createValue(5));
+        entity.setDeprecated("d");
+        entity.setTitle("t");
+        entity.setDescription("x");
+        entity.getProperties().put("a", new Property());
+        entity.getOperations().add(Operation.CREATE);
+        entity.getInternalNames().add("internal");
+        entity.clear();
+        assertTrue(entity.getAttributes().isEmpty());
+        assertNull(entity.getDeprecated());
+        assertNull(entity.getTitle());
+        assertNull(entity.getDescription());
+        assertTrue(entity.getProperties().isEmpty());
+        assertTrue(entity.getOperations().isEmpty());
+        assertTrue(entity.getInternalNames().isEmpty());
+    }
+
+    @Test public void testFromJSONObject() throws IOException {
+        final Extension ext = new Extension(ExtensionType.JSON, "a", 
ExtensionState.OPTIONAL);
+        ext.setJSON("{ \"internal-names\" : [ \"a\", \"b\"], \"operations\" : 
[\"create\"]}");
+
+        final FactoryConfiguration entity = new FactoryConfiguration();
+        entity.fromJSONObject(ext.getJSONStructure().asJsonObject());
+        assertEquals(2, entity.getInternalNames().size());
+        assertTrue(entity.getInternalNames().contains("a"));
+        assertTrue(entity.getInternalNames().contains("b"));
+        assertEquals(1, entity.getOperations().size());
+        assertEquals(Operation.CREATE, 
entity.getOperations().iterator().next());
+    }
+
+    @Test public void testToJSONObject() throws IOException {
+        final FactoryConfiguration entity = new FactoryConfiguration();
+        entity.getInternalNames().add("a");
+        entity.getInternalNames().add("b");
+        entity.getOperations().add(Operation.UPDATE);
+
+        final Extension ext = new Extension(ExtensionType.JSON, "a", 
ExtensionState.OPTIONAL);
+        ext.setJSON("{ \"internal-names\" : [ \"a\", \"b\"], \"operations\" : 
[\"UPDATE\"]}");
+
+        assertEquals(ext.getJSONStructure().asJsonObject(), 
entity.toJSONObject());
+    }
+}
\ No newline at end of file
diff --git 
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/AttributeableEntityTest.java
 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/OptionTest.java
similarity index 54%
copy from 
src/test/java/org/apache/sling/feature/extension/apiregions/api/config/AttributeableEntityTest.java
copy to 
src/test/java/org/apache/sling/feature/extension/apiregions/api/config/OptionTest.java
index 5152867..924c2b0 100644
--- 
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/AttributeableEntityTest.java
+++ 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/OptionTest.java
@@ -19,89 +19,58 @@ package 
org.apache.sling.feature.extension.apiregions.api.config;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 import java.io.IOException;
 
 import javax.json.Json;
-import javax.json.JsonValue;
 
 import org.apache.sling.feature.Extension;
 import org.apache.sling.feature.ExtensionState;
 import org.apache.sling.feature.ExtensionType;
 import org.junit.Test;
 
-public class AttributeableEntityTest {
-
-    public static class AE extends AttributeableEntity {
-        // AttributeableEntity is abstract, therefore subclassing for testing
-    }
+public class OptionTest {
 
     @Test public void testClear() {
-        final AE entity = new AE();
+        final Option entity = new Option();
         entity.getAttributes().put("a", Json.createValue(5));
+        entity.setDeprecated("d");
+        entity.setTitle("t");
+        entity.setDescription("x");
+        entity.setValue("foo");
         entity.clear();
         assertTrue(entity.getAttributes().isEmpty());
+        assertNull(entity.getDeprecated());
+        assertNull(entity.getTitle());
+        assertNull(entity.getDescription());
+        assertNull(entity.getValue());
     }
 
     @Test public void testFromJSONObject() throws IOException {
         final Extension ext = new Extension(ExtensionType.JSON, "a", 
ExtensionState.OPTIONAL);
-        ext.setJSON("{ \"a\" : 1, \"b\" : \"2\"}");
+        ext.setJSON("{ \"a\" : 1, \"b\" : \"2\", \"title\" : \"t\", 
\"description\" : \"desc\", \"value\" : \"v\" }");
 
-        final AE entity = new AE();
+        final Option entity = new Option();
         entity.fromJSONObject(ext.getJSONStructure().asJsonObject());
         assertEquals(2, entity.getAttributes().size());
         assertEquals(Json.createValue(1), entity.getAttributes().get("a"));
         assertEquals(Json.createValue("2"), entity.getAttributes().get("b"));
+        assertEquals("t", entity.getTitle());
+        assertEquals("desc", entity.getDescription());
+        assertEquals("v", entity.getValue());
     }
 
     @Test public void testToJSONObject() throws IOException {
-        final AE entity = new AE();
+        final Option entity = new Option();
         entity.getAttributes().put("a", Json.createValue(1));
         entity.getAttributes().put("b", Json.createValue("2"));
-        
+        entity.setTitle("t");
+        entity.setDescription("desc");
+        entity.setValue("v");
+
         final Extension ext = new Extension(ExtensionType.JSON, "a", 
ExtensionState.OPTIONAL);
-        ext.setJSON("{ \"a\" : 1, \"b\" : \"2\"}");
+        ext.setJSON("{ \"a\" : 1, \"b\" : \"2\", \"title\" : \"t\", 
\"description\" : \"desc\", \"value\" : \"v\" }");
 
         assertEquals(ext.getJSONStructure().asJsonObject(), 
entity.toJSONObject());
     }
-
-    @Test public void testGetString() {
-        final AE entity = new AE();
-        assertNull(entity.getString("foo"));
-        entity.getAttributes().put("foo", Json.createValue("bar"));
-        assertEquals("bar", entity.getString("foo"));
-        assertTrue(entity.getAttributes().isEmpty());
-    }
-
-    @Test public void testGetBoolean() throws IOException {
-        final AE entity = new AE();
-        assertTrue(entity.getBoolean("foo", true));
-
-        entity.getAttributes().put("foo", JsonValue.FALSE);
-        assertEquals(false, entity.getBoolean("foo", true));
-        assertTrue(entity.getAttributes().isEmpty());
-
-
-        try {
-            entity.getAttributes().put("foo", Json.createValue(1.0));
-            entity.getBoolean("foo", false);
-            fail();
-        } catch ( final IOException expected) {
-            // this is expected
-        }
-    }
-
-    @Test public void testGetInteger() throws IOException {
-        final AE entity = new AE();
-        assertEquals(7, entity.getInteger("foo", 7));
-
-        entity.getAttributes().put("foo", Json.createValue(9));
-        assertEquals(9, entity.getInteger("foo", 7));
-        assertTrue(entity.getAttributes().isEmpty());
-
-        entity.getAttributes().put("foo", Json.createValue("9"));
-        assertEquals(9, entity.getInteger("foo", 7));
-        assertTrue(entity.getAttributes().isEmpty());
-    }
 }
\ No newline at end of file
diff --git 
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/PropertyTest.java
 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/PropertyTest.java
new file mode 100644
index 0000000..b007391
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/PropertyTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.sling.feature.extension.apiregions.api.config;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import javax.json.Json;
+
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionState;
+import org.apache.sling.feature.ExtensionType;
+import org.junit.Test;
+
+public class PropertyTest {
+
+    @Test public void testClear() {
+        final Property entity = new Property();
+        entity.getAttributes().put("a", Json.createValue(5));
+        entity.setDeprecated("d");
+        entity.setTitle("t");
+        entity.setDescription("x");
+        entity.setCardinality(5);
+        entity.setExcludes(new String[] {"ex"});
+        entity.setIncludes(new String[] {"in"});
+        entity.setOptions(Arrays.asList(new Option()));
+        entity.setRange(new Range());
+        entity.setRegex(".");
+        entity.setRequired(true);
+        entity.setVariable("var");
+        entity.setType(PropertyType.BYTE);
+        entity.clear();
+        assertTrue(entity.getAttributes().isEmpty());
+        assertNull(entity.getDeprecated());
+        assertNull(entity.getTitle());
+        assertNull(entity.getDescription());
+        assertEquals(1, entity.getCardinality());
+        assertNull(entity.getExcludes());
+        assertNull(entity.getIncludes());
+        assertNull(entity.getOptions());
+        assertNull(entity.getRange());
+        assertNull(entity.getRegex());
+        assertNull(entity.getRegexPattern());
+        assertNull(entity.getVariable());
+        assertFalse(entity.isRequired());
+        assertEquals(PropertyType.STRING, entity.getType());
+    }
+
+    @Test public void testFromJSONObject() throws IOException {
+        final Extension ext = new Extension(ExtensionType.JSON, "a", 
ExtensionState.OPTIONAL);
+        ext.setJSON("{ \"type\" : \"BYTE\", \"cardinality\": 5, \"required\" : 
true, \"variable\" : \"var\"," +
+        "\"range\" : {}, \"includes\" : [\"in\"], \"excludes\" : [\"ex\"] , 
\"options\": [{}], \"regex\": \".\"}");
+
+        final Property entity = new Property();
+        entity.fromJSONObject(ext.getJSONStructure().asJsonObject());
+
+        assertEquals(5, entity.getCardinality());
+        assertEquals(PropertyType.BYTE, entity.getType());
+        assertTrue(entity.isRequired());
+        assertEquals("var", entity.getVariable());
+        assertNotNull(entity.getRange());
+        assertArrayEquals(new String[] {"ex"}, entity.getExcludes());
+        assertArrayEquals(new String[] {"in"}, entity.getIncludes());
+        assertEquals(1, entity.getOptions().size());
+        assertEquals(".", entity.getRegex());
+        assertNotNull(entity.getRegexPattern());
+
+        // test defaults and empty values
+        ext.setJSON("{ \"variable\" : \"var\", \"regex\": \".\"}");
+        entity.fromJSONObject(ext.getJSONStructure().asJsonObject());
+
+        assertEquals(1, entity.getCardinality());
+        assertEquals(PropertyType.STRING, entity.getType());
+        assertFalse(entity.isRequired());
+        assertEquals("var", entity.getVariable());
+        assertNull(entity.getRange());
+        assertNull(entity.getExcludes());
+        assertNull(entity.getIncludes());
+        assertNull(entity.getOptions());
+        assertEquals(".", entity.getRegex());
+        assertNotNull(entity.getRegexPattern());
+   }
+
+    @Test public void testToJSONObject() throws IOException {
+        final Property entity = new Property();
+        entity.setCardinality(5);
+        entity.setExcludes(new String[] {"ex"});
+        entity.setIncludes(new String[] {"in"});
+        entity.setOptions(Arrays.asList(new Option()));
+        entity.setRange(new Range());
+        entity.setRegex(".");
+        entity.setRequired(true);
+        entity.setVariable("var");
+        entity.setType(PropertyType.BYTE);
+
+        final Extension ext = new Extension(ExtensionType.JSON, "a", 
ExtensionState.OPTIONAL);
+        ext.setJSON("{ \"type\" : \"BYTE\", \"cardinality\": 5, \"required\" : 
true, \"variable\" : \"var\"," +
+            "\"range\" : {}, \"includes\" : [\"in\"], \"excludes\" : [\"ex\"] 
, \"options\": [{}], \"regex\": \".\"}");
+
+        assertEquals(ext.getJSONStructure().asJsonObject(), 
entity.toJSONObject());
+
+        // test defaults and empty values
+        entity.setCardinality(1);
+        entity.setType(null);
+        entity.setRequired(false);
+        entity.setRange(null);
+        entity.setOptions(null);
+        entity.setExcludes(null);
+        entity.setIncludes(null);
+
+        ext.setJSON("{ \"type\" : \"STRING\", \"variable\" : \"var\", 
\"regex\": \".\"}");
+
+        assertEquals(ext.getJSONStructure().asJsonObject(), 
entity.toJSONObject());
+    }
+}
\ No newline at end of file
diff --git 
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/RangeTest.java
 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/RangeTest.java
new file mode 100644
index 0000000..b894daf
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/RangeTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.sling.feature.extension.apiregions.api.config;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import javax.json.Json;
+
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionState;
+import org.apache.sling.feature.ExtensionType;
+import org.junit.Test;
+
+public class RangeTest {
+
+    @Test public void testClear() {
+        final Range entity = new Range();
+        entity.getAttributes().put("a", Json.createValue(5));
+        entity.setMax(5);
+        entity.setMin(20.1);
+        entity.clear();
+        assertTrue(entity.getAttributes().isEmpty());
+        assertNull(entity.getMax());
+        assertNull(entity.getMin());
+    }
+
+    @Test public void testFromJSONObject() throws IOException {
+        final Extension ext = new Extension(ExtensionType.JSON, "a", 
ExtensionState.OPTIONAL);
+        ext.setJSON("{ \"min\" : 5, \"max\" : 20.1 }");
+
+        final Range entity = new Range();
+        entity.fromJSONObject(ext.getJSONStructure().asJsonObject());
+        assertEquals(5L, entity.getMin());
+        assertEquals(20.1, entity.getMax());
+    }
+
+    @Test public void testToJSONObject() throws IOException {
+        final Range entity = new Range();
+        entity.setMin(5);
+        entity.setMax(20.1);
+
+        final Extension ext = new Extension(ExtensionType.JSON, "a", 
ExtensionState.OPTIONAL);
+        ext.setJSON("{ \"min\" : 5, \"max\" : 20.1 }");
+
+        assertEquals(ext.getJSONStructure().asJsonObject(), 
entity.toJSONObject());
+    }
+}
\ No newline at end of file

Reply via email to