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