Author: cziegeler
Date: Fri Jul 28 13:00:31 2017
New Revision: 1803271

URL: http://svn.apache.org/viewvc?rev=1803271&view=rev
Log:
Start implementing upgrade handling, add initial tests for feature assembling

Added:
    
sling/whiteboard/cziegeler/feature/src/test/java/org/apache/sling/feature/process/
    
sling/whiteboard/cziegeler/feature/src/test/java/org/apache/sling/feature/process/FeatureBuilderTest.java
   (with props)
    sling/whiteboard/cziegeler/feature/src/test/resources/features/process/
    
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/base.json
   (with props)
    
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/g-a-1.json
   (with props)
    
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/include-1.json
   (with props)
    
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/result-1.json
   (with props)
Modified:
    
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Feature.java
    
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Requirement.java
    
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONReader.java
    
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONWriter.java
    
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/JSONConstants.java
    
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureBuilder.java

Modified: 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Feature.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Feature.java?rev=1803271&r1=1803270&r2=1803271&view=diff
==============================================================================
--- 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Feature.java
 (original)
+++ 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Feature.java
 Fri Jul 28 13:00:31 2017
@@ -66,8 +66,15 @@ public class Feature implements Comparab
     /** The optional license. */
     private volatile String license;
 
+    /** Is this an upgrade of another feature? */
+    private volatile ArtifactId upgradeOf;
+
+    /** Flag indicating whether this is an assembled feature */
     private volatile boolean assembled = false;
 
+    /** Contained upgrades (this is usually only set for assembled features*/
+    private final List<ArtifactId> upgrades = new ArrayList<>();
+
     /**
      * Construct a new feature.
      * @param id The id of the feature.
@@ -170,6 +177,18 @@ public class Feature implements Comparab
         this.license = license;
     }
 
+    public void setUpgradeOf(final ArtifactId id) {
+        this.upgradeOf = id;
+    }
+
+    public ArtifactId getUpgradeOf() {
+        return this.upgradeOf;
+    }
+
+    public List<ArtifactId> getUpgrades() {
+        return this.upgrades;
+    }
+
     public boolean isAssembled() {
         return assembled;
     }
@@ -183,7 +202,11 @@ public class Feature implements Comparab
      * @return A copy of the feature
      */
     public Feature copy() {
-        final Feature result = new Feature(this.getId());
+        return copy(this.getId());
+    }
+
+    public Feature copy(final ArtifactId id) {
+        final Feature result = new Feature(id);
 
         // metadata
         result.setLocation(this.getLocation());

Modified: 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Requirement.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Requirement.java?rev=1803271&r1=1803270&r2=1803271&view=diff
==============================================================================
--- 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Requirement.java
 (original)
+++ 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Requirement.java
 Fri Jul 28 13:00:31 2017
@@ -75,9 +75,9 @@ public class Requirement {
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + ((attributes == null) ? 0 : 
attributes.hashCode());
-        result = prime * result + ((directives == null) ? 0 : 
directives.hashCode());
-        result = prime * result + ((namespace == null) ? 0 : 
namespace.hashCode());
+        result = prime * result + attributes.hashCode();
+        result = prime * result + directives.hashCode();
+        result = prime * result + namespace.hashCode();
         return result;
     }
 
@@ -89,21 +89,12 @@ public class Requirement {
             return false;
         if (getClass() != obj.getClass())
             return false;
-        Requirement other = (Requirement) obj;
-        if (attributes == null) {
-            if (other.attributes != null)
-                return false;
-        } else if (!attributes.equals(other.attributes))
+        final Requirement other = (Requirement) obj;
+        if (!attributes.equals(other.attributes))
             return false;
-        if (directives == null) {
-            if (other.directives != null)
-                return false;
-        } else if (!directives.equals(other.directives))
+        if (!directives.equals(other.directives))
             return false;
-        if (namespace == null) {
-            if (other.namespace != null)
-                return false;
-        } else if (!namespace.equals(other.namespace))
+        if (!namespace.equals(other.namespace))
             return false;
         return true;
     }

Modified: 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONReader.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONReader.java?rev=1803271&r1=1803270&r2=1803271&view=diff
==============================================================================
--- 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONReader.java
 (original)
+++ 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONReader.java
 Fri Jul 28 13:00:31 2017
@@ -131,6 +131,22 @@ public class FeatureJSONReader extends J
         this.readRequirements(map);
         this.readIncludes(map);
 
+        if ( map.containsKey(JSONConstants.FEATURE_UPGRADEOF) ) {
+            final Object idObj = map.get(JSONConstants.FEATURE_UPGRADEOF);
+            checkType(JSONConstants.FEATURE_UPGRADEOF, idObj, String.class);
+            this.feature.setUpgradeOf(ArtifactId.fromMvnId(idObj.toString()));
+        }
+        if ( map.containsKey(JSONConstants.FEATURE_UPGRADES) ) {
+            final Object listObj = map.get(JSONConstants.FEATURE_UPGRADES);
+            checkType(JSONConstants.FEATURE_UPGRADES, listObj, List.class);
+            @SuppressWarnings("unchecked")
+            final List<Object> list = (List<Object>) listObj;
+            for(final Object element : list) {
+                checkType(JSONConstants.FEATURE_UPGRADES, element, 
String.class);
+                
feature.getUpgrades().add(ArtifactId.fromMvnId(element.toString()));
+            }
+
+        }
         this.readExtensions(map,
                 JSONConstants.FEATURE_KNOWN_PROPERTIES,
                 this.feature.getExtensions(), 
this.feature.getConfigurations());

Modified: 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONWriter.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONWriter.java?rev=1803271&r1=1803270&r2=1803271&view=diff
==============================================================================
--- 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONWriter.java
 (original)
+++ 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONWriter.java
 Fri Jul 28 13:00:31 2017
@@ -70,6 +70,20 @@ public class FeatureJSONWriter extends J
         writeProperty(w, JSONConstants.FEATURE_VENDOR, feature.getVendor());
         writeProperty(w, JSONConstants.FEATURE_LICENSE, feature.getLicense());
 
+        // upgradeOf
+        if ( feature.getUpgradeOf() != null ) {
+            writeProperty(w, JSONConstants.FEATURE_UPGRADEOF, 
feature.getUpgradeOf().toMvnId());
+        }
+
+        // upgrades
+        if ( !feature.getUpgrades().isEmpty() ) {
+            w.writeStartArray(JSONConstants.FEATURE_UPGRADES);
+            for(final ArtifactId id : feature.getUpgrades()) {
+                w.write(id.toMvnId());
+            }
+            w.writeEnd();
+        }
+
         // includes
         if ( !feature.getIncludes().isEmpty() ) {
             w.writeStartArray(JSONConstants.FEATURE_INCLUDES);

Modified: 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/JSONConstants.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/JSONConstants.java?rev=1803271&r1=1803270&r2=1803271&view=diff
==============================================================================
--- 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/JSONConstants.java
 (original)
+++ 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/JSONConstants.java
 Fri Jul 28 13:00:31 2017
@@ -45,6 +45,10 @@ public abstract class JSONConstants {
 
     public static final String FEATURE_LICENSE = "license";
 
+    public static final String FEATURE_UPGRADES = "upgrades";
+
+    public static final String FEATURE_UPGRADEOF = "upgradeOf";
+
     public static final List<String> FEATURE_KNOWN_PROPERTIES = 
Arrays.asList(FEATURE_ID,
             FEATURE_BUNDLES,
             FEATURE_FRAMEWORK_PROPERTIES,
@@ -55,7 +59,9 @@ public abstract class JSONConstants {
             FEATURE_TITLE,
             FEATURE_DESCRIPTION,
             FEATURE_VENDOR,
-            FEATURE_LICENSE);
+            FEATURE_LICENSE,
+            FEATURE_UPGRADES,
+            FEATURE_UPGRADEOF);
 
     public static final String ARTIFACT_ID = "id";
 

Modified: 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureBuilder.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureBuilder.java?rev=1803271&r1=1803270&r2=1803271&view=diff
==============================================================================
--- 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureBuilder.java
 (original)
+++ 
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureBuilder.java
 Fri Jul 28 13:00:31 2017
@@ -65,105 +65,53 @@ public class FeatureBuilder {
         processedFeatures.add(feature.getId().toMvnId());
 
         // we copy the feature as we set the assembled flag on the result
-        final Feature result = feature.copy();
-        if ( !feature.getIncludes().isEmpty() ) {
+        final Feature result;
+
+        if ( feature.getUpgradeOf() != null ) {
+            Include found = null;
+            for(final Include inc : feature.getIncludes()) {
+                if ( inc.getId().equals(feature.getUpgradeOf()) ) {
+                    found = inc;
+                    break;
+                }
+            }
+
+            result = feature.copy(feature.getUpgradeOf());
+
+            // add base as the first include
+            if ( found == null ) {
+                result.getIncludes().add(0, new 
Include(feature.getUpgradeOf()));
+            } else {
+                result.getIncludes().remove(found);
+                result.getIncludes().add(0, found);
+            }
+            result.getUpgrades().add(feature.getId());
+        } else {
+            result = feature.copy();
+        }
+
+        if ( !result.getIncludes().isEmpty() ) {
+
+            final List<Include> includes = new 
ArrayList<>(result.getIncludes());
 
             // clear everything in the result, will be added in the process
-            feature.getBundles().clear();
-            feature.getFrameworkProperties().clear();
-            feature.getConfigurations().clear();
-            feature.getRequirements().clear();
-            feature.getCapabilities().clear();
-            feature.getIncludes().clear();
-            feature.getExtensions().clear();
+            result.getBundles().clear();
+            result.getFrameworkProperties().clear();
+            result.getConfigurations().clear();
+            result.getRequirements().clear();
+            result.getCapabilities().clear();
+            result.getIncludes().clear();
+            result.getExtensions().clear();
 
-            for(final Include i : feature.getIncludes()) {
+            for(final Include i : includes) {
                 final Feature f = provider.provide(i.getId());
                 if ( f == null ) {
                     throw new IllegalStateException("Unable to find included 
feature " + i.getId());
                 }
-                final Feature af = internalAssemble(processedFeatures, 
feature, provider);
-
-                // process removals
-                // bundles
-                for(final ArtifactId a : i.getBundleRemovals()) {
-                    af.getBundles().removeExact(a);
-                    final Iterator<Configuration> iter = 
af.getConfigurations().iterator();
-                    while ( iter.hasNext() ) {
-                        final Configuration cfg = iter.next();
-                        final String bundleId = 
(String)cfg.getProperties().get(Configuration.PROP_ARTIFACT);
-                        if ( a.toMvnId().equals(bundleId) ) {
-                            iter.remove();
-                        }
-                    }
-                }
-                // configurations
-                for(final String c : i.getConfigurationRemovals()) {
-                    final int attrPos = c.indexOf('@');
-                    final String val = (attrPos == -1 ? c : c.substring(0, 
attrPos));
-                    final String attr = (attrPos == -1 ? null : 
c.substring(attrPos + 1));
-
-                    final int sepPos = val.indexOf('~');
-                    Configuration found = null;
-                    if ( sepPos == -1 ) {
-                        for(final Configuration cfg : af.getConfigurations()) {
-                            if ( !cfg.isFactoryConfiguration() && 
val.equals(cfg.getPid()) ) {
-                                found = cfg;
-                                break;
-                            }
-                        }
+                final Feature af = internalAssemble(processedFeatures, f, 
provider);
 
-                    } else {
-                        final String factoryPid = val.substring(0, sepPos);
-                        final String name = val.substring(sepPos + 1);
-
-                        for(final Configuration cfg : af.getConfigurations()) {
-                            if ( cfg.isFactoryConfiguration()
-                                 && factoryPid.equals(cfg.getFactoryPid())
-                                 && name.equals(cfg.getName()) ) {
-                                found = cfg;
-                                break;
-                            }
-                        }
-                    }
-                    if ( found != null ) {
-                        if ( attr == null ) {
-                            af.getConfigurations().remove(found);
-                        } else {
-                            found.getProperties().remove(attr);
-                        }
-                    }
-                }
-
-                // framework properties
-                for(final String p : i.getFrameworkPropertiesRemovals()) {
-                    af.getFrameworkProperties().remove(p);
-                }
-
-                // extensions
-                for(final String name : i.getExtensionRemovals()) {
-                    for(final Extension ext : af.getExtensions()) {
-                        if ( ext.getName().equals(name) ) {
-                            af.getExtensions().remove(ext);
-                            break;
-                        }
-                    }
-                }
-                for(final Map.Entry<String, List<ArtifactId>> entry : 
i.getArtifactExtensionRemovals().entrySet()) {
-                    for(final Extension ext : af.getExtensions()) {
-                        if ( ext.getName().equals(entry.getKey()) ) {
-                            for(final ArtifactId id : entry.getValue() ) {
-                                for(final Artifact a : ext.getArtifacts()) {
-                                    if ( a.getId().equals(id) ) {
-                                        ext.getArtifacts().remove(a);
-                                        break;
-                                    }
-                                }
-                            }
-                            break;
-                        }
-                    }
-                }
+                // process include instructions
+                include(af, i);
 
                 // and now merge
                 merge(result, af);
@@ -303,5 +251,88 @@ public class FeatureBuilder {
                 }
             }
         }
+    }
+
+    private static void include(final Feature base, final Include i) {
+        // process removals
+        // bundles
+        for(final ArtifactId a : i.getBundleRemovals()) {
+            base.getBundles().removeExact(a);
+            final Iterator<Configuration> iter = 
base.getConfigurations().iterator();
+            while ( iter.hasNext() ) {
+                final Configuration cfg = iter.next();
+                final String bundleId = 
(String)cfg.getProperties().get(Configuration.PROP_ARTIFACT);
+                if ( a.toMvnId().equals(bundleId) ) {
+                    iter.remove();
+                }
+            }
+        }
+        // configurations
+        for(final String c : i.getConfigurationRemovals()) {
+            final int attrPos = c.indexOf('@');
+            final String val = (attrPos == -1 ? c : c.substring(0, attrPos));
+            final String attr = (attrPos == -1 ? null : c.substring(attrPos + 
1));
+
+            final int sepPos = val.indexOf('~');
+            Configuration found = null;
+            if ( sepPos == -1 ) {
+                for(final Configuration cfg : base.getConfigurations()) {
+                    if ( !cfg.isFactoryConfiguration() && 
val.equals(cfg.getPid()) ) {
+                        found = cfg;
+                        break;
+                    }
+                }
+
+            } else {
+                final String factoryPid = val.substring(0, sepPos);
+                final String name = val.substring(sepPos + 1);
+
+                for(final Configuration cfg : base.getConfigurations()) {
+                    if ( cfg.isFactoryConfiguration()
+                         && factoryPid.equals(cfg.getFactoryPid())
+                         && name.equals(cfg.getName()) ) {
+                        found = cfg;
+                        break;
+                    }
+                }
+            }
+            if ( found != null ) {
+                if ( attr == null ) {
+                    base.getConfigurations().remove(found);
+                } else {
+                    found.getProperties().remove(attr);
+                }
+            }
+        }
+
+        // framework properties
+        for(final String p : i.getFrameworkPropertiesRemovals()) {
+            base.getFrameworkProperties().remove(p);
+        }
+
+        // extensions
+        for(final String name : i.getExtensionRemovals()) {
+            for(final Extension ext : base.getExtensions()) {
+                if ( ext.getName().equals(name) ) {
+                    base.getExtensions().remove(ext);
+                    break;
+                }
+            }
+        }
+        for(final Map.Entry<String, List<ArtifactId>> entry : 
i.getArtifactExtensionRemovals().entrySet()) {
+            for(final Extension ext : base.getExtensions()) {
+                if ( ext.getName().equals(entry.getKey()) ) {
+                    for(final ArtifactId id : entry.getValue() ) {
+                        for(final Artifact a : ext.getArtifacts()) {
+                            if ( a.getId().equals(id) ) {
+                                ext.getArtifacts().remove(a);
+                                break;
+                            }
+                        }
+                    }
+                    break;
+                }
+            }
+        }
     }
 }

Added: 
sling/whiteboard/cziegeler/feature/src/test/java/org/apache/sling/feature/process/FeatureBuilderTest.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/test/java/org/apache/sling/feature/process/FeatureBuilderTest.java?rev=1803271&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/feature/src/test/java/org/apache/sling/feature/process/FeatureBuilderTest.java
 (added)
+++ 
sling/whiteboard/cziegeler/feature/src/test/java/org/apache/sling/feature/process/FeatureBuilderTest.java
 Fri Jul 28 13:00:31 2017
@@ -0,0 +1,174 @@
+/*
+ * 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.process;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sling.feature.Artifact;
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Capability;
+import org.apache.sling.feature.Configuration;
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.Requirement;
+import org.apache.sling.feature.json.U;
+import org.junit.Test;
+
+public class FeatureBuilderTest {
+
+    private final FeatureProvider provider = new FeatureProvider() {
+
+        @Override
+        public Feature provide(final ArtifactId id) {
+            try {
+                return U.readFeature("process/" + id.getGroupId() + "-" + 
id.getArtifactId() + "-" + id.getVersion());
+            } catch (Exception e) {
+                return null;
+            }
+        }
+    };
+
+    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);
+        }
+        return result;
+    }
+
+    private void equals(final Feature expected, final Feature actuals) {
+        assertFalse(expected.isAssembled());
+        assertTrue(actuals.isAssembled());
+
+        assertEquals(expected.getId(), actuals.getId());
+        assertEquals(expected.getTitle(), actuals.getTitle());
+        assertEquals(expected.getDescription(), actuals.getDescription());
+        assertEquals(expected.getVendor(), actuals.getVendor());
+        assertEquals(expected.getLicense(), actuals.getLicense());
+        assertEquals(expected.getUpgradeOf(), actuals.getUpgradeOf());
+        assertEquals(expected.getUpgrades(), actuals.getUpgrades());
+
+        // bundles
+        final List<Map.Entry<Integer, Artifact>> expectedBundles = 
getBundles(expected);
+        final List<Map.Entry<Integer, Artifact>> actualsBundles = 
getBundles(actuals);
+        assertEquals(expectedBundles.size(), actualsBundles.size());
+        for(final Map.Entry<Integer, Artifact> entry : expectedBundles) {
+            boolean found = false;
+            for(final Map.Entry<Integer, Artifact> inner : actualsBundles) {
+                if ( inner.getValue().getId().equals(entry.getValue().getId()) 
) {
+                    found = true;
+                    assertEquals("Startlevel of bundle " + entry.getValue(), 
entry.getKey(), inner.getKey());
+                    assertEquals("Metadata of bundle " + entry.getValue(), 
entry.getValue().getMetadata(), inner.getValue().getMetadata());
+                    break;
+                }
+            }
+            assertTrue("Bundle " + entry.getValue() + " in level " + 
entry.getKey(), found);
+        }
+
+        // configurations
+        assertEquals(expected.getConfigurations().size(), 
actuals.getConfigurations().size());
+        for(final Configuration cfg : expected.getConfigurations()) {
+            final Configuration found = (cfg.isFactoryConfiguration() ? 
actuals.getConfigurations().getFactoryConfiguration(cfg.getFactoryPid(), 
cfg.getName())
+                                                                      : 
actuals.getConfigurations().getConfiguration(cfg.getPid()));
+            assertNotNull("Configuration " + cfg, found);
+            assertEquals("Configuration " + cfg, cfg.getProperties(), 
found.getProperties());
+        }
+
+        // frameworkProperties
+        assertEquals(expected.getFrameworkProperties(), 
actuals.getFrameworkProperties());
+
+        // requirements
+        assertEquals(expected.getRequirements().size(), 
actuals.getRequirements().size());
+        for(final Requirement r : expected.getRequirements()) {
+            boolean found = false;
+            for(final Requirement i : actuals.getRequirements()) {
+                if ( r.equals(i) ) {
+                    found = true;
+                    break;
+                }
+            }
+            assertTrue(found);
+        }
+
+        // capabilities
+        assertEquals(expected.getCapabilities().size(), 
actuals.getCapabilities().size());
+        for(final Capability r : expected.getCapabilities()) {
+            boolean found = false;
+            for(final Capability i : actuals.getCapabilities()) {
+                if ( r.equals(i) ) {
+                    found = true;
+                    break;
+                }
+            }
+            assertTrue(found);
+        }
+
+        // extensions
+        assertEquals(expected.getExtensions().size(), 
actuals.getExtensions().size());
+        for(final Extension ext : expected.getExtensions()) {
+            final Extension inner = 
actuals.getExtensions().getByName(ext.getName());
+            assertNotNull(inner);
+            assertEquals(ext.getType(), inner.getType());
+            switch ( ext.getType()) {
+                case JSON : assertEquals(ext.getJSON(), inner.getJSON());
+                            break;
+                case TEXT : assertEquals(ext.getText(), inner.getText());
+                            break;
+                case ARTIFACTS : assertEquals(ext.getArtifacts().size(), 
inner.getArtifacts().size());
+                                 for(final Artifact art : ext.getArtifacts()) {
+                                     boolean found = false;
+                                     for(final Artifact i : 
inner.getArtifacts()) {
+                                         if ( art.getId().equals(i.getId()) ) {
+                                             found = true;
+                                             assertEquals(art.getMetadata(), 
i.getMetadata());
+                                             break;
+                                         }
+                                     }
+                                     assertTrue(found);
+                                 }
+            }
+        }
+
+        // includes should always be empty
+        assertTrue(actuals.getIncludes().isEmpty());
+    }
+
+    @Test public void testNoIncludesNoUpgrade() throws Exception {
+        final Feature base = U.readFeature("process/base");
+        assertFalse(base.isAssembled());
+
+        final Feature assembled = FeatureBuilder.assemble(base, provider);
+
+        equals(base, assembled);
+    }
+
+    @Test public void testSingleInclude() throws Exception {
+        final Feature base = U.readFeature("process/include-1");
+        assertFalse(base.isAssembled());
+
+        final Feature assembled = FeatureBuilder.assemble(base, provider);
+
+        equals(U.readFeature("process/result-1"), assembled);
+    }
+}

Propchange: 
sling/whiteboard/cziegeler/feature/src/test/java/org/apache/sling/feature/process/FeatureBuilderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/feature/src/test/java/org/apache/sling/feature/process/FeatureBuilderTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/base.json
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/test/resources/features/process/base.json?rev=1803271&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/base.json
 (added)
+++ 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/base.json
 Fri Jul 28 13:00:31 2017
@@ -0,0 +1,61 @@
+{
+    "id" : "org.apache.sling/test-feature/1.1",
+
+    "requirements" : [
+          {
+              "namespace" : "osgi.contract",
+              "directives" : {
+                  "filter" : "(&(osgi.contract=JavaServlet)(version=3.1))"
+              }
+          }
+    ],
+    "capabilities" : [
+        {
+             "namespace" : "osgi.implementation",
+             "attributes" : {
+                   "osgi.implementation" : "osgi.http",
+                   "version:Version" : "1.1"
+             },
+             "directives" : {
+                  "uses" : 
"javax.servlet,javax.servlet.http,org.osgi.service.http.context,org.osgi.service.http.whiteboard"
+             }
+        },
+        {
+             "namespace" : "osgi.service",
+             "attributes" : {
+                  "objectClass:List<String>" : 
"org.osgi.service.http.runtime.HttpServiceRuntime"
+             },
+             "directives" : {
+                  "uses" : 
"org.osgi.service.http.runtime,org.osgi.service.http.runtime.dto"
+             }
+        }
+    ],
+    "framework-properties" : {
+        "foo" : 1,
+        "brave" : "something",
+        "org.apache.felix.scr.directory" : "launchpad/scr"
+    },
+    "bundles" : {
+      "1" : [
+            {
+              "id" : "org.apache.sling/oak-server/1.0.0",
+              "hash" : "4632463464363646436"
+            },
+            "org.apache.sling/application-bundle/2.0.0",
+            "org.apache.sling/another-bundle/2.1.0"
+          ],
+      "2" : [
+            "org.apache.sling/foo-xyz/1.2.3"
+          ]
+    },
+    "configurations" : {
+        "my.pid" : {
+           "foo" : 5,
+           "bar" : "test",
+           "number:Integer" : 7
+        },
+        "my.factory.pid~name" : {
+           "a.value" : "yeah"
+        }
+    }
+}
\ No newline at end of file

Propchange: 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/base.json
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/base.json
------------------------------------------------------------------------------
    svn:keywords = Id

Added: 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/g-a-1.json
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/test/resources/features/process/g-a-1.json?rev=1803271&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/g-a-1.json
 (added)
+++ 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/g-a-1.json
 Fri Jul 28 13:00:31 2017
@@ -0,0 +1,18 @@
+{
+    "id" : "g/a/1",
+
+    "framework-properties" : {
+        "foo" : 2,
+        "bar" : "X"
+    },
+    "bundles" : {
+      "3" : [
+            "org.apache.sling/foo-bar/4.5.6"
+           ]
+    },
+    "configurations" : {
+        "org.apache.sling.foo" : {
+           "prop" : "value"
+        }
+    }
+}
\ No newline at end of file

Propchange: 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/g-a-1.json
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/g-a-1.json
------------------------------------------------------------------------------
    svn:keywords = Id

Added: 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/include-1.json
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/test/resources/features/process/include-1.json?rev=1803271&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/include-1.json
 (added)
+++ 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/include-1.json
 Fri Jul 28 13:00:31 2017
@@ -0,0 +1,74 @@
+{
+    "id" : "org.apache.sling/test-feature/1.1",
+
+    "includes" : [
+         {
+             "id" : "g/a/1",
+             "removals" : {
+                 "configurations" : [
+                 ],
+                 "bundles" : [
+                 ],
+                 "framework-properties" : [
+                 ]
+             }
+         }
+    ],
+    "requirements" : [
+          {
+              "namespace" : "osgi.contract",
+              "directives" : {
+                  "filter" : "(&(osgi.contract=JavaServlet)(version=3.1))"
+              }
+          }
+    ],
+    "capabilities" : [
+        {
+             "namespace" : "osgi.implementation",
+             "attributes" : {
+                   "osgi.implementation" : "osgi.http",
+                   "version:Version" : "1.1"
+             },
+             "directives" : {
+                  "uses" : 
"javax.servlet,javax.servlet.http,org.osgi.service.http.context,org.osgi.service.http.whiteboard"
+             }
+        },
+        {
+             "namespace" : "osgi.service",
+             "attributes" : {
+                  "objectClass:List<String>" : 
"org.osgi.service.http.runtime.HttpServiceRuntime"
+             },
+             "directives" : {
+                  "uses" : 
"org.osgi.service.http.runtime,org.osgi.service.http.runtime.dto"
+             }
+        }
+    ],
+    "framework-properties" : {
+        "foo" : 1,
+        "brave" : "something",
+        "org.apache.felix.scr.directory" : "launchpad/scr"
+    },
+    "bundles" : {
+      "1" : [
+            {
+              "id" : "org.apache.sling/oak-server/1.0.0",
+              "hash" : "4632463464363646436"
+            },
+            "org.apache.sling/application-bundle/2.0.0",
+            "org.apache.sling/another-bundle/2.1.0"
+          ],
+      "2" : [
+            "org.apache.sling/foo-xyz/1.2.3"
+          ]
+    },
+    "configurations" : {
+        "my.pid" : {
+           "foo" : 5,
+           "bar" : "test",
+           "number:Integer" : 7
+        },
+        "my.factory.pid~name" : {
+           "a.value" : "yeah"
+        }
+    }
+}
\ No newline at end of file

Propchange: 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/include-1.json
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/include-1.json
------------------------------------------------------------------------------
    svn:keywords = Id

Added: 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/result-1.json
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/test/resources/features/process/result-1.json?rev=1803271&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/result-1.json
 (added)
+++ 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/result-1.json
 Fri Jul 28 13:00:31 2017
@@ -0,0 +1,68 @@
+{
+    "id" : "org.apache.sling/test-feature/1.1",
+
+    "requirements" : [
+          {
+              "namespace" : "osgi.contract",
+              "directives" : {
+                  "filter" : "(&(osgi.contract=JavaServlet)(version=3.1))"
+              }
+          }
+    ],
+    "capabilities" : [
+        {
+             "namespace" : "osgi.implementation",
+             "attributes" : {
+                   "osgi.implementation" : "osgi.http",
+                   "version:Version" : "1.1"
+             },
+             "directives" : {
+                  "uses" : 
"javax.servlet,javax.servlet.http,org.osgi.service.http.context,org.osgi.service.http.whiteboard"
+             }
+        },
+        {
+             "namespace" : "osgi.service",
+             "attributes" : {
+                  "objectClass:List<String>" : 
"org.osgi.service.http.runtime.HttpServiceRuntime"
+             },
+             "directives" : {
+                  "uses" : 
"org.osgi.service.http.runtime,org.osgi.service.http.runtime.dto"
+             }
+        }
+    ],
+    "framework-properties" : {
+        "foo" : 1,
+        "brave" : "something",
+        "org.apache.felix.scr.directory" : "launchpad/scr",
+        "bar" : "X"        
+    },
+    "bundles" : {
+      "1" : [
+            {
+              "id" : "org.apache.sling/oak-server/1.0.0",
+              "hash" : "4632463464363646436"
+            },
+            "org.apache.sling/application-bundle/2.0.0",
+            "org.apache.sling/another-bundle/2.1.0"
+          ],
+      "2" : [
+            "org.apache.sling/foo-xyz/1.2.3"
+          ],
+      "3" : [
+            "org.apache.sling/foo-bar/4.5.6"
+           ]
+    },
+    "configurations" : {
+        "my.pid" : {
+           "foo" : 5,
+           "bar" : "test",
+           "number:Integer" : 7
+        },
+        "my.factory.pid~name" : {
+           "a.value" : "yeah"
+        },
+        "org.apache.sling.foo" : {
+           "prop" : "value"
+        }        
+    }
+}
\ No newline at end of file

Propchange: 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/result-1.json
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/feature/src/test/resources/features/process/result-1.json
------------------------------------------------------------------------------
    svn:keywords = Id


Reply via email to