195 } |
195 } |
196 if (time != null && time.isSupported(field)) { |
196 if (time != null && time.isSupported(field)) { |
197 return time.getLong(field); |
197 return time.getLong(field); |
198 } |
198 } |
199 if (field instanceof ChronoField) { |
199 if (field instanceof ChronoField) { |
200 throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName()); |
200 throw new UnsupportedTemporalTypeException("Unsupported field: " + field); |
201 } |
201 } |
202 return field.getFrom(this); |
202 return field.getFrom(this); |
203 } |
203 } |
204 |
204 |
205 @SuppressWarnings("unchecked") |
205 @SuppressWarnings("unchecked") |
253 resolveTimeFields(); |
253 resolveTimeFields(); |
254 |
254 |
255 // if any other fields, handle them |
255 // if any other fields, handle them |
256 // any lenient date resolution should return epoch-day |
256 // any lenient date resolution should return epoch-day |
257 if (fieldValues.size() > 0) { |
257 if (fieldValues.size() > 0) { |
258 boolean changed = false; |
258 int changedCount = 0; |
259 outer: |
259 outer: |
260 while (true) { |
260 while (changedCount < 50) { |
261 for (Map.Entry<TemporalField, Long> entry : fieldValues.entrySet()) { |
261 for (Map.Entry<TemporalField, Long> entry : fieldValues.entrySet()) { |
262 TemporalField targetField = entry.getKey(); |
262 TemporalField targetField = entry.getKey(); |
263 Map<TemporalField, Long> changes = targetField.resolve(this, entry.getValue(), resolverStyle); |
263 ChronoLocalDate resolvedDate = targetField.resolve(fieldValues, chrono, zone, resolverStyle); |
264 if (changes != null) { |
264 if (resolvedDate != null) { |
265 changed = true; |
265 updateCheckConflict(resolvedDate); |
266 resolveFieldsMakeChanges(targetField, changes); |
266 changedCount++; |
267 fieldValues.remove(targetField); // helps avoid infinite loops |
267 continue outer; // have to restart to avoid concurrent modification |
|
268 } else if (fieldValues.containsKey(targetField) == false) { |
|
269 changedCount++; |
268 continue outer; // have to restart to avoid concurrent modification |
270 continue outer; // have to restart to avoid concurrent modification |
269 } |
271 } |
270 } |
272 } |
271 break; |
273 break; |
272 } |
274 } |
|
275 if (changedCount == 50) { // catch infinite loops |
|
276 throw new DateTimeException("One of the parsed fields has an incorrectly implemented resolve method"); |
|
277 } |
273 // if something changed then have to redo ChronoField resolve |
278 // if something changed then have to redo ChronoField resolve |
274 if (changed) { |
279 if (changedCount > 0) { |
275 resolveDateFields(); |
280 resolveDateFields(); |
276 resolveTimeFields(); |
281 resolveTimeFields(); |
277 } |
|
278 } |
|
279 } |
|
280 |
|
281 private void resolveFieldsMakeChanges(TemporalField targetField, Map<TemporalField, Long> changes) { |
|
282 for (Map.Entry<TemporalField, Long> change : changes.entrySet()) { |
|
283 TemporalField changeField = change.getKey(); |
|
284 Long changeValue = change.getValue(); |
|
285 Objects.requireNonNull(changeField, "changeField"); |
|
286 if (changeValue != null) { |
|
287 updateCheckConflict(targetField, changeField, changeValue); |
|
288 } else { |
|
289 fieldValues.remove(changeField); |
|
290 } |
282 } |
291 } |
283 } |
292 } |
284 } |
293 |
285 |
294 private void updateCheckConflict(TemporalField targetField, TemporalField changeField, Long changeValue) { |
286 private void updateCheckConflict(TemporalField targetField, TemporalField changeField, Long changeValue) { |
303 //----------------------------------------------------------------------- |
295 //----------------------------------------------------------------------- |
304 private void resolveDateFields() { |
296 private void resolveDateFields() { |
305 updateCheckConflict(chrono.resolveDate(fieldValues, resolverStyle)); |
297 updateCheckConflict(chrono.resolveDate(fieldValues, resolverStyle)); |
306 } |
298 } |
307 |
299 |
308 private void updateCheckConflict(ChronoLocalDate<?> cld) { |
300 private void updateCheckConflict(ChronoLocalDate cld) { |
309 if (date != null) { |
301 if (date != null) { |
310 if (cld != null && date.equals(cld) == false) { |
302 if (cld != null && date.equals(cld) == false) { |
311 throw new DateTimeException("Conflict found: Fields resolved to two different dates: " + date + " " + cld); |
303 throw new DateTimeException("Conflict found: Fields resolved to two different dates: " + date + " " + cld); |
312 } |
304 } |
313 } else { |
305 } else { |