001    /*
002     * ????
003     * 1/5/2006 this code was copied from the Knowtator annotation tool
004     * for internal use at Mayo.  The Knowtator code was originally copied
005     * from the WordFreak library and modified extensively for Knowtator.  
006     * 
007     * The contents of this file are subject to the Mozilla Public
008     * License Version 1.1 (the "License"); you may not use this file
009     * except in compliance with the License. You may obtain a copy of
010     * the License at http://www.mozilla.org/MPL/
011     * 
012     * Software distributed under the License is distributed on an "AS
013     * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
014     * implied. See the License for the specific language governing
015     * rights and limitations under the License.
016     * 
017     * The Original Code is the WordFreak annotation tool.
018     *
019     * The Initial Developer of the Original Code is Thomas S. Morton
020     * Copyright (C) 2002.  All Rights Reserved.
021     * 
022     * Contributor(s):
023     *   Thomas S. Morton <tsmorton@cis.upenn.edu> (Original Author)
024     *   Jeremy LaCivita <lacivita@linc.cis.upenn.edu>
025     */
026    
027    /**
028     *  This code was taken from the wordfreak project and modified for Knowtator.  See
029     *  license above for more information.
030     *
031     */
032    package edu.uchsc.ccp.iaa;
033    
034    import java.util.List;
035    
036    public class Span implements Comparable {
037            private int start;
038    
039            private int end;
040    
041            public Span(int start, int end) {
042                    this.start = start;
043                    this.end = end;
044                    if (start > end) {
045                            throw new IndexOutOfBoundsException(
046                                            "Span is invalid because the start of the span is greater than the end of it: start=" + start
047                                                            + " end=" + end);
048                    }
049                    if (start < 0) {
050                            throw new IndexOutOfBoundsException(
051                                            "Span is invalid because the start of the span is less than zero: start=" + start);
052                    }
053            }
054    
055            public static boolean isValid(int start, int end) {
056                    if (start > end || start < 0)
057                            return false;
058                    return true;
059            }
060    
061            public int length() {
062                    return end - start;
063            }
064    
065            public int getStart() {
066                    return start;
067            }
068    
069            public int getEnd() {
070                    return end;
071            }
072    
073            /**
074             * @return the length of the span (end - start)
075             * 
076             */
077            public int getSize() {
078                    return getEnd() - getStart();
079            }
080    
081            public int compareTo(Object object) {
082                    Span span = (Span) object;
083                    if (getStart() < span.getStart()) {
084                            return -1;
085                    } else if (getStart() == span.getStart()) {
086                            if (getEnd() > span.getEnd()) {
087                                    return -1;
088                            } else if (getEnd() < span.getEnd()) {
089                                    return 1;
090                            } else {
091                                    return 0;
092                            }
093                    } else {
094                            return 1;
095                    }
096            }
097    
098            public String toString() {
099                    return "" + start + "|" + end;
100            }
101    
102            public boolean equals(Object object) {
103                    if (object == null || !(object instanceof Span)) {
104                            return false;
105                    }
106                    Span span = (Span) object;
107                    return getStart() == span.getStart() && getEnd() == span.getEnd();
108            }
109    
110            public int hashCode() {
111                    return ((this.start << 16) | (0x0000FFFF | this.end));
112            }
113    
114            public boolean contains(Span span) {
115                    return (getStart() <= span.getStart() && span.getEnd() <= getEnd());
116            }
117    
118            public boolean contains(int i) {
119                    return (getStart() <= i && i < getEnd());
120            }
121    
122            /**
123             * we need some junit tests
124             */
125            public boolean intersects(Span span) {
126                    int spanStart = span.getStart();
127                    // either span's start is in this or this' start is in span
128                    return this.contains(span)
129                                    || span.contains(this)
130                                    || (getStart() <= spanStart && spanStart < getEnd() || spanStart <= getStart()
131                                                    && getStart() < span.getEnd());
132            }
133    
134            public boolean crosses(Span span) {
135                    int spanStart = span.getStart();
136    
137                    // either s's start is in this or this' start is in s
138                    return !this.contains(span)
139                                    && !span.contains(this)
140                                    && (getStart() <= spanStart && spanStart < getEnd() || spanStart <= getStart()
141                                                    && getStart() < span.getEnd());
142            }
143    
144            public boolean lessThan(Span span) {
145                    return getStart() < span.getStart() && getEnd() < span.getEnd();
146            }
147    
148            public boolean greaterThan(Span span) {
149                    return getStart() > span.getStart() && getEnd() > span.getEnd();
150            }
151    
152            public static Span parseSpan(String spanString) {
153                    String startString = spanString.substring(0, spanString.indexOf("|"));
154                    String endString = spanString.substring(spanString.indexOf("|") + 1);
155                    int start = Integer.parseInt(startString);
156                    int end = Integer.parseInt(endString);
157                    return new Span(start, end);
158            }
159    
160            public static boolean intersects(List<Span> spans1, List<Span> spans2) {
161                    for (Span span1 : spans1) {
162                            for (Span span2 : spans2) {
163                                    if (span1.intersects(span2))
164                                            return true;
165                            }
166                    }
167                    return false;
168            }
169    
170            /**
171             * This method assumes that the both lists of spans are sorted the same way
172             * and that a span in one list at the same index as a span in the other list
173             * should be the same.
174             * 
175             * @param spans1
176             *            sorted list of spans
177             * @param spans2
178             *            sorted list of spans
179             * @return true if the two lists of spans are the same.
180             */
181            public static boolean spansMatch(List<Span> spans1, List<Span> spans2) {
182                    if (spans1.size() == spans2.size()) {
183                            for (int i = 0; i < spans1.size(); i++) {
184                                    if (!spans1.get(i).equals(spans2.get(i))) {
185                                            return false;
186                                    }
187                            }
188                            return true;
189                    }
190                    return false;
191            }
192    
193            public static Span shortest(List<Span> spans) {
194                    if (spans.size() == 0)
195                            return null;
196                    if (spans.size() == 1)
197                            return spans.get(0);
198    
199                    Span shortestSpan = spans.get(0);
200                    int shortestSize = shortestSpan.getSize();
201                    for (int i = 1; i < spans.size(); i++) {
202                            if (spans.get(i).getSize() < shortestSize) {
203                                    shortestSpan = spans.get(i);
204                                    shortestSize = shortestSpan.getSize();
205                            }
206                    }
207    
208                    return shortestSpan;
209            }
210    
211            public static String substring(String string, Span span) {
212                    int start = Math.max(0, span.getStart());
213                    start = Math.min(start, string.length() - 1);
214                    int end = Math.max(0, span.getEnd());
215                    end = Math.min(end, string.length() - 1);
216                    return string.substring(start, end);
217            }
218    }