Package urban.shapes

Source Code of urban.shapes.Shape

package urban.shapes;

import static org.apache.commons.collections15.CollectionUtils.collect;
import static org.apache.commons.collections15.CollectionUtils.select;
import static org.apache.commons.collections15.CollectionUtils.union;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

import org.apache.commons.collections15.Predicate;
import org.apache.commons.collections15.SortedBag;
import org.apache.commons.collections15.Transformer;
import org.apache.commons.collections15.bag.TreeBag;

import urban.model.Agent;
import urban.model.Site;
import urban.transformers.CanonicalBindingsTransformer;
import urban.transformers.ShapeToRuleGraphTransformer;

/**
* A shape - a connected set of agents.
*/
public class Shape {
  private static CanonicalBindingsTransformer transformer = new CanonicalBindingsTransformer();
  private final Collection<Agent> agents;
  private final Transformer<ShapePlusSite, RuleGraph> createGraph = new ShapeToRuleGraphTransformer();
 

  /**
   * @param agents The agents that make up the shape
   */
  public Shape(Collection<Agent> agents) {
    this.agents = canonicalise(agents);
  }

  /**
   * @return the agents that make up the shape
   */
  public Collection<Agent> getAgents() {
    return agents;
  }

  /**
   * Adds this shape to the rule graph in all possible ways to produce new rule graphs.
   * @param rg1 the rulegraph that is to be extended
   * @return a collection of rule graphs
   */
  public Collection<RuleGraph> getMatchPermutations(RuleGraph rg1) {
    List<RuleGraph> result = new ArrayList<RuleGraph>();
   
    result.addAll(getMatchPermutations(rg1, true));
    result.addAll(getMatchPermutations(rg1, false));
    return result;
  }

  /**
   * Adds this shape to the rule graph in all possible ways to produce new rule graphs.
   * @param rg1 the rulegraph that is to be extended
   * @param left true is shape is to be merge on the left
   * @return a collection of rule graphs
   */
  public Collection<RuleGraph> getMatchPermutations(RuleGraph rg1, boolean left) {
    List<RuleGraph> result = new ArrayList<RuleGraph>();
   
    for(RuleGraph r : getPossibleGraphs(rg1, left)){
      RuleGraph tmp = new RuleMerger(rg1, r).merge();
      if (tmp != null)
        result.add(tmp);
    }
   
    return result;
  }
 
  @Override
  public String toString(){
    return new ArrayList<Agent>(agents).toString();
  }


  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((agents == null) ? 0 : agents.hashCode());
    return result;
  }


  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    Shape other = (Shape) obj;
    if (agents == null) {
      if (other.agents != null)
        return false;
    } else if (!agents.equals(other.agents))
      return false;
    return true;
  }


  private Collection<Agent> canonicalise(Collection<Agent> agents2) {
    SortedBag<Agent> bag = new TreeBag<Agent>(new Comparator<Agent>() {
      @Override
      public int compare(Agent o1, Agent o2) {
        int tmp = o1.getName().compareTo(o2.getName());
        if (tmp != 0)
          return tmp;
       
        return o1.toString().compareTo(o2.toString());
      }
    });
   
    bag.addAll(transformer.transform(agents2));
    return bag;
  }


  private Collection<RuleGraph> getPossibleGraphs(RuleGraph rg1, boolean left) {
    if (left && rg1.hasSymmetricalBond()){
      // there is an awkward case where a site may match both sides of a bond if
      // the bond is on the same agent and site eg. A(a!1),A(a!1)
      return union(
          collect(select(toSites(agents), siteMatchesNode(rg1, left,true)), createGraph),
          collect(select(toSites(agents), siteMatchesNode(rg1, left,false)), new ShapeToRuleGraphTransformer(rg1)));
    }
    else
      return collect(select(toSites(agents), siteMatchesNode(rg1, left)), createGraph);
  }
 
  private Predicate<ShapePlusSite> siteMatchesNode(final RuleGraph rg1, final boolean onLeft) {
    final Node root = rg1.getRoot();

    if (root instanceof BondNode) {
      Iterator<Entry<Link, RuleGraph>> iterator = rg1.getChildren().iterator();
      final Entry<Link, RuleGraph> left = iterator.next();
      final Entry<Link, RuleGraph> right = iterator.next();

      return new Predicate<ShapePlusSite>() {
        public boolean evaluate(ShapePlusSite p) {
          Site s = p.site;
          if (!onLeft && s.getBindingMark() == null)
            return false;
          if (onLeft && s.getBindingMark() != null)
            return false;
          return test(s, left) || test(s, right);
        }

        private boolean test(Site s, Entry<Link, RuleGraph> e) {
          return (e.getKey().getDst().equals(s.getName())
          && e.getValue().getRoot().getName().equals(s.getAgent()));
        }
      };
    } else {
      final String state = ((SiteNode)root).getLeft().getState();
     
      return new Predicate<ShapePlusSite>() {
        public boolean evaluate(ShapePlusSite p) {
          Site s = p.site;
         
          return root.getName().equals(s.getAgent())
          && root.getGenerator().equals(s.getName())
          && (
            (onLeft && state.equals(s.getState()))
          ||
            (!onLeft && !state.equals(s.getState()))
          );         
        }
      };   
    }
  }

  private Predicate<ShapePlusSite> siteMatchesNode(final RuleGraph rg1, final boolean onLeft, final boolean firstAgent) {
    Iterator<Entry<Link, RuleGraph>> iterator = rg1.getChildren().iterator();
    final Entry<Link, RuleGraph> left = iterator.next();
    final Entry<Link, RuleGraph> right = iterator.next();

    return new Predicate<ShapePlusSite>() {
      public boolean evaluate(ShapePlusSite p) {
        Site s = p.site;
        if (s.getBindingMark() != null)
          return false;
        return (firstAgent && test(s, left)) || (!firstAgent && test(s, right));
      }

      private boolean test(Site s, Entry<Link, RuleGraph> e) {
        return (e.getKey().getDst().equals(s.getName())
        && e.getValue().getRoot().getName().equals(s.getAgent()));
      }
    };
  }

  private Collection<ShapePlusSite> toSites(Collection<Agent> agents){
    List<ShapePlusSite> sites = new ArrayList<ShapePlusSite>();
    for(Agent a : agents){
      for(Site s : a.getSites())
        sites.add(new ShapePlusSite(this, a,s));
    }
    return sites;
  }

  /**
   * Simple class for representing a Shape plus a site within the shape.
   */
  public static class ShapePlusSite {
    /**
     * Target shape
     */
    public final Shape shape;
    /**
     * Agent that site can be found in
     */
    public final Agent agent;
    /**
     * Target site
     */
    public final Site site;
   
    ShapePlusSite(Shape shape, Agent agent, Site site) {
      this.shape = shape;
      this.agent = agent;
      this.site = site;
    }
  }
}
TOP

Related Classes of urban.shapes.Shape

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.