/* * Data Hub Service (DHuS) - For Space data distribution. * Copyright (C) 2016 GAEL Systems * * This file is part of DHuS software sources. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package fr.gael.dhus.olingo.v1.map; import fr.gael.dhus.olingo.v1.FunctionalVisitor; import fr.gael.dhus.olingo.v1.visitor.ExecutableExpressionTree; import fr.gael.dhus.util.functional.collect.SortedMap; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.Set; import org.apache.commons.collections4.functors.ConstantFactory; import org.apache.olingo.odata2.api.exception.ODataApplicationException; import org.apache.olingo.odata2.api.uri.expression.ExceptionVisitExpression; /** * This class is the base class to create a read-only, sortable, filterable Map view on another map. * * @param <K> Key type. * @param <V> Object (values) type. */ public class FunctionalMap<K, V> implements Map<K, V>, SubMap<K, V> { /** Map which contain the data. */ protected final Map<K, V> sourceMap; /** To convert an OlingoExpressionTree to an ExecutableExpressionTree. */ protected final FunctionalVisitor transliterator; /** * Creates a FunctionalMap from the given datasource and translierator. * @param source data source. * @param visitor transliterator. */ public FunctionalMap(Map<K, V> source, FunctionalVisitor visitor) { Objects.requireNonNull(source); Objects.requireNonNull(visitor); sourceMap = source; transliterator = visitor; } /// vvvv SubMap internface. vvvv @Override public SubMapBuilder<K, V> getSubMapBuilder() { return new SubMapBuilder<K, V>() { @Override public Map<K, V> build() { // Creates an ExecutableExpressionTree from `filter` ExecutableExpressionTree eet; if (filter != null) { try { eet = ExecutableExpressionTree.class.cast(filter.accept(transliterator)); } catch (ExceptionVisitExpression | ODataApplicationException ex) { throw new RuntimeException(ex); } } else { eet = new ExecutableExpressionTree( ExecutableExpressionTree.Node.createLeave( ConstantFactory.constantFactory(Boolean.TRUE))); } Map<K, V> new_source = new HashMap<>(); // Builds a new map from entries validated by the `eet` for (Entry<K, V> e: sourceMap.entrySet()) { if ((boolean) eet.exec(e.getValue())) { if (skip > 0) { skip--; } else { new_source.put(e.getKey(), e.getValue()); if (top > 0) { top--; if (top == 0) { break; } } } } } if (this.orderBy != null) { Comparator cmp; try { cmp = Comparator.class.cast(orderBy.accept(transliterator)); } catch (ExceptionVisitExpression | ODataApplicationException ex) { throw new RuntimeException(ex); } new_source = new SortedMap<>(new_source, cmp); } return new_source; } }; } /// vvvv Map interface. vvvv @Override public int size() { return sourceMap.size(); } @Override public boolean isEmpty() { return sourceMap.isEmpty(); } @Override public boolean containsKey(Object key) { return sourceMap.containsKey(key); } @Override public V get(Object key) { return sourceMap.get(key); } @Override public Collection<V> values() { return Collections.unmodifiableCollection(sourceMap.values()); } @Override public Set<K> keySet() { return Collections.unmodifiableSet(sourceMap.keySet()); } @Override public Set<Map.Entry<K, V>> entrySet() { return Collections.unmodifiableSet(sourceMap.entrySet()); } /// ^^^^ Implemented. ^^^^ /// vvvv Not implemented. vvvv @Override public V put(K key, V value) { throw new UnsupportedOperationException("Read-Only"); } @Override public boolean containsValue(Object value) { throw new UnsupportedOperationException("Don't use"); } @Override public V remove(Object key) { throw new UnsupportedOperationException("Read-Only"); } @Override public void putAll(Map<? extends K, ? extends V> m) { throw new UnsupportedOperationException("Read-Only"); } @Override public void clear() { throw new UnsupportedOperationException("Read-Only"); } }