Package urban.model.info

Source Code of urban.model.info.ModelInfo

package urban.model.info;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.collections15.CollectionUtils;
import org.apache.commons.collections15.SortedBag;
import org.apache.commons.collections15.bag.TreeBag;

import urban.model.Agent;
import urban.model.Rule;
import urban.model.ShapeParameterStatement;
import urban.model.Site;
import urban.model.SiteArray;
import urban.model.Statement;
import urban.shapes.ShapeParameters;

/**
* This provides all sorts of useful calculated information about a collection of statements
*/
public class ModelInfo {
  private HashMap<String, Site> sites;
  private HashMap<String, SiteArray> arrays;
  private Collection<Statement> lines;
  private HashMap<String, Set<String>> bindings;
  private ShapeParameters shapeParameters;
 
  private HashMap<String, Agent> agents;

  /**
   * The constructor requires the collection of statements to be used.
   * The collection is not changed in any way by this class.
   * @param lines
   */
  public ModelInfo(Collection<Statement> lines) {
    this.lines = lines;
  }

  /**
   * @return Any parameters related to shapes are returned as ShapeParameters
   */
  public ShapeParameters getShapeParameters(){
    if (shapeParameters == null)
      shapeParameters = createShapeParameters();
    return shapeParameters;
  }
 
  /**
   * @return The set of sites mentioned in the model
   */
  public Collection<Site> getSites() {
    if (sites == null){
      sites = new HashMap<String, Site>();
      arrays = new HashMap<String, SiteArray>();
      for(Statement s : lines)
        addAllSites(s.getSites());
    }
    return CollectionUtils.union(sites.values(), arrays.values());
  }

 
  /**
   * The sites within the agent will be a merged set of sites referred to
   * @return The set of agents mentioned in the model.
   */
  public Collection<Agent> getAgents() {
    if (agents == null){
      agents = new HashMap<String, Agent>();
      for(Statement s : lines)
        addAgent(s.getAgents());
    }
    return agents.values();
  }

  /**
   * @param qualifiedName
   * @return A collection of sites that may be bound to the site name given
   */
  public Collection<String> getBindingsForSite(String qualifiedName){
    getSites();
    getBindings();
    return getSiteSet(qualifiedName);
  }

  /**
   * @return a map of all the bindings in the model
   */
  public HashMap<String, Set<String>> getBindings() {
    if (bindings == null)
      bindings = new HashMap<String, Set<String>>();
   
    for(Statement s : lines){
      if (s instanceof Rule){
        addBindings((Rule)s);
      }
    }
    return bindings;
  }

  /**
   * @param qualifiedName
   * @return A list of possible states for the given site
   */
  public Collection<String> getStatesForSite(String qualifiedName) {
    getSites();
    final Site site = sites.get(qualifiedName);
    if (site == null)
      return null;
    final String state = site.getState();
    if (state == null)
      return null;
    return Arrays.asList(state.split(", "));
  }

  /**
   * @param name
   * @return An agent with the name if it exists in the model or null
   */
  public Agent getAgent(String name) {
    if (agents == null)
      getAgents();
    return agents.get(name);
  }

  private ShapeParameters createShapeParameters() {
    ShapeParameters tmp = new ShapeParameters();
    for (Statement s : lines)
      if (s instanceof ShapeParameterStatement){
        ((ShapeParameterStatement)s).addParametersTo(tmp);
      }
    return tmp;
  }

  private Comparator<? super Site> compareByName = new Comparator<Site>() {
    public int compare(Site o1, Site o2) {
      return o1.getName().compareTo(o2.getName());
    }
  };
 
  private void addAgent(Collection<Agent> list) {
    for(Agent a : list){
      final Agent mergeAgent = mergeAgent(a, agents.get(a.getName()));
      agents.put(a.getName(), mergeAgent);
    }
  }

  private Agent mergeAgent(Agent a1, Agent a2) {
    if (a1 == null)
      return a2;
    if (a2 == null)
      return a1;
   
    return new Agent(a1.getName(), mergeSites(a1.getSites(), a2.getSites()));
  }   
 
  Collection<Site> mergeSites(Collection<Site> a, Collection<Site> b) {
    SortedBag<Site> s1 = getSorted(a);
    SortedBag<Site> s2 = getSorted(b);
    SortedBag<Site> result = getSorted(Collections.<Site>emptyList());

    Iterator<Site> i1= s1.iterator();
    Iterator<Site> i2 = s2.iterator();
   
    Site x=null,y = null;
    while(x != null || i1.hasNext() || y != null || i2.hasNext()){
     
      if (i1.hasNext())
        x = i1.next();
      if (i2.hasNext())
        y = i2.next();

      if (x == null){
        result.add(y);
        y = null;
        continue;
      }
     
      if (y == null){
        result.add(x);
        x = null;
        continue;
      }
     
      int comparison = x.getName().compareTo(y.getName());
     
      if (comparison == 0){ // have the same name
        result.add(mergeSite(x,y));
        x = null;
        y = null;
      } else if (comparison < 0){ // x is less than y
        result.add(x);
        x = null;
      } else if (comparison > 0){ // x is less than y
        result.add(y);
        y = null;
      }
    }
    return result;
  }

  Site mergeSite(Site x, Site y) {
    String states = null;

    if (x.getState() != null && y.getState() != null){
      TreeSet<String> list = new TreeSet<String>(Arrays.asList(x.getState().split(", ")));
      list.addAll( Arrays.asList(y.getState().split(", ")) );
      states = list.toString().replaceAll("[\\[\\]]", "");
    } else if (x.getState() != null) {
      states = x.getState();
    } else if (y.getState() != null) {
        states = y.getState();
    }
    return new Site(x.getAgent(), x.getName(), states, null);
  }

  private SortedBag<Site> getSorted(Collection<Site> a) {
    TreeBag<Site> tb = new TreeBag<Site>(compareByName);
    tb.addAll(a);
    return tb;
  }

  private void addAllSites(Collection<Site> toBeAdded) {
    for(Site s : toBeAdded){
      if (s.getClass() == SiteArray.class)
        addToArrays((SiteArray) s);
      else
        addToSite(s);
    }
  }

  private void addToSite(Site s) {
    String key = s.getQualifiedName();
    Site tmp = sites.get(key);
   
    if (tmp == null)
      sites.put(key, s);
    else {
      sites.put(key, mergeSite(tmp,s));
    }
  }

  private void addToArrays(SiteArray s) {
    String key = s.getQualifiedName();
    SiteArray tmp = arrays.get(key);
   
    if (tmp == null)
      arrays.put(key, s);
    else {
      if (tmp.getIndex() < s.getIndex()){
        arrays.put(key, s);
      }
    }
  }

  private void addBindings(Rule s) {
    addBindings(s.getLhs());
    addBindings(s.getRhs());
  }

  private void addBindings(Collection<Agent> agents) {
    HashMap<String, Site> b = new HashMap<String, Site>();
   
    for (Agent a : agents){
      for (Site s : a.getSites()){
        if (s.getBindingMark() != null){
          final Site s1 = b.get(s.getBindingMark());
          if (s1 != null){
            if (s.getQualifiedName().compareTo(s1.getQualifiedName()) <= 0)
              addBinding(s.getQualifiedName(), s1);
            else
              addBinding(s1.getQualifiedName(), s);
          } else {
            b.put(s.getBindingMark(), s);
          }
        }
      }
    }
  }

  private void addBinding(String qualifiedName, Site s) {
    getSiteSet(qualifiedName).add(s.getQualifiedName());
  }

  private Set<String> getSiteSet(String qualifiedName) {
    Set<String> set = bindings.get(qualifiedName);
   
    if (set == null){
      set = new HashSet<String>();
      bindings.put(qualifiedName, set);
    }
    return set;
  }
}
TOP

Related Classes of urban.model.info.ModelInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.