/* * Copyright (C) 2014-2015 Matthias Heizmann (heizmann@informatik.uni-freiburg.de) * Copyright (C) 2012-2015 University of Freiburg * * This file is part of the ULTIMATE Util Library. * * The ULTIMATE Util Library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The ULTIMATE Util Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the ULTIMATE Util Library. If not, see . * * Additional permission under GNU GPL version 3 section 7: * If you modify the ULTIMATE Util Library, or any covered work, by linking * or combining it with Eclipse RCP (or a modified version of Eclipse RCP), * containing parts covered by the terms of the Eclipse Public License, the * licensors of the ULTIMATE Util Library grant you additional permission * to convey the resulting work. */ package de.uni_freiburg.informatik.ultimate.util.datastructures.relation; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.function.Function; import java.util.stream.Stream; /** * TODO: comment * * @author Matthias Heizmann * @author Alexander Nutz (nutz@informatik.uni-freiburg.de) * @author Daniel Tischner {@literal } * * @param * @param * @param * @param */ public class NestedMap3 { private final Map> mK1ToK2ToK3ToV = new HashMap<>(); /** * Construct an empty NestedMap3 */ public NestedMap3() { } /** * Returns a stream to all values of the nested map. The values are backed by * the map. * * @return A backed stream to all values of the nested map */ public Stream values() { return this.mK1ToK2ToK3ToV.values().stream().flatMap(NestedMap2::values); } /** * Copy constructor * * @param original */ public NestedMap3(final NestedMap3 original) { for (final K1 k1 : original.keySet()) { mK1ToK2ToK3ToV.put(k1, new NestedMap2<>(original.get(k1))); } } public V put(final K1 key1, final K2 key2, final K3 key3, final V value) { NestedMap2 k2tok3toV = mK1ToK2ToK3ToV.get(key1); if (k2tok3toV == null) { k2tok3toV = new NestedMap2<>(); mK1ToK2ToK3ToV.put(key1, k2tok3toV); } return k2tok3toV.put(key2, key3, value); } public V get(final K1 key1, final K2 key2, final K3 key3) { final NestedMap2 k2tok3toV = mK1ToK2ToK3ToV.get(key1); if (k2tok3toV == null) { return null; } else { return k2tok3toV.get(key2, key3); } } public Map get(final K1 key1, final K2 key2) { final NestedMap2 k2toV = mK1ToK2ToK3ToV.get(key1); if (k2toV == null) { return null; } else { return k2toV.get(key2); } } public NestedMap2 get(final K1 key1) { return mK1ToK2ToK3ToV.get(key1); } public Set keySet() { return mK1ToK2ToK3ToV.keySet(); } public void clear() { mK1ToK2ToK3ToV.clear(); } public Iterable> keys3() { final Iterator>> innerIterator = mK1ToK2ToK3ToV.entrySet().iterator(); final Function>, Iterator>> nextOuterIteratorProvider = (x -> x .getValue().keys2().iterator()); final Function>, Function, Triple>> resultProvider = (x -> (y -> new Triple( x.getKey(), y.getFirst(), y.getSecond()))); return () -> new NestedIterator>, Pair, Triple>( innerIterator, nextOuterIteratorProvider, resultProvider); } public Iterable> entrySet() { final Iterator>> innerIterator = mK1ToK2ToK3ToV.entrySet().iterator(); final Function>, Iterator>> nextOuterIteratorProvider = (x -> x .getValue().entrySet().iterator()); final Function>, Function, Quad>> resultProvider = (x -> (y -> new Quad( x.getKey(), y.getFirst(), y.getSecond(), y.getThird()))); return () -> new NestedIterator>, Triple, Quad>( innerIterator, nextOuterIteratorProvider, resultProvider); } /** * @return all entries where first element is k1 */ public Iterable> entries(final K1 k1) { final NestedMap2 k2Tok3ToV = get(k1); if (k2Tok3ToV == null) { return Collections.emptySet(); } else { final Function, Quad> transformer = (x -> new Quad(k1, x.getFirst(), x.getSecond(), x.getThird())); return () -> new TransformIterator, Quad>(k2Tok3ToV.entrySet().iterator(), transformer); } } /** * @return all entries where first element is k1 and the second element is k2 */ public Iterable> entries(final K1 k1, final K2 k2) { final Map k3ToV = get(k1, k2); if (k3ToV == null) { return Collections.emptySet(); } else { final Function, Quad> transformer = (x -> new Quad(k1, k2, x.getKey(), x.getValue())); return () -> new TransformIterator, Quad>(k3ToV.entrySet().iterator(), transformer); } } public NestedMap2 remove(final K1 k1) { return mK1ToK2ToK3ToV.remove(k1); } public Map remove(final K1 k1, final K2 k2) { final NestedMap2 k1Tok2ToV = mK1ToK2ToK3ToV.get(k1); if (k1Tok2ToV == null) { return null; } return k1Tok2ToV.remove(k2); } public V remove(final K1 k1, final K2 k2, final K3 k3) { final NestedMap2 k1Tok2ToV = mK1ToK2ToK3ToV.get(k1); if (k1Tok2ToV == null) { return null; } return k1Tok2ToV.remove(k2, k3); } public int size() { int result = 0; for (final Entry> entry : mK1ToK2ToK3ToV.entrySet()) { result += entry.getValue().size(); } return result; } public Set projektTo2() { final Set result = new HashSet<>(); for (final Entry> entry : mK1ToK2ToK3ToV.entrySet()) { result.addAll(entry.getValue().keySet()); } return result; } @Override public String toString() { return mK1ToK2ToK3ToV.toString(); } }