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

net.javapla.jawn.core.Registry Maven / Gradle / Ivy

The newest version!
package net.javapla.jawn.core;

import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Objects;
import java.util.function.Supplier;

import net.javapla.jawn.core.annotation.Named;
import net.javapla.jawn.core.internal.injection.Provider;
import net.javapla.jawn.core.internal.reflection.Materialise;


/**
 * Dependency Injection pattern which may be provided by a dependency injection framework
 *
 */
public interface Registry {
// formerly known as Injection
    
    // TODO come back to all the throwables
     T require(Class type) throws Up.RegistryException;
    
     T require(Class type, String name) throws Up.RegistryException;
    
     T require(Key key) throws Up.RegistryException;
    
     Provider provider(Key key) throws Up.RegistryException;
    
    default  Provider provider(Class clazz) {
        return provider(Key.of(clazz));
    }
    
     Registry register(Key key, T instance);

     Registry register(Key key, Provider provider);
    
    default  Registry register(Class clazz, T service) {
        return register(Key.of(clazz), service);
    }
    
    @SuppressWarnings("unchecked")
    default  Registry register(T service) {
        return register( (Class) service.getClass(), service);
    }
    
    
    /**
     * Registry for storing services in a simple key/value mechanism.
     */
    public static interface ServiceRegistry {
        
        /**
         * Register a service. 
         * Overrides any previous registered service
         * 
         * @param  Service type
         * @param key
         * @param service
         * @return this 
         * //Any previously registered service or null
         */
         ServiceRegistry register(RegistryKey key, T service);
        
        default  ServiceRegistry register(Class clazz, T service) {
            //return register(RegistryKey.of(clazz), service);
            return register(Key.of(clazz), service);
        }
        
        /**
         * Register a service. 
         * Overrides any previous registered service
         * 
         * @param  Service type
         * @param key
         * @param service
         * @return this 
         * //Any previously registered service or null
         */
        @Deprecated
         ServiceRegistry register(RegistryKey key, Supplier service);
        
        @Deprecated
        default  ServiceRegistry register(Class clazz, Supplier service) {
            return register(RegistryKey.of(clazz), service);
        }
        
         ServiceRegistry register(Key key, Provider service);
        default  ServiceRegistry register(Class clazz, Provider service) {
            return register(Key.of(clazz), service);
        }
        
        /*@Override
        default  T require(Class type) throws RegistryException {
            return require(Key.of(type));//require(RegistryKey.of(type));
        }
        
        @Override
        default  T require(Class type, String name) throws RegistryException {
            return require(type, name);//require(RegistryKey.of(type, name));
        }*/

         ServiceRegistry register(Key key, T service);
    }
    
    public static final class ProvisionException extends RuntimeException {
        public ProvisionException(Throwable cause) {
            super(cause);
        }
        
        public ProvisionException(String msg) {
            super(msg);
        }
        
        private static final long serialVersionUID = 1L;
    }
    
    public static final class Key {
        public final Class type;
        public final String name;
        public final int hashCode;
        public final Class annotation;
        
        private Key(Class type, String name, Class annotation) {
            this.type = type;
            this.name = name;
            this.annotation = annotation;
            this.hashCode = Arrays.hashCode(new Object[]{type, name, annotation}); // automatically checks for null
        }
        
        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null || getClass() != obj.getClass()) return false;
            
            if (!(obj instanceof Key)) return false;
            
            Key that = (Key) obj;
            return this.type.equals(that.type) && Objects.equals(this.name, that.name) && Objects.equals(this.annotation, that.annotation);
        }
        
        @Override
        public int hashCode() {
            return hashCode;
        }
        
        @Override
        public String toString() {
            String s = type.getName();
            if (name != null) s += "(" + name + ")";
            if (annotation != null) s += "@" + annotation.getSimpleName();
            return s;
        }
        
        public static  Key of(Class type) {
            return new Key<>(type, null, null);
        }
        
        public static  Key of(Class type, String name) {
            return new Key<>(type, name, Named.class);
        }
        
        public static  Key of(Class type, Annotation annotation) {
            if (annotation == null) return Key.of(type);
            
            return annotation.annotationType().equals(Named.class) ?
                Key.of(type, ((Named)annotation).value()) :
                new Key<>(type, null, annotation.annotationType());
        }
    }
    
    @Deprecated
    public static final class RegistryKey {
        public final TypeLiteral typeLiteral;
        
        public final int hash;
        
        public final String name;
        
        private RegistryKey(Class type, String name) {
            this(TypeLiteral.get(type), name);
        }
        
        private RegistryKey(TypeLiteral type, String name) {
            this.typeLiteral = Materialise.canonicalizeKey(type);
            this.hash = Arrays.hashCode(new Object[]{type, name}); // automatically checks for null
            this.name = name;
        }
        
        @Override
        public int hashCode() {
            return hash;
        }
        
        @Override
        public boolean equals(Object obj) {
            if (obj instanceof RegistryKey) {
                RegistryKey that = (RegistryKey) obj;
                return this.typeLiteral == that.typeLiteral && Objects.equals(this.name, that.name);
            }
            return false;
        }
        
        @Override
        public String toString() {
            if (name == null) return typeLiteral.type.getTypeName();
            return typeLiteral.type.getTypeName() + "(" + name + ")";
        }
        
        public static  RegistryKey of(Class type) {
            return new RegistryKey<>(type, null);
        }
        
        public static  RegistryKey of(Class type, String name) {
            return new RegistryKey<>(type, name);
        }
        
        public static  RegistryKey of(TypeLiteral type) {
            return new RegistryKey<>(type, null);
        }
    }
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy