/*************************************************************************
* *
* 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;
}
}