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

davidb pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git


The following commit(s) were added to refs/heads/master by this push:
     new 8b0fe89  SLING-7860 Enhance slingfeature-maven-plugin to aggregate 
multiple features into a single feature
8b0fe89 is described below

commit 8b0fe89d1c9753a3ee1be9958e3dd3daf7746e6f
Author: David Bosschaert <[email protected]>
AuthorDate: Fri Aug 31 13:58:37 2018 +0100

    SLING-7860 Enhance slingfeature-maven-plugin to aggregate multiple features 
into a single feature
    
    This commit ensures that the order in which non-wildcard features are
    processed in the order in which they are listed in the pom.
---
 .../feature/maven/mojos/AggregateFeatures.java     | 40 +++++++------
 .../feature/maven/mojos/AggregateFeaturesTest.java | 67 +++++++++++++++++++++-
 .../resources/aggregate-features/dir4/test_t.json  |  8 +++
 .../resources/aggregate-features/dir4/test_u.json  | 11 ++++
 .../resources/aggregate-features/dir4/test_v.json  | 11 ++++
 .../resources/aggregate-features/dir4/test_w.json  |  8 +++
 .../resources/aggregate-features/dir4/test_x.json  | 20 +++++++
 .../resources/aggregate-features/dir4/test_y.json  | 14 +++++
 .../resources/aggregate-features/dir4/test_z.json  |  8 +++
 9 files changed, 167 insertions(+), 20 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/feature/maven/mojos/AggregateFeatures.java 
b/src/main/java/org/apache/sling/feature/maven/mojos/AggregateFeatures.java
index 162910b..ca4f6cb 100644
--- a/src/main/java/org/apache/sling/feature/maven/mojos/AggregateFeatures.java
+++ b/src/main/java/org/apache/sling/feature/maven/mojos/AggregateFeatures.java
@@ -30,7 +30,6 @@ import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.repository.RepositorySystem;
 import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Feature;
-import org.apache.sling.feature.Include;
 import org.apache.sling.feature.builder.BuilderContext;
 import org.apache.sling.feature.builder.FeatureBuilder;
 import org.apache.sling.feature.builder.FeatureExtensionHandler;
@@ -44,17 +43,16 @@ import java.io.FileWriter;
 import java.io.IOException;
 import java.io.StringReader;
 import java.nio.file.Files;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.ServiceLoader;
-import java.util.Set;
 import java.util.Spliterator;
 import java.util.Spliterators;
-import java.util.stream.Collectors;
 import java.util.stream.StreamSupport;
 
 /**
@@ -92,14 +90,6 @@ public class AggregateFeatures extends AbstractFeatureMojo {
 
         Map<ArtifactId, Feature> featureMap = readFeatures(features, 
contextFeatures);
 
-        ArtifactId newFeatureID = new ArtifactId(project.getGroupId(), 
project.getArtifactId(),
-                project.getVersion(), classifier, 
FeatureConstants.PACKAGING_FEATURE);
-        Feature newFeature = new Feature(newFeatureID);
-        newFeature.getIncludes().addAll(
-                featureMap.keySet().stream()
-                .map(Include::new)
-                .collect(Collectors.toList()));
-
         BuilderContext builderContext = new BuilderContext(new 
FeatureProvider() {
             @Override
             public Feature provide(ArtifactId id) {
@@ -124,7 +114,9 @@ public class AggregateFeatures extends AbstractFeatureMojo {
                 ServiceLoader.load(FeatureExtensionHandler.class).iterator(), 
Spliterator.ORDERED), false)
                 .toArray(FeatureExtensionHandler[]::new));
 
-        Feature result = FeatureBuilder.assemble(newFeature, builderContext);
+        ArtifactId newFeatureID = new ArtifactId(project.getGroupId(), 
project.getArtifactId(),
+                project.getVersion(), classifier, 
FeatureConstants.PACKAGING_FEATURE);
+        Feature result = FeatureBuilder.assemble(newFeatureID, builderContext, 
featureMap.values().toArray(new Feature[] {}));
 
         try (FileWriter fileWriter = new FileWriter(new 
File(aggregatedFeaturesDir, classifier + ".json"))) {
             FeatureJSONWriter.write(fileWriter, result);
@@ -134,7 +126,7 @@ public class AggregateFeatures extends AbstractFeatureMojo {
     }
 
     private Map<ArtifactId, Feature> readFeatures(Collection<FeatureConfig> 
featureConfigs, Map<ArtifactId, Feature> contextFeatures) throws 
MojoExecutionException {
-        Map<ArtifactId, Feature> featureMap = new HashMap<>();
+        Map<ArtifactId, Feature> featureMap = new LinkedHashMap<>();
 
         try {
             for (FeatureConfig fc : featureConfigs) {
@@ -189,6 +181,7 @@ public class AggregateFeatures extends AbstractFeatureMojo {
     }
 
     private void readFeaturesFromDirectory(FeatureConfig fc, Map<ArtifactId, 
Feature> featureMap) throws IOException {
+        Map<String,Feature> readFeatures = new HashMap<>();
         Map<String,String> includes = new HashMap<>();
         Map<String,String> excludes = new HashMap<>();
 
@@ -202,7 +195,7 @@ public class AggregateFeatures extends AbstractFeatureMojo {
         nextFile:
         for (File f : new File(fc.location).listFiles()) {
             // First check that it is allowed as part of the includes
-            boolean matchesIncludes = includes.size() == 0;
+            boolean matchesIncludes = fc.includes.size() == 0;
 
             for (Iterator<String> it = includes.values().iterator(); 
it.hasNext(); ) {
                 String inc = it.next();
@@ -232,8 +225,19 @@ public class AggregateFeatures extends AbstractFeatureMojo 
{
             }
 
             Feature feat = readFeatureFromFile(f);
-            featureMap.put(feat.getId(), feat);
+            readFeatures.put(f.getName(), feat);
+        }
+
+        // Ordering:
+        // put the read features in the main featureMap, order the non-globbed 
ones as specified in the plugin
+        for (String inc : fc.includes) {
+            Feature feat = readFeatures.remove(inc);
+            if (feat != null) {
+                featureMap.put(feat.getId(), feat);
+            }
         }
+        // Put all the remaining features on the map
+        readFeatures.values().stream().forEach(f -> featureMap.put(f.getId(), 
f));
 
         // If there are any non-glob includes/excludes left, fail as the 
plugin is then incorrectly configured
         for (Map.Entry<String,String> i : includes.entrySet()) {
@@ -281,8 +285,8 @@ public class AggregateFeatures extends AbstractFeatureMojo {
     public static class FeatureConfig {
         // If the configuration is a directory
         String location;
-        Set<String> includes = new HashSet<>();
-        Set<String> excludes = new HashSet<>();
+        List<String> includes = new ArrayList<>();
+        List<String> excludes = new ArrayList<>();
 
         // If the configuration is an artifact
         String groupId;
diff --git 
a/src/test/java/org/apache/sling/feature/maven/mojos/AggregateFeaturesTest.java 
b/src/test/java/org/apache/sling/feature/maven/mojos/AggregateFeaturesTest.java
index 8e7b90e..72e9523 100644
--- 
a/src/test/java/org/apache/sling/feature/maven/mojos/AggregateFeaturesTest.java
+++ 
b/src/test/java/org/apache/sling/feature/maven/mojos/AggregateFeaturesTest.java
@@ -104,8 +104,8 @@ public class AggregateFeaturesTest {
         fc.setType("slingfeature");
         fc.setClassifier("clf1");
 
-        assertEquals(new HashSet<>(Arrays.asList("i1", "i2")), fc.includes);
-        assertEquals(Collections.singleton("e1"), fc.excludes);
+        assertEquals(Arrays.asList("i1", "i2"), fc.includes);
+        assertEquals(Collections.singletonList("e1"), fc.excludes);
 
         assertEquals("loc1", fc.location);
         assertEquals("gid1", fc.groupId);
@@ -304,6 +304,69 @@ public class AggregateFeaturesTest {
     }
 
     @Test
+    public void testIncludeOrdering() throws Exception {
+        File featuresDir = new File(
+                getClass().getResource("/aggregate-features/dir4").getFile());
+
+        FeatureConfig fc1 = new FeatureConfig();
+        fc1.setLocation(featuresDir.getAbsolutePath());
+        fc1.setIncludes("test_x.json");
+
+        FeatureConfig fc2 = new FeatureConfig();
+        fc2.setLocation(featuresDir.getAbsolutePath());
+        fc2.setIncludes("test_u.json");
+        fc2.setIncludes("test_y.json");
+        fc2.setIncludes("test_v.json");
+        fc2.setIncludes("test_z.json");
+
+        FeatureConfig fc3 = new FeatureConfig();
+        fc3.setLocation(featuresDir.getAbsolutePath());
+        fc3.setIncludes("test_t.json");
+
+        Build mockBuild = Mockito.mock(Build.class);
+        Mockito.when(mockBuild.getDirectory()).thenReturn(tempDir.toString());
+
+        MavenProject mockProj = Mockito.mock(MavenProject.class);
+        Mockito.when(mockProj.getBuild()).thenReturn(mockBuild);
+        Mockito.when(mockProj.getGroupId()).thenReturn("g");
+        Mockito.when(mockProj.getArtifactId()).thenReturn("a");
+        Mockito.when(mockProj.getVersion()).thenReturn("999");
+
+        AggregateFeatures af = new AggregateFeatures();
+        af.classifier = "agg";
+        af.features = Arrays.asList(fc1, fc2, fc3);
+        af.project = mockProj;
+
+        af.execute();
+
+        File expectedFile = new File(tempDir.toFile(), 
FeatureConstants.FEATURE_PROCESSED_LOCATION + "/agg.json");
+        try (Reader fr = new FileReader(expectedFile)) {
+            Feature genFeat = FeatureJSONReader.read(fr, null);
+            ArtifactId id = genFeat.getId();
+
+            assertEquals("g", id.getGroupId());
+            assertEquals("a", id.getArtifactId());
+            assertEquals("999", id.getVersion());
+            assertEquals("slingfeature", id.getType());
+            assertEquals("agg", id.getClassifier());
+
+            Map<String, Dictionary<String, Object>> expectedConfigs = new 
HashMap<>();
+            expectedConfigs.put("t.pid", new 
Hashtable<>(Collections.singletonMap("t", "t")));
+            expectedConfigs.put("u.pid", new 
Hashtable<>(Collections.singletonMap("u", "u")));
+            expectedConfigs.put("v.pid", new 
Hashtable<>(Collections.singletonMap("v", "v")));
+            expectedConfigs.put("x.pid", new 
Hashtable<>(Collections.singletonMap("x", "x")));
+            expectedConfigs.put("y.pid", new 
Hashtable<>(Collections.singletonMap("y", "y")));
+            expectedConfigs.put("z.pid", new 
Hashtable<>(Collections.singletonMap("z", "z")));
+
+            Map<String, Dictionary<String, Object>> actualConfigs = new 
HashMap<>();
+            for (org.apache.sling.feature.Configuration conf : 
genFeat.getConfigurations()) {
+                actualConfigs.put(conf.getPid(), conf.getProperties());
+            }
+            assertEquals(expectedConfigs, actualConfigs);
+        }
+    }
+
+    @Test
     public void testReadFeatureFromArtifact() throws Exception {
         File featureFile = new File(
                 
getClass().getResource("/aggregate-features/test_x.json").getFile());
diff --git a/src/test/resources/aggregate-features/dir4/test_t.json 
b/src/test/resources/aggregate-features/dir4/test_t.json
new file mode 100644
index 0000000..f459d53
--- /dev/null
+++ b/src/test/resources/aggregate-features/dir4/test_t.json
@@ -0,0 +1,8 @@
+{
+  "id":"test:t:9.9.9",
+  "configurations": {
+    "t.pid": {
+      "t": "t"
+    }
+  }
+}
diff --git a/src/test/resources/aggregate-features/dir4/test_u.json 
b/src/test/resources/aggregate-features/dir4/test_u.json
new file mode 100644
index 0000000..9f8ffb5
--- /dev/null
+++ b/src/test/resources/aggregate-features/dir4/test_u.json
@@ -0,0 +1,11 @@
+{
+  "id":"test:u:9.9.9",
+  "configurations": {
+    "u.pid": {
+      "u": "u"
+    },
+    "y.pid": {
+      "y": "u"
+    }
+  }
+}
diff --git a/src/test/resources/aggregate-features/dir4/test_v.json 
b/src/test/resources/aggregate-features/dir4/test_v.json
new file mode 100644
index 0000000..78269af
--- /dev/null
+++ b/src/test/resources/aggregate-features/dir4/test_v.json
@@ -0,0 +1,11 @@
+{
+  "id":"test:v:9.9.9",
+  "configurations": {
+    "v.pid": {
+      "v": "v"
+    },
+    "z.pid": {
+      "z": "v"
+    }
+  }
+}
diff --git a/src/test/resources/aggregate-features/dir4/test_w.json 
b/src/test/resources/aggregate-features/dir4/test_w.json
new file mode 100644
index 0000000..8cf9e79
--- /dev/null
+++ b/src/test/resources/aggregate-features/dir4/test_w.json
@@ -0,0 +1,8 @@
+{
+  "id":"test:w:9.9.9",
+  "configurations": {
+    "some.pid": {
+      "x": "z"
+    }
+  }
+}
diff --git a/src/test/resources/aggregate-features/dir4/test_x.json 
b/src/test/resources/aggregate-features/dir4/test_x.json
new file mode 100644
index 0000000..8df875b
--- /dev/null
+++ b/src/test/resources/aggregate-features/dir4/test_x.json
@@ -0,0 +1,20 @@
+{
+  "id":"test:x:9.9.9",
+  "configurations": {
+    "t.pid": {
+      "t": "x"
+    },
+    "v.pid": {
+      "v": "x"
+    },
+    "x.pid": {
+      "x": "x"
+    },    
+    "y.pid": {
+      "y": "x"
+    },
+    "z.pid": {
+      "z": "x"
+    }
+  }
+}
diff --git a/src/test/resources/aggregate-features/dir4/test_y.json 
b/src/test/resources/aggregate-features/dir4/test_y.json
new file mode 100644
index 0000000..4ce4e5e
--- /dev/null
+++ b/src/test/resources/aggregate-features/dir4/test_y.json
@@ -0,0 +1,14 @@
+{
+  "id":"test:y:9.9.9",
+  "configurations": {
+    "v.pid": {
+      "v": "y"
+    },
+    "y.pid": {
+      "y": "y"
+    },
+    "z.pid": {
+      "z": "y"
+    }
+  }
+}
diff --git a/src/test/resources/aggregate-features/dir4/test_z.json 
b/src/test/resources/aggregate-features/dir4/test_z.json
new file mode 100644
index 0000000..95103c5
--- /dev/null
+++ b/src/test/resources/aggregate-features/dir4/test_z.json
@@ -0,0 +1,8 @@
+{
+  "id":"test:z:1.0.1",
+  "configurations": {
+    "z.pid": {
+      "z": "z"
+    }
+  }
+}

Reply via email to