Merge "Eliminate the use of Name and its broken equals contract"
diff --git a/platform/northbound/sensinact-access/src/main/java/org/eclipse/sensinact/gateway/nthbnd/endpoint/LoginResponse.java b/platform/northbound/sensinact-access/src/main/java/org/eclipse/sensinact/gateway/nthbnd/endpoint/LoginResponse.java
index 79c473f..d2ae9e6 100644
--- a/platform/northbound/sensinact-access/src/main/java/org/eclipse/sensinact/gateway/nthbnd/endpoint/LoginResponse.java
+++ b/platform/northbound/sensinact-access/src/main/java/org/eclipse/sensinact/gateway/nthbnd/endpoint/LoginResponse.java
@@ -126,7 +126,7 @@
     @Override
     public String getJSON() {
         StringBuilder builder = new StringBuilder();
-        Iterator<Map.Entry<TypedKey<?>, Object>> iterator = super.properties.entrySet().iterator();
+        Iterator<Map.Entry<TypedKey<?>, Object>> iterator = typedKeyValues();
 
         builder.append(JSONUtils.OPEN_BRACE);
         int index = 0;
diff --git a/platform/northbound/sensinact-access/src/main/java/org/eclipse/sensinact/gateway/nthbnd/endpoint/RegisteringResponse.java b/platform/northbound/sensinact-access/src/main/java/org/eclipse/sensinact/gateway/nthbnd/endpoint/RegisteringResponse.java
index 31aa026..f968dc4 100644
--- a/platform/northbound/sensinact-access/src/main/java/org/eclipse/sensinact/gateway/nthbnd/endpoint/RegisteringResponse.java
+++ b/platform/northbound/sensinact-access/src/main/java/org/eclipse/sensinact/gateway/nthbnd/endpoint/RegisteringResponse.java
@@ -110,7 +110,7 @@
      */
     public String getJSON() {
         StringBuilder builder = new StringBuilder();
-        Iterator<Map.Entry<TypedKey<?>, Object>> iterator = super.properties.entrySet().iterator();
+        Iterator<Map.Entry<TypedKey<?>, Object>> iterator = typedKeyValues();
 
         builder.append(JSONUtils.OPEN_BRACE);
         int index = 0;
diff --git a/platform/sensinact-common/src/main/java/org/eclipse/sensinact/gateway/common/primitive/Elements.java b/platform/sensinact-common/src/main/java/org/eclipse/sensinact/gateway/common/primitive/Elements.java
index e04e5cf..0716dbb 100644
--- a/platform/sensinact-common/src/main/java/org/eclipse/sensinact/gateway/common/primitive/Elements.java
+++ b/platform/sensinact-common/src/main/java/org/eclipse/sensinact/gateway/common/primitive/Elements.java
@@ -15,6 +15,7 @@
 
 import java.util.ArrayList;
 import java.util.Enumeration;
+import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -95,15 +96,12 @@
         if (name == null) {
             return null;
         }
-        int index = -1;
-        P element = null;
-
         synchronized (this.elements) {
-            if ((index = this.elements.indexOf(new Name<P>(name))) > -1) {
-                element = this.elements.get(index);
-            }
+        	return elements.stream()
+        			.filter(p -> name.equals(p.getName()))
+        			.findFirst()
+        			.orElse(null);
         }
-        return element;
     }
 
     /**
@@ -136,10 +134,13 @@
         if (element == null) {
             return false;
         }
+        String name = element.getName();
+        if(name == null) {
+        	return false;
+        }
         synchronized (this.elements) {
-            if (this.elements.indexOf(new Name<P>(element.getName())) == -1) {
-                this.elements.add(element);
-                return true;
+            if (this.elements.stream().noneMatch(p -> name.equals(p.getName()))) {
+                return this.elements.add(element);
             }
         }
         return false;
@@ -158,10 +159,14 @@
             return null;
         }
         synchronized (this.elements) {
-            int index = -1;
-            if ((index = this.elements.indexOf(new Name<Description>(element))) > -1) {
-                return this.elements.remove(index);
-            }
+        	Iterator<P> iterator = this.elements.iterator();
+        	while(iterator.hasNext()) {
+        		P p = iterator.next();
+        		if(element.equals(p.getName())) {
+        			iterator.remove();
+        			return p;
+        		}
+        	}
         }
         return null;
     }
diff --git a/platform/sensinact-common/src/main/java/org/eclipse/sensinact/gateway/common/primitive/Name.java b/platform/sensinact-common/src/main/java/org/eclipse/sensinact/gateway/common/primitive/Name.java
deleted file mode 100644
index 209eac7..0000000
--- a/platform/sensinact-common/src/main/java/org/eclipse/sensinact/gateway/common/primitive/Name.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-* Copyright (c) 2020 Kentyou.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
-*    Kentyou - initial API and implementation
- */
-package org.eclipse.sensinact.gateway.common.primitive;
-
-/**
- * String wrapper for equality evaluation purpose of
- * {@link Nameable} objects
- *
- * @author <a href="mailto:christophe.munilla@cea.fr">Christophe Munilla</a>
- */
-public class Name<N extends Nameable> {
-    private final String name;
-    private final boolean ignoreCase;
-
-    /**
-     * Constructor
-     *
-     * @param name the wrapped string name
-     */
-    public Name(String name) {
-        this(name, false);
-    }
-
-    /**
-     * Constructor
-     *
-     * @param name the wrapped string name
-     */
-    public Name(String name, boolean ignoreCase) {
-        this.name = name;
-        this.ignoreCase = ignoreCase;
-    }
-
-    /**
-     * @inheritDoc
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    public boolean equals(Object object) {
-        boolean equals = false;
-        if (this.name == null) {
-            return equals;
-        }
-        try {
-            @SuppressWarnings("unchecked") String name = ((N) object).getName();
-            if (ignoreCase) {
-                equals = this.name.equalsIgnoreCase(name);
-            } else {
-                equals = this.name.equals(name);
-            }
-
-        } catch (ClassCastException e) {
-            if (object.getClass() == String.class) {
-                if (ignoreCase) {
-                    equals = this.name.equalsIgnoreCase(((String) object));
-                } else {
-                    equals = this.name.equals(((String) object));
-                }
-            }
-        }
-        return equals;
-    }
-
-    /**
-     * @inheritDoc
-     * @see java.lang.Object#hashCode()
-     */
-    public int hashCode() {
-        return this.name.hashCode();
-    }
-}
diff --git a/platform/sensinact-common/src/main/java/org/eclipse/sensinact/gateway/common/props/TypedKey.java b/platform/sensinact-common/src/main/java/org/eclipse/sensinact/gateway/common/props/TypedKey.java
index be2521a..ce315e4 100644
--- a/platform/sensinact-common/src/main/java/org/eclipse/sensinact/gateway/common/props/TypedKey.java
+++ b/platform/sensinact-common/src/main/java/org/eclipse/sensinact/gateway/common/props/TypedKey.java
@@ -10,6 +10,8 @@
  */
 package org.eclipse.sensinact.gateway.common.props;
 
+import java.util.Objects;
+
 import org.eclipse.sensinact.gateway.common.primitive.Nameable;
 
 /**
@@ -49,32 +51,25 @@
         return this.type;
     }
 
-    /**
-     * @inheritDoc
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    public boolean equals(Object object) {
-        if (object == null) {
-            return false;
-        }
-        if (object.getClass() == String.class) {
-            return ((String) object).equals(this.name);
-        }
-        if (Nameable.class.isAssignableFrom(object.getClass())) {
-            return ((Nameable) object).getName().equals(this.name);
-        }
-        return false;
+    @Override
+    public boolean equals(Object obj) {
+    	if (this == obj)
+    		return true;
+    	if (obj == null)
+    		return false;
+    	if (getClass() != obj.getClass())
+    		return false;
+    	TypedKey<?> other = (TypedKey<?>) obj;
+    	return Objects.equals(name, other.name);
     }
 
-    /**
-     * @inheritDoc
-     * @see java.lang.Object#hashCode()
-     */
-    public int hashCode() {
-        return this.name.hashCode();
-    }
+    @Override
+	public int hashCode() {
+		return Objects.hash(name);
+	}
 
-    /**
+
+	/**
      * Returns false if this TypeKey has to appear
      * into the JSON formated string describing the
      * TypedProperties instance holding it; otherwise
diff --git a/platform/sensinact-common/src/main/java/org/eclipse/sensinact/gateway/common/props/TypedProperties.java b/platform/sensinact-common/src/main/java/org/eclipse/sensinact/gateway/common/props/TypedProperties.java
index 85fe5f8..5957dc0 100644
--- a/platform/sensinact-common/src/main/java/org/eclipse/sensinact/gateway/common/props/TypedProperties.java
+++ b/platform/sensinact-common/src/main/java/org/eclipse/sensinact/gateway/common/props/TypedProperties.java
@@ -13,9 +13,9 @@
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import org.eclipse.sensinact.gateway.common.primitive.JSONable;
-import org.eclipse.sensinact.gateway.common.primitive.Name;
 import org.eclipse.sensinact.gateway.util.CastUtils;
 import org.eclipse.sensinact.gateway.util.JSONUtils;
 
@@ -26,10 +26,37 @@
  * @author <a href="mailto:christophe.munilla@cea.fr">Christophe Munilla</a>
  */
 public abstract class TypedProperties<T extends Enum<T> & KeysCollection> implements JSONable {
+	
+	private static class TypedKeyValue implements Entry<TypedKey<?>, Object>{
+		private final TypedKey<?> key;
+		private final Object value;
+		
+		public TypedKeyValue(TypedKey<?> key, Object value) {
+			this.key = key;
+			this.value = value;
+		}
+
+		@Override
+		public TypedKey<?> getKey() {
+			return key;
+		}
+
+		@Override
+		public Object getValue() {
+			return value;
+		}
+
+		@Override
+		public Object setValue(Object value) {
+			throw new UnsupportedOperationException("Changing the value via the iterator is not supported");
+		}
+	}
+	
     protected static final String TYPE = "type";
 
-    protected final Map<TypedKey<?>, Object> properties;
+    private final Map<String,Entry<TypedKey<?>, Object>> properties;
 
+    private final T type;
 
     /**
      * Constructor
@@ -37,13 +64,9 @@
      * @param type      the type of this event
      */
     public TypedProperties(T type) {
-        this.properties = new HashMap<TypedKey<?>, Object>();
-        TypedKey<?> key = type.key(TypedProperties.TYPE);
-        if (key == null) {
-            this.putValue(new TypedKey<T>(TypedProperties.TYPE, (Class<T>) type.getClass(), false), type);
-        } else {
-            this.putValue(key, type);
-        }
+        this.properties = new HashMap<>();
+        this.type = type;
+        putValue(TYPE, type);
     }
 
     /**
@@ -53,7 +76,7 @@
     @Override
     public String getJSON() {
         StringBuilder builder = new StringBuilder();
-        Iterator<Map.Entry<TypedKey<?>, Object>> iterator = this.properties.entrySet().iterator();
+        Iterator<Entry<TypedKey<?>, Object>> iterator = this.properties.values().iterator();
 
         builder.append(JSONUtils.OPEN_BRACE);
         int index = 0;
@@ -86,7 +109,7 @@
      * @param value the value to set
      */
     protected void putValue(TypedKey<?> key, Object value) {
-        this.properties.put(key, value);
+        this.properties.put(key.getName(), new TypedKeyValue(key, value));
     }
 
     /**
@@ -142,11 +165,15 @@
      *               created if relevant
      */
     public void put(String key, Object value, boolean hidden) {
-        if (!this.getType().keys().contains(new Name<TypedKey<?>>(key))) {
+        if (notPresentInType(key)) {
             this.putValue(key, value, hidden);
         }
     }
 
+	private boolean notPresentInType(String key) {
+		return this.getType().keys().stream().noneMatch(k -> k.getName().equals(key));
+	}
+
     /**
      * Removes from the key (and its associated value) from
      * this TypedProperties
@@ -154,10 +181,12 @@
      * @param key the key of the property to remove
      */
     public Object remove(String key) {
-        if (!this.getType().keys().contains(new Name<TypedKey<?>>(key))) {
-            return this.properties.remove(key);
+    	Object value = null;
+        if (notPresentInType(key)) {
+        	Entry<TypedKey<?>, Object> e = this.properties.remove(key);
+            value = e == null ? null : e.getValue(); 
         }
-        return null;
+        return value;
     }
 
     /**
@@ -168,22 +197,21 @@
      * property
      */
     @SuppressWarnings("unchecked")
-    public <V> V get(String key) {
-        TypedKey<V> typedKey = null;
+	public <V> V get(String key) {
 
-        Object object = this.properties.get(new Name<TypedKey<?>>(key));
-        try {
-            typedKey = (TypedKey<V>) this.getType().key(key);
-
-        } finally {
-            if (object == null) {
-                return (V) object;
-            }
-            if (typedKey != null && !typedKey.getType().isAssignableFrom(object.getClass())) {
-                return CastUtils.cast(typedKey.getType(), object);
-            }
+    	Entry<TypedKey<?>, Object> e = this.properties.get(key);
+    	
+        if (e == null) {
+        	return null;
         }
-        return (V) object;
+        
+        Class<?> type = e.getKey().getType();
+        Object value = e.getValue();
+        
+        if (!type.isInstance(value)) {
+        	return (V) CastUtils.cast(type, value);
+        }
+        return (V) e.getValue();
     }
 
     /**
@@ -192,6 +220,10 @@
      * @return this TypedProperties type
      */
     public T getType() {
-        return (T) this.properties.get(new Name<TypedKey>(TypedProperties.TYPE));
+        return type;
+    }
+    
+    protected Iterator<Map.Entry<TypedKey<?>, Object>> typedKeyValues() {
+    	return ((Map<String, Entry<TypedKey<?>, Object>>)properties).values().iterator();
     }
 }
diff --git a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/Attribute.java b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/Attribute.java
index 77a568f..0ebbfca 100644
--- a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/Attribute.java
+++ b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/Attribute.java
@@ -21,7 +21,6 @@
 import org.eclipse.sensinact.gateway.common.primitive.Description;
 import org.eclipse.sensinact.gateway.common.primitive.InvalidValueException;
 import org.eclipse.sensinact.gateway.common.primitive.Modifiable;
-import org.eclipse.sensinact.gateway.common.primitive.Name;
 import org.eclipse.sensinact.gateway.common.primitive.Primitive;
 import org.eclipse.sensinact.gateway.common.primitive.PrimitiveDescription;
 import org.eclipse.sensinact.gateway.util.CastUtils;
@@ -147,23 +146,24 @@
 		}
 		// modifiable Metadata added only if it does not already exist
 		// it is not overridden if defined as modifiable
-		if (!this.metadata.contains(new Name<Metadata>(Metadata.MODIFIABLE))) {
+		
+		if (this.metadata.stream().noneMatch(m -> Metadata.MODIFIABLE.equals(m.getName()))) {
 			Metadata modifiableMeta = new Metadata(super.mediator, Metadata.MODIFIABLE, Modifiable.class,
 					Modifiable.MODIFIABLE, Modifiable.FIXED);
 			this.addMetadata(modifiableMeta);
 		}
 		// hidden Metadata added only if it does not already exist
 		// it is not overridden if defined as modifiable
-		if (!this.metadata.contains(new Name<Metadata>(Metadata.HIDDEN))) {
+		if (this.metadata.stream().noneMatch(m -> Metadata.HIDDEN.equals(m.getName()))) {
 			Metadata hiddenMeta = new Metadata(super.mediator, Metadata.HIDDEN, boolean.class, false, Modifiable.FIXED);
 			this.addMetadata(hiddenMeta);
 		}
-		if (!this.metadata.contains(new Name<Metadata>(Metadata.TIMESTAMP))) {
+		if (this.metadata.stream().noneMatch(m -> Metadata.TIMESTAMP.equals(m.getName()))) {
 			Metadata timestampMeta = new Metadata(super.mediator, Metadata.TIMESTAMP, long.class,
 					System.currentTimeMillis(), Modifiable.UPDATABLE);
 			this.addMetadata(timestampMeta);
 		}
-		if (!this.metadata.contains(new Name<Metadata>(Metadata.LOCKED))) {
+		if (this.metadata.stream().noneMatch(m -> Metadata.LOCKED.equals(m.getName()))) {
 			Metadata lockedMeta = new Metadata(super.mediator, Metadata.LOCKED, boolean.class, false,
 					Modifiable.UPDATABLE);
 			this.addMetadata(lockedMeta);
@@ -460,14 +460,12 @@
 	 * @return the {@link Metadata} with the specified name
 	 */
 	protected Metadata get(String name) {
-		int index = -1;
-		Metadata metadata = null;
 		synchronized (this.metadata) {
-			if ((index = this.metadata.indexOf(new Name<Attribute>(name))) != -1) {
-				metadata = this.metadata.get(index);
-			}
+			return this.metadata.stream()
+				.filter(m -> m.getName().equals(name))
+				.findFirst()
+				.orElse(null);
 		}
-		return metadata;
 	}
 
 	/**
diff --git a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/ModelElement.java b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/ModelElement.java
index 3305824..ce029d5 100644
--- a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/ModelElement.java
+++ b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/ModelElement.java
@@ -24,7 +24,6 @@
 import org.eclipse.sensinact.gateway.common.execution.Executable;
 import org.eclipse.sensinact.gateway.common.primitive.Elements;
 import org.eclipse.sensinact.gateway.common.primitive.ElementsProxy;
-import org.eclipse.sensinact.gateway.common.primitive.Name;
 import org.eclipse.sensinact.gateway.common.primitive.Nameable;
 import org.eclipse.sensinact.gateway.common.primitive.ProcessableData;
 import org.eclipse.sensinact.gateway.core.message.SnaConstants;
@@ -294,13 +293,15 @@
 		Class<S> proxied = (Class<S>) this.getProxyType();
 		M proxy = this.proxies.get(accessLevelOption);
 		if (proxy == null) {
-			int index = -1;
 			List<MethodAccessibility> methodAccessibilities = this.modelInstance.getAuthorizations(this, accessLevelOption);
-
+			
 			// if the describe method does not exists it means
 			// that the user is not allowed to access this ModelElement
-			if ((index = methodAccessibilities.indexOf(new Name<MethodAccessibility>(AccessMethod.DESCRIBE))) == -1
-					|| !methodAccessibilities.get(index).isAccessible()) {
+			if (methodAccessibilities.stream()
+					.filter(ma -> AccessMethod.DESCRIBE.equals(ma.getName()))
+					.map(ma -> !ma.isAccessible())
+					.findFirst()
+					.orElse(true)) {
 				return (S) Proxy.newProxyInstance(ModelElement.class.getClassLoader(), new Class<?>[] { proxied },
 						new UnaccessibleModelElementProxyWrapper(new UnaccessibleModelElementProxy(
 								this.modelInstance.mediator(), proxied, this.getPath())));
diff --git a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/RequirementBuilder.java b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/RequirementBuilder.java
index d4b88f3..72853a1 100644
--- a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/RequirementBuilder.java
+++ b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/RequirementBuilder.java
@@ -16,7 +16,6 @@
 import java.util.Map;
 
 import org.eclipse.sensinact.gateway.common.primitive.Modifiable;
-import org.eclipse.sensinact.gateway.common.primitive.Name;
 import org.eclipse.sensinact.gateway.common.primitive.Nameable;
 
 /**
@@ -81,10 +80,10 @@
 	 * @param builders
 	 */
 	public void apply(String service, List<AttributeBuilder> builders) {
-		int index = builders.indexOf(new Name<AttributeBuilder>(this.attributeName));
-		if (index == -1) 
-			return;		
-		this.apply(service, builders.get(index));
+		builders.stream()
+			.filter(b -> this.attributeName.equals(b.getName()))
+			.findFirst()
+			.ifPresent(b -> this.apply(service, b));
 	}
 
 	/**
diff --git a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/ResourceConfig.java b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/ResourceConfig.java
index d7102f9..69e3309 100644
--- a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/ResourceConfig.java
+++ b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/ResourceConfig.java
@@ -16,8 +16,8 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 
-import org.eclipse.sensinact.gateway.common.primitive.Name;
 import org.eclipse.sensinact.gateway.common.primitive.Nameable;
 import org.eclipse.sensinact.gateway.core.AttributeBuilder.Requirement;
 import org.eclipse.sensinact.gateway.core.Resource.UpdatePolicy;
@@ -52,11 +52,13 @@
 	public String buildName(String service) {			
 		if (service == null || service.length() == 0) 
 			return null;	
-		String name = null;
-		int index = -1;
-		if ((index = this.requirementBuilders.indexOf(new Name<RequirementBuilder>(Resource.NAME))) > -1)
-			name = ((StringPatternValue) this.requirementBuilders.get(index).get(service)).build();
-		return name;
+		return this.requirementBuilders.stream()
+				.filter(rb -> Resource.NAME.equals(rb.getName()))
+				.map(rb -> rb.get(service))
+				.map(StringPatternValue.class::cast)
+				.map(StringPatternValue::build)
+				.findFirst()
+				.orElse(null);
 	}
 	
 	@Override
@@ -70,11 +72,13 @@
 	public String getName(String service) {			
 		if (service == null || service.length() == 0) 
 			return this.getName(ResourceConfig.ALL_TARGETS);		
-		String name = null;
-		int index = -1;
-		if ((index = this.requirementBuilders.indexOf(new Name<RequirementBuilder>(Resource.NAME))) > -1)
-			name = ((StringPatternValue) this.requirementBuilders.get(index).get(service)).getLast();
-		return name;
+		return this.requirementBuilders.stream()
+				.filter(rb -> Resource.NAME.equals(rb.getName()))
+				.map(rb -> rb.get(service))
+				.map(StringPatternValue.class::cast)
+				.map(StringPatternValue::getLast)
+				.findFirst()
+				.orElse(null);
 	}
 
 
@@ -85,11 +89,13 @@
 	public String getRawName(String serviceName) {	
 		if (serviceName == null || serviceName.length() == 0) 
 			return this.getRawName(ResourceConfig.ALL_TARGETS);		
-		String name = null;
-		int index = -1;
-		if ((index = this.requirementBuilders.indexOf(new Name<RequirementBuilder>(Resource.NAME))) > -1)
-			name = ((StringPatternValue) this.requirementBuilders.get(index).get(serviceName)).getRaw();
-		return name;
+		return this.requirementBuilders.stream()
+			.filter(rb -> Resource.NAME.equals(rb.getName()))
+			.map(rb -> rb.get(serviceName))
+			.map(StringPatternValue.class::cast)
+			.map(StringPatternValue::getRaw)
+			.findFirst()
+			.orElse(null);
 	}
 
 	/**
@@ -99,9 +105,11 @@
 	 * @param name the name to be set
 	 */
 	public void configureName(String service, String name) {
-		int index = -1;
-		if ((index = this.requirementBuilders.indexOf(new Name<RequirementBuilder>(Resource.NAME))) > -1) 
-			this.requirementBuilders.get(index).put(service, name);
+		Optional<RequirementBuilder> found = this.requirementBuilders.stream()
+			.filter(rb -> Resource.NAME.equals(rb.getName()))
+			.findFirst();
+		if (found.isPresent()) 
+			found.get().put(service, name);
 		else {
 			RequirementBuilder builder = new RequirementBuilder(Requirement.VALUE, Resource.NAME);
 			builder.put(service, name);
diff --git a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/ResourceProxy.java b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/ResourceProxy.java
index 2734f4c..56713e1 100644
--- a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/ResourceProxy.java
+++ b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/ResourceProxy.java
@@ -16,7 +16,6 @@
 import java.util.Map;
 
 import org.eclipse.sensinact.gateway.common.bundle.Mediator;
-import org.eclipse.sensinact.gateway.common.primitive.Name;
 import org.eclipse.sensinact.gateway.core.method.AccessMethod;
 import org.eclipse.sensinact.gateway.core.method.UnaccessibleAccessMethod;
 import org.eclipse.sensinact.gateway.core.security.MethodAccessibility;
@@ -41,7 +40,7 @@
 	ResourceProxy(Mediator mediator, ResourceImpl resource, List<MethodAccessibility> methodAccessibilities) {
 		super(mediator, Resource.class, resource.getPath());
 
-		Map<String, AccessMethod<?,?>> methods = new HashMap<String, AccessMethod<?,?>>();
+		Map<String, AccessMethod<?,?>> methods = new HashMap<>();
 		AccessMethod.Type[] existingTypes = AccessMethod.Type.values();
 
 		int index = 0;
@@ -52,16 +51,19 @@
 			if ((method = resource.getAccessMethod(existingTypes[index])) == null) {
 				continue;
 			}
-			int accessIndex = -1;
-
-			if ((accessIndex = methodAccessibilities.indexOf(new Name<MethodAccessibility>(existingTypes[index].name()))) == -1
-					|| !methodAccessibilities.get(accessIndex).isAccessible()) {
+			String name = existingTypes[index].name();
+			
+			if (methodAccessibilities.stream()
+					.filter(ma -> name.equals(ma.getName()))
+					.map(ma -> !ma.isAccessible())
+					.findFirst()
+					.orElse(true)) {
 				methods.put(existingTypes[index].name(),new UnaccessibleAccessMethod(mediator, super.getPath(), existingTypes[index]));
 			} else {
 				methods.put(existingTypes[index].name(), method);
 			}
 		}
-		this.methods = Collections.<String, AccessMethod<?,?>>unmodifiableMap(methods);
+		this.methods = Collections.unmodifiableMap(methods);
 	}
 
 	@Override
diff --git a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/message/SnaMessageListener.java b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/message/SnaMessageListener.java
index 0460aa0..6d500c2 100644
--- a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/message/SnaMessageListener.java
+++ b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/message/SnaMessageListener.java
@@ -21,7 +21,6 @@
 
 import org.eclipse.sensinact.gateway.common.bundle.Mediator;
 import org.eclipse.sensinact.gateway.common.execution.Executable;
-import org.eclipse.sensinact.gateway.common.primitive.Name;
 import org.eclipse.sensinact.gateway.core.SensiNactResourceModelConfiguration;
 import org.eclipse.sensinact.gateway.core.method.AccessMethod;
 import org.eclipse.sensinact.gateway.core.method.AccessMethodResponse;
@@ -98,15 +97,20 @@
 		synchronized (this.callbacks) {
 			Iterator<Entry<SnaFilter, List<MidCallback>>> iterator = this.callbacks.entrySet().iterator();
 
-			while (iterator.hasNext()) {
+			outer: while (iterator.hasNext()) {
 				Entry<SnaFilter, List<MidCallback>> entry = iterator.next();
 
 				List<MidCallback> list = entry.getValue();
-				if (list.remove(new Name<MidCallback>(callback))) {
-					if (list.isEmpty()) {
-						iterator.remove();
+				Iterator<MidCallback> it2 = list.iterator();
+				while(it2.hasNext()) {
+					MidCallback mid = it2.next();
+					if(mid.getName().equals(callback)) {
+						it2.remove();
+						if (list.isEmpty()) {
+							iterator.remove();
+						}
+						break outer;
 					}
-					break;
 				}
 			}
 		}
@@ -247,7 +251,6 @@
 						public Void execute(SnaAgent agent) throws Exception {	
 							String agentKey = agent.getPublicKey();						
 							List<MethodAccessibility> methodAccessibilities = SnaMessageListener.this.agentsAccessibility.get(agentKey);
-							int index = -1;
 							if (methodAccessibilities == null) {
 								AccessLevelOption option = SnaMessageListener.this.configuration.getAuthenticatedAccessLevelOption(path, agentKey);
 								if (option == null) {
@@ -255,9 +258,13 @@
 								}
 								methodAccessibilities = SnaMessageListener.this.configuration.getAccessibleMethods(path, option);
 								SnaMessageListener.this.agentsAccessibility.put(agentKey, methodAccessibilities);
-							}						
-							if ((index = methodAccessibilities.indexOf(new Name<MethodAccessibility>(method))) > -1
-									&& methodAccessibilities.get(index).isAccessible()) {
+							}
+							
+							if (methodAccessibilities.stream()
+									.filter(ma -> method.equals(ma.getName()))
+									.map(MethodAccessibility::isAccessible)
+									.findFirst()
+									.orElse(false)) {
 								agent.register(message);
 							}
 							return null;
diff --git a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/method/ActResponse.java b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/method/ActResponse.java
index 3cb9eba..cdd1ae4 100644
--- a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/method/ActResponse.java
+++ b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/method/ActResponse.java
@@ -53,7 +53,7 @@
 	 */
 	@SuppressWarnings("unchecked")
 	public JSONArray getTriggers() {
-		List<String> triggered = (List<String>) super.properties.get(SnaConstants.TRIGGERED_KEY);
+		List<String> triggered = this.<List<String>>get(SnaConstants.TRIGGERED_KEY);
 
 		if (triggered == null) {
 			triggered = new ArrayList<String>();
@@ -70,7 +70,7 @@
 	 *            {@link StateVariableResource}
 	 */
 	public void addTriggered(String trigger) {
-		List<String> triggered = (List<String>) super.properties.get(SnaConstants.TRIGGERED_KEY);
+		List<String> triggered = this.<List<String>>get(SnaConstants.TRIGGERED_KEY);
 
 		if (triggered == null) {
 			triggered = new ArrayList<String>();
diff --git a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/method/DescribeResponse.java b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/method/DescribeResponse.java
index 0b86307..24bd7a4 100644
--- a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/method/DescribeResponse.java
+++ b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/method/DescribeResponse.java
@@ -75,7 +75,7 @@
 			return JSONUtils.toJSONFormat(super.get("response"));
 		}
 		StringBuilder builder = new StringBuilder();
-		Iterator<Map.Entry<TypedKey<?>, Object>> iterator = super.properties.entrySet().iterator();
+		Iterator<Map.Entry<TypedKey<?>, Object>> iterator = typedKeyValues();
 
 		builder.append(JSONUtils.OPEN_BRACE);
 		int index = 0;
diff --git a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/method/RemoteAccessMethodExecutable.java b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/method/RemoteAccessMethodExecutable.java
index 4e55ae1..51c18ab 100644
--- a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/method/RemoteAccessMethodExecutable.java
+++ b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/method/RemoteAccessMethodExecutable.java
@@ -15,7 +15,6 @@
 
 import org.eclipse.sensinact.gateway.common.bundle.Mediator;
 import org.eclipse.sensinact.gateway.common.execution.Executable;
-import org.eclipse.sensinact.gateway.common.primitive.Name;
 import org.eclipse.sensinact.gateway.common.props.TypedKey;
 import org.eclipse.sensinact.gateway.core.message.Recipient;
 import org.eclipse.sensinact.gateway.core.method.AccessMethod.Type;
@@ -94,21 +93,6 @@
 		return this;
 	}
 
-	protected <P> P get(String name) {
-		Object o = this.props.get(new Name<TypedKey<P>>(name));
-		try {
-			P p = (P) o;
-			return p;
-		} catch (ClassCastException e) {
-		}
-		return (P) null;
-	}
-
-	protected <P> P get(TypedKey<P> key) {
-		P p = (P) this.props.get(key);
-		return p;
-	}
-
 	/**
 	 * @inheritDoc
 	 *
@@ -125,14 +109,14 @@
 		switch (this.method.name()) {
 		case "ACT":
 			json = core.act(publicKey, provider, service, resource, CastUtils.cast(
-					JSONArray.class, this.<Object[]>get(ARGUMENTS_TK)).toString());
+					JSONArray.class, this.props.get(ARGUMENTS_TK)).toString());
 			break;
 		case "GET":
 			json = core.get(publicKey, provider, service, resource, attribute);
 			break;
 		case "SET":
 			json = core.set(publicKey, provider, service, resource, attribute, CastUtils.cast(
-					JSONArray.class, this.<Object>get(VALUE_TK)).toString());
+					JSONArray.class, this.props.get(VALUE_TK)).toString());
 			break;
 		case "SUBSCRIBE":
 		case "UNSUBSCRIBE":
diff --git a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/security/AccessNodeImpl.java b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/security/AccessNodeImpl.java
index 69a6636..52a57ec 100644
--- a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/security/AccessNodeImpl.java
+++ b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/security/AccessNodeImpl.java
@@ -10,15 +10,18 @@
  */
 package org.eclipse.sensinact.gateway.core.security;
 
+import static java.util.Collections.emptyList;
+import static java.util.Optional.ofNullable;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.EnumMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 
-import org.eclipse.sensinact.gateway.common.primitive.Name;
 import org.eclipse.sensinact.gateway.core.ModelElement;
 import org.eclipse.sensinact.gateway.core.method.AccessMethod;
 import org.eclipse.sensinact.gateway.core.method.AccessMethod.Type;
@@ -211,17 +214,19 @@
 	 *         </ul>
 	 */
 	protected boolean isAccessibleMethod(AccessMethod.Type accessMethod, AccessLevelOption optionLevel) {
-		int index = -1;
 		boolean accessible = false;
 
-		List<MethodAccessibility> methodAccesses;
+		List<MethodAccessibility> methodAccesses = accesses == null ? emptyList() :
+			ofNullable(accesses.get(optionLevel)).orElse(emptyList()); 
 
-		if (this.accesses == null || (methodAccesses = this.accesses.get(optionLevel)) == null
-				|| (index = methodAccesses.indexOf(new Name<MethodAccessibility>(accessMethod.name()))) == -1) {
-			accessible = super.parent == null ? false : super.parent.isAccessibleMethod(accessMethod, optionLevel);
+		Optional<MethodAccessibility> found = methodAccesses.stream()
+				.filter(ma -> ma.getName().equals(accessMethod.name()))
+				.findFirst();
+		
+		if (found.isPresent()) {
+			accessible = found.get().isAccessible();
 		} else {
-			MethodAccessibility access = methodAccesses.get(index);
-			accessible = access == null ? false : access.isAccessible();
+			accessible = super.parent == null ? false : super.parent.isAccessibleMethod(accessMethod, optionLevel);
 		}
 		return accessible;
 	}
diff --git a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/security/ImmutableAccessNode.java b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/security/ImmutableAccessNode.java
index 780d18b..84cd0e2 100644
--- a/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/security/ImmutableAccessNode.java
+++ b/platform/sensinact-core/src/main/java/org/eclipse/sensinact/gateway/core/security/ImmutableAccessNode.java
@@ -10,6 +10,9 @@
  */

 package org.eclipse.sensinact.gateway.core.security;

 

+import static java.util.Collections.emptyList;

+import static java.util.Optional.ofNullable;

+

 import java.util.ArrayList;

 import java.util.Arrays;

 import java.util.Collections;

@@ -17,9 +20,9 @@
 import java.util.Iterator;

 import java.util.List;

 import java.util.Map;

+import java.util.Optional;

 import java.util.Set;

 

-import org.eclipse.sensinact.gateway.common.primitive.Name;

 import org.eclipse.sensinact.gateway.core.ModelElement;

 import org.eclipse.sensinact.gateway.core.method.AccessMethod;

 import org.eclipse.sensinact.gateway.core.method.AccessMethod.Type;

@@ -179,17 +182,19 @@
 	 *         </ul>

 	 */

 	protected boolean isAccessibleMethod(AccessMethod.Type accessMethod, AccessLevelOption optionLevel) {

-		int index = -1;

 		boolean accessible = false;

 

-		List<MethodAccessibility> methodAccesses;

+		List<MethodAccessibility> methodAccesses = accesses == null ? emptyList() :

+			ofNullable(accesses.get(optionLevel)).orElse(emptyList()); 

 

-		if (this.accesses == null || (methodAccesses = this.accesses.get(optionLevel)) == null

-				|| (index = methodAccesses.indexOf(new Name<MethodAccessibility>(accessMethod.name()))) == -1) {

-			accessible = super.parent == null ? false : super.parent.isAccessibleMethod(accessMethod, optionLevel);

+		Optional<MethodAccessibility> found = methodAccesses.stream()

+				.filter(ma -> ma.getName().equals(accessMethod.name()))

+				.findFirst();

+		

+		if (found.isPresent()) {

+			accessible = found.get().isAccessible();

 		} else {

-			MethodAccessibility access = methodAccesses.get(index);

-			accessible = access == null ? false : access.isAccessible();

+			accessible = super.parent == null ? false : super.parent.isAccessibleMethod(accessMethod, optionLevel);

 		}

 		return accessible;

 	}

diff --git a/platform/sensinact-generic/src/main/java/org/eclipse/sensinact/gateway/generic/ExtResourceConfig.java b/platform/sensinact-generic/src/main/java/org/eclipse/sensinact/gateway/generic/ExtResourceConfig.java
index 7609b43..856e70c 100644
--- a/platform/sensinact-generic/src/main/java/org/eclipse/sensinact/gateway/generic/ExtResourceConfig.java
+++ b/platform/sensinact-generic/src/main/java/org/eclipse/sensinact/gateway/generic/ExtResourceConfig.java
@@ -11,7 +11,6 @@
 package org.eclipse.sensinact.gateway.generic;
 
 import org.eclipse.sensinact.gateway.common.bundle.Mediator;
-import org.eclipse.sensinact.gateway.common.primitive.Name;
 import org.eclipse.sensinact.gateway.core.AttributeBuilder;
 import org.eclipse.sensinact.gateway.core.RequirementBuilder;
 import org.eclipse.sensinact.gateway.core.ResourceConfig;
@@ -33,6 +32,7 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Optional;
 
 /**
  * Extended {@link ExtResourceConfig} generated from an xml file
@@ -155,9 +155,12 @@
             AttributeDefinition attributeDefinition = iterator.next();
             if (!attributeDefinition.isTargeted(service))
                 continue;
-            int builderIndex = -1;
-            if ((builderIndex = builders.indexOf(new Name<AttributeBuilder>(attributeDefinition.getName()))) > -1) {
-                AttributeBuilder builder = builders.get(builderIndex);
+            String name = attributeDefinition.getName();
+            Optional<AttributeBuilder> found = builders.stream()
+            	.filter(b -> name.equals(b.getName()))
+            	.findFirst();
+            if (found.isPresent()) {
+                AttributeBuilder builder = found.get();
                 List<RequirementBuilder> requirementBuilders = attributeDefinition.getRequirementBuilders(service);
                 int index = 0;
                 int length = requirementBuilders.size();
diff --git a/platform/sensinact-generic/src/main/java/org/eclipse/sensinact/gateway/generic/packet/PayloadFragmentImpl.java b/platform/sensinact-generic/src/main/java/org/eclipse/sensinact/gateway/generic/packet/PayloadFragmentImpl.java
index 0463747..d3e8bff 100644
--- a/platform/sensinact-generic/src/main/java/org/eclipse/sensinact/gateway/generic/packet/PayloadFragmentImpl.java
+++ b/platform/sensinact-generic/src/main/java/org/eclipse/sensinact/gateway/generic/packet/PayloadFragmentImpl.java
@@ -14,8 +14,6 @@
 import java.util.Iterator;
 import java.util.List;
 
-import org.eclipse.sensinact.gateway.common.primitive.Name;
-
 /**
  * Implementation of a {@link PayloadFragment}
  *
@@ -40,7 +38,7 @@
 
      */
     public PayloadFragmentImpl() {
-        this.payloadFragments = new ArrayList<PayloadServiceFragment>();
+        this.payloadFragments = new ArrayList<>();
     }
 
     /**
@@ -192,30 +190,4 @@
     public String getName() {
         return this.getServiceProviderIdentifier();
     }
-
-    /**
-     * Returns the index of the {@link PayloadServiceFragment} of
-     * this PayloadFragment, whose name is passed as parameter  
-     * 
-     * @param name the name of the {@link PayloadServiceFragment}
-     * 
-     * @return the index of the {@link PayloadServiceFragment} with
-     * the specified name
-     */
-    public int indexOf(Name<PayloadServiceFragment> name) {
-        return this.payloadFragments.indexOf(name);
-    }
-
-    /**
-     * Returns the {@link PayloadServiceFragment} of this {@link PayloadFragment}
-     * at the index passed as parameter  
-     * 
-     * @param index the index of the {@link PayloadServiceFragment}
-     * 
-     * @return the {@link PayloadServiceFragment} with
-     * the specified index
-     */
-    public PayloadServiceFragmentImpl get(int index) {
-        return (PayloadServiceFragmentImpl) this.payloadFragments.get(index);
-    }
 }
diff --git a/platform/sensinact-generic/src/main/java/org/eclipse/sensinact/gateway/generic/packet/SimplePacketReader.java b/platform/sensinact-generic/src/main/java/org/eclipse/sensinact/gateway/generic/packet/SimplePacketReader.java
index 35afcb3..373af30 100644
--- a/platform/sensinact-generic/src/main/java/org/eclipse/sensinact/gateway/generic/packet/SimplePacketReader.java
+++ b/platform/sensinact-generic/src/main/java/org/eclipse/sensinact/gateway/generic/packet/SimplePacketReader.java
@@ -10,7 +10,8 @@
  */
 package org.eclipse.sensinact.gateway.generic.packet;
 
-import org.eclipse.sensinact.gateway.common.primitive.Name;
+import java.util.Optional;
+
 import org.eclipse.sensinact.gateway.generic.Task.CommandType;
 import org.eclipse.sensinact.gateway.generic.TaskManager;
 
@@ -168,7 +169,6 @@
      * Creates the SubPacket, PayloadFragment and PayloadAttributeFragment
      */
     protected void configure() {
-        boolean isNewPayloadFragment = false;
         PayloadFragmentImpl subPacket = null;
         
         if (this.serviceProviderId == null) {
@@ -181,7 +181,6 @@
         subPacket.isGoodbyeMessage(this.isGoodbyeMessage);
         subPacket.isHelloMessage(this.isHelloMessage);
         
-        PayloadServiceFragmentImpl payloadFragment = null;
         StringBuilder builder = new StringBuilder();
         if (this.command != null) {
             builder.append(this.command.name());
@@ -195,28 +194,32 @@
         }
         if (this.resourceId != null) 
             builder.append(this.resourceId);
-        int index = -1;
+
         String name = builder.toString();
         
         if (name.length() > 0) {
-            if ((index = subPacket.payloadFragments.indexOf(new Name<PayloadServiceFragment>(name))) != -1)
-                payloadFragment = (PayloadServiceFragmentImpl) subPacket.payloadFragments.get(index);
-            else {
+        	PayloadServiceFragmentImpl payloadFragment = null;
+
+        	Optional<PayloadServiceFragmentImpl> found = subPacket.payloadFragments.stream()
+        		.filter(PayloadServiceFragmentImpl.class::isInstance)
+        		.map(PayloadServiceFragmentImpl.class::cast)
+        		.filter(psf -> psf.getName().equals(name))
+        		.findFirst();
+            if (found.isPresent()) {
+            	payloadFragment = found.get();
+            } else {
                 payloadFragment = newPayloadFragment();
                 payloadFragment.setCommand(this.command);
                 payloadFragment.setServiceId(this.serviceId);
                 payloadFragment.setResourceId(this.resourceId);
-                isNewPayloadFragment = true;
-            }
-        }
-        if (payloadFragment != null) {
-            if (this.attributeId != null || this.data != null) {
-                PayloadResourceFragmentImpl payloadAttributeFragment = newPayloadAttributeFragment(this.attributeId, this.metadataId, this.data);
-                payloadAttributeFragment.setTimestamp(this.timestamp);
-                payloadFragment.addPayloadAttributeFragment(payloadAttributeFragment);
-            }
-            if (isNewPayloadFragment) 
                 subPacket.addPayloadFragment(payloadFragment);
+            }
+            
+            if (this.attributeId != null || this.data != null) {
+            	PayloadResourceFragmentImpl payloadAttributeFragment = newPayloadAttributeFragment(this.attributeId, this.metadataId, this.data);
+            	payloadAttributeFragment.setTimestamp(this.timestamp);
+            	payloadFragment.addPayloadAttributeFragment(payloadAttributeFragment);
+            }
         }
         reset();
         super.setSubPacket(subPacket);