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

org.op4j.functions.FnMapOf Maven / Gradle / Ivy

The newest version!
/*
 * =============================================================================
 * 
 *   Copyright (c) 2010, The OP4J team (http://www.op4j.org)
 * 
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 * 
 * =============================================================================
 */

package org.op4j.functions;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import org.javaruntype.type.Type;
import org.op4j.exceptions.ExecutionException;
import org.op4j.util.ExecCtxImpl;
import org.op4j.util.VarArgsUtil;

/**
 * 
 * @since 1.0
 * 
 * @author Daniel Fernández
 * 
 */
public final class FnMapOf {


    
    protected final Type keyType;
    protected final Type valueType;

    
    private static final Count COUNT = new Count();

    
    
    
    
    public final Function,Map> sortByKey() {
        return new SortByKey();
    }

    public final Function,Map> sortEntries(final Comparator> comparator) {
        return new SortEntries(comparator);
    }

    
    public final Function,Map> sortBy(final IFunction, ?> by) {
        return new SortBy(by);
    }

    
    public final Function,Map> put(final K key, final V value) {
        return new Put(key, value);
    }
    
    public final Function,Map> insert(final int position, final K key, final V value) {
        return new Insert(position, key, value);
    }
    
    public final Function,Map> putAll(final Map map) {
        return new PutAll(map);
    }
    
    public final Function,Map> insertAll(final int position, final Map map) {
        return new InsertAll(position, map);
    }
    
    public final Function,Map> removeAllKeys(final K... keys) {
        return new RemoveAllKeys(keys);
    }
    
    public final Function,Map> removeAllTrue(final IFunction,Boolean> eval) {
        return new RemoveAllTrue(eval);
    }
    
    public final Function,Map> removeAllFalse(final IFunction,Boolean> eval) {
        return new RemoveAllFalse(eval);
    }
    
    public final Function,Map> removeAllKeysNot(final K... keys) {
        return new RemoveAllKeysNot(keys);
    }
    
    public final Function,Set> extractKeys() {
        return new ExtractKeys();
    }
    
    public final Function,List> extractValues() {
        return new ExtractValues();
    }
    

    
    

    public final Function,Boolean> all(final IFunction,Boolean> eval) {
        return new All(eval);
    }
    
    public final Function,Boolean> any(final IFunction,Boolean> eval) {
        return new Any(eval);
    }
    
    
    
    
    
    
    
    public final Function,Integer> count() {
        return COUNT;
    }
    
    
    
    
    
    
    public final Function,Boolean> containsKey(final K key) {
        return new ContainsKey(key);
    }
    
    public final Function,Boolean> notContainsKey(final K key) {
        return FnBoolean.not(containsKey(key));
    }
    
    public final Function,Boolean> containsAllKeys(final K... keys) {
        return new ContainsAllKeys(VarArgsUtil.asRequiredObjectList(keys));
    }
    
    public final Function,Boolean> containsAnyKeys(final K... keys) {
        return new ContainsAnyKeys(VarArgsUtil.asRequiredObjectList(keys));
    }
    
    public final Function,Boolean> containsNoneKeys(final K... keys) {
        return new ContainsNoneKeys(VarArgsUtil.asRequiredObjectList(keys));
    }
    
    
    
    
    
    public final Function,Map> reverse() {
        return new Reverse();
    }
    
    
    
    
    
    
    
    protected FnMapOf(final Type keyType, final Type valueType) {
        super();
        this.keyType = keyType;
        this.valueType = valueType;
    }

    
    
    
    
    
    static final class SortByKey extends AbstractNotNullNonConvertingFunc> {

        SortByKey() {
            super();
        }

        @Override
        protected Map notNullExecute(final Map object, final ExecCtx ctx) throws Exception {
            return doSort(object, ctx);
        }
        

        @SuppressWarnings({ "unchecked" })
        private Map doSort(final Map object, final ExecCtx ctx) throws Exception {
            final List keys = new ArrayList(object.keySet());
            Collections.sort((List)keys);
            final Map result = new LinkedHashMap();
            for (final K key : (List) keys) {
                result.put(key, object.get(key));
            }
            return result;
        }
        
    }

    
    
    static final class SortEntries extends AbstractNotNullNonConvertingFunc> {

        private final Comparator> comparator;

        SortEntries(final Comparator> comparator) {
            super();
            this.comparator = comparator;
        }

        @Override
        protected Map notNullExecute(final Map object, final ExecCtx ctx) throws Exception {
            final List> entries = new ArrayList>(object.entrySet());
            Collections.sort(entries, this.comparator);
            final Map result = new LinkedHashMap();
            for (final Map.Entry entry : entries) {
                result.put(entry.getKey(), entry.getValue());
            }
            return result;
        }
        
    }
    

    

    
    
    
    
    static final class SortBy extends AbstractNotNullNonConvertingFunc> {

        private final IFunction, ?> by;
        
        SortBy(final IFunction, ?> by) {
            super();
            this.by = by;
        }

        @Override
        protected Map notNullExecute(final Map object, final ExecCtx ctx) throws Exception {

            final List>> ordList = new ArrayList>>();
            int index = 0;
            for (final Map.Entry element : object.entrySet()) {
                ordList.add(
                    new OrderableElement>(
                        element, 
                        (Comparable) this.by.execute(element, new ExecCtxImpl(Integer.valueOf(index)))));
            }
            Collections.sort(ordList);
            final Map resultMap = new LinkedHashMap();
            for (final OrderableElement> element : ordList) {
                resultMap.put(element.getElement().getKey(), element.getElement().getValue());
            }
            return resultMap;
            
        }
        
        private static class OrderableElement implements Comparable> {

            private final T element;
            private final Comparable comparator;
            
            public OrderableElement(final T element, final Comparable comparator) {
                super();
                this.element = element;
                this.comparator = comparator;
                if (this.comparator == null) {
                    throw new NullPointerException("Cannot sort null elements");
                }
            }
            
            public T getElement() {
                return this.element;
            }

            public Comparable getComparator() {
                return this.comparator;
            }

            @SuppressWarnings({ "unchecked" })
            public int compareTo(OrderableElement o) {
                if (this.comparator == null) {
                    throw new NullPointerException("Cannot sort null elements");
                }
                return ((Comparable)this.comparator).compareTo(o.getComparator());
            }

            @Override
            public int hashCode() {
                final int prime = 31;
                int result = 1;
                result = prime * result
                        + ((this.comparator == null) ? 0 : this.comparator.hashCode());
                return result;
            }

            @Override
            @SuppressWarnings("unchecked")
            public boolean equals(Object obj) {
                if (this == obj) {
                    return true;
                }
                if (obj == null) {
                    return false;
                }
                if (getClass() != obj.getClass()) {
                    return false;
                }
                final OrderableElement other = (OrderableElement) obj;
                return this.comparator.equals(other.comparator);
            }
            
        }
        

    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    static final class Put extends AbstractNotNullNonConvertingFunc> {

        private final K key;
        private final V value;
        
        Put(final K key, final V value) {
            super();
            this.key = key;
            this.value = value;
        }

        @Override
        protected Map notNullExecute(final Map object, final ExecCtx ctx) throws Exception {
            final Map result = new LinkedHashMap(object);
            result.put(this.key, this.value);
            return result;
        }
        
    }

    
    
    static final class Insert extends AbstractNotNullNonConvertingFunc> {

        private final int position;
        private final K key;
        private final V value;
        
        Insert(final int position, final K key, final V value) {
            super();
            this.position = position;
            this.key = key;
            this.value = value;
        }

        @Override
        protected Map notNullExecute(final Map object, final ExecCtx ctx) throws Exception {
            final Map result = new LinkedHashMap(object);
            int index = 0;
            for (final Map.Entry entry : object.entrySet()) {
                if (index == this.position) {
                    result.put(this.key, this.value);
                }
                if (!result.containsKey(entry.getKey())) {
                    result.put(entry.getKey(), entry.getValue());
                }
                index++;
            }
            return result;
        }
        
    }


    
    
    
    static final class PutAll extends AbstractNotNullNonConvertingFunc> {

        private final Map map;
        
        PutAll(final Map map) {
            super();
            this.map = new LinkedHashMap(map);
        }

        @Override
        protected Map notNullExecute(final Map object, final ExecCtx ctx) throws Exception {
            final Map result = new LinkedHashMap(object);
            result.putAll(this.map);
            return result;
        }
        
    }


    
    
    
    static final class InsertAll extends AbstractNotNullNonConvertingFunc> {

        private final int position;
        private final Map map;
        
        InsertAll(final int position, final Map map) {
            super();
            this.position = position;
            this.map = new LinkedHashMap(map);
        }

        @Override
        protected Map notNullExecute(final Map object, final ExecCtx ctx) throws Exception {
            final Map result = new LinkedHashMap(object);
            int index = 0;
            for (final Map.Entry entry : object.entrySet()) {
                if (index == this.position) {
                    for (final Map.Entry newEntry : this.map.entrySet()) {
                        result.put(newEntry.getKey(), newEntry.getValue());
                    }
                }
                if (!result.containsKey(entry.getKey())) {
                    result.put(entry.getKey(), entry.getValue());
                }
                index++;
            }
            return result;
        }
        
    }

    
    

    
    static final class RemoveAllKeys extends AbstractNotNullNonConvertingFunc> {

        private final List keys;
        
        RemoveAllKeys(final K... keys) {
            super();
            this.keys = VarArgsUtil.asRequiredObjectList(keys);
        }

        @Override
        protected Map notNullExecute(final Map object, final ExecCtx ctx) throws Exception {
            final Map result = new LinkedHashMap(object);
            for (final K key : this.keys) {
                result.remove(key);
            }
            return result;
        }
        
    }

    
    

    
    static final class RemoveAllTrue extends AbstractNotNullNonConvertingFunc> {

        private final IFunction,Boolean> eval;
        
        RemoveAllTrue(final IFunction,Boolean> eval) {
            super();
            this.eval = eval;
        }

        @Override
        protected Map notNullExecute(final Map object, final ExecCtx ctx) throws Exception {
            final Map result = new LinkedHashMap();
            for (final Map.Entry entry : object.entrySet()) {
                if (!this.eval.execute(entry, ctx).booleanValue()) {
                    result.put(entry.getKey(), entry.getValue());
                }
            }
            return result;
        }
        
    }

    
    

    
    static final class RemoveAllFalse extends AbstractNotNullNonConvertingFunc> {

        private final IFunction,Boolean> eval;
        
        RemoveAllFalse(final IFunction,Boolean> eval) {
            super();
            this.eval = eval;
        }

        @Override
        protected Map notNullExecute(final Map object, final ExecCtx ctx) throws Exception {
            final Map result = new LinkedHashMap();
            for (final Map.Entry entry : object.entrySet()) {
                if (this.eval.execute(entry, ctx).booleanValue()) {
                    result.put(entry.getKey(), entry.getValue());
                }
            }
            return result;
        }
        
    }
    
    

    
    
    static final class RemoveAllKeysNot extends AbstractNotNullNonConvertingFunc> {

        private final List keys;
        
        RemoveAllKeysNot(final K... keys) {
            super();
            this.keys = VarArgsUtil.asRequiredObjectList(keys);
        }

        @Override
        protected Map notNullExecute(final Map object, final ExecCtx ctx) throws Exception {
            final Map result = new LinkedHashMap();
            for (final Map.Entry entry : object.entrySet()) {
                if (this.keys.contains(entry.getKey())) {
                    result.put(entry.getKey(), entry.getValue());
                }
            }
            return result;
        }
        
    }

    
    
    
    static final class ExtractKeys extends AbstractNotNullFunction,Set> {

        ExtractKeys() {
            super();
        }

        @Override
        protected Set notNullExecute(final Map object, final ExecCtx ctx) throws Exception {
            return new LinkedHashSet(object.keySet());
        }
        
    }
    
    
    
    static final class ExtractValues extends AbstractNotNullFunction,List> {

        ExtractValues() {
            super();
        }

        @Override
        protected List notNullExecute(final Map object, final ExecCtx ctx) throws Exception {
            return new ArrayList(object.values());
        }
        
    }
    
    
    
    
    
    
    
    
    static final class Any extends AbstractNotNullFunction,Boolean> {

        private final IFunction, Boolean> function;
        
        
        public Any(IFunction, Boolean> function) {
            super();
            this.function = function;
        }
        
        
        @Override
        protected Boolean notNullExecute(final Map object, final ExecCtx ctx) throws Exception {
            int index = 0;
            for (final Map.Entry element : object.entrySet()) {
                final Boolean elementResult = 
                    this.function.execute(element, new ExecCtxImpl(Integer.valueOf(index)));
                if (elementResult == null) {
                    throw new ExecutionException("Evaluation function returned null, which is " +
                            "not allowed executing \"any\"");
                }
                if (elementResult.booleanValue()) {
                    return Boolean.TRUE;
                }
                index++;
            }
            return Boolean.FALSE;
        }
        
    }

    
    
    static final class All extends AbstractNotNullFunction,Boolean> {

        private final IFunction, Boolean> function;
        
        
        public All(IFunction, Boolean> function) {
            super();
            this.function = function;
        }
        
        
        @Override
        protected Boolean notNullExecute(final Map object, final ExecCtx ctx) throws Exception {
            int index = 0;
            for (final Map.Entry element : object.entrySet()) {
                final Boolean elementResult = 
                    this.function.execute(element, new ExecCtxImpl(Integer.valueOf(index)));
                if (elementResult == null) {
                    throw new ExecutionException("Evaluation function returned null, which is " +
                            "not allowed executing \"all\"");
                }
                if (!elementResult.booleanValue()) {
                    return Boolean.FALSE;
                }
                index++;
            }
            return Boolean.TRUE;
        }
        
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    static final class ContainsKey extends AbstractNotNullFunction,Boolean> {
        
        private final K key;
        
        public ContainsKey(final K key) {
            super();
            this.key = key;
        }

        @Override
        protected Boolean notNullExecute(final Map input, final ExecCtx ctx) throws Exception {
            for (final K element : input.keySet()) {
                if (element == null) {
                    if (this.key == null) {
                        return Boolean.TRUE;
                    }
                } else if (element.equals(this.key)) {
                    return Boolean.TRUE;
                }
            }
            return Boolean.FALSE;
        }
        
    }
    
    
    static final class ContainsAllKeys extends AbstractNotNullFunction,Boolean> {
        
        private final List keys;
        
        public ContainsAllKeys(final List keys) {
            super();
            this.keys = keys;
        }

        @Override
        protected Boolean notNullExecute(final Map input, final ExecCtx ctx) throws Exception {
            final Set notContained = new HashSet(this.keys);
            for (final K element : input.keySet()) {
                for (final K comparedElement : this.keys) {
                    if (element == null) {
                        if (comparedElement == null) {
                            notContained.remove(null);
                        }
                    } else if (element.equals(comparedElement)) {
                        notContained.remove(comparedElement);
                    }
                }
            }
            return (notContained.isEmpty()? Boolean.TRUE : Boolean.FALSE);
        }
        
    }
    
    
    
    static final class ContainsAnyKeys extends AbstractNotNullFunction,Boolean> {
        
        private final List keys;
        
        public ContainsAnyKeys(final List keys) {
            super();
            this.keys = keys;
        }

        @Override
        protected Boolean notNullExecute(final Map input, final ExecCtx ctx) throws Exception {
            for (final K element : input.keySet()) {
                for (final K comparedElement : this.keys) {
                    if (element == null) {
                        if (comparedElement == null) {
                            return Boolean.TRUE;
                        }
                    } else if (element.equals(comparedElement)) {
                        return Boolean.TRUE;
                    }
                }
            }
            return Boolean.FALSE;
        }
        
    }
    
    
    
    static final class ContainsNoneKeys extends AbstractNotNullFunction,Boolean> {
        
        private final List keys;
        
        public ContainsNoneKeys(final List keys) {
            super();
            this.keys = keys;
        }

        @Override
        protected Boolean notNullExecute(final Map input, final ExecCtx ctx) throws Exception {
            for (final K element : input.keySet()) {
                for (final K comparedElement : this.keys) {
                    if (element == null) {
                        if (comparedElement == null) {
                            return Boolean.FALSE;
                        }
                    } else if (element.equals(comparedElement)) {
                        return Boolean.FALSE;
                    }
                }
            }
            return Boolean.TRUE;
        }
        
    }
    
    
    
    
    static final class Reverse extends AbstractNotNullNonConvertingFunc> {
        
        public Reverse() {
            super();
        }

        @Override
        @SuppressWarnings("unchecked")
        protected Map notNullExecute(final Map input, final ExecCtx ctx) throws Exception {
            
            final Object[] revertArray = input.entrySet().toArray(new Object[input.size()]); 
            if (revertArray.length < 2) {
                return new LinkedHashMap(input);
            }
            int size = revertArray.length;
            Object aux = null;
            for (int i = 0, z = size / 2; i < z; i++) {
                aux = revertArray[i];
                revertArray[i] = revertArray[size - (i + 1)];
                revertArray[size - (i + 1)] = aux;
            }
            final Map result = new LinkedHashMap();
            for (final Object element : revertArray) {
                final Map.Entry entry = (Map.Entry) element;
                result.put(entry.getKey(), entry.getValue());
            }
            return result;
        }
        
    }
    
    static final class Count extends AbstractNotNullFunction,Integer> {
        
        public Count() {
            super();
        }
        
        @Override
        protected Integer notNullExecute(final Map object, final ExecCtx ctx) throws Exception {
            return Integer.valueOf(object.size());
        }
        
    }
    
}