View Javadoc

1   /*
2    * Copyright 2005 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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      // Package private: outside this package, use Location.UNKNOWN.
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 }