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

rinde.sim.core.model.ModelManager Maven / Gradle / Ivy

There is a newer version: 4.4.6
Show newest version
/**
 * 
 */
package rinde.sim.core.model;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;

/**
 * Models manager keeps track of all models used in the simulator. It is
 * responsible for adding a simulation object to the appropriate models
 * 
 * @author Bartosz Michalik 
 * @author Rinde van Lon 
 */
public class ModelManager implements ModelProvider {

  private final Multimap, Model> registry;
  private final List> models;
  private boolean configured;

  /**
   * Instantiate a new model manager.
   */
  public ModelManager() {
    registry = LinkedHashMultimap.create();
    models = new LinkedList>();
  }

  /**
   * Adds a model to the manager. Note: a model can be added only once.
   * @param model The model to be added.
   * @return true when the addition was successful, false otherwise.
   * @throws IllegalStateException when method called after calling configure
   */
  public boolean add(Model model) {
    checkState(!configured, "model can not be registered after configure()");
    final Class supportedType = model.getSupportedType();
    checkArgument(supportedType != null,
        "model must implement getSupportedType() and return a non-null");
    models.add(model);
    final boolean result = registry.put(supportedType, model);
    if (!result) {
      models.remove(model);
    }
    return result;
  }

  /**
   * Method that allows for initialization of the manager (e.g., resolution of
   * the dependencies between models) Should be called after all models were
   * registered in the manager.
   */
  public void configure() {
    for (final Model m : models) {
      if (m instanceof ModelReceiver) {
        ((ModelReceiver) m).registerModelProvider(this);
      }
    }
    configured = true;
  }

  /**
   * Add object to all models that support a given object.
   * @param object object to register
   * @param  the type of object to register
   * @return true if object was added to at least one model
   */
  @SuppressWarnings("unchecked")
  public  boolean register(T object) {
    if (object instanceof Model) {
      return add((Model) object);
    }
    checkState(configured,
        "can not register an object if configure() has not been called");

    boolean result = false;
    final Set> modelSupportedTypes = registry.keySet();
    for (final Class modelSupportedType : modelSupportedTypes) {
      if (modelSupportedType.isAssignableFrom(object.getClass())) {
        final Collection> assignableModels = registry
            .get(modelSupportedType);
        for (final Model m : assignableModels) {
          result |= ((Model) m).register(object);
        }
      }
    }
    return result;
  }

  /**
   * Unregister an object from all models it was attached to.
   * @param object object to unregister
   * @param  the type of object to unregister
   * @return true when the unregistration succeeded in at least one
   *         model
   * @throws IllegalStateException if the method is called before simulator is
   *           configured
   */
  @SuppressWarnings("unchecked")
  public  boolean unregister(T object) {
    checkArgument(!(object instanceof Model), "can not unregister a model");
    checkState(configured,
        "can not unregister when not configured, call configure() first");

    boolean result = false;
    final Set> modelSupportedTypes = registry.keySet();
    for (final Class modelSupportedType : modelSupportedTypes) {
      // check if object is from a known type
      if (modelSupportedType.isAssignableFrom(object.getClass())) {
        final Collection> assignableModels = registry
            .get(modelSupportedType);
        for (final Model m : assignableModels) {
          result |= ((Model) m).unregister(object);
        }
      }
    }
    return result;
  }

  /**
   * @return An unmodifiable view on all registered models.
   */
  public List> getModels() {
    return Collections.unmodifiableList(models);
  }

  @SuppressWarnings("unchecked")
  @Override
  public > T getModel(Class clazz) {
    for (final Model model : models) {
      if (clazz.isInstance(model)) {
        return (T) model;
      }
    }
    throw new IllegalArgumentException("There is no model of type: " + clazz);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy