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

brooklyn.entity.proxying.BasicEntitySpec Maven / Gradle / Ivy

There is a newer version: 0.7.0-M1
Show newest version
package brooklyn.entity.proxying;

import static com.google.common.base.Preconditions.checkNotNull;

import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import brooklyn.config.ConfigKey;
import brooklyn.config.ConfigKey.HasConfigKey;
import brooklyn.entity.Entity;
import brooklyn.management.Task;
import brooklyn.policy.Policy;
import brooklyn.util.exceptions.Exceptions;

import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

public class BasicEntitySpec> implements EntitySpec {

    private static final Logger log = LoggerFactory.getLogger(BasicEntitySpec.ConcreteEntitySpec.class);
    
    private static class ConcreteEntitySpec extends BasicEntitySpec> {
        ConcreteEntitySpec(Class type) {
            super(type);
        }
    }

    public static  BasicEntitySpec newInstance(Class type) {
        return new ConcreteEntitySpec(type);
    }

    public static  BasicEntitySpec newInstance(Class type, Class implType) {
        return new ConcreteEntitySpec(type).impl(implType);
    }

    private final Class type;
    private String displayName;
    private Class impl;
    private Entity parent;
    private final Map flags = Maps.newLinkedHashMap();
    private final Map, Object> config = Maps.newLinkedHashMap();
    private final List policies = Lists.newArrayList();
    private final Set> additionalInterfaces = Sets.newLinkedHashSet();
    
    public BasicEntitySpec(Class type) {
        this.type = type;
    }
    
    @SuppressWarnings("unchecked")
    protected S self() {
       return (S) this;
    }

    public S displayName(String val) {
        displayName = val;
        return self();
    }

    public S impl(Class val) {
        checkIsImplementation(checkNotNull(val, "impl"));
        checkIsNewStyleImplementation(val);
        impl = val;
        return self();
    }

    public S additionalInterfaces(Class... vals) {
        for (Class val : vals) {
            additionalInterfaces.add(val);
        }
        return self();
    }

    public S additionalInterfaces(Iterable> val) {
        additionalInterfaces.addAll(Sets.newLinkedHashSet(val));
        return self();
    }

    public S parent(Entity val) {
        parent = checkNotNull(val, "parent");
        return self();
    }
    
    public S configure(Map val) {
        for (Map.Entry entry: val.entrySet()) {
            if (entry.getKey()==null) throw new NullPointerException("Null key not permitted");
            if (entry.getKey() instanceof CharSequence)
                flags.put(entry.getKey().toString(), entry.getValue());
            else if (entry.getKey() instanceof ConfigKey)
                config.put((ConfigKey)entry.getKey(), entry.getValue());
            else if (entry.getKey() instanceof HasConfigKey)
                config.put(((HasConfigKey)entry.getKey()).getConfigKey(), entry.getValue());
            else {
                log.warn("Spec "+this+" ignoring unknown config key "+entry.getKey());
            }
        }
        return self();
    }
    
    public S configure(CharSequence key, Object val) {
        flags.put(checkNotNull(key, "key").toString(), val);
        return self();
    }
    
    public  S configure(ConfigKey key, V val) {
        config.put(checkNotNull(key, "key"), val);
        return self();
    }

    public  S configure(ConfigKey key, Task val) {
        config.put(checkNotNull(key, "key"), val);
        return self();
    }

    public  S configure(HasConfigKey key, V val) {
        config.put(checkNotNull(key, "key").getConfigKey(), val);
        return self();
    }

    public  S configure(HasConfigKey key, Task val) {
        config.put(checkNotNull(key, "key").getConfigKey(), val);
        return self();
    }

    public  S policy(Policy val) {
        policies.add(val);
        return self();
    }

    @Override
    public Class getType() {
        return type;
    }
    
    @Override
    public String getDisplayName() {
        return displayName;
    }
    
    @Override
    public Class getImplementation() {
        return impl;
    }
    
    public Set> getAdditionalInterfaces() {
        return additionalInterfaces;
    }

    @Override
    public Entity getParent() {
        return parent;
    }
    
    @Override
    public Map getFlags() {
        return Collections.unmodifiableMap(flags);
    }
    
    @Override
    public Map, Object> getConfig() {
        return Collections.unmodifiableMap(config);
    }
        
    @Override
    public List getPolicies() {
        return policies;
    }
    
    @Override
    public String toString() {
        return Objects.toStringHelper(this).add("type", type).toString();
    }
    
    // TODO Duplicates method in BasicEntityTypeRegistry
    private void checkIsImplementation(Class val) {
        if (!type.isAssignableFrom(val)) throw new IllegalStateException("Implementation "+val+" does not implement "+type);
        if (val.isInterface()) throw new IllegalStateException("Implementation "+val+" is an interface, but must be a non-abstract class");
        if (Modifier.isAbstract(val.getModifiers())) throw new IllegalStateException("Implementation "+val+" is abstract, but must be a non-abstract class");
    }

    // TODO Duplicates method in BasicEntityTypeRegistry, and InternalEntityFactory.isNewStyleEntity
    private void checkIsNewStyleImplementation(Class implClazz) {
        try {
            implClazz.getConstructor(new Class[0]);
        } catch (NoSuchMethodException e) {
            throw new IllegalStateException("Implementation "+implClazz+" must have a no-argument constructor");
        } catch (SecurityException e) {
            throw Exceptions.propagate(e);
        }
        
        if (implClazz.isInterface()) throw new IllegalStateException("Implementation "+implClazz+" is an interface, but must be a non-abstract class");
        if (Modifier.isAbstract(implClazz.getModifiers())) throw new IllegalStateException("Implementation "+implClazz+" is abstract, but must be a non-abstract class");
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy