001 /*
002 * Copyright (c) 2006 Henri Sivonen
003 *
004 * Permission is hereby granted, free of charge, to any person obtaining a
005 * copy of this software and associated documentation files (the "Software"),
006 * to deal in the Software without restriction, including without limitation
007 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
008 * and/or sell copies of the Software, and to permit persons to whom the
009 * Software is furnished to do so, subject to the following conditions:
010 *
011 * The above copyright notice and this permission notice shall be included in
012 * all copies or substantial portions of the Software.
013 *
014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
017 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
019 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
020 * DEALINGS IN THE SOFTWARE.
021 */
022
023 package org.whattf.checker.table;
024
025 import org.xml.sax.Locator;
026
027 /**
028 * Represents a contiguous range of columns that was established by a single
029 * element and that does not yet have cells in it.
030 *
031 * @version $Id: ColumnRange.java 189 2007-10-08 11:27:05Z hsivonen $
032 * @author hsivonen
033 */
034 final class ColumnRange {
035
036 /**
037 * The locator associated with the element that established this column range.
038 */
039 private final Locator locator;
040
041 /**
042 * The local name of the element that established this column range.
043 */
044 private final String element;
045
046 /**
047 * The leftmost column that is part of this range.
048 */
049 private int left;
050
051 /**
052 * The first column to the right that is not part of this range.
053 */
054 private int right;
055
056 /**
057 * The next range in the linked list of ranges.
058 */
059 private ColumnRange next;
060
061 /**
062 * Constructor
063 * @param element the local name of the establishing element
064 * @param locator a locator associated with the establishing element;
065 * <em>must be suitable for retaining out-of-SAX-event!</em>
066 * @param left the leftmost column that is part of this range
067 * @param right the first column to the right that is not part of this range
068 */
069 public ColumnRange(String element, Locator locator, int left, int right) {
070 super();
071 assert right > left;
072 this.element = element;
073 this.locator = locator;
074 this.left = left;
075 this.right = right;
076 this.next = null;
077 }
078
079 /**
080 * Returns the element.
081 *
082 * @return the element
083 */
084 String getElement() {
085 return element;
086 }
087
088 /**
089 * Returns the locator.
090 *
091 * @return the locator
092 */
093 Locator getLocator() {
094 return locator;
095 }
096
097 /**
098 * Hit testing.
099 * @param column column index
100 * @return -1 if the column is to the left of this range,
101 * 0 if the column is in this range and
102 * 1 if the column is to the right of this range
103 */
104 int hits(int column) {
105 if (column < left) {
106 return -1;
107 } if (column >= right) {
108 return 1;
109 } else {
110 return 0;
111 }
112 }
113
114 /**
115 * Removes a column from the range possibly asking it to be destroyed or
116 * splitting it.
117 * @param column a column index
118 * @return <code>null</code> if this range gets destroyed,
119 * <code>this</code> if the range gets resized and
120 * the new right half range if the range gets split
121 */
122 ColumnRange removeColumn(int column) {
123 // first, let's see if this is a 1-column range that should
124 // be destroyed
125 if (isSingleCol()) {
126 return null;
127 } else if (column == left) {
128 left++;
129 return this;
130 } else if (column + 1 == right) {
131 right--;
132 return this;
133 } else {
134 ColumnRange created = new ColumnRange(this.element, this.locator,
135 column + 1, this.right);
136 created.next = this.next;
137 this.next = created;
138 this.right = column;
139 return created;
140 }
141 }
142
143 /**
144 * Returns the next.
145 *
146 * @return the next
147 */
148 ColumnRange getNext() {
149 return next;
150 }
151
152 /**
153 * Sets the next.
154 *
155 * @param next the next to set
156 */
157 void setNext(ColumnRange next) {
158 this.next = next;
159 }
160
161 boolean isSingleCol() {
162 return left + 1 == right;
163 }
164
165 /**
166 * @see java.lang.Object#toString()
167 */
168 public String toString() {
169 if (isSingleCol()) {
170 return Integer.toString(right);
171 } else {
172 return (left + 1) + "\u2026" + (right);
173 }
174 }
175
176 }