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

us.bpsm.edn.protocols.Protocols Maven / Gradle / Ivy

// (c) 2012 B Smith-Mannschott -- Distributed under the Eclipse Public License
package us.bpsm.edn.protocols;

import static us.bpsm.edn.protocols.C3.methodResolutionOrder;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * Factories for {@link Protocol}s
 */
@SuppressWarnings("rawtypes")
public class Protocols {

    static final String SINGLE_USE_MSG =
            "This builder can only be used to build a single Protocol.";

    static final String NO_MODIFY_MSG =
            "This builder is single-use and may not be modified after " +
            "the Protocol has been built.";

    static final String MUST_HAVE_NAME =
            "Each Protocol must have a name";

    static final String FN_MUST_NOT_BE_NULL =
            "The value ('fn') associated with a class must not be null.";

    private Protocols() {
        throw new UnsupportedOperationException();
    }

    /**
     * Return a new, empty single-use {@code Protocol.Builder} with
     * the given name.
     *
     * @param name not null.
     *
     * @return an empty {@code Protocol.Builder}, never null.
     */
    public static  Protocol.Builder builder(final String name) {
        return new ProtocolImpl(name);
    }

    static class ProtocolImpl implements Protocol.Builder, Protocol {
        final String name;
        F nullFn = null;
        final Map, F> m = new HashMap, F>();
        boolean built = false;

        public String toString() {
            if (built) {
                return "Protocol '" + name + "'";
            } else {
                return "Protocol.Builder '" + name + "'";
            }
        }

        ProtocolImpl(String name) {
            if (name == null) {
                throw new NullPointerException(MUST_HAVE_NAME);
            }
            this.name = name;
        }

        public Protocol.Builder put(Class selfClass, F fn) {
            if (built) {
                throw new IllegalStateException(NO_MODIFY_MSG);
            }
            if (fn == null) {
                throw new NullPointerException(FN_MUST_NOT_BE_NULL);
            }
            if (selfClass == null) {
                nullFn = fn;
            } else {
                m.put(selfClass, fn);
            }
            return this;
        }

        public Protocol build() {
            if (built) {
                throw new IllegalStateException(SINGLE_USE_MSG);
            }
            built = true;
            return this;
        }

        @Override
        public String name() {
            return name;
        }

        @Override
        public F lookup(Class selfClass) {
            if (selfClass == null) {
                return nullFn;
            }
            synchronized (m) {
                F fn;
                fn = m.get(selfClass);
                if (fn != null) {
                    return fn;
                }
                for (Class c: butfirst(methodResolutionOrder(selfClass))) {
                    fn = m.get(c);
                    if (fn != null) {
                        m.put(selfClass, fn);
                        return fn;
                    }
                }
                return null;
            }
        }
    }

    static  List butfirst(List es) {
        return es.isEmpty() ? es : es.subList(1, es.size());
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy