001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.preferences;
003
004import java.util.ArrayList;
005import java.util.Collections;
006import java.util.Iterator;
007import java.util.LinkedHashMap;
008import java.util.List;
009import java.util.Map;
010import java.util.Map.Entry;
011import java.util.Objects;
012
013/**
014 * Setting containing a {@link List} of {@link Map}s of {@link String} values.
015 * @since 9759
016 */
017public class MapListSetting extends AbstractSetting<List<Map<String, String>>> {
018
019    /**
020     * Constructs a new {@code MapListSetting} with the given value
021     * @param value The setting value
022     */
023    public MapListSetting(List<Map<String, String>> value) {
024        super(value);
025        consistencyTest();
026    }
027
028    @Override
029    public boolean equalVal(List<Map<String, String>> otherVal) {
030        if (value == null)
031            return otherVal == null;
032        if (otherVal == null)
033            return false;
034        if (value.size() != otherVal.size())
035            return false;
036        Iterator<Map<String, String>> itA = value.iterator();
037        Iterator<Map<String, String>> itB = otherVal.iterator();
038        while (itA.hasNext()) {
039            if (!equalMap(itA.next(), itB.next()))
040                return false;
041        }
042        return true;
043    }
044
045    private static boolean equalMap(Map<String, String> a, Map<String, String> b) {
046        if (a == null)
047            return b == null;
048        if (b == null)
049            return false;
050        if (a.size() != b.size())
051            return false;
052        for (Entry<String, String> e : a.entrySet()) {
053            if (!Objects.equals(e.getValue(), b.get(e.getKey())))
054                return false;
055        }
056        return true;
057    }
058
059    @Override
060    public MapListSetting copy() {
061        if (value == null)
062            return new MapListSetting(null);
063        List<Map<String, String>> copy = new ArrayList<>(value.size());
064        for (Map<String, String> map : value) {
065            Map<String, String> mapCopy = new LinkedHashMap<>(map);
066            copy.add(Collections.unmodifiableMap(mapCopy));
067        }
068        return new MapListSetting(Collections.unmodifiableList(copy));
069    }
070
071    private void consistencyTest() {
072        if (value == null)
073            return;
074        if (value.contains(null))
075            throw new IllegalArgumentException("Error: Null as list element in preference setting");
076        for (Map<String, String> map : value) {
077            if (map.keySet().contains(null))
078                throw new IllegalArgumentException("Error: Null as map key in preference setting");
079            if (map.values().contains(null))
080                throw new IllegalArgumentException("Error: Null as map value in preference setting");
081        }
082    }
083
084    @Override
085    public void visit(SettingVisitor visitor) {
086        visitor.visit(this);
087    }
088
089    @Override
090    public MapListSetting getNullInstance() {
091        return new MapListSetting(null);
092    }
093
094    @Override
095    public boolean equals(Object other) {
096        if (!(other instanceof MapListSetting))
097            return false;
098        return equalVal(((MapListSetting) other).getValue());
099    }
100}