You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@felix.apache.org by Guillaume Nodet <gn...@apache.org> on 2018/04/20 07:01:29 UTC

Re: svn commit: r1829625 - in /felix/trunk/utils: ./ src/main/java/org/apache/felix/utils/capabilities/ src/test/java/org/apache/felix/utils/capabilities/

I'm going to work on those classes too then, in order to reuse them instead
of the one we have in Karaf. They are actually closer to the ones in the
framework.  It also includes a CapabilitySet / SimpleFilter which speeds
things a lot when using the resolver.
One point though, I'm not sure I like the setResource(xx) on the Capability
/ Requirement, because there's a risk of running out of sync with
Resource#getCapabilities / getRequirements.  So I wonder if a final
Resource field would be more appropriate.

I think a Resource implementation would be interesting too.

2018-04-20 8:34 GMT+02:00 <da...@apache.org>:

> 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);
> +    }
>  }
>
>
>


-- 
------------------------
Guillaume Nodet

Re: svn commit: r1829625 - in /felix/trunk/utils: ./ src/main/java/org/apache/felix/utils/capabilities/ src/test/java/org/apache/felix/utils/capabilities/

Posted by David Bosschaert <da...@gmail.com>.
I've added https://issues.apache.org/jira/browse/FELIX-5838

Best regards,

David

On 20 April 2018 at 08:43, Carsten Ziegeler <cz...@apache.org> wrote:

> Capability and requirement must be immutable (according to the javadoc)
> so a setResource sounds dangerous.
>
> Could we maybe have a jira issue tracking the changes/additions to utils?
>
> Regards
>
> Carsten
>
>
> David Bosschaert wrote
> > Hi Guillaume,
> >
> > The setResource() came from the implementation used by the Felix
> > BundleRepository, which I used as a starting point.
> > I'll have a look if we can remove it.
> >
> > BTW +1 on a shareable Resource Implementation. There is one in the Felix
> > BundleRepository already which might be a starting point?
> >
> > Best regards,
> >
> > David
> >
> > On 20 April 2018 at 08:01, Guillaume Nodet <gn...@apache.org> wrote:
> >
> >> I'm going to work on those classes too then, in order to reuse them
> instead
> >> of the one we have in Karaf. They are actually closer to the ones in the
> >> framework.  It also includes a CapabilitySet / SimpleFilter which speeds
> >> things a lot when using the resolver.
> >> One point though, I'm not sure I like the setResource(xx) on the
> Capability
> >> / Requirement, because there's a risk of running out of sync with
> >> Resource#getCapabilities / getRequirements.  So I wonder if a final
> >> Resource field would be more appropriate.
> >>
> >> I think a Resource implementation would be interesting too.
> >>
> >> 2018-04-20 8:34 GMT+02:00 <da...@apache.org>:
> >>
> >>> 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);
> >>> +    }
> >>>  }
> >>>
> >>>
> >>>
> >>
> >>
> >> --
> >> ------------------------
> >> Guillaume Nodet
> >>
> >
> --
> Carsten Ziegeler
> Adobe Research Switzerland
> cziegeler@apache.org
>

Re: svn commit: r1829625 - in /felix/trunk/utils: ./ src/main/java/org/apache/felix/utils/capabilities/ src/test/java/org/apache/felix/utils/capabilities/

Posted by Guillaume Nodet <gn...@apache.org>.
I've merge in some optimizations we have in Karaf, mainly:
  - a CapabilitySet / SimpleFilter, both coming originally from the felix
framework
  - a StringArrayMap to optimize the memory used by large amounts of
resources
  - a ResourceBuilder that can be used to create full Resource from
manifest headers

2018-04-20 9:43 GMT+02:00 Carsten Ziegeler <cz...@apache.org>:

> Capability and requirement must be immutable (according to the javadoc)
> so a setResource sounds dangerous.
>
> Could we maybe have a jira issue tracking the changes/additions to utils?
>
> Regards
>
> Carsten
>
>
> David Bosschaert wrote
> > Hi Guillaume,
> >
> > The setResource() came from the implementation used by the Felix
> > BundleRepository, which I used as a starting point.
> > I'll have a look if we can remove it.
> >
> > BTW +1 on a shareable Resource Implementation. There is one in the Felix
> > BundleRepository already which might be a starting point?
> >
> > Best regards,
> >
> > David
> >
> > On 20 April 2018 at 08:01, Guillaume Nodet <gn...@apache.org> wrote:
> >
> >> I'm going to work on those classes too then, in order to reuse them
> instead
> >> of the one we have in Karaf. They are actually closer to the ones in the
> >> framework.  It also includes a CapabilitySet / SimpleFilter which speeds
> >> things a lot when using the resolver.
> >> One point though, I'm not sure I like the setResource(xx) on the
> Capability
> >> / Requirement, because there's a risk of running out of sync with
> >> Resource#getCapabilities / getRequirements.  So I wonder if a final
> >> Resource field would be more appropriate.
> >>
> >> I think a Resource implementation would be interesting too.
> >>
> >> 2018-04-20 8:34 GMT+02:00 <da...@apache.org>:
> >>
> >>> 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);
> >>> +    }
> >>>  }
> >>>
> >>>
> >>>
> >>
> >>
> >> --
> >> ------------------------
> >> Guillaume Nodet
> >>
> >
> --
> Carsten Ziegeler
> Adobe Research Switzerland
> cziegeler@apache.org
>



-- 
------------------------
Guillaume Nodet

Re: svn commit: r1829625 - in /felix/trunk/utils: ./ src/main/java/org/apache/felix/utils/capabilities/ src/test/java/org/apache/felix/utils/capabilities/

Posted by Carsten Ziegeler <cz...@apache.org>.
Capability and requirement must be immutable (according to the javadoc)
so a setResource sounds dangerous.

Could we maybe have a jira issue tracking the changes/additions to utils?

Regards

Carsten


David Bosschaert wrote
> Hi Guillaume,
> 
> The setResource() came from the implementation used by the Felix
> BundleRepository, which I used as a starting point.
> I'll have a look if we can remove it.
> 
> BTW +1 on a shareable Resource Implementation. There is one in the Felix
> BundleRepository already which might be a starting point?
> 
> Best regards,
> 
> David
> 
> On 20 April 2018 at 08:01, Guillaume Nodet <gn...@apache.org> wrote:
> 
>> I'm going to work on those classes too then, in order to reuse them instead
>> of the one we have in Karaf. They are actually closer to the ones in the
>> framework.  It also includes a CapabilitySet / SimpleFilter which speeds
>> things a lot when using the resolver.
>> One point though, I'm not sure I like the setResource(xx) on the Capability
>> / Requirement, because there's a risk of running out of sync with
>> Resource#getCapabilities / getRequirements.  So I wonder if a final
>> Resource field would be more appropriate.
>>
>> I think a Resource implementation would be interesting too.
>>
>> 2018-04-20 8:34 GMT+02:00 <da...@apache.org>:
>>
>>> 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);
>>> +    }
>>>  }
>>>
>>>
>>>
>>
>>
>> --
>> ------------------------
>> Guillaume Nodet
>>
> 
-- 
Carsten Ziegeler
Adobe Research Switzerland
cziegeler@apache.org

Re: svn commit: r1829625 - in /felix/trunk/utils: ./ src/main/java/org/apache/felix/utils/capabilities/ src/test/java/org/apache/felix/utils/capabilities/

Posted by David Bosschaert <da...@gmail.com>.
Hi Guillaume,

The setResource() came from the implementation used by the Felix
BundleRepository, which I used as a starting point.
I'll have a look if we can remove it.

BTW +1 on a shareable Resource Implementation. There is one in the Felix
BundleRepository already which might be a starting point?

Best regards,

David

On 20 April 2018 at 08:01, Guillaume Nodet <gn...@apache.org> wrote:

> I'm going to work on those classes too then, in order to reuse them instead
> of the one we have in Karaf. They are actually closer to the ones in the
> framework.  It also includes a CapabilitySet / SimpleFilter which speeds
> things a lot when using the resolver.
> One point though, I'm not sure I like the setResource(xx) on the Capability
> / Requirement, because there's a risk of running out of sync with
> Resource#getCapabilities / getRequirements.  So I wonder if a final
> Resource field would be more appropriate.
>
> I think a Resource implementation would be interesting too.
>
> 2018-04-20 8:34 GMT+02:00 <da...@apache.org>:
>
> > 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);
> > +    }
> >  }
> >
> >
> >
>
>
> --
> ------------------------
> Guillaume Nodet
>

Re: svn commit: r1829625 - in /felix/trunk/utils: ./ src/main/java/org/apache/felix/utils/capabilities/ src/test/java/org/apache/felix/utils/capabilities/

Posted by Karl Pauls <ka...@gmail.com>.
I think the reason for the thread save-ness is that it is used in the
ServiceRegistry where we don't hold a lock. For the resolver it is
only accessed inside a synchronized. Maybe we could make it
configurable whether it needs to be thread save or not?

regards,

Karl

On Fri, Apr 20, 2018 at 2:47 PM, Guillaume Nodet <gn...@apache.org> wrote:
> While they should be similar to the framework one, I saw two differences in
> the CapabilitySet: the framework implementation is thread safe, while the
> one I added is not (I don't recall if I removed it for perfs or if it was
> added later in the framework though).  Also, the framework one is using
> BundleCapability / BundleRequirement while the other one uses the
> Capability / Requirement interfaces.
> But there's definitely some overlap.
> The header parsing could be reused too.
>
> 2018-04-20 10:56 GMT+02:00 Karl Pauls <ka...@gmail.com>:
>
>> On Fri, Apr 20, 2018 at 9:01 AM, Guillaume Nodet <gn...@apache.org>
>> wrote:
>> > I'm going to work on those classes too then, in order to reuse them
>> instead
>> > of the one we have in Karaf. They are actually closer to the ones in the
>> > framework.  It also includes a CapabilitySet / SimpleFilter which speeds
>> > things a lot when using the resolver.
>>
>> I was hoping we could maybe reuse them in the framework as well.
>>
>> regards,
>>
>> Karl
>>
>> > One point though, I'm not sure I like the setResource(xx) on the
>> Capability
>> > / Requirement, because there's a risk of running out of sync with
>> > Resource#getCapabilities / getRequirements.  So I wonder if a final
>> > Resource field would be more appropriate.
>> >
>> > I think a Resource implementation would be interesting too.
>> >
>> > 2018-04-20 8:34 GMT+02:00 <da...@apache.org>:
>> >
>> >> 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);
>> >> +    }
>> >>  }
>> >>
>> >>
>> >>
>> >
>> >
>> > --
>> > ------------------------
>> > Guillaume Nodet
>>
>>
>>
>> --
>> Karl Pauls
>> karlpauls@gmail.com
>>
>
>
>
> --
> ------------------------
> Guillaume Nodet



-- 
Karl Pauls
karlpauls@gmail.com

Re: svn commit: r1829625 - in /felix/trunk/utils: ./ src/main/java/org/apache/felix/utils/capabilities/ src/test/java/org/apache/felix/utils/capabilities/

Posted by Karl Pauls <ka...@gmail.com>.
Regarding the header parsing, should we try to move as much code from
the framework manifest parsing to utils as well and merge it with
whatever you have in the ResourceBuilder ? It feels like a generic
ManifestParser that you can give manifest headers and have to give you
back OSGi specific info would be useful.

As far as I can see, you have that somewhat implicitly in your
ResourceBuilder and we have it in the framework in the ManifestParser
and I'm sure David has it someplace as well.

regards,

Karl

On Fri, Apr 20, 2018 at 2:47 PM, Guillaume Nodet <gn...@apache.org> wrote:
> While they should be similar to the framework one, I saw two differences in
> the CapabilitySet: the framework implementation is thread safe, while the
> one I added is not (I don't recall if I removed it for perfs or if it was
> added later in the framework though).  Also, the framework one is using
> BundleCapability / BundleRequirement while the other one uses the
> Capability / Requirement interfaces.
> But there's definitely some overlap.
> The header parsing could be reused too.
>
> 2018-04-20 10:56 GMT+02:00 Karl Pauls <ka...@gmail.com>:
>
>> On Fri, Apr 20, 2018 at 9:01 AM, Guillaume Nodet <gn...@apache.org>
>> wrote:
>> > I'm going to work on those classes too then, in order to reuse them
>> instead
>> > of the one we have in Karaf. They are actually closer to the ones in the
>> > framework.  It also includes a CapabilitySet / SimpleFilter which speeds
>> > things a lot when using the resolver.
>>
>> I was hoping we could maybe reuse them in the framework as well.
>>
>> regards,
>>
>> Karl
>>
>> > One point though, I'm not sure I like the setResource(xx) on the
>> Capability
>> > / Requirement, because there's a risk of running out of sync with
>> > Resource#getCapabilities / getRequirements.  So I wonder if a final
>> > Resource field would be more appropriate.
>> >
>> > I think a Resource implementation would be interesting too.
>> >
>> > 2018-04-20 8:34 GMT+02:00 <da...@apache.org>:
>> >
>> >> 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);
>> >> +    }
>> >>  }
>> >>
>> >>
>> >>
>> >
>> >
>> > --
>> > ------------------------
>> > Guillaume Nodet
>>
>>
>>
>> --
>> Karl Pauls
>> karlpauls@gmail.com
>>
>
>
>
> --
> ------------------------
> Guillaume Nodet



-- 
Karl Pauls
karlpauls@gmail.com

Re: svn commit: r1829625 - in /felix/trunk/utils: ./ src/main/java/org/apache/felix/utils/capabilities/ src/test/java/org/apache/felix/utils/capabilities/

Posted by Guillaume Nodet <gn...@apache.org>.
While they should be similar to the framework one, I saw two differences in
the CapabilitySet: the framework implementation is thread safe, while the
one I added is not (I don't recall if I removed it for perfs or if it was
added later in the framework though).  Also, the framework one is using
BundleCapability / BundleRequirement while the other one uses the
Capability / Requirement interfaces.
But there's definitely some overlap.
The header parsing could be reused too.

2018-04-20 10:56 GMT+02:00 Karl Pauls <ka...@gmail.com>:

> On Fri, Apr 20, 2018 at 9:01 AM, Guillaume Nodet <gn...@apache.org>
> wrote:
> > I'm going to work on those classes too then, in order to reuse them
> instead
> > of the one we have in Karaf. They are actually closer to the ones in the
> > framework.  It also includes a CapabilitySet / SimpleFilter which speeds
> > things a lot when using the resolver.
>
> I was hoping we could maybe reuse them in the framework as well.
>
> regards,
>
> Karl
>
> > One point though, I'm not sure I like the setResource(xx) on the
> Capability
> > / Requirement, because there's a risk of running out of sync with
> > Resource#getCapabilities / getRequirements.  So I wonder if a final
> > Resource field would be more appropriate.
> >
> > I think a Resource implementation would be interesting too.
> >
> > 2018-04-20 8:34 GMT+02:00 <da...@apache.org>:
> >
> >> 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);
> >> +    }
> >>  }
> >>
> >>
> >>
> >
> >
> > --
> > ------------------------
> > Guillaume Nodet
>
>
>
> --
> Karl Pauls
> karlpauls@gmail.com
>



-- 
------------------------
Guillaume Nodet

Re: svn commit: r1829625 - in /felix/trunk/utils: ./ src/main/java/org/apache/felix/utils/capabilities/ src/test/java/org/apache/felix/utils/capabilities/

Posted by Karl Pauls <ka...@gmail.com>.
On Fri, Apr 20, 2018 at 9:01 AM, Guillaume Nodet <gn...@apache.org> wrote:
> I'm going to work on those classes too then, in order to reuse them instead
> of the one we have in Karaf. They are actually closer to the ones in the
> framework.  It also includes a CapabilitySet / SimpleFilter which speeds
> things a lot when using the resolver.

I was hoping we could maybe reuse them in the framework as well.

regards,

Karl

> One point though, I'm not sure I like the setResource(xx) on the Capability
> / Requirement, because there's a risk of running out of sync with
> Resource#getCapabilities / getRequirements.  So I wonder if a final
> Resource field would be more appropriate.
>
> I think a Resource implementation would be interesting too.
>
> 2018-04-20 8:34 GMT+02:00 <da...@apache.org>:
>
>> 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);
>> +    }
>>  }
>>
>>
>>
>
>
> --
> ------------------------
> Guillaume Nodet



-- 
Karl Pauls
karlpauls@gmail.com