blob: d68425fd2f0c599457bfb5707eb5ebbe86ec4c85 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2017 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.internal.p2.core.helpers;
import java.util.*;
/**
* A Properties collection that maintains the order of insertion.
* <p>
* This class is used to store properties similar to {@link java.util.Properties}.
* In particular both keys and values are strings and must be not null.
* However this class is somewhat simplified and does not implement Cloneable,
* Serializable and Hashtable.
* <p>
* In contrast to java.util.Properties this class maintains the order by which
* properties are added. This is implemented using a {@link LinkedHashMap}.
* <p>
* The class does not support default properties as they can be expressed by
* creating java.util.Properties hierarchies.
*/
public class OrderedProperties extends Dictionary<String, String> implements Map<String, String> {
LinkedHashMap<String, String> propertyMap = null;
public static OrderedProperties unmodifiableProperties(Map<String, String> properties) {
return new UnmodifiableProperties(properties);
}
public OrderedProperties() {
super();
}
public OrderedProperties(int size) {
super();
propertyMap = new LinkedHashMap<>(size);
}
public OrderedProperties(Map<String, String> properties) {
super();
propertyMap = new LinkedHashMap<>(properties.size());
putAll(properties);
}
/**
* Set the property value.
* <p>
* If a property with the key already exists, the previous
* value is replaced. Otherwise a new property is added at
* the end collection.
*
* @param key must not be null
* @param value must not be null
* @return previous value associated with specified key, or <tt>null</tt>
* if there was no mapping for key.
*/
public Object setProperty(String key, String value) {
init();
return propertyMap.put(key.intern(), value);
}
public String getProperty(String key) {
return (propertyMap == null ? null : propertyMap.get(key));
}
/**
* Initialize the map.
*/
private void init() {
if (propertyMap == null) {
propertyMap = new LinkedHashMap<>();
}
}
@Override
public int size() {
return propertyMap == null ? 0 : propertyMap.size();
}
@Override
public boolean isEmpty() {
return propertyMap == null ? true : propertyMap.isEmpty();
}
@Override
public synchronized void clear() {
propertyMap = null;
}
@Override
public String put(String key, String value) {
init();
return propertyMap.put(key.intern(), value);
}
@Override
public boolean containsKey(Object key) {
return propertyMap != null ? propertyMap.containsKey(key) : false;
}
@Override
public boolean containsValue(Object value) {
return propertyMap != null ? propertyMap.containsValue(value) : false;
}
@Override
public Set<Map.Entry<String, String>> entrySet() {
return propertyMap != null ? propertyMap.entrySet() : Collections.emptySet();
}
@Override
public String get(Object key) {
return propertyMap != null ? propertyMap.get(key) : null;
}
@Override
public Set<String> keySet() {
return propertyMap != null ? propertyMap.keySet() : Collections.emptySet();
}
@Override
public void putAll(Map<? extends String, ? extends String> arg0) {
init();
propertyMap.putAll(arg0);
}
@Override
public String remove(Object key) {
return propertyMap != null ? propertyMap.remove(key) : null;
}
@Override
public Collection<String> values() {
return propertyMap != null ? propertyMap.values() : Collections.emptyList();
}
@Override
public boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof OrderedProperties) {
OrderedProperties rhs = (OrderedProperties) o;
if (rhs.propertyMap == this.propertyMap)
return true;
if (rhs.propertyMap == null)
return this.propertyMap.isEmpty();
else if (this.propertyMap == null)
return rhs.isEmpty();
return rhs.propertyMap.equals(this.propertyMap);
}
if (this.propertyMap == null) {
if (o instanceof Map<?, ?>)
return ((Map<?, ?>) o).isEmpty();
return false;
}
return this.propertyMap.equals(o);
}
@Override
public int hashCode() {
return propertyMap == null || propertyMap.isEmpty() ? 0 : propertyMap.hashCode();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(propertyMap);
return sb.toString();
}
private class StringsEnum implements Enumeration<String> {
private final Iterator<String> iterator;
public StringsEnum(Collection<String> elems) {
this.iterator = elems.iterator();
}
@Override
public boolean hasMoreElements() {
return iterator.hasNext();
}
@Override
public String nextElement() {
return iterator.next();
}
}
@Override
public Enumeration<String> elements() {
return new StringsEnum(propertyMap.values());
}
@Override
public Enumeration<String> keys() {
return new StringsEnum(propertyMap.keySet());
}
private static class UnmodifiableProperties extends OrderedProperties {
UnmodifiableProperties(Map<String, String> properties) {
super();
for (Map.Entry<String, String> entry : properties.entrySet()) {
super.put(entry.getKey(), entry.getValue());
}
}
@Override
public synchronized Object setProperty(String key, String value) {
throw new UnsupportedOperationException();
}
@Override
public synchronized String put(String key, String value) {
throw new UnsupportedOperationException();
}
@Override
public synchronized String remove(Object key) {
throw new UnsupportedOperationException();
}
@Override
public synchronized void putAll(Map<? extends String, ? extends String> t) {
throw new UnsupportedOperationException();
}
@Override
public synchronized void clear() {
throw new UnsupportedOperationException();
}
}
}