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

functionalj.lens.lenses.MapAccess Maven / Gradle / Ivy

// ============================================================================
// Copyright (c) 2017-2019 Nawapunth Manusitthipol (NawaMan - http://nawaman.net).
// ----------------------------------------------------------------------------
// MIT License
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ============================================================================
package functionalj.lens.lenses;

import static java.util.stream.Collectors.toSet;

import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Predicate;

import functionalj.function.Func1;
import functionalj.lens.core.AccessParameterized;
import functionalj.lens.core.AccessParameterized2;
import lombok.val;

@SuppressWarnings("javadoc")
@FunctionalInterface
public interface MapAccess, 
                            VALUEACCESS extends AnyAccess>
                    extends AccessParameterized2, KEY, VALUE, KEYACCESS, VALUEACCESS> {

    public AccessParameterized2, KEY, VALUE, KEYACCESS, VALUEACCESS> accessParameterized2();
    
    @Override
    public default Map applyUnsafe(HOST host) throws Exception {
        return accessParameterized2().apply(host);
    }

    @Override
    public default KEYACCESS createSubAccess1(Function, KEY> accessToParameter) {
        return keyAccess(accessToParameter);
    }

    @Override
    public default VALUEACCESS createSubAccess2(Function, VALUE> accessToParameter) {
        return valueAccess(accessToParameter);
    }

    @Override
    public default KEYACCESS createSubAccessFromHost1(Function accessToParameter) {
        return accessParameterized2().createSubAccessFromHost1(accessToParameter);
    }
    
    @Override
    public default VALUEACCESS createSubAccessFromHost2(Function accessToParameter) {
        return accessParameterized2().createSubAccessFromHost2(accessToParameter);
    }
    

    public default KEYACCESS keyAccess(Function, KEY> accessToParameter) {
        return accessParameterized2().createSubAccess1(accessToParameter);
    }

    public default VALUEACCESS valueAccess(Function, VALUE> accessToParameter) {
        return accessParameterized2().createSubAccess2(accessToParameter);
    }
    
    public default VALUEACCESS get(KEY key) {
        return valueAccess(map -> map.get(key));
    }
    public default VALUEACCESS getOrDefault(KEY key, VALUE defaultValue) {
        return valueAccess(map -> map.getOrDefault(key, defaultValue));
    }
    
    public default IntegerAccess size() {
        return intAccess(0, map -> map.size());
    }
    
    public default BooleanAccess isEmpty() {
        return booleanAccess(true, map -> map.isEmpty());
    }
    
    public default BooleanAccess containsKey(KEY key) {
        return booleanAccess(false, map -> map.containsKey(key));
    }
    public default BooleanAccess containsKey(Predicate keyPredicate) {
        return booleanAccess(false, map -> map.keySet().stream().anyMatch(keyPredicate));
    }
    
    public default BooleanAccess containsValue(VALUE value) {
        return booleanAccess(false, map -> map.containsValue(value));
    }
    public default BooleanAccess containsValue(Predicate valuePredicate) {
        return booleanAccess(false, map -> map.values().stream().anyMatch(valuePredicate));
    }
    
    public default BooleanAccess containsEntry(Predicate> entryPredicate) {
        return booleanAccess(false, map -> map.entrySet().stream().anyMatch(entryPredicate));
    }
    public default BooleanAccess containsEntry(BiPredicate entryBiPredicate) {
        return containsEntry(entry -> entryBiPredicate.test(entry.getKey(), entry.getValue()));
    }
    
    public default CollectionAccess>, Map.Entry,
                    MapEntryAccess, KEY, VALUE, KEYACCESS, VALUEACCESS>> 
            entries() {
        val entryCollectionSpec = Helper.createEntryCollectionSpec(accessParameterized2(), map -> map.entrySet());
        return () -> entryCollectionSpec;
    }
    public default CollectionAccess>, Map.Entry, 
                    MapEntryAccess, KEY, VALUE, KEYACCESS, VALUEACCESS>> 
            filterEntries(Predicate> entryPredicate) {
        val entryCollectionSpec = Helper.createEntryCollectionSpec(accessParameterized2(), map->{
            return map.entrySet().stream().filter(entryPredicate).collect(toSet());
        });
        return () -> entryCollectionSpec;
    }
    public default CollectionAccess>, Map.Entry, 
                    MapEntryAccess, KEY, VALUE, KEYACCESS, VALUEACCESS>> 
            filterEntries(BiPredicate entryBiPredicate) {
        val entryCollectionSpec = Helper.createEntryCollectionSpec(accessParameterized2(), map->{
            return map.entrySet().stream()
                    .filter(entry -> entryBiPredicate.test(entry.getKey(), entry.getValue()))
                    .collect(toSet());
        });
        return () -> entryCollectionSpec;
    }
    public default CollectionAccess>, Map.Entry, 
                    MapEntryAccess, KEY, VALUE, KEYACCESS, VALUEACCESS>> 
            filter(Predicate keyPredicate) {
        val entryCollectionSpec = Helper.createEntryCollectionSpec(accessParameterized2(), map->{
            return map.entrySet().stream()
                    .filter(entry->keyPredicate.test(entry.getKey()))
                    .collect(toSet());
        });
        return () -> entryCollectionSpec;
    }
    
    public default CollectionAccess, KEY, KEYACCESS> keys() {
        val keyCollectionSpec = Helper.createKeyCollectionSpec(accessParameterized2(), Map::keySet);
        return () -> keyCollectionSpec;
    }
    
    public default CollectionAccess, VALUE, VALUEACCESS> values() {
        val valueCollectionSpec = Helper.createValueCollectionSpec(accessParameterized2(), Map::values);
        return () -> valueCollectionSpec;
    }
    
    //== Just some helpers -- ignore this ==
    
    public static class Helper {
        
        public static , VALUEACCESS extends AnyAccess>
            AccessParameterized, KEY, KEYACCESS> createKeyCollectionSpec(
                    AccessParameterized2, KEY, VALUE, KEYACCESS, VALUEACCESS> spec,
                    Function, Collection>                                      getKeys) {
            return new AccessParameterized, KEY, KEYACCESS>() {
                @Override
                public Collection applyUnsafe(HOST host) throws Exception {
                    return getKeys.apply(spec.apply(host));
                }
                @Override
                public KEYACCESS createSubAccessFromHost(Function accessToParameter) {
                    return spec.createSubAccessFromHost1(accessToParameter);
                }
            };
        }

        public static , VALUEACCESS extends AnyAccess>
            AccessParameterized, VALUE, VALUEACCESS> createValueCollectionSpec(
                    AccessParameterized2, KEY, VALUE, KEYACCESS, VALUEACCESS> spec,
                    Function, Collection> getValues) {
            return new AccessParameterized, VALUE, VALUEACCESS>() {
                @Override
                public Collection applyUnsafe(HOST host) throws Exception {
                    return getValues.apply(spec.apply(host));
                }
                @Override
                public VALUEACCESS createSubAccessFromHost(Function accessToParameter) {
                    return spec.createSubAccessFromHost2(accessToParameter);
                }
            };
        }

        public static , VALUEACCESS extends AnyAccess>
            AccessParameterized>, Entry, MapEntryAccess, KEY, VALUE, KEYACCESS, VALUEACCESS>>
            createEntryCollectionSpec(
                    AccessParameterized2, KEY, VALUE, KEYACCESS, VALUEACCESS> spec,
                    Function, Collection>> accessEntrySet) {
            val access = new AccessParameterized>, 
                                Map.Entry, 
                                MapEntryAccess, KEY, VALUE, KEYACCESS, VALUEACCESS>>() {
                
                            @Override
                            public Collection> applyUnsafe(HOST host) throws Exception {
                                return accessEntrySet.apply(spec.apply(host));
                            }
                            @Override
                            public MapEntryAccess, KEY, VALUE, KEYACCESS, VALUEACCESS> createSubAccessFromHost(
                                    Function> accessToParameter) {
                                // TODO - generalized this or just move it to other place.
                                return new MapEntryAccess, KEY, VALUE, KEYACCESS, VALUEACCESS>() {
                                    @Override
                                    public AccessParameterized2, KEY, VALUE, KEYACCESS, VALUEACCESS> accessParameterized2() {
                                        AccessParameterized2, KEY, VALUE, KEYACCESS, VALUEACCESS> accessParameterized2 = new AccessParameterized2, KEY, VALUE, KEYACCESS, VALUEACCESS>() {
                                            @Override
                                            public Entry applyUnsafe(HOST host) throws Exception {
                                                val entry = accessToParameter.apply(host);
                                                return entry;
                                            }
                                            @Override
                                            public KEYACCESS createSubAccessFromHost1(Function accessToParameter) {
                                                return spec.createSubAccessFromHost1(accessToParameter);
                                            }
                                            @Override
                                            public VALUEACCESS createSubAccessFromHost2(Function accessToParameter) {
                                                return spec.createSubAccessFromHost2(accessToParameter);
                                            }
                                        };
                                        return accessParameterized2;
                                    }
                                };
                            }
                        };
            return access;
        }

        public static , VALUEACCESS extends AnyAccess>
            AccessParameterized2, KEY, VALUE, KEYACCESS, VALUEACCESS> createEntrySpec(
                AccessParameterized2, KEY, VALUE, KEYACCESS, VALUEACCESS> mapAccessSpec,
                Func1, Map.Entry>                                   accessEntry) {
            AccessParameterized2, KEY, VALUE, KEYACCESS, VALUEACCESS> entrySpec
            = new AccessParameterized2, KEY, VALUE, KEYACCESS, VALUEACCESS>() {
                @Override
                public Entry applyUnsafe(HOST host) throws Exception {
                    val map   = mapAccessSpec.apply(host);
                    val entry = accessEntry.apply(map);
                    return entry;
                }
                
                @Override
                public KEYACCESS createSubAccessFromHost1(Function accessToParameter) {
                    return mapAccessSpec.createSubAccessFromHost1(accessToParameter);
                }
                @Override
                public VALUEACCESS createSubAccessFromHost2(Function accessToParameter) {
                    return mapAccessSpec.createSubAccessFromHost2(accessToParameter);
                }
            };
            return entrySpec;
        }
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy