content: /*************************************************************************
  *                                                                        *
  *  This file is part of the 20n/act project.                             *
  *  20n/act enables DNA prediction for synthetic biology/bioengineering.  *
  *  Copyright (C) 2017 20n Labs, Inc.                                     *
  *                                                                        *
  *  Please direct all queries to act@20n.com.                             *
  *                                                                        *
  *  This program is free software: you can redistribute it and/or modify  *
  *  it under the terms of the GNU General Public License as published by  *
  *  the Free Software Foundation, either version 3 of the License, or     *
  *  (at your option) any later version.                                   *
  *                                                                        *
  *  This program is distributed in the hope that it will be useful,       *
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  *  GNU General Public License for more details.                          *
  *                                                                        *
  *  You should have received a copy of the GNU General Public License     *
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  *                                                                        *
  *************************************************************************/
  
  package act.shared;
  
  import java.io.Serializable;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Set;
  
  import act.shared.helpers.T;
  
  /**
   * This is the class the backend can use to pass pathways to the front end.
   * Currently, what is essential is the compoundList, the list of chemicals.
   * No other information about the path is guaranteed to exist right now.
   *
   */
  
  public class Path implements Serializable {
    private static final long serialVersionUID = 42L;
    protected List<Chemical> compoundList;
    protected List<T<Long, ReactionType, Double>> edgeList;
  
    /**
     * Reactants required at each step,
     * and the products produced at each step.
     * Excludes what's already in compoundList
     */
    private List<Set<Chemical>> reactants, products;
  
    /**
     * The rxnsList has limited expressiveness:
     *  1) Multiple reactions exist that can take compound A to B
     *  2) The reaction may have been abstract (ie CRO).
     * So it's only useful now as an example of a concrete path.
     */
    private List<Long> reactionIDList;
    private List<Reaction> reactionList;
      public Integer pathID;
  
  
    public Path(List<Chemical> compounds, List<Long> operators) {
      compoundList = compounds;
          pathID = this.hashCode();
    }
  
    public Path() {
      // Dummy
      compoundList = new ArrayList<Chemical>();
      for (int i = 0; i < 6; i++){
        compoundList.add(new Chemical(0, 0L, "", ""));
      }
          pathID = this.hashCode();
    }
  
    public Path(List<Chemical> compounds) {
      this(compounds, null);
    }
    public List<Chemical> getCompoundList() {
      return compoundList;
    }
    public List<Long> getReactionIDList() {
      return reactionIDList;
    }
  
    public void setReactionIDList(List<Long> rxns) {
      reactionIDList = rxns;
    }
  
    public void setPathID(int id) { pathID = id; }
  
  
    @Override
    public int hashCode() {
      int hash = 0;
      for(Chemical c : compoundList) {
        hash = (int) (hash ^ c.getUuid());
      }
      if(reactionIDList!=null) {
        for(Long rxn : reactionIDList) {
          hash = (int) (hash ^ rxn.intValue());
        }
      }
      return hash;
    }
  
    public List<Set<Chemical>> getReactants() {
      if (reactants == null) {
        reactants = new ArrayList<Set<Chemical>>();
        for (int i = 0; i < compoundList.size() - 1; i++)
          reactants.add(new HashSet<Chemical>());
      }
      return reactants;
    }
  
    public void setReactants(List<Set<Chemical>> reactants) {
      this.reactants = reactants;
    }
  
    public List<Set<Chemical>> getProducts() {
      if (products == null) {
        products = new ArrayList<Set<Chemical>>();
        for (int i = 0; i < compoundList.size() - 1; i++)
          products.add(new HashSet<Chemical>());
  
      }
      return products;
    }
  
    public void setProducts(List<Set<Chemical>> products) {
      this.products = products;
    }
  
    public void setEdgeList(List<T<Long, ReactionType, Double>> edges) {
      this.edgeList = edges;
    }
  
    public List<T<Long, ReactionType, Double>> getEdgeList() {
      return edgeList;
    }
  
    public void setReactionList(List<Reaction> reactions) {
      reactionList = reactions;
    }
  
    public List<Reaction> getReactionList() {
      return reactionList;
    }
  
    public void reverse() {
      Collections.reverse(compoundList);
      if (reactants!=null)
        Collections.reverse(reactants);
      if (products!=null)
        Collections.reverse(products);
  
      List<Set<Chemical>> temp = reactants;
      reactants = products;
      products = temp;
  
      if (edgeList != null)
        Collections.reverse(edgeList);
      if (reactionIDList!=null)
        Collections.reverse(reactionIDList);
      if (reactionList!=null)
        Collections.reverse(reactionList);
  
      this.pathID = this.hashCode();
    }
  
    public static Path concat(Path p1, Path p2) {
      Path ret = new Path(new ArrayList<Chemical>(p1.getCompoundList()));
      ret.setProducts(new ArrayList<Set<Chemical>>(p1.getProducts()));
      ret.setReactants(new ArrayList<Set<Chemical>>(p1.getReactants()));
      if (p1.edgeList != null)
        ret.setEdgeList(new ArrayList<T<Long, ReactionType, Double>>(p1.edgeList));
      if (p1.reactionList != null)
        ret.setReactionList(p1.reactionList);
      if (p1.reactionIDList != null)
        ret.setReactionIDList(p1.reactionIDList);
  
      ret.compoundList.addAll(p2.compoundList);
      ret.products.addAll(p2.getProducts());
      ret.reactants.addAll(p2.getReactants());
      if (ret.edgeList != null && p2.edgeList != null)
        ret.edgeList.addAll(p2.edgeList);
      if (ret.reactionList != null && p2.reactionList != null)
        ret.reactionList.addAll(p2.reactionList);
      if (ret.reactionIDList != null && p2.reactionIDList != null)
        ret.reactionIDList.addAll(p2.reactionIDList);
      ret.pathID = ret.hashCode();
      return ret;
    }
  
  }
  