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

cziegeler pushed a commit to branch master
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/master by this push:
     new 7a2d220  SLING-10117 : Support different configuration validation modes
7a2d220 is described below

commit 7a2d2204406ecfb76a2df42732516138ee603696
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Sat Feb 13 12:33:16 2021 +0100

    SLING-10117 : Support different configuration validation modes
---
 .../apiregions/ConfigurationApiMergeHandler.java   |  4 ++
 .../config/validation/ConfigurationValidator.java  |  3 +
 .../api/config/validation/FeatureValidator.java    | 42 +++++++++++
 .../validation/PropertyValidationResult.java       | 51 ++++++++++++++
 .../api/config/validation/PropertyValidator.java   |  4 ++
 .../config/validation/FeatureValidatorTest.java    | 81 ++++++++++++++++++++++
 .../config/validation/PropertyValidatorTest.java   | 11 +++
 7 files changed, 196 insertions(+)

diff --git 
a/src/main/java/org/apache/sling/feature/extension/apiregions/ConfigurationApiMergeHandler.java
 
b/src/main/java/org/apache/sling/feature/extension/apiregions/ConfigurationApiMergeHandler.java
index 8a43382..082ee61 100644
--- 
a/src/main/java/org/apache/sling/feature/extension/apiregions/ConfigurationApiMergeHandler.java
+++ 
b/src/main/java/org/apache/sling/feature/extension/apiregions/ConfigurationApiMergeHandler.java
@@ -58,6 +58,7 @@ public class ConfigurationApiMergeHandler implements 
MergeHandler {
             // region merging
             if ( context.isInitialMerge() ) {
                 targetApi.setRegion(sourceApi.getRegion());
+                targetApi.setMode(sourceApi.getMode());
             } else {
                 // region merging is different for prototypes
                 if ( sourceApi.getRegion() != targetApi.getRegion() ) {
@@ -69,6 +70,9 @@ public class ConfigurationApiMergeHandler implements 
MergeHandler {
                         targetApi.setRegion(Region.GLOBAL);
                     }
                 }
+                if ( targetApi.getMode().ordinal() > 
sourceApi.getMode().ordinal() ) {
+                    targetApi.setMode(sourceApi.getMode());
+                }
             }
 
             // merge - but throw on duplicates
diff --git 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/ConfigurationValidator.java
 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/ConfigurationValidator.java
index f817e73..ced08c7 100644
--- 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/ConfigurationValidator.java
+++ 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/ConfigurationValidator.java
@@ -137,6 +137,9 @@ public class ConfigurationValidator {
         } else if ( validationMode == Mode.LENIENT || validationMode == 
Mode.DEFINITIVE ) {
             result.getWarnings().add(msg);
         }
+        if ( validationMode == Mode.DEFINITIVE || validationMode == 
Mode.SILENT_DEFINITIVE ) {
+            result.setUseDefaultValue(true);
+        }
     }
     
     private boolean isAllowedProperty(final String name) {
diff --git 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/FeatureValidator.java
 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/FeatureValidator.java
index 919511d..e26f773 100644
--- 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/FeatureValidator.java
+++ 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/FeatureValidator.java
@@ -159,6 +159,48 @@ public class FeatureValidator {
         return result;
     }
 
+    /**
+     * Apply default values from the result of a validation run.
+     * Defaults should be applied, if configuration properties are invalid and 
the validation mode
+     * for such a properties is definitive.
+     * @param feature The feature containing the configurations
+     * @param result The result
+     * @return {@code true} if a default value has been applied (the feature 
has been changed)
+     * @since 1.2
+     */
+    public boolean applyDefaultValues(final Feature feature, final 
FeatureValidationResult result) {
+        boolean changed = false;
+
+        for(final Map.Entry<String, ConfigurationValidationResult> entry : 
result.getConfigurationResults().entrySet()) {
+            for(final Map.Entry<String, PropertyValidationResult> propEntry : 
entry.getValue().getPropertyResults().entrySet()) {
+                if ( propEntry.getValue().isUseDefaultValue() ) {
+                    final Configuration cfg = 
feature.getConfigurations().getConfiguration(entry.getKey());
+                    if ( cfg != null ) {
+                        if ( propEntry.getValue().getDefaultValue() == null ) {
+                            cfg.getProperties().remove(propEntry.getKey());
+                        } else {
+                            cfg.getProperties().put(propEntry.getKey(), 
propEntry.getValue().getDefaultValue());
+                        }
+                        changed = true;
+                    }
+                }
+            }
+        }
+
+        for(final Map.Entry<String, PropertyValidationResult> propEntry : 
result.getFrameworkPropertyResults().entrySet()) {
+            if ( propEntry.getValue().isUseDefaultValue() ) {
+                if ( propEntry.getValue().getDefaultValue() == null ) {
+                    
feature.getFrameworkProperties().remove(propEntry.getKey());
+                } else {
+                    feature.getFrameworkProperties().put(propEntry.getKey(), 
propEntry.getValue().getDefaultValue().toString());
+                }
+                changed = true;
+            }
+        }
+
+        return changed;
+    }
+
     Region getConfigurationApiRegion(final ArtifactId id, final 
Map<ArtifactId, Region> cache) {
         Region result = cache.get(id);
         if ( result == null ) {
diff --git 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/PropertyValidationResult.java
 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/PropertyValidationResult.java
index e5bdbed..b93680c 100644
--- 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/PropertyValidationResult.java
+++ 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/PropertyValidationResult.java
@@ -31,6 +31,18 @@ public class PropertyValidationResult {
 
     private boolean skipped = false;
 
+    /** 
+     * Should the default be used?
+     * @since 1.2
+     */
+    private boolean useDefault = false;
+
+    /**
+     * The default value
+     * @since 1.2
+     */
+    private Object defaultValue;
+
     /**
      * Is the property value valid?
      * @return {@code true} if the value is valid
@@ -70,4 +82,43 @@ public class PropertyValidationResult {
     public void markSkipped() {
         this.skipped = true;
     }
+
+       /**
+     * Should the default be used instead of the configuration value?
+        * @return {@code true} if the default should be used.
+     * @see #getDefaultValue()
+     * @since 1.2
+        */
+       public boolean isUseDefaultValue() {
+               return useDefault;
+       }
+
+       /**
+     * Set whether the default value should be used
+        * @param useDefault boolean flag
+     * @since 1.2
+        */
+       public void setUseDefaultValue(final boolean useDefault) {
+               this.useDefault = useDefault;
+       }
+
+       /**
+     * Get the default value. The default value is only returned
+     * if {@link #isUseDefaultValue()} returns {@code true}.
+        * @return the defaultValue (it might be {@code null})
+     * @since 1.2
+        */
+       public Object getDefaultValue() {
+               return defaultValue;
+       }
+
+       /**
+     * Set the default value
+        * @param defaultValue the defaultValue to set
+     * @since 1.2
+        */
+       public void setDefaultValue(final Object defaultValue) {
+               this.defaultValue = defaultValue;
+       }
+    
 }
\ No newline at end of file
diff --git 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/PropertyValidator.java
 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/PropertyValidator.java
index b643d9d..6cfc4f1 100644
--- 
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/PropertyValidator.java
+++ 
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/PropertyValidator.java
@@ -103,6 +103,10 @@ public class PropertyValidator {
         } else if ( context.validationMode == Mode.LENIENT || 
context.validationMode == Mode.DEFINITIVE ) {
             context.result.getWarnings().add(msg);
         }
+        if ( context.validationMode == Mode.DEFINITIVE || 
context.validationMode == Mode.SILENT_DEFINITIVE ) {
+            context.result.setUseDefaultValue(true);
+            
context.result.setDefaultValue(context.description.getDefaultValue());
+        }
     }
 
     /**
diff --git 
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/validation/FeatureValidatorTest.java
 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/validation/FeatureValidatorTest.java
index 3bd6d6b..20330cc 100644
--- 
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/validation/FeatureValidatorTest.java
+++ 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/validation/FeatureValidatorTest.java
@@ -37,9 +37,11 @@ import 
org.apache.sling.feature.extension.apiregions.api.config.ConfigurationApi
 import 
org.apache.sling.feature.extension.apiregions.api.config.ConfigurationDescription;
 import 
org.apache.sling.feature.extension.apiregions.api.config.FactoryConfigurationDescription;
 import 
org.apache.sling.feature.extension.apiregions.api.config.FrameworkPropertyDescription;
+import org.apache.sling.feature.extension.apiregions.api.config.Mode;
 import org.apache.sling.feature.extension.apiregions.api.config.Operation;
 import 
org.apache.sling.feature.extension.apiregions.api.config.PropertyDescription;
 import org.apache.sling.feature.extension.apiregions.api.config.PropertyType;
+import org.apache.sling.feature.extension.apiregions.api.config.Range;
 import org.apache.sling.feature.extension.apiregions.api.config.Region;
 import org.junit.Before;
 import org.junit.Test;
@@ -713,4 +715,83 @@ public class FeatureValidatorTest {
         FeatureValidationResult result = validator.validate(feature);
         assertTrue(result.isValid());
     }
+
+    @Test public void testDefinitiveModeForConfigurationProperties() {
+        for(int i=0; i<2;i++) {
+            final Feature f = new Feature(ArtifactId.parse("g:a:1"));
+            final Configuration cfg = new Configuration("org.apache.sling");
+            cfg.getProperties().put("a", 1);
+            cfg.getProperties().put("b", 1);
+            cfg.getProperties().put("c", 1);
+            f.getConfigurations().add(cfg);
+
+            final ConfigurationApi api = new ConfigurationApi();
+            api.setMode(i == 0 ? Mode.DEFINITIVE : Mode.SILENT_DEFINITIVE);
+            final ConfigurationDescription desc = new 
ConfigurationDescription();
+            final PropertyDescription pda = new PropertyDescription();
+            pda.setType(PropertyType.INTEGER);
+            final PropertyDescription pdb = new PropertyDescription();
+            pdb.setType(PropertyType.INTEGER);
+            pdb.setRange(new Range());
+            pdb.getRange().setMin(2);
+            final PropertyDescription pdc = new PropertyDescription();
+            pdc.setType(PropertyType.INTEGER);
+            pdc.setRange(new Range());
+            pdc.getRange().setMin(2);
+            pdc.setDefaultValue(4);
+            desc.getPropertyDescriptions().put("a", pda);
+            desc.getPropertyDescriptions().put("b", pdb);
+            desc.getPropertyDescriptions().put("c", pdc);
+            api.getConfigurationDescriptions().put("org.apache.sling", desc);
+
+            final FeatureValidationResult result = this.validator.validate(f, 
api);
+            assertTrue(result.isValid());
+
+            // values have not changed
+            assertEquals(1, cfg.getConfigurationProperties().get("a"));
+            assertEquals(1, cfg.getConfigurationProperties().get("b"));
+            assertEquals(1, cfg.getConfigurationProperties().get("c"));
+
+            // apply changes
+            this.validator.applyDefaultValues(f, result);
+            assertEquals(1, cfg.getConfigurationProperties().get("a"));
+            assertNull(cfg.getConfigurationProperties().get("b"));
+            assertEquals(4, cfg.getConfigurationProperties().get("c"));
+        }
+    }
+
+    @Test public void testDefinitiveModeForFrameworkProperties() {
+        for(int i=0; i<2;i++) {
+            final Feature f = new Feature(ArtifactId.parse("g:a:1"));
+            f.getFrameworkProperties().put("a", "hello");
+            f.getFrameworkProperties().put("b", "world");
+            f.getFrameworkProperties().put("c", "world");
+
+            final ConfigurationApi api = new ConfigurationApi();
+            api.setMode(i == 0 ? Mode.DEFINITIVE : Mode.SILENT_DEFINITIVE);
+            final FrameworkPropertyDescription pda = new 
FrameworkPropertyDescription();
+            final FrameworkPropertyDescription pdb = new 
FrameworkPropertyDescription();
+            pdb.setRegex("h(.*)");
+            final FrameworkPropertyDescription pdc = new 
FrameworkPropertyDescription();
+            pdc.setRegex("h(.*)");
+            pdc.setDefaultValue("hi");
+            api.getFrameworkPropertyDescriptions().put("a", pda);
+            api.getFrameworkPropertyDescriptions().put("b", pdb);
+            api.getFrameworkPropertyDescriptions().put("c", pdc);
+
+            final FeatureValidationResult result = this.validator.validate(f, 
api);
+            assertTrue(result.isValid());
+
+            // values have not changed
+            assertEquals("hello", f.getFrameworkProperties().get("a"));
+            assertEquals("world", f.getFrameworkProperties().get("b"));
+            assertEquals("world", f.getFrameworkProperties().get("c"));
+
+            // apply changes
+            this.validator.applyDefaultValues(f, result);
+            assertEquals("hello", f.getFrameworkProperties().get("a"));
+            assertNull(f.getFrameworkProperties().get("b"));
+            assertEquals("hi", f.getFrameworkProperties().get("c"));
+        }
+    }
 }
diff --git 
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/validation/PropertyValidatorTest.java
 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/validation/PropertyValidatorTest.java
index b2803f4..f62b9e9 100644
--- 
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/validation/PropertyValidatorTest.java
+++ 
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/validation/PropertyValidatorTest.java
@@ -18,6 +18,7 @@ package 
org.apache.sling.feature.extension.apiregions.api.config.validation;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import java.util.ArrayList;
@@ -71,12 +72,16 @@ public class PropertyValidatorTest {
         assertEquals(errors, result.getWarnings().size());
         assertTrue(result.isValid());
         assertFalse(result.isSkipped());
+        assertTrue(result.isUseDefaultValue());
+        assertEquals(result.getDefaultValue(), prop.getDefaultValue());
 
         // error - mode silent definitive 
         result = validator.validate(value, prop, Mode.SILENT_DEFINITIVE);
         assertTrue(result.getWarnings().isEmpty());
         assertTrue(result.isValid());
         assertFalse(result.isSkipped());
+        assertTrue(result.isUseDefaultValue());
+        assertEquals(result.getDefaultValue(), prop.getDefaultValue());
     }
 
     /**
@@ -87,6 +92,8 @@ public class PropertyValidatorTest {
         assertTrue(result.isValid());
         assertFalse(result.isSkipped());
         assertTrue(result.getErrors().isEmpty());
+        assertFalse(result.isUseDefaultValue());
+        assertNull(result.getDefaultValue());
     }
 
     @Test public void testValidateWithNull() {
@@ -309,6 +316,10 @@ public class PropertyValidatorTest {
         validateValid(prop, "hello world");
 
         validateError(prop, "world");
+
+        // apply default
+        prop.setDefaultValue("hello world");
+        validateError(prop, "world");
     }
 
     @Test public void testValidateOptions() {

Reply via email to