1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.struts.flow.core.location;
17
18 import java.io.Serializable;
19
20 import org.apache.commons.lang.ObjectUtils;
21
22 /***
23 * A simple immutable and serializable implementation of {@link Location}.
24 *
25 * @since 2.1.8
26 * @version $Id: LocationImpl.java 280946 2005-09-14 21:43:05Z sylvain $
27 */
28 public class LocationImpl implements Location, Serializable {
29 private final String uri;
30 private final int line;
31 private final int column;
32 private final String description;
33
34
35 static final LocationImpl UNKNOWN = new LocationImpl(null, null, -1, -1);
36
37 /***
38 * Build a location for a given URI, with unknown line and column numbers.
39 *
40 * @param uri the resource URI
41 */
42 public LocationImpl(String description, String uri) {
43 this(description, uri, -1, -1);
44 }
45
46 /***
47 * Build a location for a given URI and line and columb numbers.
48 *
49 * @param uri the resource URI
50 * @param line the line number (starts at 1)
51 * @param column the column number (starts at 1)
52 */
53 public LocationImpl(String description, String uri, int line, int column) {
54 if (uri == null || uri.length() == 0) {
55 this.uri = null;
56 this.line = -1;
57 this.column = -1;
58 } else {
59 this.uri = uri;
60 this.line = line;
61 this.column = column;
62 }
63
64 if (description != null && description.length() == 0) {
65 description = null;
66 }
67 this.description = description;
68 }
69
70 /***
71 * Copy constructor.
72 *
73 * @param location the location to be copied
74 */
75 public LocationImpl(Location location) {
76 this(location.getDescription(), location.getURI(), location.getLineNumber(), location.getColumnNumber());
77 }
78
79 /***
80 * Create a location from an existing one, but with a different description
81 */
82 public LocationImpl(String description, Location location) {
83 this(description, location.getURI(), location.getLineNumber(), location.getColumnNumber());
84 }
85
86 /***
87 * Obtain a <code>LocationImpl</code> from a {@link Location}. If <code>location</code> is
88 * already a <code>LocationImpl</code>, it is returned, otherwise it is copied.
89 * <p>
90 * This method is useful when an immutable and serializable location is needed, such as in locatable
91 * exceptions.
92 *
93 * @param location the location
94 * @return an immutable and serializable version of <code>location</code>
95 */
96 public static LocationImpl get(Location location) {
97 if (location instanceof LocationImpl) {
98 return (LocationImpl)location;
99 } else if (location == null) {
100 return UNKNOWN;
101 } else {
102 return new LocationImpl(location);
103 }
104 }
105
106 /***
107 * Get the description of this location
108 *
109 * @return the description (can be <code>null</code>)
110 */
111 public String getDescription() {
112 return this.description;
113 }
114
115 /***
116 * Get the URI of this location
117 *
118 * @return the URI (<code>null</code> if unknown).
119 */
120 public String getURI() {
121 return this.uri;
122 }
123
124 /***
125 * Get the line number of this location
126 *
127 * @return the line number (<code>-1</code> if unknown)
128 */
129 public int getLineNumber() {
130 return this.line;
131 }
132
133 /***
134 * Get the column number of this location
135 *
136 * @return the column number (<code>-1</code> if unknown)
137 */
138 public int getColumnNumber() {
139 return this.column;
140 }
141
142 public boolean equals(Object obj) {
143 if (obj == this) {
144 return true;
145 }
146
147 if (obj instanceof Location) {
148 Location other = (Location)obj;
149 return this.line == other.getLineNumber() && this.column == other.getColumnNumber()
150 && ObjectUtils.equals(this.uri, other.getURI())
151 && ObjectUtils.equals(this.description, other.getDescription());
152 }
153
154 return false;
155 }
156
157 public int hashCode() {
158 int hash = line ^ column;
159 if (uri != null) hash ^= uri.hashCode();
160 if (description != null) hash ^= description.hashCode();
161
162 return hash;
163 }
164
165 public String toString() {
166 return LocationUtils.toString(this);
167 }
168
169 /***
170 * Ensure serialized unknown location resolve to {@link Location#UNKNOWN}.
171 */
172 private Object readResolve() {
173 return this.equals(Location.UNKNOWN) ? Location.UNKNOWN : this;
174 }
175 }