001 /*
002 * Copyright 2001-2006 Stephen Colebourne
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.joda.time.field;
017
018 import java.util.Locale;
019
020 import org.joda.time.DateTimeField;
021 import org.joda.time.DateTimeFieldType;
022 import org.joda.time.DurationField;
023 import org.joda.time.ReadableInstant;
024 import org.joda.time.ReadablePartial;
025
026 /**
027 * AbstractPartialFieldProperty is a base class for binding a
028 * ReadablePartial to a DateTimeField.
029 * <p>
030 * It allows the date and time manipulation code to be field based yet
031 * still easy to use.
032 *
033 * @author Stephen Colebourne
034 * @author Brian S O'Neill
035 * @since 1.0
036 */
037 public abstract class AbstractPartialFieldProperty {
038
039 /**
040 * Constructor.
041 */
042 protected AbstractPartialFieldProperty() {
043 super();
044 }
045
046 //-----------------------------------------------------------------------
047 /**
048 * Gets the field being used.
049 *
050 * @return the field
051 */
052 public abstract DateTimeField getField();
053
054 /**
055 * Gets the field type being used.
056 *
057 * @return the field type
058 */
059 public DateTimeFieldType getFieldType() {
060 return getField().getType();
061 }
062
063 /**
064 * Gets the name of the field.
065 *
066 * @return the field name
067 */
068 public String getName() {
069 return getField().getName();
070 }
071
072 /**
073 * Gets the partial instant being used.
074 *
075 * @return the partial instant
076 */
077 protected abstract ReadablePartial getReadablePartial();
078
079 //-----------------------------------------------------------------------
080 /**
081 * Gets the value of this property from the instant.
082 * <p>
083 * For example, the following two lines of code are equivalent:
084 * <pre>
085 * partial.getDayOfMonth();
086 * partial.dayOfMonth().get();
087 * </pre>
088 *
089 * @return the current value
090 */
091 public abstract int get();
092
093 /**
094 * Gets the value of this property from the instant as a string.
095 * <p>
096 * This method returns the value converted to a <code>String</code>
097 * using <code>Integer.toString</code>. This method does NOT return
098 * textual descriptions such as 'Monday' or 'January'.
099 * 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 }