All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nl.vpro.util.OrderedProperties Maven / Gradle / Ivy

There is a newer version: 5.3.1
Show newest version
package nl.vpro.util;

import java.io.Serial;
import java.util.*;
import java.util.function.BiConsumer;

import org.checkerframework.checker.nullness.qual.NonNull;

/**
 * Extension of properties that remembers insertion order.
 * @author Michiel Meeuwissen
 * @since 1.8
 */
public class OrderedProperties extends Properties {

    @Serial
    private static final long serialVersionUID = 5640271520019127358L;

    private final List names = new ArrayList<>();


    @Override
    public synchronized Enumeration propertyNames() {
        return Collections.enumeration(names);
    }

    @Override
    public synchronized @NonNull Set keySet() {
        return new LinkedHashSet<>(names);
    }

    @Override
    public synchronized @NonNull Enumeration keys() {
        return Collections.enumeration(names);
    }
    @Override
    public @NonNull Collection values() {
        return entrySet().stream().map(Map.Entry::getValue).toList();
    }


    @Override
    public synchronized void forEach(BiConsumer action) {
        entrySet().forEach(e -> action.accept(e.getKey(), e.getValue()));
    }


    @Override
    public Enumeration elements() {
        // CHM.elements() returns Iterator w/ remove() - instead wrap values()
        return Collections.enumeration(values().stream().toList());
    }

    @NonNull
    @Override
    public Set> entrySet() {
        return new AbstractSet<>() {

            @NonNull
            @Override
            public Iterator> iterator() {
                final Iterator i = names.iterator();
                return new Iterator>() {

                    @Override
                    public boolean hasNext() {
                        return i.hasNext();
                    }

                    @Override
                    public Map.Entry next() {
                        Object key = i.next();
                        return new AbstractMap.SimpleEntry<>(key, OrderedProperties.this.get(key));
                    }

                    @Override
                    public void remove() {
                        throw new UnsupportedOperationException();
                    }
                };
            }

            @Override
            public int size() {
                return OrderedProperties.this.size();
            }
        };
    }

    @Override
    public synchronized Object put(Object key, Object value) {
        names.remove(key);
        names.add(key);
        return super.put(key, value);
    }

    @Override
    public synchronized Object remove(Object key) {
        names.remove(key);
        return super.remove(key);
    }

    @Override
    public synchronized String toString() {
        return sortedMap().toString();
    }

    protected Map sortedMap() {
        return new AbstractMap<>() {
            @Override
            public @NonNull Set> entrySet() {
                return OrderedProperties.this.entrySet();
            }
        };
    }

}