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 fi.iki.hsivonen.xml.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,v 1.4 2006/12/01 12:34:30 hsivonen Exp $
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 this.element = element;
072 this.locator = locator;
073 this.left = left;
074 this.right = right;
075 this.next = null;
076 }
077
078 /**
079 * Returns the element.
080 *
081 * @return the element
082 */
083 String getElement() {
084 return element;
085 }
086
087 /**
088 * Returns the locator.
089 *
090 * @return the locator
091 */
092 Locator getLocator() {
093 return locator;
094 }
095
096 /**
097 * Hit testing.
098 * @param column column index
099 * @return -1 if the column is to the left of this range,
100 * 0 if the column is in this range and
101 * 1 if the column is to the right of this range
102 */
103 int hits(int column) {
104 if (column < left) {
105 return -1;
106 } if (column >= right) {
107 return 1;
108 } else {
109 return 0;
110 }
111 }
112
113 /**
114 * Removes a column from the range possibly asking it to be destroyed or
115 * splitting it.
116 * @param column a column index
117 * @return <code>null</code> if this range gets destroyed,
118 * <code>this</code> if the range gets resized and
119 * the new right half range if the range gets split
120 */
121 ColumnRange removeColumn(int column) {
122 // first, let's see if this is a 1-column range that should
123 // be destroyed
124 if (isSingleCol()) {
125 return null;
126 } else if (column == left) {
127 left++;
128 return this;
129 } else if (column + 1 == right) {
130 right--;
131 return this;
132 } else {
133 ColumnRange created = new ColumnRange(this.element, this.locator,
134 column + 1, this.right);
135 created.next = this.next;
136 this.next = created;
137 this.right = column;
138 return created;
139 }
140 }
141
142 /**
143 * Returns the next.
144 *
145 * @return the next
146 */
147 ColumnRange getNext() {
148 return next;
149 }
150
151 /**
152 * Sets the next.
153 *
154 * @param next the next to set
155 */
156 void setNext(ColumnRange next) {
157 this.next = next;
158 }
159
160 boolean isSingleCol() {
161 return left + 1 == right;
162 }
163
164 /**
165 * @see java.lang.Object#toString()
166 */
167 public String toString() {
168 if (isSingleCol()) {
169 return Integer.toString(right);
170 } else {
171 return (left + 1) + "\u2026" + (right);
172 }
173 }
174
175 }