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     */
022    package org.biojava3.core.sequence.location;
023    
024    import org.biojava3.core.sequence.location.template.Point;
025    import org.biojava3.core.util.Equals;
026    import org.biojava3.core.util.Hashcoder;
027    
028    /**
029     * Implementation for resolving fuzzy locations. Caches the calculated
030     * value.
031     *
032     * @author ayates
033     */
034    public 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        @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
124        public boolean equals(Object obj) {
125            boolean equals = false;
126            if (Equals.classEqual(this, obj)) {
127                FuzzyPoint p = (FuzzyPoint) obj;
128                equals = (Equals.equal(getMin(), p.getMin())
129                        && Equals.equal(getMax(), p.getMax())
130                        && Equals.equal(isUnknown(), p.isUnknown())
131                        && Equals.equal(isUncertain(), p.isUncertain())
132                        );
133            }
134            return equals;
135        }
136    
137        @Override
138        public int hashCode() {
139            int r = Hashcoder.SEED;
140            r = Hashcoder.hash(r, getMin());
141            r = Hashcoder.hash(r, getMax());
142            r = Hashcoder.hash(r, isUncertain());
143            r = Hashcoder.hash(r, isUnknown());
144            return r;
145        }
146    
147        @Override
148        public int compareTo(Point point) {
149            //If we can assign this to a FuzzyPoint then work with a bit more info
150            if(FuzzyPoint.class.isAssignableFrom(point.getClass())) {
151                FuzzyPoint fuzzy = (FuzzyPoint)point;
152                int minComparison = getMin().compareTo(fuzzy.getMin());
153                if(minComparison != 0)
154                    return minComparison;
155                return getMax().compareTo(fuzzy.getMax());
156            }
157            //If not fuzzy then compare on position as normal
158            return super.compareTo(point);
159        }
160    }