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

il.ac.bgu.cs.bp.bpjs.execution.jsproxy.MapProxy Maven / Gradle / Ivy

Go to download

Provides runtime and analysis for behavioral programs written in JavaScript. It can run stand-alone (from the commmandline) or be embedded in larger JVM-based systems.

The newest version!
/*
 * The MIT License
 *
 * Copyright 2020 michael.
 *
 * 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 il.ac.bgu.cs.bp.bpjs.execution.jsproxy;


import il.ac.bgu.cs.bp.bpjs.internal.ScriptableUtils;
import java.util.*;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

/**
 * A Proxy to a map.Stores changes to the proxied map, but does not change it.
 * @author michael
 * @param  Type of the keys in the map.
 * @param  Type of values in the map.
 */
public class MapProxy implements java.io.Serializable {

    public static abstract class Modification implements java.io.Serializable {
        public static final Modification DELETE = new Modification(){};
    }
    
    public static class PutValue extends Modification implements java.io.Serializable {
        final VV value;

        public PutValue(VV aValue) {
            value = aValue;
        }

        public VV getValue() {
            return value;
        }
        
        @Override
        public int hashCode() {
            int hash = 5;
            hash = 23 * hash + ScriptableUtils.jsHashCode(this.value);
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)  return true;
            if (obj == null) return false;
            if (getClass() != obj.getClass()) return false;
            final PutValue other = (PutValue) obj;
            
            return ScriptableUtils.jsEquals(this.value, other.value);
        }        
    }
   
    
    /**
     * The map we are proxying.
     */
    Map seed;

    private final Map> modifications;
    
    public MapProxy(Map aSeed) {
        seed = aSeed;
        modifications = new HashMap<>();
    }

    public MapProxy(Map aSeed, Map> someModifications) {
        seed = aSeed;
        modifications = someModifications;
    }
    
    public void put(K key, V value ) {
        modifications.put(key, new PutValue<>(value));
    }
    
    public void remove(K key) {
        modifications.put(key, Modification.DELETE);
    }

    public Map filter(BiFunction func) {
        Map result = modifications.entrySet().stream()
            .filter(entry -> entry.getValue() != Modification.DELETE && func.apply(entry.getKey(), ((PutValue) entry.getValue()).value))
            .collect(Collectors.toMap(Map.Entry::getKey, entry -> ((PutValue) entry.getValue()).value));
        result.putAll(seed.entrySet().stream()
            .filter(entry -> !modifications.containsKey(entry.getKey()) && func.apply(entry.getKey(), entry.getValue()))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)));
        return result;
    }

    public V get( K key ) {
        if ( modifications.containsKey(key) ) {
            Modification m = modifications.get(key);
            if ( m == Modification.DELETE ) {
                return null;
            } else {
                return ((PutValue)m).value;
            }
        } else {
            return seed.get(key);
        }
    }
    
    public boolean has( K key ) {
        if ( modifications.containsKey(key) ) {
            Modification m = modifications.get(key);
            return ( m != Modification.DELETE );
        } else {
            return seed.containsKey(key);
        }
    }

    public Collection values() {
        return filter((k, v) -> true).values();
    }

    public Set keys() {
        Set retVal = new HashSet<>(seed.keySet());
        modifications.forEach((k,v)->{
            if ( v == Modification.DELETE ) {
                retVal.remove(k);
            } else {
                retVal.add(k);
            }
        });
        return retVal;
    }

    public Set> entrySet() {
        return filter((k, v) -> true).entrySet();
    }
    
    /**
     * Size of the map AFTER the modifications would be applied.
     * @return 
     */
    public int size() { 
        return keys().size();
    }
    
    /**
     * Returns the modifications registered since last reset.
     * Note that in case of multiple chagnes to the same key, only the 
     * last change is returned.
     * @return the modifications registered since last reset.
     */
    public Map> getModifications() {
        return modifications;
    }
    
    /**
     * Sets the underlying map. Does not reset changes!
     * @param aNewSeed 
     */
    public void setSeed( Map aNewSeed ) {
        seed = aNewSeed;
    }

    /**
     * Returns the underlying map.
     * @return the underlying map.
     */
    public Map getSeed() {
        return seed;
    }
    
    // clear modifications?
    public void reset() {
        modifications.clear();
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 23 * hash + ScriptableUtils.jsHashCode(this.modifications);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        
        final MapProxy other = (MapProxy) obj;
        if (!ScriptableUtils.jsMapEquals(this.seed, other.seed)) {
            return false;
        }
        return ScriptableUtils.jsMapEquals(getModifications(), other.getModifications());
    }
    
    
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy