001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 * Created on 01-21-2010
021 */
022package org.biojava.nbio.core.sequence.location;
023
024import org.biojava.nbio.core.sequence.location.template.Point;
025import org.biojava.nbio.core.util.Equals;
026import org.biojava.nbio.core.util.Hashcoder;
027
028/**
029 * Implementation for resolving fuzzy locations. Caches the calculated
030 * value.
031 *
032 * @author ayates
033 */
034public class FuzzyPoint extends SimplePoint {
035
036        /**
037         * Always uses the min point to resolve a location
038         */
039        public static final Resolver<FuzzyPoint> MIN_RESOLVER = new Resolver<FuzzyPoint>() {
040                @Override
041                public int resolve(FuzzyPoint point) {
042                        return point.getMin();
043                }
044        };
045
046        /**
047         * Always uses the max point to resolve a location
048         */
049        public static final Resolver<FuzzyPoint> MAX_RESOLVER = new Resolver<FuzzyPoint>() {
050                @Override
051                public int resolve(FuzzyPoint point) {
052                        return point.getMax();
053                }
054        };
055
056        /**
057         * Combines min and max and then gets the mean of it
058         */
059        public static final Resolver<FuzzyPoint> MEAN_RESOLVER = new Resolver<FuzzyPoint>() {
060                @Override
061                public int resolve(FuzzyPoint point) {
062                        return (point.getMin() + point.getMax()) / 2;
063                }
064        };
065
066        private final int min;
067        private final int max;
068        private final Resolver<FuzzyPoint> resolver;
069
070        public FuzzyPoint(int minPoint, int maxPoint) {
071                this(minPoint, maxPoint, MEAN_RESOLVER, false, false);
072        }
073
074        public FuzzyPoint(int minPoint, int maxPoint, Resolver<FuzzyPoint> resolver) {
075                this(minPoint, maxPoint, resolver, false, false);
076        }
077
078        public FuzzyPoint(int minPoint, int maxPoint, Resolver<FuzzyPoint> resolver, boolean unknown, boolean uncertain) {
079                this.min = minPoint;
080                this.max = maxPoint;
081                this.resolver = resolver;
082                setUncertain(uncertain);
083                setUnknown(unknown);
084                setPosition(-1); //Means we have not resolved this position yet
085        }
086
087        @Override
088        public Integer getPosition() {
089                if(super.getPosition() == -1) {
090                        super.setPosition(getResolver().resolve(this));
091                }
092                return super.getPosition();
093        }
094
095        protected Integer getMax() {
096                return max;
097        }
098
099        protected Integer getMin() {
100                return min;
101        }
102
103        protected Resolver<FuzzyPoint> getResolver() {
104                return resolver;
105        }
106
107        @Override
108        public Point reverse(int length) {
109                int revMin = reverse(getMin(), length);
110                int revMax = reverse(getMax(), length);
111                return new FuzzyPoint(revMin, revMax, getResolver(), isUnknown(), isUncertain());
112        }
113
114        @Override
115        public Point offset(int distance) {
116                int offMin = getMin() + distance;
117                int offMax = getMax() + distance;
118                return new FuzzyPoint(offMin, offMax, getResolver(), isUnknown(), isUncertain());
119        }
120
121
122        @Override
123        public boolean equals(Object obj) {
124                boolean equals = false;
125                if (Equals.classEqual(this, obj)) {
126                        FuzzyPoint p = (FuzzyPoint) obj;
127                        equals = (Equals.equal(getMin(), p.getMin())
128                                        && Equals.equal(getMax(), p.getMax())
129                                        && Equals.equal(isUnknown(), p.isUnknown())
130                                        && Equals.equal(isUncertain(), p.isUncertain())
131                                        );
132                }
133                return equals;
134        }
135
136        @Override
137        public int hashCode() {
138                int r = Hashcoder.SEED;
139                r = Hashcoder.hash(r, getMin());
140                r = Hashcoder.hash(r, getMax());
141                r = Hashcoder.hash(r, isUncertain());
142                r = Hashcoder.hash(r, isUnknown());
143                return r;
144        }
145
146        @Override
147        public int compareTo(Point point) {
148                //If we can assign this to a FuzzyPoint then work with a bit more info
149                if(FuzzyPoint.class.isAssignableFrom(point.getClass())) {
150                        FuzzyPoint fuzzy = (FuzzyPoint)point;
151                        int minComparison = getMin().compareTo(fuzzy.getMin());
152                        if(minComparison != 0)
153                                return minComparison;
154                        return getMax().compareTo(fuzzy.getMax());
155                }
156                //If not fuzzy then compare on position as normal
157                return super.compareTo(point);
158        }
159}