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

org.teavm.common.CachedMapper Maven / Gradle / Ivy

There is a newer version: 0.10.2
Show newest version
/*
 *  Copyright 2013 Alexey Andreev.
 *
 *  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.teavm.common;

import java.util.*;

/**
 *
 * @author Alexey Andreev
 *
 * @param  which type this mapper takes.
 * @param  which type this mapper produces.
 */
public class CachedMapper implements Mapper {
    private Mapper innerMapper;
    private Map> cache = new HashMap<>();
    private List> keyListeners = new ArrayList<>();

    private static class Wrapper {
        S value;
        boolean computed;
    }

    public CachedMapper(Mapper innerMapper) {
        this.innerMapper = innerMapper;
    }

    public R getKnown(T preimage) {
        Wrapper wrapper = cache.get(preimage);
        return wrapper != null ? wrapper.value : null;
    }

    @Override
    public R map(T preimage) {
        Wrapper wrapper = cache.get(preimage);
        if (wrapper == null) {
            wrapper = new Wrapper<>();
            cache.put(preimage, wrapper);
            wrapper.value = innerMapper.map(preimage);
            wrapper.computed = true;
            for (KeyListener listener : keyListeners) {
                listener.keyAdded(preimage);
            }
        }
        if (!wrapper.computed) {
            throw new IllegalStateException("Recursive calls are not allowed");
        }
        return wrapper.value;
    }

    public void invalidate(T preimage) {
        cache.remove(preimage);
    }

    public boolean caches(T preimage) {
        return cache.get(preimage) != null;
    }

    public Collection getCachedPreimages() {
        return new HashSet<>(cache.keySet());
    }

    public void addKeyListener(KeyListener listener) {
        keyListeners.add(listener);
    }

    public interface KeyListener {
        void keyAdded(S key);
    }
}