001package org.biopax.paxtools.pattern.constraint;
002
003import org.biopax.paxtools.model.BioPAXElement;
004import org.biopax.paxtools.model.level3.*;
005import org.biopax.paxtools.pattern.Match;
006import org.biopax.paxtools.pattern.util.Blacklist;
007import org.biopax.paxtools.pattern.util.RelType;
008
009import java.util.Collection;
010import java.util.HashSet;
011import java.util.Set;
012
013/**
014 * Gets input or output participants of a Conversion.
015 *
016 * if NOT consider Control and NOT considerPathway (default):
017 *
018 * var0 is a Conversion
019 * var1 is a PE
020 *
021 * else if considerControl and NOT considerPathway
022 *
023 * var0 is a Control
024 * var1 is a Conversion
025 * var2 is a PE
026 *
027 * else if NOT considerControl and considerPathway
028 *
029 * var0 is a Pathway
030 * var1 is a Conversion
031 * var2 is a PE
032 *
033 * else if considerControl and consider pathway
034 *
035 * var0 is a Pathway
036 * var1 is a Control
037 * var2 is a Conversion
038 * var3 is a PE
039 *
040 * @author Ozgun Babur
041 */
042public class Participant extends ConstraintAdapter
043{
044        /**
045         * Input or output.
046         */
047        RelType type;
048
049        /**
050         * Tells if there is a Control that we should consider while navigating.
051         */
052        boolean considerControl;
053
054        /**
055         * Tells if there is a Pathway that we should consider while navigating.
056         */
057        boolean considerPathway;
058
059        /**
060         * Constructor with parameters.
061         * @param type input or output conversion
062         * @param blacklist for detecting ubiquitous small molecules
063         * @param considerControl whether there is a Control that we should consider
064         * @param considerPathway whether there is a Pathway that we should consider
065         */
066        public Participant(RelType type, Blacklist blacklist, boolean considerControl,
067                boolean considerPathway)
068        {
069                super(considerControl && considerPathway ? 4 : considerControl || considerPathway ? 3 : 2,
070                        blacklist);
071                this.type = type;
072                this.considerControl = considerControl;
073                this.considerPathway = considerPathway;
074        }
075
076        /**
077         * Constructor with parameters.
078         * @param type input or output of the conversion
079         */
080        public Participant(RelType type)
081        {
082                this(type, null, false, false);
083        }
084
085        /**
086         * Constructor with parameters.
087         * @param type input or output conversion
088         * @param blacklist for detecting ubiquitous small molecules
089         */
090        public Participant(RelType type, Blacklist blacklist)
091        {
092                this(type, blacklist, false, false);
093        }
094
095        /**
096         * Constructor with parameters.
097         * @param type input or output conversion
098         * @param blacklist for detecting ubiquitous small molecules
099         * @param considerControl whether there is a Control that we should consider
100         */
101        public Participant(RelType type, Blacklist blacklist, boolean considerControl)
102        {
103                this(type, blacklist, considerControl, false);
104        }
105
106        /**
107         * Constructor with parameters.
108         * @param type input or output of the conversion
109         * @param considerControl whether there is a Control that we should consider
110         *
111         */
112        public Participant(RelType type, boolean considerControl)
113        {
114                this(type, null, considerControl, false);
115        }
116
117        /**
118         * Constructor with parameters.
119         * @param type input or output of the conversion
120         * @param considerControl whether there is a Control that we should consider
121         * @param considerPathway whether there is a Pathway that we should consider
122         *
123         */
124        public Participant(RelType type, boolean considerControl, boolean considerPathway)
125        {
126                this(type, null, considerControl, considerPathway);
127        }
128
129        /**
130         * This is a generative constraint.
131         * @return true
132         */
133        @Override
134        public boolean canGenerate()
135        {
136                return true;
137        }
138
139        /**
140         * Identifies the conversion direction and gets the related participants.
141         * @param match current pattern match
142         * @param ind mapped indices
143         * @return input or output participants
144         */
145        @Override
146        public Collection<BioPAXElement> generate(Match match, int... ind)
147        {
148                Conversion cnv = (Conversion) match.get(ind[getVariableSize() - 2]);
149
150                ConversionDirectionType dir;
151
152                if (considerControl && considerPathway)
153                {
154                        Pathway pathway = (Pathway) match.get(ind[0]);
155                        Control control = (Control) match.get(ind[1]);
156                        dir = getDirection(cnv, pathway, control);
157                }
158                else if (considerControl)
159                {
160                        Control control = (Control) match.get(ind[0]);
161                        dir = getDirection(cnv, control);
162                }
163                else if (considerPathway)
164                {
165                        Pathway pathway = (Pathway) match.get(ind[0]);
166                        dir = getDirection(cnv, pathway);
167                }
168                else dir = getDirection(cnv);
169
170                Set<Set<PhysicalEntity>> sides = new HashSet<Set<PhysicalEntity>>();
171
172                if (dir == ConversionDirectionType.REVERSIBLE)
173                {
174                        sides.add(cnv.getLeft());
175                        sides.add(cnv.getRight());
176                }
177                else if (dir == ConversionDirectionType.RIGHT_TO_LEFT)
178                {
179                        sides.add(type == RelType.INPUT ? cnv.getRight() : cnv.getLeft());
180                }
181                // Note that null direction is treated as if LEFT_TO_RIGHT. This is not a best
182                // practice, but it is a good approximation.
183                else if ((dir == ConversionDirectionType.LEFT_TO_RIGHT || dir == null))
184                {
185                        sides.add(type == RelType.OUTPUT ? cnv.getRight() : cnv.getLeft());
186                }
187
188                Collection<BioPAXElement> result = new HashSet<BioPAXElement>();
189
190                if (blacklist == null)
191                {
192                        for (Set<PhysicalEntity> side : sides)
193                        {
194                                result.addAll(side);
195                        }
196                }
197                else
198                {
199                        // remove the blacklisted from the result
200                        for (Set<PhysicalEntity> side : sides)
201                        {
202                                // if direction is reversible then do not mind the context
203                                result.addAll(blacklist.getNonUbiques(side,
204                                        dir == ConversionDirectionType.REVERSIBLE ? null : type));
205                        }
206                }
207
208                return result;
209        }
210}