001package org.biopax.paxtools.query.wrapperL3;
002
003import org.biopax.paxtools.model.level3.*;
004import org.biopax.paxtools.model.level3.Process;
005import org.biopax.paxtools.query.model.AbstractNode;
006import org.biopax.paxtools.query.model.Edge;
007import org.biopax.paxtools.query.model.Node;
008
009import java.util.Collection;
010import java.util.HashSet;
011import java.util.Set;
012
013/**
014 * Wrapper for PhysicalEntity.
015 *
016 * @author Ozgun Babur
017 */
018public class PhysicalEntityWrapper extends AbstractNode
019{
020        /**
021         * Wrapped PhysicalEntity.
022         */
023        protected PhysicalEntity pe;
024
025        /**
026         * Flag to remember if parent equivalents initialized.
027         */
028        protected boolean upperEquivalentInited;
029
030        /**
031         * Flag to remember if child equivalents initialized.
032         */
033        protected boolean lowerEquivalentInited;
034
035        /**
036         * Flag to say this is a ubiquitous molecule.
037         */
038        protected boolean ubique;
039
040        /**
041         * Constructor with the wrapped PhysicalEntity and the owner graph.
042         * @param pe PhysicalEntity to wrap
043         * @param graph Owner graph
044         */
045        public PhysicalEntityWrapper(PhysicalEntity pe, GraphL3 graph)
046        {
047                super(graph);
048                this.pe = pe;
049                this.upperEquivalentInited = false;
050                this.lowerEquivalentInited = false;
051                this.ubique = false;
052        }
053
054        /**
055         * @return Whether this is ubique
056         */
057        public boolean isUbique()
058        {
059                return ubique;
060        }
061
062        /**
063         * Set the ubique flag.
064         * @param ubique Whether this is a ubiquitous molecule
065         */
066        public void setUbique(boolean ubique)
067        {
068                this.ubique = ubique;
069        }
070
071        /**
072         * Binds to upstream interactions.
073         */
074        public void initUpstream()
075        {
076                for (Conversion conv : getUpstreamConversions(pe.getParticipantOf()))
077                {
078                        ConversionWrapper conW = (ConversionWrapper) graph.getGraphObject(conv);
079                        if (conW == null) continue;
080
081                        if (conv.getConversionDirection() == ConversionDirectionType.REVERSIBLE &&
082                                conv.getLeft().contains(pe))
083                        {
084                                conW = conW.getReverse();
085                        }
086                        Edge edge = new EdgeL3(conW, this, graph);
087                        conW.getDownstreamNoInit().add(edge);
088                        this.getUpstreamNoInit().add(edge);
089                }
090
091                for (Interaction inter : pe.getParticipantOf())
092                {
093                        if (inter instanceof TemplateReaction)
094                        {
095                                TemplateReaction tr = (TemplateReaction) inter;
096                                TemplateReactionWrapper trw = (TemplateReactionWrapper) graph.getGraphObject(tr);
097                                if (trw == null) continue;
098
099                                Edge edge = new EdgeL3(trw, this, graph);
100
101                                assert trw.getDownstreamNoInit() != null;
102
103                                trw.getDownstreamNoInit().add(edge);
104                                this.getUpstreamNoInit().add(edge);
105                        }
106                }
107        }
108
109        /**
110         * Binds to downstream interactions.
111         */
112        public void initDownstream()
113        {
114                for (Interaction inter : getDownstreamInteractions(pe.getParticipantOf()))
115                {
116                        AbstractNode node = (AbstractNode) graph.getGraphObject(inter);
117
118                        if (node == null) continue;
119
120                        if (inter instanceof Conversion)
121                        {
122                                Conversion conv = (Conversion) inter;
123                                ConversionWrapper conW = (ConversionWrapper) node;
124                                if (conv.getConversionDirection() == ConversionDirectionType.REVERSIBLE &&
125                                        conv.getRight().contains(pe))
126                                {
127                                        node = conW.getReverse();
128                                }
129                        }
130
131                        Edge edge = new EdgeL3(this, node, graph);
132                        this.getDownstreamNoInit().add(edge);
133                        node.getUpstreamNoInit().add(edge);
134                }
135        }
136
137        //--- Upstream conversions --------------------------------------------------------------------|
138
139        /**
140         * Gets the conversions at the upstream of this PhysicalEntity.
141         * @param inters Interactions to search for
142         * @return Upstream conversions
143         */
144        protected Set<Conversion> getUpstreamConversions(Collection<Interaction> inters)
145        {
146                Set<Conversion> set = new HashSet<Conversion>();
147
148                for (Interaction inter : inters)
149                {
150                        if (inter instanceof Conversion)
151                        {
152                                Conversion conv = (Conversion) inter;
153                                ConversionDirectionType dir = conv.getConversionDirection();
154
155                                if (dir == ConversionDirectionType.REVERSIBLE ||
156                                        (dir == ConversionDirectionType.RIGHT_TO_LEFT && conv.getLeft().contains(pe)) ||
157                                        ((dir == ConversionDirectionType.LEFT_TO_RIGHT || dir == null) &&
158                                                conv.getRight().contains(pe)))
159                                {
160                                        set.add(conv);
161                                }
162                        }
163                }
164                return set;
165        }
166
167        //--- Downstream interactions ------------------------------------------------------------------|
168
169        /**
170         * Gets the downstream interactions among the given set.
171         * @param inters Interactions to search
172         * @return Downstream interactions
173         */
174        protected Set<Interaction> getDownstreamInteractions(Collection<Interaction> inters)
175        {
176                Set<Interaction> set = new HashSet<Interaction>();
177
178                for (Interaction inter : inters)
179                {
180                        if (inter instanceof Conversion)
181                        {
182                                Conversion conv = (Conversion) inter;
183                                ConversionDirectionType dir = conv.getConversionDirection();
184
185                                if (dir == ConversionDirectionType.REVERSIBLE ||
186                                        (dir == ConversionDirectionType.RIGHT_TO_LEFT && conv.getRight().contains(pe)) ||
187                                        ((dir == ConversionDirectionType.LEFT_TO_RIGHT || dir == null) &&
188                                                conv.getLeft().contains(pe)))
189                                {
190                                        set.add(conv);
191                                }
192                        }
193                        else if (inter instanceof Control)
194                        {
195                                set.add(inter);
196                        }
197                }
198                return set;
199        }
200
201        //--- Related conversions ---------------------------------------------------------------------|
202
203        /**
204         * Get all related Conversions of the given Interaction set.
205         * @param inters Interactions to query
206         * @return Related Conversions
207         */
208        private Set<Conversion> getRelatedConversions(Collection<Interaction> inters)
209        {
210                Set<Conversion> set = new HashSet<Conversion>();
211
212                for (Interaction inter : inters)
213                {
214                        if (inter instanceof Conversion)
215                        {
216                                set.add((Conversion) inter);
217                        }
218                        else if (inter instanceof Control)
219                        {
220                                getRelatedConversions((Control) inter, set);
221                        }
222                }
223                return set;
224        }
225
226        /**
227         * Recursively searches the related Conversions of a Control.
228         * @param ctrl Control to query
229         * @param set Set to collect the related Conversions
230         * @return The same set
231         */
232        private Set<Conversion> getRelatedConversions(Control ctrl, Set<Conversion> set)
233        {
234                for (Process process : ctrl.getControlled())
235                {
236                        if (process instanceof Conversion)
237                        {
238                                set.add((Conversion) process);
239                        }
240                        else if (process instanceof Control)
241                        {
242                                getRelatedConversions((Control) process, set);
243                        }
244                }
245                return set;
246        }
247
248        //----- Equivalence ---------------------------------------------------------------------------|
249
250        /**
251         * @return Parent equivalent objects
252         */
253        @Override
254        public Collection<Node> getUpperEquivalent()
255        {
256                if (!upperEquivalentInited)
257                {
258                        initUpperEquivalent();
259                }
260                return super.getUpperEquivalent();
261        }
262
263        /**
264         * @return Child equivalent objects
265         */
266        @Override
267        public Collection<Node> getLowerEquivalent()
268        {
269                if (!lowerEquivalentInited)
270                {
271                        initLowerEquivalent();
272                }
273                return super.getLowerEquivalent();
274        }
275
276        /**
277         * Finds homology parent.
278         */
279        protected void initUpperEquivalent()
280        {
281                this.upperEquivalent = new HashSet<Node>();
282
283                for (PhysicalEntity eq : pe.getMemberPhysicalEntityOf())
284                {
285                        Node node = (Node) graph.getGraphObject(eq);
286                        if (node != null) this.upperEquivalent.add(node);
287                }
288
289                upperEquivalentInited = true;
290        }
291
292        /**
293         * Finds member nodes if this is a homology node
294         */
295        protected void initLowerEquivalent()
296        {
297                this.lowerEquivalent = new HashSet<Node>();
298
299                for (PhysicalEntity eq : pe.getMemberPhysicalEntity())
300                {
301                        Node node = (Node) graph.getGraphObject(eq);
302                        if (node != null) this.lowerEquivalent.add(node);
303                }
304
305                lowerEquivalentInited = true;
306        }
307
308        //------ Other --------------------------------------------------------------------------------|
309
310        /**
311         * PhysicalEntity is a breadth node.
312         * @return True
313         */
314        public boolean isBreadthNode()
315        {
316                return true;
317        }
318
319        /**
320         * PhysicalEntity have positive sign.
321         * @return POSITIVE (1)
322         */
323        public int getSign()
324        {
325                return POSITIVE;
326        }
327
328        /**
329         * RDF ID of the PhysicalEntity is used as key.
330         * @return Key
331         */
332        public String getKey()
333        {
334                return pe.getRDFId();
335        }
336
337        /**
338         * @return Wrapped PhysicalEntity
339         */
340        public PhysicalEntity getPhysicalEntity()
341        {
342                return pe;
343        }
344
345        /**
346         * @return display name with ID added
347         */
348        @Override
349        public String toString()
350        {
351                return pe.getDisplayName() + " -- "+ pe.getRDFId();
352        }
353}