001package org.biopax.paxtools.pattern.constraint;
002
003import org.biopax.paxtools.model.BioPAXElement;
004import org.biopax.paxtools.pattern.Constraint;
005import org.biopax.paxtools.pattern.MappedConst;
006import org.biopax.paxtools.pattern.Match;
007
008import java.util.Collection;
009import java.util.HashSet;
010import java.util.Set;
011
012/**
013 * Used for using several constraints as a chain. The generated elements from a constraint is used
014 * as input by the next constraint in the chain. All constraints except the first one has to be
015 * size 2.
016 *
017 * @author Ozgun Babur
018 */
019public class ConstraintChain extends ConstraintAdapter
020{
021        /**
022         * Constraint to be chained.
023         */
024        Constraint[] con;
025
026        /**
027         * Constructor with the chained constraints. All constraints has to be generative, and all
028         * constraints, except the first one, has to be size 2. The input to these constraints is the
029         * element that is generated by the previous constraint in the chain.
030         * @param con mapped constraints
031         */
032        public ConstraintChain(Constraint... con)
033        {
034                if (con.length < 2) throw new IllegalArgumentException(
035                        "Parameter constraint has to be more than one.");
036
037                this.con = con;
038
039                for (int i = 1; i < con.length; i++)
040                {
041                        if (con[i].getVariableSize() > 2) throw new IllegalArgumentException("All chained " +
042                                "constraints (except first) has to have variable size 2. Unlike con[" + i + "]: "
043                                + con[i]);
044                }
045
046                setSize(con[0].getVariableSize());
047        }
048
049        /**
050         * Chains the member constraints and returns the output of the last constraint.
051         * @param match match to process
052         * @param ind mapped indices
053         * @return satisfying elements
054         */
055        @Override
056        public Collection<BioPAXElement> generate(Match match, int... ind)
057        {
058
059                Collection<BioPAXElement> gen = new HashSet<BioPAXElement> (
060                        con[0].generate(match, ind));
061
062                Set<BioPAXElement> input = new HashSet<BioPAXElement>();
063                Set<BioPAXElement> output = new HashSet<BioPAXElement>(gen);
064                int[] tempInd = {0, 1};
065
066                for (int i = 1; i < con.length; i++)
067                {
068                        if (output.isEmpty()) break;
069                        input.clear();
070                        input.addAll(output);
071                        output.clear();
072
073                        for (BioPAXElement ele : input)
074                        {
075                                Match m = new Match(2);
076                                m.set(ele, 0);
077                                output.addAll(con[i].generate(m, tempInd));
078                        }
079                }
080
081                return output;
082        }
083}