Author: davidb
Date: Fri Apr 20 06:34:25 2018
New Revision: 1829625

URL: http://svn.apache.org/viewvc?rev=1829625&view=rev
Log:
Improvements to the OSGi Capability and Requirement implementations

These come from the Apache Sling Whitenboard Feature Model project. Merged with 
Felix Utils to increase sharing across projects.

Added:
    
felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/AbstractCapabilityRequirement.java
Modified:
    felix/trunk/utils/pom.xml
    
felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/CapabilityImpl.java
    
felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/RequirementImpl.java
    
felix/trunk/utils/src/test/java/org/apache/felix/utils/capabilities/CapabilityImplTest.java
    
felix/trunk/utils/src/test/java/org/apache/felix/utils/capabilities/RequirementImplTest.java

Modified: felix/trunk/utils/pom.xml
URL: 
http://svn.apache.org/viewvc/felix/trunk/utils/pom.xml?rev=1829625&r1=1829624&r2=1829625&view=diff
==============================================================================
--- felix/trunk/utils/pom.xml (original)
+++ felix/trunk/utils/pom.xml Fri Apr 20 06:34:25 2018
@@ -27,7 +27,7 @@
     <modelVersion>4.0.0</modelVersion>
     <name>Apache Felix Utils</name>
     <description>Utility classes for OSGi.</description>
-    <version>1.10.5-SNAPSHOT</version>
+    <version>1.11.0-SNAPSHOT</version>
     <artifactId>org.apache.felix.utils</artifactId>
 
     <scm>

Added: 
felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/AbstractCapabilityRequirement.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/AbstractCapabilityRequirement.java?rev=1829625&view=auto
==============================================================================
--- 
felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/AbstractCapabilityRequirement.java
 (added)
+++ 
felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/AbstractCapabilityRequirement.java
 Fri Apr 20 06:34:25 2018
@@ -0,0 +1,135 @@
+/*
+ * 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.felix.utils.capabilities;
+
+import org.osgi.resource.Resource;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+abstract class AbstractCapabilityRequirement {
+
+    /** The namespace. Required. */
+    private final String namespace;
+
+    /** Optional resource. */
+    private volatile Resource resource;
+
+    /** Optional attributes. Never null. */
+    private final Map<String, Object> attributes;
+
+    /** Optional attributes. Never null. */
+    private final Map<String, String> directives;
+
+    AbstractCapabilityRequirement(final String ns, final Map<String, Object> 
attrs, final Map<String, String> dirs, final Resource res) {
+        if ( ns == null ) {
+            throw new IllegalArgumentException("Namespace must not be null.");
+        }
+        namespace = ns;
+        attributes = attrs == null
+                ? Collections.<String, Object>emptyMap()
+                : Collections.unmodifiableMap(new HashMap<String, 
Object>(attrs));
+        directives = dirs == null
+                ? Collections.<String,String>emptyMap()
+                : Collections.unmodifiableMap(new 
HashMap<String,String>(dirs));
+                resource = res;
+    }
+
+    /**
+     * Return the namespace.
+     * @return The namespace. This is never @{code null}.
+     */
+    public String getNamespace() {
+        return namespace;
+    }
+
+    /**
+     * Return the attributes.
+     * @return The attributes, might be empty.
+     */
+    public Map<String, Object> getAttributes() {
+        return attributes;
+    }
+
+    /**
+     * Return the directives.
+     * @return The directives, might be empty.
+     */
+    public Map<String, String> getDirectives() {
+        return directives;
+    }
+
+    /**
+     * Return the resource.
+     * @return The resource or @{code null}.
+     */
+    public Resource getResource() {
+        return resource;
+    }
+
+    /**
+     * Set the resource associated with this requirement.
+     *
+     * @param res The resource.
+     */
+    public void setResource(Resource res) {
+        resource = res;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + attributes.hashCode();
+        result = prime * result + directives.hashCode();
+        result = prime * result + namespace.hashCode();
+
+        if (resource != null)
+            result = prime * result + resource.hashCode();
+
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        AbstractCapabilityRequirement other = (AbstractCapabilityRequirement) 
obj;
+        if (!namespace.equals(other.namespace))
+            return false;
+        if (!attributes.equals(other.attributes))
+            return false;
+        if (!directives.equals(other.directives))
+            return false;
+        if (resource == null) {
+            return other.resource == null;
+        } else {
+            return resource.equals(other.resource);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + " [resource=" + resource + ", 
namespace=" + namespace + ", attributes=" + attributes
+                + ", directives=" + directives + "]";
+    }
+}

Modified: 
felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/CapabilityImpl.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/CapabilityImpl.java?rev=1829625&r1=1829624&r2=1829625&view=diff
==============================================================================
--- 
felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/CapabilityImpl.java
 (original)
+++ 
felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/CapabilityImpl.java
 Fri Apr 20 06:34:25 2018
@@ -1,161 +1,59 @@
 /*
- * 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
+ * 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
+ * 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.
+ * 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.felix.utils.capabilities;
 
 import org.osgi.resource.Capability;
 import org.osgi.resource.Resource;
 
-import java.util.Collections;
 import java.util.Map;
 
 /**
  * Implementation of the OSGi Capability interface.
  */
-public class CapabilityImpl implements Capability
-{
-    private final String namespace;
-    private final Map<String, Object> attributes;
-    private final Map<String, String> directives;
-    private volatile Resource resource;
-
+public class CapabilityImpl extends AbstractCapabilityRequirement implements 
Capability {
     /**
-     * Create a capability.
-     *
+     * Create a capability that is not associated with a resource.
+     * @param res The resource associated with the capability. May be null.
      * @param ns The namespace of the capability.
      * @param attrs The attributes of the capability.
      * @param dirs The directives of the capability.
      */
-    public CapabilityImpl(String ns, Map<String, Object> attrs, Map<String, 
String> dirs)
-    {
+    public CapabilityImpl(String ns, Map<String, Object> attrs, Map<String, 
String> dirs) {
         this(ns, attrs, dirs, null);
     }
 
     /**
      * Create a capability.
-     *
      * @param ns The namespace of the capability.
      * @param attrs The attributes of the capability.
      * @param dirs The directives of the capability.
-     * @param res The resource associated with the capability.
-     */
-    public CapabilityImpl(String ns, Map<String, Object> attrs, Map<String, 
String> dirs, Resource res)
-    {
-        namespace = ns;
-        attributes = Collections.unmodifiableMap(attrs);
-        directives = Collections.unmodifiableMap(dirs);
-        resource = res;
-    }
-
-    /**
-     * Returns the namespace of this capability.
-     *
-     * @return The namespace of this capability.
-     */
-    public String getNamespace()
-    {
-        return namespace;
-    }
-
-    /**
-     * Returns the attributes of this capability.
-     *
-     * @return An unmodifiable map of attribute names to attribute values for
-     *         this capability, or an empty map if this capability has no
-     *         attributes.
-     */
-    public Map<String, Object> getAttributes()
-    {
-        return attributes;
-    }
-
-    /**
-     * Returns the directives of this capability.
-     *
-     * @return An unmodifiable map of directive names to directive values for
-     *         this capability, or an empty map if this capability has no
-     *         directives.
+     * @param res The resource associated with the capability. May be null.
      */
-    public Map<String, String> getDirectives()
-    {
-        return directives;
+    public CapabilityImpl(String ns, Map<String, Object> attrs, Map<String, 
String> dirs, Resource res) {
+        super(ns, attrs, dirs, res);
     }
 
     /**
-     * Returns the resource declaring this capability.
-     *
-     * @return The resource declaring this capability.
+     * Create a capability based on an existing capability, providing the 
resource.
+     * The namespace, attributes and directives are copied from the provided 
capability.
+     * @param capability The capability to base the new requirement on.
+     * @param resource The resource to be associated with the capability
      */
-    public Resource getResource()
-    {
-        return resource;
-    }
-
-    /**
-     * Sets the resource associated with this capability.
-     *
-     * @param res The resource.
-     */
-    public void setResource(Resource res)
-    {
-        resource = res;
-    }
-
-    @Override
-    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 + ((resource == null) ? 0 : 
resource.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        CapabilityImpl other = (CapabilityImpl) obj;
-        if (attributes == null) {
-            if (other.attributes != null)
-                return false;
-        } else if (!attributes.equals(other.attributes))
-            return false;
-        if (directives == null) {
-            if (other.directives != null)
-                return false;
-        } else if (!directives.equals(other.directives))
-            return false;
-        if (namespace == null) {
-            if (other.namespace != null)
-                return false;
-        } else if (!namespace.equals(other.namespace))
-            return false;
-        if (resource == null) {
-            if (other.resource != null)
-                return false;
-        } else if (!resource.equals(other.resource))
-            return false;
-        return true;
+    public CapabilityImpl(Resource resource, Capability capability) {
+        this(capability.getNamespace(), capability.getAttributes(), 
capability.getDirectives(), resource);
     }
 }

Modified: 
felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/RequirementImpl.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/RequirementImpl.java?rev=1829625&r1=1829624&r2=1829625&view=diff
==============================================================================
--- 
felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/RequirementImpl.java
 (original)
+++ 
felix/trunk/utils/src/main/java/org/apache/felix/utils/capabilities/RequirementImpl.java
 Fri Apr 20 06:34:25 2018
@@ -1,20 +1,18 @@
 /*
- * 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
+ * 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
+ * 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.
+ * 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.felix.utils.capabilities;
 
@@ -28,154 +26,51 @@ import java.util.Map;
 /**
  * Implementation of the OSGi Requirement interface.
  */
-public class RequirementImpl implements Requirement
-{
-    private final String namespace;
-    private final Map<String, Object> attributes;
-    private final Map<String, String> directives;
-    private volatile Resource resource;
-
+public class RequirementImpl extends AbstractCapabilityRequirement implements 
Requirement {
     /**
-     * Create a requirement.
-     *
+     * Create a requirement that is not associated with a resource.
+     * @param res The resource associated with the requirement.
      * @param ns The namespace of the requirement.
      * @param attrs The attributes of the requirement.
      * @param dirs The directives of the requirement.
      */
-    public RequirementImpl(String ns, Map<String, Object> attrs, Map<String, 
String> dirs)
-    {
+    public RequirementImpl(String ns, Map<String, Object> attrs, Map<String, 
String> dirs) {
         this(ns, attrs, dirs, null);
     }
 
     /**
      * Create a requirement.
-     *
      * @param ns The namespace of the requirement.
      * @param attrs The attributes of the requirement.
      * @param dirs The directives of the requirement.
      * @param res The resource associated with the requirement.
      */
-    public RequirementImpl(String ns, Map<String, Object> attrs, Map<String, 
String> dirs, Resource res)
-    {
-        namespace = ns;
-        attributes = attrs;
-        directives = dirs;
-        resource = res;
-    }
-
-    /**
-     * Create a requirement with a namespace and a filter.
-     *
-     * This is a convenience method that creates a requirement with
-     * an empty attributes map and a single 'filter' directive.
-     * @param ns The namespace for the requirement.
-     * @param filter The filter.
-     */
-    public RequirementImpl(String ns, String filter)
-    {
-        this(ns, Collections.<String, Object>emptyMap(),
-            filter == null ? Collections.<String, String> emptyMap() :
-            Collections.singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE, 
filter));
+    public RequirementImpl(String ns, Map<String, Object> attrs, Map<String, 
String> dirs, Resource res) {
+        super(ns, attrs, dirs, res);
     }
 
     /**
-     * Returns the namespace of this requirement.
-     *
-     * @return The namespace of this requirement.
+      * Create a requirement with a namespace and a filter.
+      *
+      * This is a convenience method that creates a requirement with
+      * an empty attributes map and a single 'filter' directive.
+      * @param ns The namespace for the requirement.
+      * @param filter The filter.
+      */
+     public RequirementImpl(String ns, String filter)
+     {
+         this(ns, Collections.<String, Object>emptyMap(),
+             filter == null ? Collections.<String, String> emptyMap() :
+             Collections.singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE, 
filter));
+     }
+
+    /**
+     * Create a requirement based on an existing requirement, providing the 
resource.
+     * The namespace, attributes and directives are copied from the provided 
requirement.
+     * @param requirement The requirement to base the new requirement on.
+     * @param resource The resource to be associated with the requirement
      */
-    public String getNamespace()
-    {
-        return namespace;
-    }
-
-    /**
-     * Returns the attributes of this requirement.
-     *
-     * <p>
-     * Requirement attributes have no specified semantics and are considered
-     * extra user defined information.
-     *
-     * @return An unmodifiable map of attribute names to attribute values for
-     *         this requirement, or an empty map if this requirement has no
-     *         attributes.
-     */
-    public Map<String, Object> getAttributes()
-    {
-        return Collections.unmodifiableMap(attributes);
-    }
-
-    /**
-     * Returns the directives of this requirement.
-     *
-     * @return An unmodifiable map of directive names to directive values for
-     *         this requirement, or an empty map if this requirement has no
-     *         directives.
-     */
-    public Map<String, String> getDirectives()
-    {
-        return Collections.unmodifiableMap(directives);
-    }
-
-    /**
-     * Returns the resource declaring this requirement.
-     *
-     * @return The resource declaring this requirement. This can be {@code 
null}
-     *         if this requirement is synthesized.
-     */
-    public Resource getResource()
-    {
-        return resource;
-    }
-
-    /**
-     * Set the resource associated with this requirement.
-     *
-     * @param res The resource.
-     */
-    public void setResource(Resource res) {
-        resource = res;
-    }
-
-    @Override
-    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 + ((resource == null) ? 0 : 
resource.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        RequirementImpl other = (RequirementImpl) obj;
-        if (attributes == null) {
-            if (other.attributes != null)
-                return false;
-        } else if (!attributes.equals(other.attributes))
-            return false;
-        if (directives == null) {
-            if (other.directives != null)
-                return false;
-        } else if (!directives.equals(other.directives))
-            return false;
-        if (namespace == null) {
-            if (other.namespace != null)
-                return false;
-        } else if (!namespace.equals(other.namespace))
-            return false;
-        if (resource == null) {
-            if (other.resource != null)
-                return false;
-        } else if (!resource.equals(other.resource))
-            return false;
-        return true;
+    public RequirementImpl(Resource resource, Requirement requirement) {
+        this(requirement.getNamespace(), requirement.getAttributes(), 
requirement.getDirectives(), resource);
     }
 }

Modified: 
felix/trunk/utils/src/test/java/org/apache/felix/utils/capabilities/CapabilityImplTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/utils/src/test/java/org/apache/felix/utils/capabilities/CapabilityImplTest.java?rev=1829625&r1=1829624&r2=1829625&view=diff
==============================================================================
--- 
felix/trunk/utils/src/test/java/org/apache/felix/utils/capabilities/CapabilityImplTest.java
 (original)
+++ 
felix/trunk/utils/src/test/java/org/apache/felix/utils/capabilities/CapabilityImplTest.java
 Fri Apr 20 06:34:25 2018
@@ -57,4 +57,18 @@ public class CapabilityImplTest extends
         assertFalse(c1.equals(c3));
         assertFalse(c1.hashCode() == c3.hashCode());
     }
+
+    public void testCopyCapability() {
+        CapabilityImpl c = new CapabilityImpl("x.y.z",
+                Collections.<String, Object>singletonMap("a", 123),
+                Collections.<String, String>singletonMap("x", "y"),
+                Mockito.mock(Resource.class));
+
+        Resource res2 = Mockito.mock(Resource.class);
+        CapabilityImpl c2 = new CapabilityImpl(res2, c);
+        assertFalse("Should not be equal, the resources are different", 
c.equals(c2));
+
+        c.setResource(res2);
+        assertEquals(c, c2);
+    }
 }

Modified: 
felix/trunk/utils/src/test/java/org/apache/felix/utils/capabilities/RequirementImplTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/utils/src/test/java/org/apache/felix/utils/capabilities/RequirementImplTest.java?rev=1829625&r1=1829624&r2=1829625&view=diff
==============================================================================
--- 
felix/trunk/utils/src/test/java/org/apache/felix/utils/capabilities/RequirementImplTest.java
 (original)
+++ 
felix/trunk/utils/src/test/java/org/apache/felix/utils/capabilities/RequirementImplTest.java
 Fri Apr 20 06:34:25 2018
@@ -69,4 +69,18 @@ public class RequirementImplTest extends
         assertEquals(0, r2.getAttributes().size());
         assertEquals(0, r2.getDirectives().size());
     }
+
+    public void testCopyRequirement() {
+        RequirementImpl r = new RequirementImpl("x.y.z",
+                Collections.<String, Object>singletonMap("a", 123),
+                Collections.<String, String>singletonMap("x", "y"),
+                Mockito.mock(Resource.class));
+
+        Resource res2 = Mockito.mock(Resource.class);
+        RequirementImpl r2 = new RequirementImpl(res2, r);
+        assertFalse("Should not be equal, the resources are different", 
r.equals(r2));
+
+        r.setResource(res2);
+        assertEquals(r, r2);
+    }
 }


Reply via email to