Re: [threeten-develop] Flexible field extensibility
Status: Alpha
Brought to you by:
scolebourne
From: Roger R. <Roger.Riggs@Oracle.com> - 2012-05-26 10:15:24
|
Yes, but that coding pattern plus the definition of the CalendricalAdjuster interface is what doesn't seem right in the API. Forcing adjusters and the replacement values of components through a single method raises the complexity without raising the value. Mixing the concepts of objects that can produce a new value with objects that are a new value attempts to combine disjoint concepts into a single function. CalendricalAdjuster interface is effectively at the top of the type hierarchy but mixes different roles and only for the convenience of the implementation, not because it is expressing a clear API concept. A cleaner solution is needed. Roger On 5/25/12 6:32 PM, Stephen Colebourne wrote: > Take a look at the implementation. It handles DateAdjuster, > TimeAdjuster and sub parts of the relevent CalObj. > > On 25/05/2012, Roger Riggs<Rog...@or...> wrote: >> Hi Stephen, >> >> I think you've missed the purpose and intention of my proposal. >> >> The CalendricalObject.with() method is intended so the CalendricalObject >> itself >> would do the replacement of the argument in its own composite. >> The CalendricalObject should *not* be delegating to any other object >> to do the update. Is should just determine if the object passed is of a >> type that replaces the whole object or one of its components. >> If the object passed is not a replacement for the object or a component >> it throws an exception because the requested replacement cannot occur, >> it is a programming error. >> >> Just creating a union of the Date and Time Adjusters is not sufficient >> and is still too limiting. It still special cases the kind of updates >> that a DateTimeField can make. >> >> Roger >> >> >> >> >> In all the cases >> On 05/25/2012 01:46 PM, Stephen Colebourne wrote: >>> I've pushed the piratecalobj branch with code along this line of >>> thought. It does eliminate a lot of public methods, but doesn't feel >>> quite right yet. The key question is how implement the method. Lets ask >>> this in terms of a question: >>> >>> Should this throw an error? Or just change the offset in a? >>> OffsetDate a >>> OffsetTime b >>> a.with(b) // return type is an OffsetDate >>> >>> Should this throw an error? Or do nothing? >>> LocalDate a >>> LocalTime b >>> a.with(b) // return type is an LocalDate >>> >>> Should this throw an error? Or do nothing? (same question as above >>> really!) >>> LocalTime a >>> MonthOfYear b >>> a.with(b) // return type is an LocalTime >>> >>> Stephen >>> >>> >>> >>> On 23 May 2012 16:09, Stephen Colebourne<sco...@jo...> wrote: >>>> I think this approach definitely has some merit and is worth >>>> exploring. I'm still trying to get my head aroud the implications. >>>> >>>> Basically, there are three cases that the "with" concept would apply to >>>> - known types - LDT with LD, ODT with ZO etc >>>> - "unknown" types that are major objects >>>> - "unknown" types that are subparts of LD or LT, such as MonthDay or >>>> Year >>>> >>>> The patch below handles the first of these. I think that the following >>>> has the potential to solve the third >>>> >>>> public LocalDateTime with(CalendricalObject<?> calendrical) { >>>> if (calendrical instanceof LocalDateTime) { >>>> return (LocalDateTime) calendrical; >>>> } else if (calendrical instanceof LocalDate) { >>>> return with((LocalDate) calendrical, time); >>>> } else if (calendrical instanceof LocalTime) { >>>> return with(date, (LocalTime) calendrical); >>>> } else if (calendrical instanceof DateAdjuster) { >>>> return with(((DateAdjuster) calendrical).adjustDate(date), >>>> time); >>>> } else if (calendrical instanceof TimeAdjuster) { >>>> return with(date, ((TimeAdjuster) >>>> calendrical).adjustTime(time)); >>>> } >>>> DateTimes.checkNotNull(calendrical, "Calendrical must not be >>>> null"); >>>> throw new CalendricalException("Unable to combine calendrical >>>> with LocalTime: " + calendrical.getClass()); >>>> } >>>> >>>> This looks good, and would allow the removal of the with(DateAdjuster) >>>> and with(TimeAdjuster) methods. However it would require DateAdjuster >>>> and TimeAdjuster to extend CalendrcialObject which doesn't really make >>>> sense, so there might be a need for a further unifying interface. Not >>>> sure yet. >>>> >>>> The second case, unknown objects, like java.util.Date or Joda-Time >>>> classes (future 310 compatible Joda-Time), could potentially be solved >>>> by handling DateTimeBuilder. >>>> >>>> } else { >>>> // try to extract builder >>>> // extract known types from builder >>>> // merge them in >>>> return with(date, ((TimeAdjuster) >>>> calendrical).adjustTime(time)); >>>> } >>>> >>>> If we can get all three of these cases unified in a single way, that >>>> feels like it would be a major step forward. >>>> >>>> On TimeField and DateField, I'm beginning to lean towards losing the >>>> type safety and only having DateTimeField. The code with the patch >>>> looks overly generified to me. If there is just DateTimeField then >>>> perhaps it has no generics and date.get(someTimeField) simply throws a >>>> runtime exception. Again, worth an investigation. >>>> >>>> Stephen >>>> >>>> >>>> On 14 May 2012 22:30, Roger Riggs<Rog...@or...> wrote: >>>>> Here's another idea on the interface used by a DateTimeField to access >>>>> the components of the date-time objects. >>>>> >>>>> The field needs to be able to extract information from the date-time >>>>> object >>>>> or a component of it, and modify it according to the field type and >>>>> new value before returning a new component constructed with the new >>>>> value. >>>>> The current interface burdens the field with responsiblity for >>>>> reconstructing the original >>>>> date-time object such as LDT, ODT, OT, OD, and ZDT composites. >>>>> >>>>> If instead, the composite classes were responsible for replacing the >>>>> components >>>>> it would relieve the DateTimeField from knowing about the composite. >>>>> The >>>>> field >>>>> should only need to know about the LocalDate or LocalTime that it >>>>> applies >>>>> to. >>>>> The DateTimeField should not need know how to create the composite but >>>>> should delegate to the composite. Adding a "with" method to >>>>> CalendricalObject >>>>> provides the necessary opportunity for delegation. >>>>> >>>>> The javadoc is: http://cr.openjdk.java.net/~rriggs/threeten >>>>> >>>>> The key element is the CalendricalObject.with method and >>>>> the signatures of the get, with, and roll methods of DateTimeField. >>>>> >>>>> >>>>> CalendricalObject<R> { >>>>> <T> T extract (Class<T>); >>>>> R with(CalendricalObject newValue); >>>>> } >>>>> >>>>> The code in the field can look something like: >>>>> >>>>> + @Override >>>>> + public<R extends CalendricalObject<R>> R >>>>> roll(CalendricalObject<R> >>>>> value, long newValue) { >>>>> + LocalDate date = value.extract(LocalDate.class); >>>>> + if (date == null) { >>>>> + throw new CalendricalException("LocalDate not available"); >>>>> + } >>>>> + >>>>> + switch (this) { >>>>> + case DAY_OF_WEEK: >>>>> + date = date.plusDays(newValue); >>>>> + break; >>>>> + .... >>>>> + default: >>>>> + ... >>>>> + } >>>>> + return value.with(date); >>>>> + } >>>>> >>>>> This allows the field to access any component of the date-time object >>>>> with >>>>> extract(), >>>>> and when the new value of the component is computed, it can be use the >>>>> CalendricalObject.with method to create a new date-time instance with >>>>> the >>>>> new value. >>>>> >>>>> >>>>> DateTimeFields should be specific about what component LD, LT, etc they >>>>> use >>>>> and affect. Adding a generic type to DateTimeField<T> allows the >>>>> subtypes >>>>> to >>>>> be specific about what D/T components they require/accept. But it does >>>>> not >>>>> restrict a DateTimeField to a few well known types. Generics can be >>>>> used to >>>>> document >>>>> the affected type and provide better compile time type checking. >>>>> >>>>> A patch with the diffs is at: >>>>> http://cr.openjdk.java.net/~rriggs/threeten/df784c.patch >>>>> >>>>> Roger >>>>> >>>>> >>>>> >>>>> ------------------------------------------------------------------------------ >>>>> Live Security Virtual Conference >>>>> Exclusive live event will cover all the ways today's security and >>>>> threat landscape has changed and how IT managers can respond. >>>>> Discussions >>>>> will include endpoint security, mobile security and the latest in >>>>> malware >>>>> threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ >>>>> _______________________________________________ >>>>> threeten-develop mailing list >>>>> thr...@li... >>>>> https://lists.sourceforge.net/lists/listinfo/threeten-develop >>>>> >>> ------------------------------------------------------------------------------ >>> Live Security Virtual Conference >>> Exclusive live event will cover all the ways today's security and >>> threat landscape has changed and how IT managers can respond. Discussions >>> will include endpoint security, mobile security and the latest in malware >>> threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ >>> _______________________________________________ >>> threeten-develop mailing list >>> thr...@li... >>> https://lists.sourceforge.net/lists/listinfo/threeten-develop >> > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and > threat landscape has changed and how IT managers can respond. Discussions > will include endpoint security, mobile security and the latest in malware > threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > _______________________________________________ > threeten-develop mailing list > thr...@li... > https://lists.sourceforge.net/lists/listinfo/threeten-develop |