You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2022/02/18 06:01:53 UTC

[sling-org-apache-sling-feature-extension-apiregions] 01/02: SLING-11151 : When configuration defauls are applied take excludes/includes into account

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

commit e8f284b6836000d3185b28dfb68e4a6afd97900f
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Fri Feb 18 06:59:18 2022 +0100

    SLING-11151 : When configuration defauls are applied take excludes/includes into account
---
 .../api/config/validation/FeatureValidator.java    | 86 +++++++++++++++++++++-
 .../validation/PropertyValidationResult.java       | 42 ++++++++++-
 .../api/config/validation/PropertyValidator.java   |  8 +-
 .../api/config/validation/package-info.java        |  2 +-
 .../config/validation/FeatureValidatorTest.java    | 47 ++++++++++++
 5 files changed, 181 insertions(+), 4 deletions(-)

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 9cc0658..ac89b6b 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
@@ -16,11 +16,18 @@
  */
 package org.apache.sling.feature.extension.apiregions.api.config.validation;
 
+import java.lang.reflect.Array;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Configuration;
@@ -32,6 +39,8 @@ import org.apache.sling.feature.extension.apiregions.api.config.FactoryConfigura
 import org.apache.sling.feature.extension.apiregions.api.config.FrameworkPropertyDescription;
 import org.apache.sling.feature.extension.apiregions.api.config.Operation;
 import org.apache.sling.feature.extension.apiregions.api.config.Region;
+import org.osgi.util.converter.Converter;
+import org.osgi.util.converter.Converters;
 
 /**
  * Validator to validate a feature
@@ -234,7 +243,82 @@ public class FeatureValidator {
                     final Configuration cfg = feature.getConfigurations().getConfiguration(entry.getKey());
                     if ( cfg != null ) {
                         if ( propEntry.getValue().getDefaultValue() == null ) {
-                            cfg.getProperties().remove(propEntry.getKey());
+                            if ( propEntry.getValue().getUseExcludes() != null || propEntry.getValue().getUseIncludes() != null ) {
+                                final List<String> includes = new ArrayList<>();
+                                final Set<String> excludes = new LinkedHashSet<>();
+                                if ( propEntry.getValue().getUseIncludes() != null ) {
+                                    for(final String v : propEntry.getValue().getUseIncludes()) {
+                                        includes.add(0, v);
+                                    }
+                                }
+                                if ( propEntry.getValue().getUseExcludes() != null ) {
+                                    for(final String v : propEntry.getValue().getUseExcludes()) {
+                                        excludes.add(v);
+                                    }
+                                }
+
+                                Object value = cfg.getProperties().get(propEntry.getKey());
+                                if ( value.getClass().isArray() ) {
+                                    // array
+                                    int l = Array.getLength(value);
+                                    int i = 0;
+                                    while ( i < l ) {
+                                        final String val = Array.get(value, i).toString();
+                                        if ( excludes.contains(val) ) {
+                                            final Object newArray = Array.newInstance(value.getClass().getComponentType(), l - 1);
+                                            int newIndex = 0;
+                                            for(int oldIndex = 0; oldIndex < l; oldIndex++) {
+                                                if ( oldIndex != i ) {
+                                                    Array.set(newArray, newIndex, Array.get(value, oldIndex));
+                                                    newIndex++;
+                                                }
+                                            }
+                                            value = newArray;
+                                            i--;
+                                            l--;
+                                            changed = true;
+                                            cfg.getProperties().put(propEntry.getKey(), value);
+                                        } else if ( includes.contains(val) ) {
+                                            includes.remove(val);
+                                        }
+                                        i++;
+                                    }
+                                    for(final String val : includes) {
+                                        final Object newArray = Array.newInstance(value.getClass().getComponentType(), Array.getLength(value) + 1);
+                                        System.arraycopy(value, 0, newArray, 1, Array.getLength(value));
+                                        Array.set(newArray, 0, 
+                                            Converters.standardConverter().convert(val).to(value.getClass().getComponentType()));
+                                        value = newArray;
+                                        cfg.getProperties().put(propEntry.getKey(), value);
+                                        changed = true;
+                                    }
+                                } else if ( value instanceof Collection ) { 
+                                    // collection
+                                    final Collection c = (Collection)value;
+                                    final Class collectionType = c.isEmpty() ? String.class : c.iterator().next().getClass();
+                                    final Iterator<?> i = c.iterator();
+                                    while ( i.hasNext() ) {
+                                        final String val = i.next().toString();
+                                        if ( excludes.contains(val) ) {
+                                            i.remove();
+                                            changed = true;
+                                        } else if ( includes.contains(val) ) {
+                                            includes.remove(val);
+                                        }
+                                    }
+                                    for(final String val : includes) {
+                                        final Object newValue = Converters.standardConverter().convert(val).to(collectionType);
+                                        if ( c instanceof List ) {
+                                            ((List)c).add(0, newValue);
+                                        } else {
+                                            c.add(newValue);
+                                        }
+                                        changed = true;
+                                    }
+                                }                    
+                            } else {
+                                cfg.getProperties().remove(propEntry.getKey());
+                            }
                         } else {
                             cfg.getProperties().put(propEntry.getKey(), propEntry.getValue().getDefaultValue());
                         }
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 b93680c..5ad4807 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 excludes/includes be used?
+     * @since 1.6
+     */
+    private String[] includes;
+
+    /**
+     * Should excludes/includes be used?
+     * @since 1.6
+     */
+    private String[] excludes;
+
     /** 
      * Should the default be used?
      * @since 1.2
@@ -120,5 +132,33 @@ public class PropertyValidationResult {
 	public void setDefaultValue(final Object defaultValue) {
 		this.defaultValue = defaultValue;
 	}
-    
+
+    /**
+     * Get the excludes to be used
+	 * @return The excludes or {@code null}
+     * @since 1.6
+	 */
+	public String[] getUseExcludes() {
+		return this.excludes;
+	}
+
+    /**
+     * Get the includes to be used
+	 * @return The includes or {@code null}
+     * @since 1.6
+	 */
+	public String[] getUseIncludes() {
+		return this.includes;
+	}
+
+    /**
+     * Set whether the excludes and includes should be used. At least one of it should not be {@code null}
+	 * @param includes The includes to use
+     * @param excludes The excludes to use
+     * @since 1.6
+	 */
+	public void setUseIncludesAndExcludes(final String[] includes, final String[] excludes) {
+		this.includes = includes;
+        this.excludes = excludes;
+	}
 }
\ 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 5617b9a..c8eeb73 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
@@ -168,7 +168,10 @@ public class PropertyValidator {
                 }
                 if ( !found ) {
                     setResult(context, desc, "Required included value " + inc + " not found");
-                }
+                    if ( context.result.isUseDefaultValue() ) {
+                        context.result.setUseIncludesAndExcludes(context.description.getIncludes(), context.description.getExcludes());
+                    }
+                 }
             }
         }
         if ( context.description.getExcludes() != null ) {
@@ -182,6 +185,9 @@ public class PropertyValidator {
                 }
                 if ( found ) {
                     setResult(context, desc, "Not allowed excluded value " + exc + " found");
+                    if ( context.result.isUseDefaultValue() ) {
+                        context.result.setUseIncludesAndExcludes(context.description.getIncludes(), context.description.getExcludes());
+                    }
                 }
             }
         }
diff --git a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/package-info.java b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/package-info.java
index 4f6c6e4..7e983c6 100644
--- a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/package-info.java
+++ b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/package-info.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-@org.osgi.annotation.versioning.Version("1.5.1")
+@org.osgi.annotation.versioning.Version("1.6.0")
 package org.apache.sling.feature.extension.apiregions.api.config.validation;
 
 
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 72670be..1f96eb2 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
@@ -16,11 +16,13 @@
  */
 package org.apache.sling.feature.extension.apiregions.api.config.validation;
 
+import static org.junit.Assert.assertArrayEquals;
 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;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
@@ -723,6 +725,15 @@ public class FeatureValidatorTest {
             cfg.getProperties().put("a", 1);
             cfg.getProperties().put("b", 1);
             cfg.getProperties().put("c", 1);
+            if ( i == 0 ) {
+                cfg.getProperties().put("d", new String[] {"a", "b", "c"});
+                cfg.getProperties().put("e", new Integer[] {1, 2, 3});    
+                cfg.getProperties().put("f", new int[] {1,2,3});
+            } else {
+                cfg.getProperties().put("d", new ArrayList<>(Arrays.asList("a", "b", "c")));
+                cfg.getProperties().put("e", new ArrayList<>(Arrays.asList(1,2,3)));
+                cfg.getProperties().put("f", new String[] {"1", "2", "3"});
+            }
             f.getConfigurations().add(cfg);
 
             final ConfigurationApi api = new ConfigurationApi();
@@ -739,9 +750,27 @@ public class FeatureValidatorTest {
             pdc.setRange(new Range());
             pdc.getRange().setMin(2);
             pdc.setDefaultValue(4);
+            final PropertyDescription pdd = new PropertyDescription();
+            pdd.setIncludes(new String[] {"a", "d"});
+            pdd.setExcludes(new String[] {"b", "e"});
+            final PropertyDescription pde = new PropertyDescription();
+            pde.setType(PropertyType.INTEGER);
+            pde.setIncludes(new String[] {"1", "4"});
+            pde.setExcludes(new String[] {"2", "5"});
+            final PropertyDescription pdf = new PropertyDescription();
+            pdf.setIncludes(new String[] {"1", "4"});
+            pdf.setExcludes(new String[] {"2", "5"});    
+            if ( i == 0 ) {
+                pdf.setType(PropertyType.INTEGER);
+            } else {
+                pdf.setDefaultValue(new String[] {"1", "4"});
+            }
             desc.getPropertyDescriptions().put("a", pda);
             desc.getPropertyDescriptions().put("b", pdb);
             desc.getPropertyDescriptions().put("c", pdc);
+            desc.getPropertyDescriptions().put("d", pdd);
+            desc.getPropertyDescriptions().put("e", pde);
+            desc.getPropertyDescriptions().put("f", pdf);
             api.getConfigurationDescriptions().put("org.apache.sling", desc);
 
             final FeatureValidationResult result = this.validator.validate(f, api);
@@ -751,12 +780,30 @@ public class FeatureValidatorTest {
             assertEquals(1, cfg.getConfigurationProperties().get("a"));
             assertEquals(1, cfg.getConfigurationProperties().get("b"));
             assertEquals(1, cfg.getConfigurationProperties().get("c"));
+            if ( i == 0 ) {
+                assertArrayEquals(new String[] {"a", "b", "c"}, (String[])cfg.getConfigurationProperties().get("d"));
+                assertArrayEquals(new Integer[] {1,2,3}, (Integer[])cfg.getConfigurationProperties().get("e"));    
+                assertArrayEquals(new int[] {1,2,3}, (int[])cfg.getConfigurationProperties().get("f"));    
+            } else {
+                assertEquals(Arrays.asList("a", "b", "c"), cfg.getConfigurationProperties().get("d"));
+                assertEquals(Arrays.asList(1,2,3), cfg.getConfigurationProperties().get("e"));    
+                assertArrayEquals(new String[] {"1", "2", "3"}, (String[])cfg.getConfigurationProperties().get("f"));
+            }
 
             // apply changes
             this.validator.applyDefaultValues(f, result);
             assertEquals(1, cfg.getConfigurationProperties().get("a"));
             assertNull(cfg.getConfigurationProperties().get("b"));
             assertEquals(4, cfg.getConfigurationProperties().get("c"));
+            if ( i == 0 ) {
+                assertArrayEquals(new String[] {"d", "a", "c"}, (String[])cfg.getConfigurationProperties().get("d"));
+                assertArrayEquals(new Integer[] {4,1,3}, (Integer[])cfg.getConfigurationProperties().get("e"));    
+                assertArrayEquals(new int[] {4,1,3}, (int[])cfg.getConfigurationProperties().get("f"));    
+            } else {
+                assertEquals(Arrays.asList("d", "a", "c"), cfg.getConfigurationProperties().get("d"));
+                assertEquals(Arrays.asList(4,1,3), cfg.getConfigurationProperties().get("e"));    
+                assertArrayEquals(new String[] {"1", "4"}, (String[])cfg.getConfigurationProperties().get("f"));
+            }
         }
     }