001package org.biopax.paxtools.pattern.constraint;
002
003import org.biopax.paxtools.pattern.Constraint;
004import org.biopax.paxtools.pattern.Match;
005import org.biopax.paxtools.model.BioPAXElement;
006
007import java.util.Collection;
008
009/**
010 * When a constraint excludes the origin element, but it is needed to be among them, use this 
011 * constraint. The wrapped constraint must have size 2.
012 * 
013 * @author Ozgun Babur
014 */
015public class SelfOrThis extends ConstraintAdapter
016{
017        int selfIndex;
018
019        /**
020         * Wrapped constraint.
021         */
022        Constraint con;
023
024        /**
025         * Constructor with the wrapped constraint. Index of self is 0 by default.
026         * @param con wrapped constraint
027         */
028        public SelfOrThis(Constraint con)
029        {
030                this(con, 0);
031        }
032
033        /**
034         * Constructor with the wrapped constraint and index of self. This index cannot map to the last
035         * element, but has to map one of the previous ones.
036         * @param con wrapped constraint
037         * @param selfIndex index of self
038         */
039        public SelfOrThis(Constraint con, int selfIndex)
040        {
041                this.selfIndex = selfIndex;
042                this.con = con;
043                if (!con.canGenerate()) throw new IllegalArgumentException(
044                        "The wrapped constraint has to be generative");
045                if (selfIndex >= con.getVariableSize() - 1) throw new IllegalArgumentException(
046                        "selfIndex has to be smaller than the index of last mapped element. selfIndex = " +
047                                selfIndex + ", size = " + con.getVariableSize());
048        }
049
050        /**
051         * Returns size of the wrapped constraint.
052         * @return size of the wrapped constraint
053         */
054        @Override
055        public int getVariableSize()
056        {
057                return con.getVariableSize();
058        }
059
060        /**
061         * This is a generative constraint.
062         * @return true
063         */
064        @Override
065        public boolean canGenerate()
066        {
067                return true;
068        }
069
070        /**
071         * Gets the first mapped element along with the generated elements of wrapped constraint.
072         * @param match current pattern match
073         * @param ind mapped indices
074         * @return first mapped element along with the generated elements of wrapped constraint
075         */
076        @Override
077        public Collection<BioPAXElement> generate(Match match, int... ind)
078        {
079                Collection<BioPAXElement> gen = con.generate(match, ind);
080                gen.add(match.get(ind[selfIndex]));
081                return gen;
082        }
083
084        /**
085         * Checks if the last index is either generated or equal to the first element.
086         * @param match current pattern match
087         * @param ind mapped indices
088         * @return true if the last index is either generated or equal to the first element
089         */
090        @Override
091        public boolean satisfies(Match match, int... ind)
092        {
093                return match.get(ind[selfIndex]) == match.get(ind[ind.length-1]) ||
094                        super.satisfies(match, ind);
095        }
096}