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 }