1 16 package org.joda.time; 17 18 import java.io.Serializable ; 19 import java.util.ArrayList ; 20 import java.util.Arrays ; 21 import java.util.List ; 22 import java.util.Locale ; 23 24 import org.joda.time.base.AbstractPartial; 25 import org.joda.time.field.AbstractPartialFieldProperty; 26 import org.joda.time.field.FieldUtils; 27 import org.joda.time.format.DateTimeFormat; 28 import org.joda.time.format.DateTimeFormatter; 29 import org.joda.time.format.ISODateTimeFormat; 30 31 68 public final class Partial 69 extends AbstractPartial 70 implements ReadablePartial, Serializable { 71 72 73 private static final long serialVersionUID = 12324121189002L; 74 75 76 private final Chronology iChronology; 77 78 private final DateTimeFieldType[] iTypes; 79 80 private final int[] iValues; 81 82 private transient DateTimeFormatter[] iFormatter; 83 84 102 public Partial() { 103 this((Chronology) null); 104 } 105 106 122 public Partial(Chronology chrono) { 123 super(); 124 iChronology = DateTimeUtils.getChronology(chrono).withUTC(); 125 iTypes = new DateTimeFieldType[0]; 126 iValues = new int[0]; 127 } 128 129 138 public Partial(DateTimeFieldType type, int value) { 139 this(type, value, null); 140 } 141 142 152 public Partial(DateTimeFieldType type, int value, Chronology chronology) { 153 super(); 154 chronology = DateTimeUtils.getChronology(chronology).withUTC(); 155 iChronology = chronology; 156 if (type == null) { 157 throw new IllegalArgumentException ("The field type must not be null"); 158 } 159 iTypes = new DateTimeFieldType[] {type}; 160 iValues = new int[] {value}; 161 chronology.validate(this, iValues); 162 } 163 164 174 public Partial(DateTimeFieldType[] types, int[] values) { 175 this(types, values, null); 176 } 177 178 189 public Partial(DateTimeFieldType[] types, int[] values, Chronology chronology) { 190 super(); 191 chronology = DateTimeUtils.getChronology(chronology).withUTC(); 192 iChronology = chronology; 193 if (types == null) { 194 throw new IllegalArgumentException ("Types array must not be null"); 195 } 196 if (values == null) { 197 throw new IllegalArgumentException ("Values array must not be null"); 198 } 199 if (values.length != types.length) { 200 throw new IllegalArgumentException ("Values array must be the same length as the types array"); 201 } 202 if (types.length == 0) { 203 iTypes = types; 204 iValues = values; 205 return; 206 } 207 for (int i = 0; i < types.length; i++) { 208 if (types[i] == null) { 209 throw new IllegalArgumentException ("Types array must not contain null: index " + i); 210 } 211 } 212 DurationField lastUnitField = null; 213 for (int i = 0; i < types.length; i++) { 214 DateTimeFieldType loopType = types[i]; 215 DurationField loopUnitField = loopType.getDurationType().getField(iChronology); 216 if (i > 0) { 217 int compare = lastUnitField.compareTo(loopUnitField); 218 if (compare < 0 || (compare != 0 && loopUnitField.isSupported() == false)) { 219 throw new IllegalArgumentException ("Types array must be in order largest-smallest: " + 220 types[i - 1].getName() + " < " + loopType.getName()); 221 } else if (compare == 0) { 222 if (types[i - 1].getRangeDurationType() == null) { 223 if (loopType.getRangeDurationType() == null) { 224 throw new IllegalArgumentException ("Types array must not contain duplicate: " + loopType.getName()); 225 } 226 } else { 227 if (loopType.getRangeDurationType() == null) { 228 throw new IllegalArgumentException ("Types array must be in order largest-smallest: " + 229 types[i - 1].getName() + " < " + loopType.getName()); 230 } 231 DurationField lastRangeField = types[i - 1].getRangeDurationType().getField(iChronology); 232 DurationField loopRangeField = loopType.getRangeDurationType().getField(iChronology); 233 if (lastRangeField.compareTo(loopRangeField) < 0) { 234 throw new IllegalArgumentException ("Types array must be in order largest-smallest: " + 235 types[i - 1].getName() + " < " + loopType.getName()); 236 } 237 if (lastRangeField.compareTo(loopRangeField) == 0) { 238 throw new IllegalArgumentException ("Types array must not contain duplicate: " + loopType.getName()); 239 } 240 } 241 } 242 } 243 lastUnitField = loopUnitField; 244 } 245 246 iTypes = (DateTimeFieldType[]) types.clone(); 247 chronology.validate(this, values); 248 iValues = (int[]) values.clone(); 249 } 250 251 257 public Partial(ReadablePartial partial) { 258 super(); 259 if (partial == null) { 260 throw new IllegalArgumentException ("The partial must not be null"); 261 } 262 iChronology = DateTimeUtils.getChronology(partial.getChronology()).withUTC(); 263 iTypes = new DateTimeFieldType[partial.size()]; 264 iValues = new int[partial.size()]; 265 for (int i = 0; i < partial.size(); i++) { 266 iTypes[i] = partial.getFieldType(i); 267 iValues[i] = partial.getValue(i); 268 } 269 } 270 271 279 Partial(Partial partial, int[] values) { 280 super(); 281 iChronology = partial.iChronology; 282 iTypes = partial.iTypes; 283 iValues = values; 284 } 285 286 295 Partial(Chronology chronology, DateTimeFieldType[] types, int[] values) { 296 super(); 297 iChronology = chronology; 298 iTypes = types; 299 iValues = values; 300 } 301 302 308 public int size() { 309 return iTypes.length; 310 } 311 312 320 public Chronology getChronology() { 321 return iChronology; 322 } 323 324 332 protected DateTimeField getField(int index, Chronology chrono) { 333 return iTypes[index].getField(chrono); 334 } 335 336 343 public DateTimeFieldType getFieldType(int index) { 344 return iTypes[index]; 345 } 346 347 355 public DateTimeFieldType[] getFieldTypes() { 356 return (DateTimeFieldType[]) iTypes.clone(); 357 } 358 359 367 public int getValue(int index) { 368 return iValues[index]; 369 } 370 371 380 public int[] getValues() { 381 return (int[]) iValues.clone(); 382 } 383 384 399 public Partial withChronologyRetainFields(Chronology newChronology) { 400 newChronology = DateTimeUtils.getChronology(newChronology); 401 newChronology = newChronology.withUTC(); 402 if (newChronology == getChronology()) { 403 return this; 404 } else { 405 Partial newPartial = new Partial(newChronology, iTypes, iValues); 406 newChronology.validate(newPartial, iValues); 407 return newPartial; 408 } 409 } 410 411 426 public Partial with(DateTimeFieldType fieldType, int value) { 427 if (fieldType == null) { 428 throw new IllegalArgumentException ("The field type must not be null"); 429 } 430 int index = indexOf(fieldType); 431 if (index == -1) { 432 DateTimeFieldType[] newTypes = new DateTimeFieldType[iTypes.length + 1]; 433 int[] newValues = new int[newTypes.length]; 434 435 int i = 0; 437 DurationField unitField = fieldType.getDurationType().getField(iChronology); 438 if (unitField.isSupported()) { 439 for (; i < iTypes.length; i++) { 440 DateTimeFieldType loopType = iTypes[i]; 441 DurationField loopUnitField = loopType.getDurationType().getField(iChronology); 442 if (loopUnitField.isSupported()) { 443 int compare = unitField.compareTo(loopUnitField); 444 if (compare > 0) { 445 break; 446 } else if (compare == 0) { 447 DurationField rangeField = fieldType.getRangeDurationType().getField(iChronology); 448 DurationField loopRangeField = loopType.getRangeDurationType().getField(iChronology); 449 if (rangeField.compareTo(loopRangeField) > 0) { 450 break; 451 } 452 } 453 } 454 } 455 } 456 System.arraycopy(iTypes, 0, newTypes, 0, i); 457 System.arraycopy(iValues, 0, newValues, 0, i); 458 newTypes[i] = fieldType; 459 newValues[i] = value; 460 System.arraycopy(iTypes, i, newTypes, i + 1, newTypes.length - i - 1); 461 System.arraycopy(iValues, i, newValues, i + 1, newValues.length - i - 1); 462 463 Partial newPartial = new Partial(iChronology, newTypes, newValues); 464 iChronology.validate(newPartial, newValues); 465 return newPartial; 466 } 467 if (value == getValue(index)) { 468 return this; 469 } 470 int[] newValues = getValues(); 471 newValues = getField(index).set(this, index, newValues, value); 472 return new Partial(this, newValues); 473 } 474 475 483 public Partial without(DateTimeFieldType fieldType) { 484 int index = indexOf(fieldType); 485 if (index != -1) { 486 DateTimeFieldType[] newTypes = new DateTimeFieldType[size() - 1]; 487 int[] newValues = new int[size() - 1]; 488 System.arraycopy(iTypes, 0, newTypes, 0, index); 489 System.arraycopy(iTypes, index + 1, newTypes, index, newTypes.length - index); 490 System.arraycopy(iValues, 0, newValues, 0, index); 491 System.arraycopy(iValues, index + 1, newValues, index, newValues.length - index); 492 Partial newPartial = new Partial(iChronology, newTypes, newValues); 493 iChronology.validate(newPartial, newValues); 494 return newPartial; 495 } 496 return this; 497 } 498 499 514 public Partial withField(DateTimeFieldType fieldType, int value) { 515 int index = indexOfSupported(fieldType); 516 if (value == getValue(index)) { 517 return this; 518 } 519 int[] newValues = getValues(); 520 newValues = getField(index).set(this, index, newValues, value); 521 return new Partial(this, newValues); 522 } 523 524 538 public Partial withFieldAdded(DurationFieldType fieldType, int amount) { 539 int index = indexOfSupported(fieldType); 540 if (amount == 0) { 541 return this; 542 } 543 int[] newValues = getValues(); 544 newValues = getField(index).add(this, index, newValues, amount); 545 return new Partial(this, newValues); 546 } 547 548 562 public Partial withFieldAddWrapped(DurationFieldType fieldType, int amount) { 563 int index = indexOfSupported(fieldType); 564 if (amount == 0) { 565 return this; 566 } 567 int[] newValues = getValues(); 568 newValues = getField(index).addWrapPartial(this, index, newValues, amount); 569 return new Partial(this, newValues); 570 } 571 572 587 public Partial withPeriodAdded(ReadablePeriod period, int scalar) { 588 if (period == null || scalar == 0) { 589 return this; 590 } 591 int[] newValues = getValues(); 592 for (int i = 0; i < period.size(); i++) { 593 DurationFieldType fieldType = period.getFieldType(i); 594 int index = indexOf(fieldType); 595 if (index >= 0) { 596 newValues = getField(index).add(this, index, newValues, 597 FieldUtils.safeMultiply(period.getValue(i), scalar)); 598 } 599 } 600 return new Partial(this, newValues); 601 } 602 603 612 public Partial plus(ReadablePeriod period) { 613 return withPeriodAdded(period, 1); 614 } 615 616 625 public Partial minus(ReadablePeriod period) { 626 return withPeriodAdded(period, -1); 627 } 628 629 640 public Property property(DateTimeFieldType type) { 641 return new Property(this, indexOfSupported(type)); 642 } 643 644 654 public boolean isMatch(ReadableInstant instant) { 655 long millis = DateTimeUtils.getInstantMillis(instant); 656 Chronology chrono = DateTimeUtils.getInstantChronology(instant); 657 for (int i = 0; i < iTypes.length; i++) { 658 int value = iTypes[i].getField(chrono).get(millis); 659 if (value != iValues[i]) { 660 return false; 661 } 662 } 663 return true; 664 } 665 666 678 public DateTimeFormatter getFormatter() { 679 DateTimeFormatter[] f = iFormatter; 680 if (f == null) { 681 if (size() == 0) { 682 return null; 683 } 684 f = new DateTimeFormatter[2]; 685 try { 686 List list = new ArrayList (Arrays.asList(iTypes)); 687 f[0] = ISODateTimeFormat.forFields(list, true, false); 688 if (list.size() == 0) { 689 f[1] = f[0]; 690 } 691 } catch (IllegalArgumentException ex) { 692 } 694 iFormatter = f; 695 } 696 return f[0]; 697 } 698 699 711 public String toString() { 712 DateTimeFormatter[] f = iFormatter; 713 if (f == null) { 714 getFormatter(); 715 f = iFormatter; 716 if (f == null) { 717 return toStringList(); 718 } 719 } 720 DateTimeFormatter f1 = f[1]; 721 if (f1 == null) { 722 return toStringList(); 723 } 724 return f1.print(this); 725 } 726 727 736 public String toStringList() { 737 int size = size(); 738 StringBuffer buf = new StringBuffer (20 * size); 739 buf.append('['); 740 for (int i = 0; i < size; i++) { 741 if (i > 0) { 742 buf.append(',').append(' '); 743 } 744 buf.append(iTypes[i].getName()); 745 buf.append('='); 746 buf.append(iValues[i]); 747 } 748 buf.append(']'); 749 return buf.toString(); 750 } 751 752 759 public String toString(String pattern) { 760 if (pattern == null) { 761 return toString(); 762 } 763 return DateTimeFormat.forPattern(pattern).print(this); 764 } 765 766 774 public String toString(String pattern, Locale locale) { 775 if (pattern == null) { 776 return toString(); 777 } 778 return DateTimeFormat.forPattern(pattern).withLocale(locale).print(this); 779 } 780 781 790 public static class Property extends AbstractPartialFieldProperty implements Serializable { 791 792 793 private static final long serialVersionUID = 53278362873888L; 794 795 796 private final Partial iPartial; 797 798 private final int iFieldIndex; 799 800 806 Property(Partial partial, int fieldIndex) { 807 super(); 808 iPartial = partial; 809 iFieldIndex = fieldIndex; 810 } 811 812 817 public DateTimeField getField() { 818 return iPartial.getField(iFieldIndex); 819 } 820 821 826 protected ReadablePartial getReadablePartial() { 827 return iPartial; 828 } 829 830 835 public Partial getPartial() { 836 return iPartial; 837 } 838 839 844 public int get() { 845 return iPartial.getValue(iFieldIndex); 846 } 847 848 866 public Partial addToCopy(int valueToAdd) { 867 int[] newValues = iPartial.getValues(); 868 newValues = getField().add(iPartial, iFieldIndex, newValues, valueToAdd); 869 return new Partial(iPartial, newValues); 870 } 871 872 890 public Partial addWrapFieldToCopy(int valueToAdd) { 891 int[] newValues = iPartial.getValues(); 892 newValues = getField().addWrapField(iPartial, iFieldIndex, newValues, valueToAdd); 893 return new Partial(iPartial, newValues); 894 } 895 896 907 public Partial setCopy(int value) { 908 int[] newValues = iPartial.getValues(); 909 newValues = getField().set(iPartial, iFieldIndex, newValues, value); 910 return new Partial(iPartial, newValues); 911 } 912 913 924 public Partial setCopy(String text, Locale locale) { 925 int[] newValues = iPartial.getValues(); 926 newValues = getField().set(iPartial, iFieldIndex, newValues, text, locale); 927 return new Partial(iPartial, newValues); 928 } 929 930 940 public Partial setCopy(String text) { 941 return setCopy(text, null); 942 } 943 944 954 public Partial withMaximumValue() { 955 return setCopy(getMaximumValue()); 956 } 957 958 967 public Partial withMinimumValue() { 968 return setCopy(getMinimumValue()); 969 } 970 } 971 972 } 973 | Popular Tags |