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    }