1 | /* |
2 | * Copyright 2001-2006 Stephen Colebourne |
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.joda.time.field; |
17 | |
18 | import java.util.Locale; |
19 | |
20 | import org.joda.time.DateTimeField; |
21 | import org.joda.time.DateTimeFieldType; |
22 | import org.joda.time.DurationField; |
23 | import org.joda.time.ReadableInstant; |
24 | import org.joda.time.ReadablePartial; |
25 | |
26 | /** |
27 | * AbstractPartialFieldProperty is a base class for binding a |
28 | * ReadablePartial to a DateTimeField. |
29 | * <p> |
30 | * It allows the date and time manipulation code to be field based yet |
31 | * still easy to use. |
32 | * |
33 | * @author Stephen Colebourne |
34 | * @author Brian S O'Neill |
35 | * @since 1.0 |
36 | */ |
37 | public abstract class AbstractPartialFieldProperty { |
38 | |
39 | /** |
40 | * Constructor. |
41 | */ |
42 | protected AbstractPartialFieldProperty() { |
43 | super(); |
44 | } |
45 | |
46 | //----------------------------------------------------------------------- |
47 | /** |
48 | * Gets the field being used. |
49 | * |
50 | * @return the field |
51 | */ |
52 | public abstract DateTimeField getField(); |
53 | |
54 | /** |
55 | * Gets the field type being used. |
56 | * |
57 | * @return the field type |
58 | */ |
59 | public DateTimeFieldType getFieldType() { |
60 | return getField().getType(); |
61 | } |
62 | |
63 | /** |
64 | * Gets the name of the field. |
65 | * |
66 | * @return the field name |
67 | */ |
68 | public String getName() { |
69 | return getField().getName(); |
70 | } |
71 | |
72 | /** |
73 | * Gets the partial instant being used. |
74 | * |
75 | * @return the partial instant |
76 | */ |
77 | protected abstract ReadablePartial getReadablePartial(); |
78 | |
79 | //----------------------------------------------------------------------- |
80 | /** |
81 | * Gets the value of this property from the instant. |
82 | * <p> |
83 | * For example, the following two lines of code are equivalent: |
84 | * <pre> |
85 | * partial.getDayOfMonth(); |
86 | * partial.dayOfMonth().get(); |
87 | * </pre> |
88 | * |
89 | * @return the current value |
90 | */ |
91 | public abstract int get(); |
92 | |
93 | /** |
94 | * Gets the value of this property from the instant as a string. |
95 | * <p> |
96 | * This method returns the value converted to a <code>String</code> |
97 | * using <code>Integer.toString</code>. This method does NOT return |
98 | * textual descriptions such as 'Monday' or 'January'. |
99 | * See {@link #getAsText()} and {@link #getAsShortText()} for those. |
100 | * |
101 | * @return the current value |
102 | * @see DateTimeField#get |
103 | * @since 1.1 |
104 | */ |
105 | public String getAsString() { |
106 | return Integer.toString(get()); |
107 | } |
108 | |
109 | /** |
110 | * Gets the textual value of this property from the instant as a |
111 | * string in the default locale. |
112 | * <p> |
113 | * This method returns the value converted to a <code>String</code> |
114 | * returning the appropriate textual description wherever possible. |
115 | * Thus, a day of week of 1 would return 'Monday' in English. |
116 | * |
117 | * @return the current text value |
118 | * @see DateTimeField#getAsText |
119 | */ |
120 | public String getAsText() { |
121 | return getAsText(null); |
122 | } |
123 | |
124 | /** |
125 | * Gets the textual value of this property from the instant as a |
126 | * string in the specified locale. |
127 | * <p> |
128 | * This method returns the value converted to a <code>String</code> |
129 | * returning the appropriate textual description wherever possible. |
130 | * Thus, a day of week of 1 would return 'Monday' in English. |
131 | * |
132 | * @param locale locale to use for selecting a text symbol, null means default |
133 | * @return the current text value |
134 | * @see DateTimeField#getAsText |
135 | */ |
136 | public String getAsText(Locale locale) { |
137 | return getField().getAsText(getReadablePartial(), get(), locale); |
138 | } |
139 | |
140 | /** |
141 | * Gets the short textual value of this property from the instant as a |
142 | * string in the default locale. |
143 | * <p> |
144 | * This method returns the value converted to a <code>String</code> |
145 | * returning the appropriate textual description wherever possible. |
146 | * Thus, a day of week of 1 would return 'Mon' in English. |
147 | * |
148 | * @return the current text value |
149 | * @see DateTimeField#getAsShortText |
150 | */ |
151 | public String getAsShortText() { |
152 | return getAsShortText(null); |
153 | } |
154 | |
155 | /** |
156 | * Gets the short textual value of this property from the instant as a |
157 | * string in the specified locale. |
158 | * <p> |
159 | * This method returns the value converted to a <code>String</code> |
160 | * returning the appropriate textual description wherever possible. |
161 | * Thus, a day of week of 1 would return 'Mon' in English. |
162 | * |
163 | * @param locale locale to use for selecting a text symbol, null means default |
164 | * @return the current text value |
165 | * @see DateTimeField#getAsShortText |
166 | */ |
167 | public String getAsShortText(Locale locale) { |
168 | return getField().getAsShortText(getReadablePartial(), get(), locale); |
169 | } |
170 | |
171 | //----------------------------------------------------------------------- |
172 | /** |
173 | * Returns the duration per unit value of this field. For example, if this |
174 | * field represents "hour of day", then the duration is an hour. |
175 | * |
176 | * @return the duration of this field, or UnsupportedDurationField |
177 | */ |
178 | public DurationField getDurationField() { |
179 | return getField().getDurationField(); |
180 | } |
181 | |
182 | /** |
183 | * Returns the range duration of this field. For example, if this field |
184 | * represents "hour of day", then the range duration is a day. |
185 | * |
186 | * @return the range duration of this field, or null if field has no range |
187 | */ |
188 | public DurationField getRangeDurationField() { |
189 | return getField().getRangeDurationField(); |
190 | } |
191 | |
192 | //----------------------------------------------------------------------- |
193 | /** |
194 | * Gets the minimum value for the field ignoring the current time. |
195 | * |
196 | * @return the minimum value |
197 | * @see DateTimeField#getMinimumValue |
198 | */ |
199 | public int getMinimumValueOverall() { |
200 | return getField().getMinimumValue(); |
201 | } |
202 | |
203 | /** |
204 | * Gets the minimum value for this field given the current field values. |
205 | * |
206 | * @return the minimum value |
207 | * @see DateTimeField#getMinimumValue |
208 | */ |
209 | public int getMinimumValue() { |
210 | return getField().getMinimumValue(getReadablePartial()); |
211 | } |
212 | |
213 | /** |
214 | * Gets the maximum value for the field ignoring the current time. |
215 | * |
216 | * @return the maximum value |
217 | * @see DateTimeField#getMaximumValue |
218 | */ |
219 | public int getMaximumValueOverall() { |
220 | return getField().getMaximumValue(); |
221 | } |
222 | |
223 | /** |
224 | * Gets the maximum value for this field given the current field values. |
225 | * |
226 | * @return the maximum value |
227 | * @see DateTimeField#getMaximumValue |
228 | */ |
229 | public int getMaximumValue() { |
230 | return getField().getMaximumValue(getReadablePartial()); |
231 | } |
232 | |
233 | //----------------------------------------------------------------------- |
234 | /** |
235 | * Gets the maximum text length for the field. |
236 | * |
237 | * @param locale optional locale to use for selecting a text symbol |
238 | * @return the maximum length |
239 | * @see DateTimeField#getMaximumTextLength |
240 | */ |
241 | public int getMaximumTextLength(Locale locale) { |
242 | return getField().getMaximumTextLength(locale); |
243 | } |
244 | |
245 | /** |
246 | * Gets the maximum short text length for the field. |
247 | * |
248 | * @param locale optional locale to use for selecting a text symbol |
249 | * @return the maximum length |
250 | * @see DateTimeField#getMaximumShortTextLength |
251 | */ |
252 | public int getMaximumShortTextLength(Locale locale) { |
253 | return getField().getMaximumShortTextLength(locale); |
254 | } |
255 | |
256 | //----------------------------------------------------------------------- |
257 | /** |
258 | * Compare this field to the same field on another instant. |
259 | * <p> |
260 | * The comparison is based on the value of the same field type, irrespective |
261 | * of any difference in chronology. Thus, if this property represents the |
262 | * hourOfDay field, then the hourOfDay field of the other instant will be queried |
263 | * whether in the same chronology or not. |
264 | * |
265 | * @param instant the instant to compare to |
266 | * @return negative value if this is less, 0 if equal, or positive value if greater |
267 | * @throws IllegalArgumentException if the instant is null or the instant |
268 | * doesn't support the field of this property |
269 | */ |
270 | public int compareTo(ReadableInstant instant) { |
271 | if (instant == null) { |
272 | throw new IllegalArgumentException("The instant must not be null"); |
273 | } |
274 | int thisValue = get(); |
275 | int otherValue = instant.get(getFieldType()); |
276 | if (thisValue < otherValue) { |
277 | return -1; |
278 | } else if (thisValue > otherValue) { |
279 | return 1; |
280 | } else { |
281 | return 0; |
282 | } |
283 | } |
284 | |
285 | /** |
286 | * Compare this field to the same field on another partial instant. |
287 | * <p> |
288 | * The comparison is based on the value of the same field type, irrespective |
289 | * of any difference in chronology. Thus, if this property represents the |
290 | * hourOfDay field, then the hourOfDay field of the other partial will be queried |
291 | * whether in the same chronology or not. |
292 | * |
293 | * @param partial the partial to compare to |
294 | * @return negative value if this is less, 0 if equal, or positive value if greater |
295 | * @throws IllegalArgumentException if the instant is null |
296 | * @throws IllegalArgumentException if the field of this property cannot be queried |
297 | * on the specified instant |
298 | */ |
299 | public int compareTo(ReadablePartial partial) { |
300 | if (partial == null) { |
301 | throw new IllegalArgumentException("The instant must not be null"); |
302 | } |
303 | int thisValue = get(); |
304 | int otherValue = partial.get(getFieldType()); |
305 | if (thisValue < otherValue) { |
306 | return -1; |
307 | } else if (thisValue > otherValue) { |
308 | return 1; |
309 | } else { |
310 | return 0; |
311 | } |
312 | } |
313 | |
314 | //----------------------------------------------------------------------- |
315 | /** |
316 | * Compares this property to another. |
317 | * |
318 | * @param object the object to compare to |
319 | * @return true if equal |
320 | */ |
321 | public boolean equals(Object object) { |
322 | if (this == object) { |
323 | return true; |
324 | } |
325 | if (object instanceof AbstractPartialFieldProperty == false) { |
326 | return false; |
327 | } |
328 | AbstractPartialFieldProperty other = (AbstractPartialFieldProperty) object; |
329 | return |
330 | get() == other.get() && |
331 | getFieldType() == other.getFieldType() && |
332 | FieldUtils.equals(getReadablePartial().getChronology(), other.getReadablePartial().getChronology()); |
333 | } |
334 | |
335 | //----------------------------------------------------------------------- |
336 | /** |
337 | * Gets a suitable hashcode for the object. |
338 | * |
339 | * @return the hashcode |
340 | * @since 1.3 |
341 | */ |
342 | public int hashCode() { |
343 | int hash = 19; |
344 | hash = 13 * hash + get(); |
345 | hash = 13 * hash + getFieldType().hashCode(); |
346 | hash = 13 * hash + getReadablePartial().getChronology().hashCode(); |
347 | return hash; |
348 | } |
349 | |
350 | //----------------------------------------------------------------------- |
351 | /** |
352 | * Output a debugging string. |
353 | * |
354 | * @return debugging string |
355 | */ |
356 | public String toString() { |
357 | return "Property[" + getName() + "]"; |
358 | } |
359 | |
360 | } |