io.coala.guice.GuiceBinder.java Source code

Java tutorial

Introduction

Here is the source code for io.coala.guice.GuiceBinder.java

Source

/* $Id: d9b583db378afc7e062e48871f0495bed3d4c05b $
 * $URL: https://dev.almende.com/svn/abms/guice-util/src/main/java/io/coala/guice/GuiceBinder.java $
 * 
 * Part of the EU project Adapt4EE, see http://www.adapt4ee.eu/
 * 
 * @license
 * 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.
 * 
 * Copyright (c) 2010-2013 Almende B.V. 
 */
package io.coala.guice;

import io.coala.agent.Agent;
import io.coala.agent.AgentFactory;
import io.coala.agent.AgentID;
import io.coala.agent.AgentStatusUpdate;
import io.coala.agent.BasicAgent;
import io.coala.bind.Binder;
import io.coala.bind.BinderFactoryConfig;
import io.coala.capability.Capability;
import io.coala.capability.CapabilityFactory;
import io.coala.capability.replicate.ReplicationConfig;
import io.coala.guice.log.InjectLoggerTypeListener;
import io.coala.log.LogUtil;
import io.coala.model.ModelComponentIDFactory;
import io.coala.name.AbstractIdentifiable;
import io.coala.random.RandomDistribution;
import io.coala.random.RandomNumberStream;
import io.coala.random.impl.RandomDistributionFactoryImpl;
import io.coala.random.impl.RandomNumberStreamFactoryWell19937c;
import io.coala.time.SimTime;
import io.coala.time.SimTimeFactory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import javax.inject.Provider;

import org.apache.log4j.Logger;

import rx.Observable;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.google.inject.matcher.Matchers;
import com.google.inject.name.Names;

/**
 * {@link GuiceBinder}
 * 
 * @date $Date: 2014-08-09 08:14:14 +0200 (Sat, 09 Aug 2014) $
 * @version $Revision: 354 $
 * @author <a href="mailto:Rick@almende.org">Rick</a>
 * 
 */
public class GuiceBinder extends AbstractIdentifiable<AgentID> implements Binder {

    /** */
    private static final long serialVersionUID = 1L;

    /** */
    private static final Logger LOG = LogUtil.getLogger(GuiceBinder.class);

    /** */
    @JsonIgnore
    private final Injector injector;

    /** */
    // private final ConfigModule configModule;

    /** */
    private final GuiceLazyBinderModule lazyInstaller;

    /** */
    private final Observable<AgentStatusUpdate> ownerStatus;

    /**
     * {@link GuiceBinder} constructor
     * 
     * @param config
     * @param clientType
     */
    public GuiceBinder(final BinderFactoryConfig config, final String clientName,
            final Class<? extends Agent> clientType, final Observable<AgentStatusUpdate> ownerStatus,
            final Module... modules) {
        this(config, config.getReplicationConfig().newID().createAgentID(clientName), clientType, ownerStatus,
                modules);
    }

    /**
     * {@link GuiceBinder} constructor
     * 
     * @param config
     * @param clientType
     */
    @SuppressWarnings("rawtypes")
    public GuiceBinder(final BinderFactoryConfig config, final AgentID clientID,
            final Class<? extends Agent> clientType, final Observable<AgentStatusUpdate> ownerStatus,
            final Module... modules) {
        super(clientID);

        this.ownerStatus = ownerStatus;

        final Class<? extends Agent> agentType = clientType != null ? clientType
                : config.getCustomAgentTypes().containsKey(getID()) ? config.getCustomAgentTypes().get(getID())
                        : config.getDefaultAgentType();
        LOG.trace(
                "Agent type for: " + getID() + " = " + agentType + ", configured: " + config.getCustomAgentTypes());

        final List<Module> moduleList = new ArrayList<Module>();

        // this.configModule = new ConfigModule(ConfigUtil.getMainConfig());
        // moduleList.add(this.configModule);

        this.lazyInstaller = new GuiceLazyBinderModule(this) {
            @Override
            protected void configure() {
                // bind BAAL @InjectLogger injection annotation
                bindListener(Matchers.any(), new InjectLoggerTypeListener());

                bind(Binder.class).toInstance(GuiceBinder.this);

                // bind(BinderFactory.class).toInstance(instance);

                bind(BinderFactoryConfig.class).toInstance(config);

                bind(ModelComponentIDFactory.class).toInstance(config.getReplicationConfig().newID());

                bind(ReplicationConfig.class).toInstance(config.getReplicationConfig());

                // FIXME replace by binder config
                bind(RandomDistribution.Factory.class).to(RandomDistributionFactoryImpl.class);

                // FIXME replace by binder config
                bind(RandomNumberStream.Factory.class).to(RandomNumberStreamFactoryWell19937c.class);

                LOG.trace(
                        "Bound " + Binder.class.getName() + " to " + GuiceBinder.this + " for client: " + getID());

                // bind(AgentID.class).toInstance(clientID);

                // TODO provide binding configuration, see guice-xml-config and
                // http://beust.com/weblog/2013/07/12/flexible-configuration-with-guice/
                // and OWNER API at http://owner.aeonbits.org/

                bindConstant().annotatedWith(Names.named(AGENT_TYPE))
                        .to(agentType == null ? Agent.class : agentType);

                for (Entry<Class<? extends CapabilityFactory>, Class<? extends Capability>> entry : config
                        .getSingletonServiceTypes().entrySet())
                    lazyInstall(entry.getKey().asSubclass(CapabilityFactory.class), entry.getValue());

                for (Entry<Class<? extends Capability>, Class<? extends Capability>> entry : config
                        .getInstantServiceTypes().entrySet())
                    bindService(entry.getKey(), entry.getValue());

                install(new FactoryModuleBuilder().implement(SimTime.class, GuiceSimTime.class)
                        .build(SimTimeFactory.class));

                install(new FactoryModuleBuilder()
                        .implement(Agent.class, agentType == null ? BasicAgent.class : agentType)
                        .build(AgentFactory.class));

            }
        };
        moduleList.add(this.lazyInstaller);
        moduleList.addAll(Arrays.asList(modules));
        this.injector = GuiceUtil.getInstance(getID(), moduleList).getInjector();
    }

    /**
     * @return
     */
    protected Injector getInjector() {
        return this.injector;
    }

    /**
     * @return
     */
    protected Observable<AgentStatusUpdate> getOwnerStatus() {
        return this.ownerStatus;
    }

    @Override
    public <T> T inject(final Class<T> type) {
        return getInjector().getInstance(type);
    }

    // protected Map<Class<?>,Object> bindings = new HashMap<>();

    @Override
    public Set<Class<?>> getBindings() {
        final Set<Class<?>> result = new HashSet<>(this.lazyInstaller.available.keySet());
        if (getInjector() != null)
            for (Key<?> key : getInjector().getBindings().keySet())
                result.add(key.getTypeLiteral().getRawType());
        return Collections.unmodifiableSet(result);
    }

    @Override
    public <T> Provider<T> rebind(final Class<T> type, final T instance) {
        return rebind(type, new Provider<T>() {
            @Override
            public T get() {
                return instance;
            }
        });
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> Provider<T> rebind(final Class<T> type, final Provider<T> provider) {
        final T old = (T) this.lazyInstaller.lazyInstances.remove(type);
        LOG.trace("Rebinding " + type.getName() + ", removed lazy instance: " + old);
        return (Provider<T>) this.lazyInstaller.available.put(type, new com.google.inject.Provider<T>() {
            @Override
            public T get() {
                return provider.get();
            }
        });
    }

}