001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.util.location;
018:
019: import java.io.Serializable;
020:
021: import org.apache.commons.lang.ObjectUtils;
022:
023: /**
024: * A simple immutable and serializable implementation of {@link Location}.
025: *
026: * @since 2.1.8
027: * @version $Id: LocationImpl.java 446917 2006-09-16 19:10:40Z vgritsenko $
028: */
029: public class LocationImpl implements Location, Serializable {
030:
031: // Package private: outside this package, use Location.UNKNOWN.
032: static final LocationImpl UNKNOWN = new LocationImpl(null, null,
033: -1, -1);
034:
035: private final String uri;
036: private final int line;
037: private final int column;
038: private final String description;
039:
040: /**
041: * Build a location for a given URI, with unknown line and column numbers.
042: *
043: * @param uri the resource URI
044: */
045: public LocationImpl(String description, String uri) {
046: this (description, uri, -1, -1);
047: }
048:
049: /**
050: * Build a location for a given URI and line and columb numbers.
051: *
052: * @param uri the resource URI
053: * @param line the line number (starts at 1)
054: * @param column the column number (starts at 1)
055: */
056: public LocationImpl(String description, String uri, int line,
057: int column) {
058: if (uri == null || uri.length() == 0) {
059: this .uri = null;
060: this .line = -1;
061: this .column = -1;
062: } else {
063: this .uri = uri;
064: this .line = line;
065: this .column = column;
066: }
067:
068: if (description != null && description.length() == 0) {
069: description = null;
070: }
071: this .description = description;
072: }
073:
074: /**
075: * Copy constructor.
076: *
077: * @param location the location to be copied
078: */
079: public LocationImpl(Location location) {
080: this (location.getDescription(), location.getURI(), location
081: .getLineNumber(), location.getColumnNumber());
082: }
083:
084: /**
085: * Create a location from an existing one, but with a different description
086: */
087: public LocationImpl(String description, Location location) {
088: this (description, location.getURI(), location.getLineNumber(),
089: location.getColumnNumber());
090: }
091:
092: /**
093: * Obtain a <code>LocationImpl</code> from a {@link Location}. If <code>location</code> is
094: * already a <code>LocationImpl</code>, it is returned, otherwise it is copied.
095: * <p>
096: * This method is useful when an immutable and serializable location is needed, such as in locatable
097: * exceptions.
098: *
099: * @param location the location
100: * @return an immutable and serializable version of <code>location</code>
101: */
102: public static LocationImpl get(Location location) {
103: if (location instanceof LocationImpl) {
104: return (LocationImpl) location;
105: } else if (location == null) {
106: return UNKNOWN;
107: } else {
108: return new LocationImpl(location);
109: }
110: }
111:
112: /**
113: * Get the description of this location
114: *
115: * @return the description (can be <code>null</code>)
116: */
117: public String getDescription() {
118: return this .description;
119: }
120:
121: /**
122: * Get the URI of this location
123: *
124: * @return the URI (<code>null</code> if unknown).
125: */
126: public String getURI() {
127: return this .uri;
128: }
129:
130: /**
131: * Get the line number of this location
132: *
133: * @return the line number (<code>-1</code> if unknown)
134: */
135: public int getLineNumber() {
136: return this .line;
137: }
138:
139: /**
140: * Get the column number of this location
141: *
142: * @return the column number (<code>-1</code> if unknown)
143: */
144: public int getColumnNumber() {
145: return this .column;
146: }
147:
148: public boolean equals(Object obj) {
149: if (obj == this ) {
150: return true;
151: }
152:
153: if (obj instanceof Location) {
154: Location other = (Location) obj;
155: return this .line == other.getLineNumber()
156: && this .column == other.getColumnNumber()
157: && ObjectUtils.equals(this .uri, other.getURI())
158: && ObjectUtils.equals(this .description, other
159: .getDescription());
160: }
161:
162: return false;
163: }
164:
165: public int hashCode() {
166: int hash = line ^ column;
167: if (uri != null)
168: hash ^= uri.hashCode();
169: if (description != null)
170: hash ^= description.hashCode();
171:
172: return hash;
173: }
174:
175: public String toString() {
176: return LocationUtils.toString(this );
177: }
178:
179: /**
180: * Ensure serialized unknown location resolve to {@link Location#UNKNOWN}.
181: */
182: private Object readResolve() {
183: return this.equals(Location.UNKNOWN) ? Location.UNKNOWN : this;
184: }
185: }
|