You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by da...@apache.org on 2018/04/27 09:51:26 UTC

[sling-org-apache-sling-feature] 06/22: Start changing start level handling to start order handling

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-org-apache-sling-feature.git

commit 062f90bcd89ccdfd684c30abdfef35ca6b647384
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Thu Jan 18 16:14:50 2018 +0100

    Start changing start level handling to start order handling
---
 .../java/org/apache/sling/feature/Artifact.java    |   3 +
 .../java/org/apache/sling/feature/Bundles.java     | 221 ++++++++++-----------
 .../java/org/apache/sling/feature/Feature.java     |   9 +-
 .../apache/sling/feature/process/BuilderUtil.java  |   4 +-
 .../java/org/apache/sling/feature/BundlesTest.java |  30 ++-
 .../sling/feature/process/BuilderUtilTest.java     |  64 ++++--
 .../sling/feature/process/FeatureBuilderTest.java  |  62 ++++--
 7 files changed, 219 insertions(+), 174 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/Artifact.java b/src/main/java/org/apache/sling/feature/Artifact.java
index 4fada27..6821e26 100644
--- a/src/main/java/org/apache/sling/feature/Artifact.java
+++ b/src/main/java/org/apache/sling/feature/Artifact.java
@@ -25,6 +25,9 @@ package org.apache.sling.feature;
  */
 public class Artifact implements Comparable<Artifact> {
 
+    /** This key might be used by bundles to define the start order. */
+    public static final String KEY_START_ORDER = "start-order";
+
     /** The artifact id. */
     private final ArtifactId id;
 
diff --git a/src/main/java/org/apache/sling/feature/Bundles.java b/src/main/java/org/apache/sling/feature/Bundles.java
index a359575..269d39f 100644
--- a/src/main/java/org/apache/sling/feature/Bundles.java
+++ b/src/main/java/org/apache/sling/feature/Bundles.java
@@ -18,60 +18,117 @@ package org.apache.sling.feature;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
-import java.util.NoSuchElementException;
 import java.util.TreeMap;
 
 /**
- * Bundles groups bundle {@code Artifact}s by start level.
+ * Bundles groups a list of bundles {@code Artifact} and provides a means
+ * to sort them based on start order.
  */
-public class Bundles implements Iterable<Map.Entry<Integer, Artifact>> {
+public class Bundles implements Iterable<Artifact> {
 
-    /** Map of bundles grouped by start level */
-    private final Map<Integer, List<Artifact>> startLevelMap = new TreeMap<>();
+    /** The list of bundles. */
+    private final List<Artifact> bundles = new ArrayList<>();
 
     /**
-     * Get the map of all bundles sorted by start level. The map is sorted
+     * Get the start order of a bundle.
+     * @param bundle The bundle
+     * @return The start order, if no start order is defined, {@code 0} is returned.
+     */
+    public static int getStartOrder(final Artifact bundle) {
+        final String order = bundle.getMetadata().get(Artifact.KEY_START_ORDER);
+        final int startOrder;
+        if ( order != null ) {
+            startOrder = Integer.parseInt(order);
+        } else {
+            startOrder = 0;
+        }
+
+        return startOrder;
+    }
+
+    /**
+     * Get the map of all bundles sorted by start order. The map is sorted
      * and iterating over the keys is done in start level order.
      * @return The map of bundles. The map is unmodifiable.
      */
-    public Map<Integer, List<Artifact>> getBundlesByStartLevel() {
-        return Collections.unmodifiableMap(this.startLevelMap);
+    public Map<Integer, List<Artifact>> getBundlesByStartOrder() {
+        final Map<Integer, List<Artifact>> startOrderMap = new TreeMap<>(new Comparator<Integer>() {
+
+            @Override
+            public int compare(final Integer o1, final Integer o2) {
+                if ( o1 == o2 ) {
+                    return 0;
+                }
+                if ( o1 == 0 ) {
+                    return 1;
+                }
+                if ( o2 == 0 ) {
+                    return -1;
+                }
+                return o1-o2;
+            }
+        });
+
+        for(final Artifact bundle : this.bundles) {
+            final int startOrder = getStartOrder(bundle);
+            List<Artifact> list = startOrderMap.get(startOrder);
+            if ( list == null ) {
+                list = new ArrayList<>();
+                startOrderMap.put(startOrder, list);
+            }
+            list.add(bundle);
+        }
+        return Collections.unmodifiableMap(startOrderMap);
+    }
+
+    public List<Map.Entry<Integer, Artifact>> getAllBundles() {
+        final List<Map.Entry<Integer, Artifact>> list = new ArrayList<>();
+        for(final Artifact a : this) {
+            list.add(new Map.Entry<Integer, Artifact>() {
+
+                @Override
+                public Artifact setValue(Artifact value) {
+                    return null;
+                }
+
+                @Override
+                public Artifact getValue() {
+                    // TODO Auto-generated method stub
+                    return a;
+                }
+
+                @Override
+                public Integer getKey() {
+                    return getStartOrder(a);
+                }
+            });
+        }
+        return list;
     }
 
     /**
-     * Add an artifact in the given start level.
-     * @param startLevel The start level
+     * Add an artifact as a bundle.
      * @param bundle The bundle
      */
-    public void add(final int startLevel, final Artifact bundle) {
-        List<Artifact> list = this.startLevelMap.get(startLevel);
-        if ( list == null ) {
-            list = new ArrayList<>();
-            this.startLevelMap.put(startLevel, list);
-        }
-        list.add(bundle);
+    public void add(final Artifact bundle) {
+        this.bundles.add(bundle);
     }
 
     /**
      * Remove the exact artifact.
-     * All start levels are searched for such an artifact. The first one found is removed.
+     * All start orders are searched for such an artifact. The first one found is removed.
      * @param id The artifact id
      * @return {@code true} if the artifact has been removed
      */
     public boolean removeExact(final ArtifactId id) {
-        for(final Map.Entry<Integer, List<Artifact>> entry : this.startLevelMap.entrySet()) {
-            for(final Artifact artifact : entry.getValue()) {
-                if ( artifact.getId().equals(id)) {
-                    entry.getValue().remove(artifact);
-                    if ( entry.getValue().isEmpty() ) {
-                        this.startLevelMap.remove(entry.getKey());
-                    }
-                    return true;
-                }
+        for(final Artifact artifact : this.bundles) {
+            if ( artifact.getId().equals(id)) {
+                this.bundles.remove(artifact);
+                return true;
             }
         }
         return false;
@@ -79,50 +136,46 @@ public class Bundles implements Iterable<Map.Entry<Integer, Artifact>> {
 
     /**
      * Remove the same artifact, neglecting the version.
-     * All start levels are searched for such an artifact. The first one found is removed.
+     * All start orders are searched for such an artifact. The first one found is removed.
      * @param id The artifact id
      * @return {@code true} if the artifact has been removed
      */
     public boolean removeSame(final ArtifactId id) {
-        for(final Map.Entry<Integer, List<Artifact>> entry : this.startLevelMap.entrySet()) {
-            for(final Artifact artifact : entry.getValue()) {
-                if ( artifact.getId().isSame(id)) {
-                    entry.getValue().remove(artifact);
-                    if ( entry.getValue().isEmpty() ) {
-                        this.startLevelMap.remove(entry.getKey());
-                    }
-                    return true;
-                }
+        for(final Artifact artifact : this.bundles) {
+            if ( artifact.getId().isSame(id)) {
+                this.bundles.remove(artifact);
+                return true;
             }
         }
         return false;
     }
 
     /**
-     * Clear the bundles map.
+     * Clear the bundles list.
      */
     public void clear() {
-        this.startLevelMap.clear();
+        this.bundles.clear();
     }
 
     /**
-     * Get start level and artifact for the given id, neglecting the version
+     * Get start order and artifact for the given id, neglecting the version
      * @param id The artifact id
-     * @return A map entry with start level and artifact, {@code null} otherwise
+     * @return A map entry with start order and artifact, {@code null} otherwise
      */
     public Map.Entry<Integer, Artifact> getSame(final ArtifactId id) {
-        for(final Map.Entry<Integer, Artifact> entry : this) {
-            if ( entry.getValue().getId().isSame(id)) {
+        for(final Artifact bundle : this) {
+            if ( bundle.getId().isSame(id)) {
+                final int startOrder = getStartOrder(bundle);
                 return new Map.Entry<Integer, Artifact>() {
 
                     @Override
                     public Integer getKey() {
-                        return entry.getKey();
+                        return startOrder;
                     }
 
                     @Override
                     public Artifact getValue() {
-                        return entry.getValue();
+                        return bundle;
                     }
 
                     @Override
@@ -141,8 +194,8 @@ public class Bundles implements Iterable<Map.Entry<Integer, Artifact>> {
      * @return {@code true} if the artifact exists
      */
     public boolean containsExact(final ArtifactId id) {
-        for(final Map.Entry<Integer, Artifact> entry : this) {
-            if ( entry.getValue().getId().equals(id)) {
+        for(final Artifact entry : this) {
+            if ( entry.getId().equals(id)) {
                 return true;
             }
         }
@@ -155,8 +208,8 @@ public class Bundles implements Iterable<Map.Entry<Integer, Artifact>> {
      * @return {@code true} if the artifact exists
      */
     public boolean containsSame(final ArtifactId id) {
-        for(final Map.Entry<Integer, Artifact> entry : this) {
-            if ( entry.getValue().getId().isSame(id)) {
+        for(final Artifact entry : this) {
+            if ( entry.getId().isSame(id)) {
                 return true;
             }
         }
@@ -167,74 +220,12 @@ public class Bundles implements Iterable<Map.Entry<Integer, Artifact>> {
      * Iterate over all bundles
      */
     @Override
-    public Iterator<Map.Entry<Integer, Artifact>> iterator() {
-        final Iterator<Map.Entry<Integer, List<Artifact>>> mainIter = this.startLevelMap.entrySet().iterator();
-        return new Iterator<Map.Entry<Integer,Artifact>>() {
-
-            private Map.Entry<Integer, Artifact> next = seek();
-
-            private Integer level;
-
-            private Iterator<Artifact> innerIter;
-
-            private Map.Entry<Integer, Artifact> seek() {
-                Map.Entry<Integer, Artifact> entry = null;
-                while ( this.innerIter != null || mainIter.hasNext() ) {
-                    if ( innerIter != null ) {
-                        if ( innerIter.hasNext() ) {
-                            final Artifact a = innerIter.next();
-                            final Integer l = this.level;
-                            entry = new Map.Entry<Integer, Artifact>() {
-
-                                @Override
-                                public Integer getKey() {
-                                    return l;
-                                }
-
-                                @Override
-                                public Artifact getValue() {
-                                    return a;
-                                }
-
-                                @Override
-                                public Artifact setValue(Artifact value) {
-                                    throw new UnsupportedOperationException();
-                                }
-                            };
-                            break;
-                        } else {
-                            innerIter = null;
-                        }
-                    } else {
-                        final Map.Entry<Integer, List<Artifact>> e = mainIter.next();
-                        this.level = e.getKey();
-                        this.innerIter = e.getValue().iterator();
-                    }
-                }
-                return entry;
-            }
-
-            @Override
-            public boolean hasNext() {
-                return this.next != null;
-            }
-
-            @Override
-            public Entry<Integer, Artifact> next() {
-                final Entry<Integer, Artifact> result = next;
-                if ( result == null ) {
-                    throw new NoSuchElementException();
-                }
-                this.next = seek();
-                return result;
-            }
-
-        };
+    public Iterator<Artifact> iterator() {
+        return Collections.unmodifiableList(this.bundles).iterator();
     }
 
     @Override
     public String toString() {
-        return "Bundles [" + this.startLevelMap
-                + "]";
+        return "Bundles " + this.bundles;
     }
 }
diff --git a/src/main/java/org/apache/sling/feature/Feature.java b/src/main/java/org/apache/sling/feature/Feature.java
index 3665689..f0f2cc5 100644
--- a/src/main/java/org/apache/sling/feature/Feature.java
+++ b/src/main/java/org/apache/sling/feature/Feature.java
@@ -19,7 +19,6 @@ package org.apache.sling.feature;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.List;
-import java.util.Map;
 
 /**
  * A feature consists of
@@ -305,11 +304,11 @@ public class Feature implements Comparable<Feature> {
         result.setAssembled(this.isAssembled());
 
         // bundles
-        for(final Map.Entry<Integer, Artifact> entry : this.getBundles()) {
-            final Artifact c = new Artifact(entry.getValue().getId());
-            c.getMetadata().putAll(entry.getValue().getMetadata());
+        for(final Artifact b : this.getBundles()) {
+            final Artifact c = new Artifact(b.getId());
+            c.getMetadata().putAll(b.getMetadata());
 
-            result.getBundles().add(entry.getKey(), c);
+            result.getBundles().add(c);
         }
 
         // configurations
diff --git a/src/main/java/org/apache/sling/feature/process/BuilderUtil.java b/src/main/java/org/apache/sling/feature/process/BuilderUtil.java
index 19c606c..1db7bf8 100644
--- a/src/main/java/org/apache/sling/feature/process/BuilderUtil.java
+++ b/src/main/java/org/apache/sling/feature/process/BuilderUtil.java
@@ -53,7 +53,7 @@ class BuilderUtil {
     static void mergeBundles(final Bundles target,
             final Bundles source,
             final ArtifactMerge artifactMergeAlg) {
-        for(final Map.Entry<Integer, List<Artifact>> entry : source.getBundlesByStartLevel().entrySet()) {
+        for(final Map.Entry<Integer, List<Artifact>> entry : source.getBundlesByStartOrder().entrySet()) {
             for(final Artifact a : entry.getValue()) {
                 // version handling - use provided algorithm
                 boolean replace = true;
@@ -65,7 +65,7 @@ class BuilderUtil {
                 }
                 if ( replace ) {
                     target.removeSame(a.getId());
-                    target.add(entry.getKey(), a);
+                    target.add(a);
                 }
             }
         }
diff --git a/src/test/java/org/apache/sling/feature/BundlesTest.java b/src/test/java/org/apache/sling/feature/BundlesTest.java
index 3346f19..59d87eb 100644
--- a/src/test/java/org/apache/sling/feature/BundlesTest.java
+++ b/src/test/java/org/apache/sling/feature/BundlesTest.java
@@ -18,6 +18,7 @@ package org.apache.sling.feature;
 
 import static org.junit.Assert.assertEquals;
 
+import java.util.List;
 import java.util.Map;
 
 import org.junit.Test;
@@ -27,19 +28,28 @@ public class BundlesTest {
     @Test
     public void testIterator() {
         final Bundles bundles = new Bundles();
-        bundles.add(1, new Artifact(ArtifactId.parse("1/a/1")));
-        bundles.add(5, new Artifact(ArtifactId.parse("5/a/5")));
-        bundles.add(5, new Artifact(ArtifactId.parse("5/b/6")));
-        bundles.add(2, new Artifact(ArtifactId.parse("2/b/2")));
-        bundles.add(2, new Artifact(ArtifactId.parse("2/a/3")));
-        bundles.add(4, new Artifact(ArtifactId.parse("4/x/4")));
+        bundles.add(createBundle("1/a/1", 1));
+        bundles.add(createBundle("5/a/5", 5));
+        bundles.add(createBundle("5/b/6", 5));
+        bundles.add(createBundle("2/b/2", 2));
+        bundles.add(createBundle("2/a/3", 2));
+        bundles.add(createBundle("4/x/4", 4));
 
         int index = 1;
-        for(final Map.Entry<Integer, Artifact> entry : bundles) {
-            assertEquals(entry.getKey().toString(), entry.getValue().getId().getGroupId());
-            assertEquals(index, entry.getValue().getId().getOSGiVersion().getMajor());
-            index++;
+        for(final Map.Entry<Integer, List<Artifact>> entry : bundles.getBundlesByStartOrder().entrySet()) {
+            for(final Artifact a : entry.getValue()) {
+                assertEquals(entry.getKey().toString(), a.getId().getGroupId());
+                assertEquals(index, a.getId().getOSGiVersion().getMajor());
+                index++;
+            }
         }
         assertEquals(7, index);
     }
+
+    public static Artifact createBundle(final String id, final int startOrder) {
+        final Artifact a = new Artifact(ArtifactId.parse(id));
+        a.getMetadata().put(Artifact.KEY_START_ORDER, String.valueOf(startOrder));
+
+        return a;
+    }
 }
diff --git a/src/test/java/org/apache/sling/feature/process/BuilderUtilTest.java b/src/test/java/org/apache/sling/feature/process/BuilderUtilTest.java
index a33ef95..42ce069 100644
--- a/src/test/java/org/apache/sling/feature/process/BuilderUtilTest.java
+++ b/src/test/java/org/apache/sling/feature/process/BuilderUtilTest.java
@@ -26,6 +26,7 @@ import java.util.Map;
 import org.apache.sling.feature.Artifact;
 import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Bundles;
+import org.apache.sling.feature.BundlesTest;
 import org.apache.sling.feature.process.BuilderUtil.ArtifactMerge;
 import org.junit.Test;
 
@@ -33,9 +34,28 @@ public class BuilderUtilTest {
 
     private List<Map.Entry<Integer, Artifact>> getBundles(final Bundles f) {
         final List<Map.Entry<Integer, Artifact>> result = new ArrayList<>();
-        for(final Map.Entry<Integer, Artifact> entry : f) {
-            result.add(entry);
+        for(final Map.Entry<Integer, List<Artifact>> entry : f.getBundlesByStartOrder().entrySet()) {
+            for(final Artifact artifact : entry.getValue()) {
+                result.add(new Map.Entry<Integer, Artifact>() {
+
+                    @Override
+                    public Integer getKey() {
+                        return entry.getKey();
+                    }
+
+                    @Override
+                    public Artifact getValue() {
+                        return artifact;
+                    }
+
+                    @Override
+                    public Artifact setValue(Artifact value) {
+                        return null;
+                    }
+                });
+            }
         }
+
         return result;
     }
 
@@ -53,14 +73,14 @@ public class BuilderUtilTest {
     @Test public void testMergeBundlesWithAlgHighest() {
         final Bundles target = new Bundles();
 
-        target.add(1, new Artifact(ArtifactId.parse("g/a/1.0")));
-        target.add(2, new Artifact(ArtifactId.parse("g/b/2.0")));
-        target.add(3, new Artifact(ArtifactId.parse("g/c/2.5")));
+        target.add(BundlesTest.createBundle("g/a/1.0", 1));
+        target.add(BundlesTest.createBundle("g/b/2.0", 2));
+        target.add(BundlesTest.createBundle("g/c/2.5", 3));
 
         final Bundles source = new Bundles();
-        source.add(1, new Artifact(ArtifactId.parse("g/a/1.1")));
-        source.add(2, new Artifact(ArtifactId.parse("g/b/1.9")));
-        source.add(3, new Artifact(ArtifactId.parse("g/c/2.5")));
+        source.add(BundlesTest.createBundle("g/a/1.1", 1));
+        source.add(BundlesTest.createBundle("g/b/1.9", 2));
+        source.add(BundlesTest.createBundle("g/c/2.5", 3));
 
         BuilderUtil.mergeBundles(target, source, ArtifactMerge.HIGHEST);
 
@@ -74,14 +94,14 @@ public class BuilderUtilTest {
     @Test public void testMergeBundlesWithAlgLatest() {
         final Bundles target = new Bundles();
 
-        target.add(1, new Artifact(ArtifactId.parse("g/a/1.0")));
-        target.add(2, new Artifact(ArtifactId.parse("g/b/2.0")));
-        target.add(3, new Artifact(ArtifactId.parse("g/c/2.5")));
+        target.add(BundlesTest.createBundle("g/a/1.0", 1));
+        target.add(BundlesTest.createBundle("g/b/2.0", 2));
+        target.add(BundlesTest.createBundle("g/c/2.5", 3));
 
         final Bundles source = new Bundles();
-        source.add(1, new Artifact(ArtifactId.parse("g/a/1.1")));
-        source.add(2, new Artifact(ArtifactId.parse("g/b/1.9")));
-        source.add(3, new Artifact(ArtifactId.parse("g/c/2.5")));
+        source.add(BundlesTest.createBundle("g/a/1.1", 1));
+        source.add(BundlesTest.createBundle("g/b/1.9", 2));
+        source.add(BundlesTest.createBundle("g/c/2.5", 3));
 
         BuilderUtil.mergeBundles(target, source, ArtifactMerge.LATEST);
 
@@ -95,10 +115,10 @@ public class BuilderUtilTest {
     @Test public void testMergeBundlesDifferentStartlevel() {
         final Bundles target = new Bundles();
 
-        target.add(1, new Artifact(ArtifactId.parse("g/a/1.0")));
+        target.add(BundlesTest.createBundle("g/a/1.0", 1));
 
         final Bundles source = new Bundles();
-        source.add(2, new Artifact(ArtifactId.parse("g/a/1.1")));
+        source.add(BundlesTest.createBundle("g/a/1.1", 2));
 
         BuilderUtil.mergeBundles(target, source, ArtifactMerge.LATEST);
 
@@ -110,14 +130,14 @@ public class BuilderUtilTest {
     @Test public void testMergeBundles() {
         final Bundles target = new Bundles();
 
-        target.add(1, new Artifact(ArtifactId.parse("g/a/1.0")));
-        target.add(2, new Artifact(ArtifactId.parse("g/b/2.0")));
-        target.add(3, new Artifact(ArtifactId.parse("g/c/2.5")));
+        target.add(BundlesTest.createBundle("g/a/1.0", 1));
+        target.add(BundlesTest.createBundle("g/b/2.0", 2));
+        target.add(BundlesTest.createBundle("g/c/2.5", 3));
 
         final Bundles source = new Bundles();
-        source.add(1, new Artifact(ArtifactId.parse("g/d/1.1")));
-        source.add(2, new Artifact(ArtifactId.parse("g/e/1.9")));
-        source.add(3, new Artifact(ArtifactId.parse("g/f/2.5")));
+        source.add(BundlesTest.createBundle("g/d/1.1", 1));
+        source.add(BundlesTest.createBundle("g/e/1.9", 2));
+        source.add(BundlesTest.createBundle("g/f/2.5", 3));
 
         BuilderUtil.mergeBundles(target, source, ArtifactMerge.LATEST);
 
diff --git a/src/test/java/org/apache/sling/feature/process/FeatureBuilderTest.java b/src/test/java/org/apache/sling/feature/process/FeatureBuilderTest.java
index 5ef1a62..4fc31b3 100644
--- a/src/test/java/org/apache/sling/feature/process/FeatureBuilderTest.java
+++ b/src/test/java/org/apache/sling/feature/process/FeatureBuilderTest.java
@@ -28,6 +28,7 @@ import java.util.Map;
 
 import org.apache.sling.feature.Artifact;
 import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.BundlesTest;
 import org.apache.sling.feature.Capability;
 import org.apache.sling.feature.Configuration;
 import org.apache.sling.feature.Extension;
@@ -46,11 +47,11 @@ public class FeatureBuilderTest {
         f1.getFrameworkProperties().put("foo", "2");
         f1.getFrameworkProperties().put("bar", "X");
 
-        f1.getBundles().add(3, new Artifact(ArtifactId.parse("org.apache.sling/foo-bar/4.5.6")));
-        f1.getBundles().add(5, new Artifact(ArtifactId.parse("group/testnewversion_low/2")));
-        f1.getBundles().add(5, new Artifact(ArtifactId.parse("group/testnewversion_high/2")));
-        f1.getBundles().add(5, new Artifact(ArtifactId.parse("group/testnewstartlevel/1")));
-        f1.getBundles().add(5, new Artifact(ArtifactId.parse("group/testnewstartlevelandversion/1")));
+        f1.getBundles().add(BundlesTest.createBundle("org.apache.sling/foo-bar/4.5.6", 3));
+        f1.getBundles().add(BundlesTest.createBundle("group/testnewversion_low/2", 5));
+        f1.getBundles().add(BundlesTest.createBundle("group/testnewversion_high/2", 5));
+        f1.getBundles().add(BundlesTest.createBundle("group/testnewstartlevel/1", 5));
+        f1.getBundles().add(BundlesTest.createBundle("group/testnewstartlevelandversion/1", 5));
 
         final Configuration c1 = new Configuration("org.apache.sling.foo");
         c1.getProperties().put("prop", "value");
@@ -69,9 +70,28 @@ public class FeatureBuilderTest {
 
     private List<Map.Entry<Integer, Artifact>> getBundles(final Feature f) {
         final List<Map.Entry<Integer, Artifact>> result = new ArrayList<>();
-        for(final Map.Entry<Integer, Artifact> entry : f.getBundles()) {
-            result.add(entry);
+        for(final Map.Entry<Integer, List<Artifact>> entry : f.getBundles().getBundlesByStartOrder().entrySet()) {
+            for(final Artifact artifact : entry.getValue()) {
+                result.add(new Map.Entry<Integer, Artifact>() {
+
+                    @Override
+                    public Integer getKey() {
+                        return entry.getKey();
+                    }
+
+                    @Override
+                    public Artifact getValue() {
+                        return artifact;
+                    }
+
+                    @Override
+                    public Artifact setValue(Artifact value) {
+                        return null;
+                    }
+                });
+            }
         }
+
         return result;
     }
 
@@ -194,11 +214,12 @@ public class FeatureBuilderTest {
         base.getFrameworkProperties().put("org.apache.felix.scr.directory", "launchpad/scr");
 
         final Artifact a1 = new Artifact(ArtifactId.parse("org.apache.sling/oak-server/1.0.0"));
+        a1.getMetadata().put(Artifact.KEY_START_ORDER, "1");
         a1.getMetadata().put("hash", "4632463464363646436");
-        base.getBundles().add(1, a1);
-        base.getBundles().add(1,  new Artifact(ArtifactId.parse("org.apache.sling/application-bundle/2.0.0")));
-        base.getBundles().add(1,  new Artifact(ArtifactId.parse("org.apache.sling/another-bundle/2.1.0")));
-        base.getBundles().add(2,  new Artifact(ArtifactId.parse("org.apache.sling/foo-xyz/1.2.3")));
+        base.getBundles().add(a1);
+        base.getBundles().add(BundlesTest.createBundle("org.apache.sling/application-bundle/2.0.0", 1));
+        base.getBundles().add(BundlesTest.createBundle("org.apache.sling/another-bundle/2.1.0", 1));
+        base.getBundles().add(BundlesTest.createBundle("org.apache.sling/foo-xyz/1.2.3", 2));
 
         final Configuration co1 = new Configuration("my.pid");
         co1.getProperties().put("foo", 5L);
@@ -237,15 +258,16 @@ public class FeatureBuilderTest {
         base.getFrameworkProperties().put("org.apache.felix.scr.directory", "launchpad/scr");
 
         final Artifact a1 = new Artifact(ArtifactId.parse("org.apache.sling/oak-server/1.0.0"));
+        a1.getMetadata().put(Artifact.KEY_START_ORDER, "1");
         a1.getMetadata().put("hash", "4632463464363646436");
-        base.getBundles().add(1, a1);
-        base.getBundles().add(1,  new Artifact(ArtifactId.parse("org.apache.sling/application-bundle/2.0.0")));
-        base.getBundles().add(1,  new Artifact(ArtifactId.parse("org.apache.sling/another-bundle/2.1.0")));
-        base.getBundles().add(2,  new Artifact(ArtifactId.parse("org.apache.sling/foo-xyz/1.2.3")));
-        base.getBundles().add(5,  new Artifact(ArtifactId.parse("group/testnewversion_low/1")));
-        base.getBundles().add(5,  new Artifact(ArtifactId.parse("group/testnewversion_high/5")));
-        base.getBundles().add(10,  new Artifact(ArtifactId.parse("group/testnewstartlevel/1")));
-        base.getBundles().add(10,  new Artifact(ArtifactId.parse("group/testnewstartlevelandversion/2")));
+        base.getBundles().add(a1);
+        base.getBundles().add(BundlesTest.createBundle("org.apache.sling/application-bundle/2.0.0", 1));
+        base.getBundles().add(BundlesTest.createBundle("org.apache.sling/another-bundle/2.1.0", 1));
+        base.getBundles().add(BundlesTest.createBundle("org.apache.sling/foo-xyz/1.2.3", 2));
+        base.getBundles().add(BundlesTest.createBundle("group/testnewversion_low/1", 5));
+        base.getBundles().add(BundlesTest.createBundle("group/testnewversion_high/5", 5));
+        base.getBundles().add(BundlesTest.createBundle("group/testnewstartlevel/1", 10));
+        base.getBundles().add(BundlesTest.createBundle("group/testnewstartlevelandversion/2", 10));
 
         final Configuration co1 = new Configuration("my.pid");
         co1.getProperties().put("foo", 5L);
@@ -263,7 +285,7 @@ public class FeatureBuilderTest {
         final Feature result = base.copy();
         result.getIncludes().remove(0);
         result.getFrameworkProperties().put("bar", "X");
-        result.getBundles().add(3,  new Artifact(ArtifactId.parse("org.apache.sling/foo-bar/4.5.6")));
+        result.getBundles().add(BundlesTest.createBundle("org.apache.sling/foo-bar/4.5.6", 3));
         final Configuration co3 = new Configuration("org.apache.sling.foo");
         co3.getProperties().put("prop", "value");
         result.getConfigurations().add(co3);

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.