/* * $Id$ * This file is a part of the Arakhne Foundation Classes, http://www.arakhne.org/afc * * Copyright (c) 2000-2012 Stephane GALLAND. * Copyright (c) 2005-10, Multiagent Team, Laboratoire Systemes et Transports, * Universite de Technologie de Belfort-Montbeliard. * Copyright (c) 2013-2016 The original authors, and other authors. * * Licensed 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.arakhne.afc.attrs.collection; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.URI; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; import java.util.UUID; import org.eclipse.xtext.xbase.lib.Pure; import org.arakhne.afc.attrs.attr.Attribute; import org.arakhne.afc.attrs.attr.AttributeException; import org.arakhne.afc.attrs.attr.AttributeImpl; import org.arakhne.afc.attrs.attr.AttributeNotInitializedException; import org.arakhne.afc.attrs.attr.AttributeType; import org.arakhne.afc.attrs.attr.AttributeValue; import org.arakhne.afc.attrs.attr.AttributeValueImpl; import org.arakhne.afc.attrs.attr.InvalidAttributeTypeException; import org.arakhne.afc.ui.vector.Color; import org.arakhne.afc.ui.vector.Image; /** * This class implements an attribute provider which * only works with the Heap space. * * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ */ @SuppressWarnings("deprecation") public class HeapAttributeCollection extends AbstractAttributeCollection { private static final long serialVersionUID = 4362736589775617590L; private Map<String, Object> heap = new TreeMap<>(new AttributeNameStringComparator()); /** Make a deep copy of this object and replies the copy. * * @return the deep copy. */ @Pure @Override public HeapAttributeCollection clone() { final HeapAttributeCollection clone = (HeapAttributeCollection) super.clone(); clone.heap = new TreeMap<>(new AttributeNameStringComparator()); clone.heap.putAll(this.heap); return clone; } @Override public void addAttributes(Map<String, Object> content) { for (final Entry<String, Object> pair : content.entrySet()) { Object value = pair.getValue(); final AttributeType type = AttributeType.fromValue(value); value = type.cast(value); final Object oldValue = this.heap.put(pair.getKey(), value); if (oldValue == null) { fireAttributeAddedEvent(pair.getKey(), new AttributeValueImpl(type, value)); } else { fireAttributeChangedEvent(pair.getKey(), new AttributeValueImpl(type, oldValue), new AttributeValueImpl(type, value)); } } } @Override public void addAttributes(AttributeProvider content) throws AttributeException { for (final Attribute attr : content.attributes()) { final Object value = attr.getValue(); final Object oldValue = this.heap.put(attr.getName(), value); if (oldValue == null) { fireAttributeAddedEvent(attr.getName(), new AttributeValueImpl(attr.getType(), value)); } else { fireAttributeChangedEvent(attr.getName(), new AttributeValueImpl(AttributeType.fromValue(oldValue), oldValue), new AttributeValueImpl(attr.getType(), value)); } } } @Override public void setAttributes(Map<String, Object> content) { setAttributesInternal(new TreeMap<>(content)); } @Override public void setAttributes(AttributeProvider content) throws AttributeException { final Map<String, Object> newAttributes = new TreeMap<>(); content.toMap(newAttributes); setAttributesInternal(newAttributes); } private void setAttributesInternal(Map<String, Object> newAttributes) { final Iterator<Entry<String, Object>> iterator = this.heap.entrySet().iterator(); while (iterator.hasNext()) { final Entry<String, Object> entry = iterator.next(); Object newValue = newAttributes.remove(entry.getKey()); if (newValue == null) { iterator.remove(); fireAttributeRemovedEvent(entry.getKey(), new AttributeValueImpl(AttributeType.fromValue(entry.getValue()), entry.getValue())); } else { final AttributeType type = AttributeType.fromValue(newValue); newValue = type.cast(newValue); entry.setValue(newValue); fireAttributeChangedEvent(entry.getKey(), new AttributeValueImpl(AttributeType.fromValue(entry.getValue()), entry.getValue()), new AttributeValueImpl(type, newValue)); } } for (final Entry<String, Object> e : newAttributes.entrySet()) { Object newValue = e.getValue(); final AttributeType type = AttributeType.fromValue(newValue); newValue = type.cast(newValue); if (newValue != null) { this.heap.put(e.getKey(), newValue); fireAttributeAddedEvent(e.getKey(), new AttributeValueImpl(type, newValue)); } } } @Override public void toMap(Map<String, Object> mapToFill) { mapToFill.putAll(this.heap); } @Pure @Override public int getAttributeCount() { return this.heap.size(); } @Pure @Override public boolean hasAttribute(String name) { return this.heap.containsKey(name); } @Pure @Override public Collection<Attribute> getAllAttributes() { final List<Attribute> list = new ArrayList<>(getAttributeCount()); for (final Entry<String, Object> entry : this.heap.entrySet()) { final String name = entry.getKey(); if (name != null) { final Object rawValue = entry.getValue(); final Attribute newAttr = new AttributeImpl(name); newAttr.castAndSet( AttributeType.fromValue(rawValue), unprotectNull(rawValue)); list.add(newAttr); } } return list; } @Pure @Override public Map<AttributeType, Collection<Attribute>> getAllAttributesByType() { final Map<AttributeType, Collection<Attribute>> map = new TreeMap<>(); for (final Entry<String, Object> entry : this.heap.entrySet()) { Object value = entry.getValue(); if (value != null) { final AttributeType type = AttributeType.fromValue(value); value = unprotectNull(value); Collection<Attribute> list = map.get(type); if (list == null) { list = new ArrayList<>(); map.put(type, list); } final Attribute attr = new AttributeImpl(entry.getKey()); attr.castAndSet(type, value); list.add(attr); } } return map; } @Pure @Override public Collection<String> getAllAttributeNames() { return Collections.unmodifiableCollection(this.heap.keySet()); } @Pure @Override public AttributeValue getAttribute(String name) { return getStoredAttributeValue(name, null); } @Pure @Override public AttributeValue getAttribute(String name, AttributeValue defaultValue) { final AttributeValue value = getStoredAttributeValue(name, defaultValue == null ? null : defaultValue.getType()); if (value == null) { return defaultValue; } return value; } @Pure @Override public Attribute getAttributeObject(String name) { return getStoredAttribute(name, null); } /** Replies the attribute with the given name. * * @param name is the name of the attribute to retreive * @param expectedType is the expected type for the attribute. * @return the value or <code>null</code> */ @Pure protected Attribute getStoredAttribute(String name, AttributeType expectedType) { Object val = this.heap.get(name); if (val != null) { final AttributeType currentType = AttributeType.fromValue(val); val = unprotectNull(val); final Attribute attr = new AttributeImpl(name); if (expectedType == null) { attr.castAndSet(currentType, val); } else { attr.castAndSet(expectedType, val); } return attr; } return null; } /** Replies the attribute with the given name. * * @param name is the name of the attribute to retreive * @param expectedType is the expected type for the attribute. * @return the value or <code>null</code> */ @Pure protected AttributeValue getStoredAttributeValue(String name, AttributeType expectedType) { Object val = this.heap.get(name); if (val != null) { final AttributeType currentType = AttributeType.fromValue(val); val = unprotectNull(val); final AttributeValue attr = new AttributeValueImpl(name); if (expectedType == null) { attr.castAndSet(currentType, val); } else { attr.castAndSet(expectedType, val); } return attr; } return null; } private AttributeValue copyValue(String name) { final Object currentValue = this.heap.get(name); if (currentValue != null) { final AttributeType oldType = AttributeType.fromValue(currentValue); final AttributeValue oldValue = new AttributeValueImpl(); oldValue.castAndSet(oldType, currentValue); return oldValue; } return null; } @Override public Attribute setAttributeType(String name, AttributeType type) throws AttributeException { assert name != null; final AttributeValue oldValue = copyValue(name); final AttributeType oldType = (oldValue == null) ? null : oldValue.getType(); if (oldType == null || type == null || oldType == type) { return null; } final Attribute attr = new AttributeImpl(name, (oldValue == null) ? null : oldValue.getValue()); attr.cast(type); this.heap.put(name, protectNull(attr.getValue(), type)); fireAttributeChangedEvent(name, oldValue, attr); return attr; } @Override public Attribute setAttribute(String name, AttributeValue value) throws AttributeException { assert name != null && value != null; final AttributeValue oldValue = copyValue(name); if (oldValue != null && oldValue.equals(value)) { return null; } this.heap.put(name, protectNull(value.getValue(), value.getType())); final Attribute attr = new AttributeImpl(name, value.getValue()); if (oldValue != null) { fireAttributeChangedEvent(name, oldValue, value); } else { fireAttributeAddedEvent(name, attr); } return attr; } @Override public Attribute setAttribute(String name, boolean value) { assert name != null; final AttributeValue oldValue = copyValue(name); if (oldValue != null && oldValue.equals(value)) { return null; } this.heap.put(name, Boolean.valueOf(value)); final Attribute attr = new AttributeImpl(name, value); if (oldValue != null) { fireAttributeChangedEvent(name, oldValue, attr); } else { fireAttributeAddedEvent(name, attr); } return attr; } @Override public Attribute setAttribute(String name, int value) { assert name != null; final AttributeValue oldValue = copyValue(name); if (oldValue != null && oldValue.equals(value)) { return null; } this.heap.put(name, Long.valueOf(value)); final Attribute attr = new AttributeImpl(name, value); if (oldValue != null) { fireAttributeChangedEvent(name, oldValue, attr); } else { fireAttributeAddedEvent(name, attr); } return attr; } @Override public Attribute setAttribute(String name, long value) { assert name != null; final AttributeValue oldValue = copyValue(name); if (oldValue != null && oldValue.equals(value)) { return null; } this.heap.put(name, Long.valueOf(value)); final Attribute attr = new AttributeImpl(name, value); if (oldValue != null) { fireAttributeChangedEvent(name, oldValue, attr); } else { fireAttributeAddedEvent(name, attr); } return attr; } @Override public Attribute setAttribute(String name, float value) { assert name != null; final AttributeValue oldValue; final Object currentValue = this.heap.get(name); if (currentValue != null) { oldValue = new AttributeValueImpl(); oldValue.castAndSet(AttributeType.fromValue(currentValue), currentValue); } else { oldValue = null; } if (oldValue != null && oldValue.equals(value)) { return null; } this.heap.put(name, Double.valueOf(value)); final Attribute attr = new AttributeImpl(name, value); if (currentValue != null) { fireAttributeChangedEvent(name, oldValue, attr); } else { fireAttributeAddedEvent(name, attr); } return attr; } @Override public Attribute setAttribute(String name, double value) { assert name != null; final AttributeValue oldValue = copyValue(name); if (oldValue != null && oldValue.equals(value)) { return null; } this.heap.put(name, Double.valueOf(value)); final Attribute attr = new AttributeImpl(name, value); if (oldValue != null) { fireAttributeChangedEvent(name, oldValue, attr); } else { fireAttributeAddedEvent(name, attr); } return attr; } @Override public Attribute setAttribute(String name, String value) { assert name != null; final AttributeValue oldValue = copyValue(name); if (oldValue != null && oldValue.equals(value)) { return null; } final Object rv = (value == null) ? AttributeType.STRING.getDefaultValue() : value; this.heap.put(name, rv); final Attribute attr = new AttributeImpl(name, rv); if (oldValue != null) { fireAttributeChangedEvent(name, oldValue, attr); } else { fireAttributeAddedEvent(name, attr); } return attr; } @Override public Attribute setAttribute(String name, UUID value) { assert name != null; final AttributeValue oldValue = copyValue(name); if (oldValue != null && oldValue.equals(value)) { return null; } final Object rv = (value == null) ? AttributeType.UUID.getDefaultValue() : value; this.heap.put(name, rv); final Attribute attr = new AttributeImpl(name, rv); if (oldValue != null) { fireAttributeChangedEvent(name, oldValue, attr); } else { fireAttributeAddedEvent(name, attr); } return attr; } @Override public Attribute setAttribute(String name, URL value) { assert name != null; final AttributeValue oldValue = copyValue(name); if (oldValue != null && oldValue.equals(value)) { return null; } this.heap.put(name, protectNull(value, AttributeType.URL)); final Attribute attr = new AttributeImpl(name, value); if (oldValue != null) { fireAttributeChangedEvent(name, oldValue, attr); } else { fireAttributeAddedEvent(name, attr); } return attr; } @Override public Attribute setAttribute(String name, URI value) { assert name != null; final AttributeValue oldValue = copyValue(name); if (oldValue != null && oldValue.equals(value)) { return null; } this.heap.put(name, protectNull(value, AttributeType.URI)); final Attribute attr = new AttributeImpl(name, value); if (oldValue != null) { fireAttributeChangedEvent(name, oldValue, attr); } else { fireAttributeAddedEvent(name, attr); } return attr; } /** * {@inheritDoc} * @deprecated since 13.0 */ @Override @Deprecated public Attribute setAttribute(String name, Image value) { assert name != null; final AttributeValue oldValue = copyValue(name); if (oldValue != null && oldValue.equals(value)) { return null; } this.heap.put(name, protectNull(value, AttributeType.IMAGE)); final Attribute attr = new AttributeImpl(name, value); if (oldValue != null) { fireAttributeChangedEvent(name, oldValue, attr); } else { fireAttributeAddedEvent(name, attr); } return attr; } @Override public Attribute setAttribute(String name, Date value) { assert name != null; final AttributeValue oldValue = copyValue(name); if (oldValue != null && oldValue.equals(value)) { return null; } final Object rv = (value == null) ? AttributeType.DATE.getDefaultValue() : value; this.heap.put(name, rv); final Attribute attr = new AttributeImpl(name, rv); if (oldValue != null) { fireAttributeChangedEvent(name, oldValue, attr); } else { fireAttributeAddedEvent(name, attr); } return attr; } /** * {@inheritDoc} * @deprecated since 13.0 */ @Override @Deprecated public Attribute setAttribute(String name, Color value) { assert name != null; final AttributeValue oldValue = copyValue(name); if (oldValue != null && oldValue.equals(value)) { return null; } final Object rv = (value == null) ? AttributeType.COLOR.getDefaultValue() : value; this.heap.put(name, rv); final Attribute attr = new AttributeImpl(name, rv); if (oldValue != null) { fireAttributeChangedEvent(name, oldValue, attr); } else { fireAttributeAddedEvent(name, attr); } return attr; } @Override public Attribute setAttribute(Attribute value) throws AttributeException { assert value != null; final String name = value.getName(); final AttributeValue oldValue = copyValue(name); if (oldValue != null && oldValue.equals(value)) { return null; } this.heap.put(name, protectNull(value.getValue(), value.getType())); if (oldValue != null) { fireAttributeChangedEvent(name, oldValue, value); } else { fireAttributeAddedEvent(name, value); } return value; } @Override public Attribute setAttribute(String name, InetAddress value) { assert name != null; final AttributeValue oldValue = copyValue(name); if (oldValue != null && oldValue.equals(value)) { return null; } this.heap.put(name, value); final Attribute attr = new AttributeImpl(name, value); if (oldValue != null) { fireAttributeChangedEvent(name, oldValue, attr); } else { fireAttributeAddedEvent(name, attr); } return attr; } @Override public Attribute setAttribute(String name, InetSocketAddress value) { return setAttribute(name, (value == null) ? null : value.getAddress()); } @Override public Attribute setAttribute(String name, Enum<?> value) { assert name != null; final AttributeValue oldValue = copyValue(name); if (oldValue != null && oldValue.equals(value)) { return null; } this.heap.put(name, value); final Attribute attr = new AttributeImpl(name, value); if (oldValue != null) { fireAttributeChangedEvent(name, oldValue, attr); } else { fireAttributeAddedEvent(name, attr); } return attr; } @Override public Attribute setAttribute(String name, Class<?> value) { assert name != null; final AttributeValue oldValue = copyValue(name); if (oldValue != null && oldValue.equals(value)) { return null; } this.heap.put(name, value); final Attribute attr = new AttributeImpl(name, value); if (oldValue != null) { fireAttributeChangedEvent(name, oldValue, attr); } else { fireAttributeAddedEvent(name, attr); } return attr; } @Override public boolean removeAttribute(String name) { assert name != null; final AttributeValue oldValue; final Object currentValue = this.heap.remove(name); if (currentValue != null) { oldValue = new AttributeValueImpl(); oldValue.castAndSet(AttributeType.fromValue(currentValue), currentValue); fireAttributeRemovedEvent(name, oldValue); return true; } return false; } @Override public boolean removeAllAttributes() { if (!this.heap.isEmpty()) { this.heap.clear(); fireAttributeClearedEvent(); return true; } return false; } @Override public boolean renameAttribute(String oldname, String newname, boolean overwrite) { if (oldname == null || newname == null || oldname.equals(newname)) { return false; } final AttributeValue valueOfOldName = copyValue(oldname); // The attribute does not exist. if (valueOfOldName == null) { return false; } final AttributeValue oldValueOfNewName = copyValue(newname); // The target attribute is existing and overwrite was disabled if ((!overwrite) && (oldValueOfNewName != null)) { return false; } Object rawValue; try { rawValue = valueOfOldName.getValue(); } catch (InvalidAttributeTypeException | AttributeNotInitializedException e) { rawValue = null; } this.heap.remove(oldname); this.heap.put(newname, protectNull(rawValue, valueOfOldName.getType())); if (oldValueOfNewName != null) { fireAttributeRemovedEvent(newname, oldValueOfNewName); } fireAttributeRenamedEvent(oldname, newname, valueOfOldName); return true; } @Override public void freeMemory() { // Do nothing } @Override public void flush() { // Do nothing } @Pure @Override public String toString() { return this.heap.toString(); } }