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

brooklyn.entity.effector.Effectors Maven / Gradle / Ivy

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

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

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

import brooklyn.config.ConfigKey;
import brooklyn.entity.Effector;
import brooklyn.entity.Entity;
import brooklyn.entity.ParameterType;
import brooklyn.entity.basic.BasicParameterType;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.basic.EntityLocal;
import brooklyn.entity.effector.EffectorTasks.EffectorBodyTaskFactory;
import brooklyn.entity.effector.EffectorTasks.EffectorTaskFactory;
import brooklyn.management.TaskAdaptable;
import brooklyn.util.config.ConfigBag;

import com.google.common.base.Objects;
import com.google.common.base.Preconditions;

public class Effectors {

    private static final Logger log = LoggerFactory.getLogger(Effectors.class);
    
    public static class EffectorBuilder {
        private Class returnType;
        private String effectorName;
        private String description;
        private List> parameters = new ArrayList>();
        private EffectorTaskFactory impl;
        
        private EffectorBuilder(Class returnType, String effectorName) {
            this.returnType = returnType;
            this.effectorName = effectorName;
        }
        public EffectorBuilder description(String description) {
            this.description = description;
            return this;                
        }
        public EffectorBuilder parameter(Class paramType, String paramName) {
            return parameter(paramType, paramName, null, null);
        }
        public EffectorBuilder parameter(Class paramType, String paramName, String paramDescription) {
            return parameter(paramType, paramName, paramDescription, null);                
        }
        public  EffectorBuilder parameter(Class paramType, String paramName, String paramDescription, V defaultValue) {
            return parameter(new BasicParameterType(paramName, paramType, paramDescription, defaultValue));
        }
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public  EffectorBuilder parameter(ConfigKey key) {
            return parameter(new BasicParameterType(key.getName(), (Class)key.getType(), key.getDescription(), key.getDefaultValue()));
        }
        public EffectorBuilder parameter(ParameterType p) {
            parameters.add(p);
            return this;
        }
        public EffectorBuilder impl(EffectorTaskFactory taskFactory) {
            this.impl = taskFactory;
            return this;
        }
        public EffectorBuilder impl(EffectorBody effectorBody) {
            this.impl = new EffectorBodyTaskFactory(effectorBody);
            return this;
        }
        /** returns the effector, with an implementation (required); @see {@link #buildAbstract()} */
        public Effector build() {
             Preconditions.checkNotNull(impl, "Cannot create effector {} with no impl (did you forget impl? or did you mean to buildAbstract?)", effectorName);
             return new EffectorAndBody(effectorName, returnType, parameters, description, impl);
        }
        
        /** returns an abstract effector, where the body will be defined later/elsewhere 
         * (impl must not be set) */
        public Effector buildAbstract() {
            Preconditions.checkArgument(impl==null, "Cannot create abstract effector {} as an impl is defined", effectorName);
            return new EffectorBase(effectorName, returnType, parameters, description);
        }
    }

    /** creates a new effector builder with the given name and return type */
    public static  EffectorBuilder effector(Class returnType, String effectorName) {
        return new EffectorBuilder(returnType, effectorName);
    }

    /** creates a new effector builder to _override_ the given effector */
    public static  EffectorBuilder effector(Effector base) {
        EffectorBuilder builder = new EffectorBuilder(base.getReturnType(), base.getName());
        for (ParameterType p: base.getParameters())
            builder.parameter(p);
        builder.description(base.getDescription());
        if (builder instanceof EffectorWithBody)
            builder.impl(((EffectorWithBody) base).getBody());
        return builder;
    }

    /** returns an unsubmitted task which invokes the given effector; use {@link Entities#invokeEffector(EntityLocal, Entity, Effector, Map)} for a submitted variant */
    public static  TaskAdaptable invocation(Entity entity, Effector eff, @SuppressWarnings("rawtypes") Map parameters) {
        @SuppressWarnings("unchecked")
        Effector eff2 = (Effector) ((EntityInternal)entity).getEffector(eff.getName());
        if (log.isTraceEnabled())
            log.trace("invoking "+eff+"/"+
                (eff instanceof EffectorWithBody ? ((EffectorWithBody)eff).getBody() : "bodyless")+
                " on entity " + entity+" "+
                (eff2==eff ? "" : " (actually "+eff2+"/"+
                        (eff2 instanceof EffectorWithBody ? ((EffectorWithBody)eff2).getBody() : "bodyless")+")"));
        if (eff2!=null) {
            if (eff2!=eff) {
                if (eff2 instanceof EffectorWithBody) {
                    log.debug("Replacing invocation of {} on {} with {} which is the impl defined at that entity", new Object[] { eff, entity, eff2 });
                    return ((EffectorWithBody)eff2).getBody().newTask(entity, eff2, ConfigBag.newInstance().putAll(parameters));
                } else {
                    log.warn("Effector {} defined on {} has no body; invoking caller-supplied {} instead", new Object[] { eff2, entity, eff });
                }
            } else {
                log.debug("Effector {} does not exist on {}; attempting to invoke anyway", new Object[] { eff, entity });
            }
        }
        
        if (eff instanceof EffectorWithBody) {
            return ((EffectorWithBody)eff).getBody().newTask(entity, eff, ConfigBag.newInstance().putAll(parameters));
        }
        
        throw new UnsupportedOperationException("No implementation registered for effector "+eff+" on "+entity);
    }    

    public static boolean sameSignature(Effector e1, Effector e2) {
        return Objects.equal(e1.getName(), e2.getName()) &&
                Objects.equal(e1.getParameters(), e2.getParameters()) &&
                Objects.equal(e1.getReturnType(), e2.getReturnType());
    }
    
    // TODO sameSignatureAndBody
    
    public static boolean sameInstance(Effector e1, Effector e2) {
        return e1 == e2;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy