001package org.biopax.paxtools.query.algorithm; 002 003import org.biopax.paxtools.query.model.GraphObject; 004import org.biopax.paxtools.query.model.Node; 005 006import java.util.*; 007 008/** 009 * Searches common downstream or common upstream of a specified set of entities 010 * based on the given direction within the boundaries of a specified length 011 * limit. Takes a source set of entities, direction of the query and 012 * distance limit. 013 * 014 * @author Ozgun Babur 015 * @author Merve Cakir 016 * @author Shatlyk Ashyralyev 017 */ 018public class CommonStreamQuery 019{ 020 /** 021 * Collection of Set of nodes. 022 * Each Set contains all states of corresponding physical entity or 023 * contains one of the selected nodes 024 */ 025 private Collection<Set<Node>> sourceSet; 026 027 /** 028 * The direction to determine whether the search will be to look for common 029 * downstream or common upstream. 030 */ 031 private Direction direction; 032 033 /** 034 * Stop distance. 035 */ 036 private int limit; 037 038 /** 039 * The map to hold the reached counts of graph objects. Reached count 040 * represents whether the particular graph object is in the boundaries 041 * of BFS. 042 */ 043 Map<GraphObject, Integer> reachedCount = new HashMap<GraphObject, Integer>(); 044 045 /** 046 * Constructor for Common Stream with Selected Nodes. 047 * @param sourceNodeSet Source nodes 048 * @param direction Common upstream or downstream. Cannot be bothstream 049 * @param limit Search length limit 050 */ 051 public CommonStreamQuery(Set<Node> sourceNodeSet, Direction direction, int limit) 052 { 053 if (direction != Direction.UPSTREAM && direction != Direction.DOWNSTREAM) 054 throw new IllegalArgumentException("Direction has to be either upstream or downstream"); 055 056 this.sourceSet = new LinkedHashSet<Set<Node>>(); 057 058 //Each set contains only one selected Node 059 for (Node node : sourceNodeSet) 060 { 061 Set<Node> sourceNode = new HashSet<Node>(); 062 sourceNode.add(node); 063 sourceSet.add(sourceNode); 064 } 065 066 this.direction = direction; 067 this.limit = limit; 068 } 069 070 /** 071 * Constructor for Common Stream with Entity States. 072 * @param sourceStateSet Collection of source node sets 073 * @param direction Common upstream or downstream. Cannot be bothstream 074 * @param limit Search length limit 075 */ 076 public CommonStreamQuery(Collection<Set<Node>> sourceStateSet, Direction direction, int limit) 077 { 078 if (direction != Direction.UPSTREAM && direction != Direction.DOWNSTREAM) 079 throw new IllegalArgumentException("Direction has to be either upstream or downstream"); 080 081 this.sourceSet = sourceStateSet; 082 this.direction = direction; 083 this.limit = limit; 084 } 085 086 /** 087 * Method to run the query. 088 * @return Common stream 089 */ 090 public Set<GraphObject> run() 091 { 092 /** 093 * Candidate contains all the graph objects that are the results of BFS. 094 * Eliminating nodes from candidate according to the reached counts 095 * will yield result. 096 */ 097 Map<GraphObject, Integer> candidate = new HashMap<GraphObject, Integer>(); 098 Set<GraphObject> result = new HashSet<GraphObject>(); 099 100 //for each set of states of entity, run BFS separately 101 for (Set<Node> source : sourceSet) 102 { 103 //run BFS for set of states of each entity 104 BFS bfs = new BFS (source, null, direction, limit); 105 Map<GraphObject, Integer> BFSResult = new HashMap<GraphObject, Integer>(); 106 BFSResult.putAll(bfs.run()); 107 108 /** 109 * Reached counts of the graph objects that are in BFSResult will 110 * be incremented by 1. 111 */ 112 for (GraphObject go : BFSResult.keySet()) 113 { 114 setLabel(go, (getLabel(go) + 1)); 115 } 116 117 //put BFS Result into candidate set 118 candidate.putAll(BFSResult); 119 } 120 121 /** 122 * Having a reached count equal to number of nodes in the source set 123 * indicates being in common stream. 124 */ 125 for(GraphObject go : candidate.keySet()) 126 { 127 if (getLabel(go) == sourceSet.size()) 128 { 129 result.add(go); 130 } 131 } 132 133 //Return the result of query 134 return result; 135 } 136 137 /** 138 * Method for getting Label of GraphObject. 139 * If Label is absent, then it returns 0. 140 * @param go Graph object to get its label 141 * @return Label of the graph object 142 */ 143 private int getLabel(GraphObject go) 144 { 145 if (!reachedCount.containsKey(go)) 146 { 147 // Absence of label is interpreted as zero 148 return 0; 149 } 150 else 151 { 152 return reachedCount.get(go); 153 } 154 } 155 156 /** 157 * Method for setting the Label of GraphObject 158 * @param go Graph object to set its label 159 * @param label New label of the graph object 160 */ 161 private void setLabel(GraphObject go, int label) 162 { 163 reachedCount.put(go, label); 164 } 165}