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.Strand;
025import org.biojava.nbio.core.sequence.location.template.AbstractLocation;
026import org.biojava.nbio.core.sequence.location.template.Location;
027import org.biojava.nbio.core.sequence.location.template.Point;
028
029import java.util.Arrays;
030import java.util.List;
031
032/**
033 * A collection of locations which are used whenever we work with INSDC; some
034 * of which could be deprecated (from INSDC's point of view) yet appear
035 * in records.
036 *
037 * @author ayates
038 * @author Paolo Pavan
039 */
040public class InsdcLocations {
041
042        /**
043         * Used to represent bond locations equivalent to bond(7,8) or bond(7).
044         * Bond locations are single position complex locations
045         */
046        public static class BondLocation extends AbstractLocation {
047
048                public BondLocation(Location... subLocations) {
049                        this(Arrays.asList(subLocations));
050                }
051
052                public BondLocation(List<Location> subLocations) {
053                        super();
054                        Location min = Tools.getMin(subLocations);
055                        Location max = Tools.getMax(subLocations);
056                        setStart(min.getStart());
057                        setEnd(max.getEnd());
058                        setStrand(Strand.UNDEFINED);
059                        setSubLocations(subLocations);
060                        assertLocation();
061                }
062
063                @Override
064                protected final void assertLocation() {
065                        for (Location l : this) {
066                                Point start = l.getStart();
067                                Point end = l.getEnd();
068                                if (!start.equals(end)) {
069                                        throw new IllegalStateException("The start "
070                                                        + start + " is not equal to the end "
071                                                        + end + ". bond locations must be a single "
072                                                        + "compound long");
073                                }
074                        }
075                }
076        }
077
078        /**
079         * Used to describe a 5' to 3' ordering but no firm assurance it is correct
080         */
081        public static class OrderLocation extends SimpleLocation {
082                public OrderLocation(List subLocations){
083                        super(
084                                        Location.Tools.getMin(subLocations).getStart(),
085                                        Location.Tools.getMax(subLocations).getEnd()
086                        );
087
088                        setStrand(Strand.UNDEFINED);
089                        setSubLocations(subLocations);
090                        assertLocation();
091                }
092
093                public OrderLocation(Location... subLocations) {
094                        this(Arrays.asList(subLocations));
095                }
096
097                public OrderLocation(Point start, Point end, Strand strand,
098                                boolean circular, Location... subLocations) {
099                        super(start, end, strand, circular, subLocations);
100                }
101
102                public OrderLocation(Point start, Point end, Strand strand,
103                                Location... subLocations) {
104                        this(start, end, strand, false, subLocations);
105                }
106
107                public OrderLocation(int start, int end, Strand strand,
108                                Location... subLocations) {
109                        this(new SimplePoint(start), new SimplePoint(end), strand, false, subLocations);
110                }
111
112                public OrderLocation(Point start, Point end, Strand strand,
113                                boolean circular, List<Location> subLocations) {
114                        super(start, end, strand, circular, subLocations);
115                }
116
117                public OrderLocation(Point start, Point end, Strand strand,
118                                List<Location> subLocations) {
119                        this(start, end, strand, false, subLocations);
120                }
121
122                public OrderLocation(int start, int end, Strand strand,
123                                List<Location> subLocations) {
124                        this(new SimplePoint(start), new SimplePoint(end), strand, false, subLocations);
125                }
126        }
127
128        /**
129         * Deprecated in INSDC yet still appears; equivalent to the order()
130         * directive except no 5' to 3' ordering is defined. The constructor
131         * reflects this relationship and only allows the creation of complex
132         * locations
133         */
134        public static class GroupLocation extends SimpleLocation {
135                public GroupLocation(List subLocations){
136                        super(
137                                        Location.Tools.getMin(subLocations).getStart(),
138                                        Location.Tools.getMax(subLocations).getEnd()
139                        );
140
141                        setStrand(Strand.UNDEFINED);
142                        setSubLocations(subLocations);
143                        assertLocation();
144                }
145
146                public GroupLocation(Location... subLocations) {
147                        this(Arrays.asList(subLocations));
148                }
149
150                public GroupLocation(Point start, Point end, Strand strand,
151                                boolean circular, Location... subLocations) {
152                        super(start, end, strand, circular, subLocations);
153                }
154
155                public GroupLocation(Point start, Point end, Strand strand,
156                                Location... subLocations) {
157                        this(start, end, strand, false, subLocations);
158                }
159
160                public GroupLocation(int start, int end, Strand strand,
161                                Location... subLocations) {
162                        this(new SimplePoint(start), new SimplePoint(end), strand, false, subLocations);
163                }
164
165                public GroupLocation(Point start, Point end, Strand strand,
166                                boolean circular, List<Location> subLocations) {
167                        super(start, end, strand, circular, subLocations);
168                }
169
170                public GroupLocation(Point start, Point end, Strand strand,
171                                List<Location> subLocations) {
172                        this(start, end, strand, false, subLocations);
173                }
174
175                public GroupLocation(int start, int end, Strand strand,
176                                List<Location> subLocations) {
177                        this(new SimplePoint(start), new SimplePoint(end), strand, false, subLocations);
178                }
179        }
180
181        /**
182         * Deprecated in INSDC; refers to a set of locations of which one
183         * location could be valid e.g. one-of(location, location, location).
184         * Originally used to describe split locations in alternative splicing
185         * or variations. Now these are dealt with in their own feature fields.
186         *
187         * The default location is chosen to be the first however if you think
188         * you need to work with this location you should use the sub-locations.
189         */
190        public static class OneOfLocation extends AbstractLocation {
191
192                public OneOfLocation(Location... locations) {
193                        this(Arrays.asList(locations));
194                }
195
196                public OneOfLocation(List<Location> locations) {
197                        super();
198                        if (locations.isEmpty()) {
199                                throw new IllegalArgumentException("Need locations to build a OneOfLocation");
200                        }
201                        Location l = locations.get(0);
202                        setStart(l.getStart());
203                        setEnd(l.getEnd());
204                        setStrand(l.getStrand());
205                        setBetweenCompounds(l.isBetweenCompounds());
206                        setCircular(l.isCircular());
207                        setSubLocations(locations);
208                }
209        }
210}