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 }