diff options
16 files changed, 272 insertions, 308 deletions
diff --git a/all/src/main/templates/release-notes.html b/all/src/main/templates/release-notes.html index f3852f2671..b16ac14949 100644 --- a/all/src/main/templates/release-notes.html +++ b/all/src/main/templates/release-notes.html @@ -124,6 +124,8 @@ <li><tt>SharedState</tt> field <tt>registeredEventListeners</tt> is a <tt>Map</tt> instead of <tt>Set</tt>.</li> <li>The client side <tt>SelectionModel</tt> interface has a new method <tt>isMultiSelectionAllowed</tt>.</li> <li><tt>AbstractDateField</tt> is not a <tt>LegacyComponent</tt> anymore.</li> + <li><tt>AbstractDateField</tt>.<tt>formatDate</tt> is now abstract.</li> + <li><tt>VAbstractTextualDate</tt>.<tt>updateDateVariables()</tt> is now <tt>updateBufferedResolutions()</tt> and <tt>updateAndSendBufferedValues()</tt>.</li> <h2>For incompatible or behavior-altering changes in 8.1, please see <a href="https://vaadin.com/download/release/8.1/8.1.0/release-notes.html#incompatible">8.1 release notes</a></h2> diff --git a/client/src/main/java/com/vaadin/client/DateTimeService.java b/client/src/main/java/com/vaadin/client/DateTimeService.java index 7367d686b6..fb4aaf130d 100644 --- a/client/src/main/java/com/vaadin/client/DateTimeService.java +++ b/client/src/main/java/com/vaadin/client/DateTimeService.java @@ -602,7 +602,6 @@ public class DateTimeService { } return date; - } private static Logger getLogger() { diff --git a/client/src/main/java/com/vaadin/client/LocaleService.java b/client/src/main/java/com/vaadin/client/LocaleService.java index 88d07ee836..39c77d4697 100644 --- a/client/src/main/java/com/vaadin/client/LocaleService.java +++ b/client/src/main/java/com/vaadin/client/LocaleService.java @@ -65,81 +65,72 @@ public class LocaleService { throws LocaleNotLoadedException { if (cache.containsKey(locale)) { return cache.get(locale).monthNames; - } else { - throw new LocaleNotLoadedException(locale); } + throw new LocaleNotLoadedException(locale); } public static String[] getShortMonthNames(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { return cache.get(locale).shortMonthNames; - } else { - throw new LocaleNotLoadedException(locale); } + throw new LocaleNotLoadedException(locale); } public static String[] getDayNames(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { return cache.get(locale).dayNames; - } else { - throw new LocaleNotLoadedException(locale); } + throw new LocaleNotLoadedException(locale); } public static String[] getShortDayNames(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { return cache.get(locale).shortDayNames; - } else { - throw new LocaleNotLoadedException(locale); } + throw new LocaleNotLoadedException(locale); } public static int getFirstDayOfWeek(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { return cache.get(locale).firstDayOfWeek; - } else { - throw new LocaleNotLoadedException(locale); } + throw new LocaleNotLoadedException(locale); } public static String getDateFormat(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { return cache.get(locale).dateFormat; - } else { - throw new LocaleNotLoadedException(locale); } + throw new LocaleNotLoadedException(locale); } public static boolean isTwelveHourClock(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { return cache.get(locale).twelveHourClock; - } else { - throw new LocaleNotLoadedException(locale); } + throw new LocaleNotLoadedException(locale); } public static String getClockDelimiter(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { return cache.get(locale).hourMinuteDelimiter; - } else { - throw new LocaleNotLoadedException(locale); } + throw new LocaleNotLoadedException(locale); } public static String[] getAmPmStrings(String locale) throws LocaleNotLoadedException { if (cache.containsKey(locale)) { return new String[] { cache.get(locale).am, cache.get(locale).pm }; - } else { - throw new LocaleNotLoadedException(locale); } + throw new LocaleNotLoadedException(locale); } public static void addLocales(List<LocaleData> localeDatas) { diff --git a/client/src/main/java/com/vaadin/client/ui/AbstractConnector.java b/client/src/main/java/com/vaadin/client/ui/AbstractConnector.java index 849f977b53..7f58bf35a3 100644 --- a/client/src/main/java/com/vaadin/client/ui/AbstractConnector.java +++ b/client/src/main/java/com/vaadin/client/ui/AbstractConnector.java @@ -336,9 +336,7 @@ public abstract class AbstractConnector OnStateChangeMethod method = propertyMethods.get(j); if (invokedMethods.add(method)) { - method.invoke(stateChangeEvent); - } } } @@ -361,7 +359,6 @@ public abstract class AbstractConnector VConsole.log( "Unregistered connector " + Util.getConnectorString(this)); } - } /** @@ -447,11 +444,7 @@ public abstract class AbstractConnector return false; } - if (getParent() == null) { - return true; - } else { - return getParent().isEnabled(); - } + return getParent() == null || getParent().isEnabled(); } @Override @@ -474,21 +467,20 @@ public abstract class AbstractConnector * Gets the URL for a resource that has been added by the server-side * connector using * {@link com.vaadin.terminal.AbstractClientConnector#setResource(String, com.vaadin.terminal.Resource)} - * with the same key. <code>null</code> is returned if no corresponding - * resource is found. + * with the same key. {@code null} is returned if no corresponding resource + * is found. * * @param key * a string identifying the resource. - * @return the resource URL as a string, or <code>null</code> if no - * corresponding resource is found. + * @return the resource URL as a string, or {@code null} if no corresponding + * resource is found. */ public String getResourceUrl(String key) { URLReference urlReference = getState().resources.get(key); if (urlReference == null) { return null; - } else { - return urlReference.getURL(); } + return urlReference.getURL(); } /* diff --git a/client/src/main/java/com/vaadin/client/ui/VAbstractPopupCalendar.java b/client/src/main/java/com/vaadin/client/ui/VAbstractPopupCalendar.java index 85594484b3..c0f8413530 100644 --- a/client/src/main/java/com/vaadin/client/ui/VAbstractPopupCalendar.java +++ b/client/src/main/java/com/vaadin/client/ui/VAbstractPopupCalendar.java @@ -231,16 +231,15 @@ public abstract class VAbstractPopupCalendar<PANEL extends VAbstractCalendarPane R resolution = getCurrentResolution(); if (currentDate == null || newDate.getTime() != currentDate.getTime()) { setCurrentDate((Date) newDate.clone()); - bufferedResolutions.put( - calendar.getResolution(calendar::isYear).name(), + bufferedResolutions.put(calendar.getResolution(calendar::isYear), newDate.getYear() + 1900); if (!calendar.isYear(resolution)) { bufferedResolutions.put( - calendar.getResolution(calendar::isMonth).name(), + calendar.getResolution(calendar::isMonth), newDate.getMonth() + 1); if (!calendar.isMonth(resolution)) { bufferedResolutions.put( - calendar.getResolution(calendar::isDay).name(), + calendar.getResolution(calendar::isDay), newDate.getDate()); } } diff --git a/client/src/main/java/com/vaadin/client/ui/VAbstractTextualDate.java b/client/src/main/java/com/vaadin/client/ui/VAbstractTextualDate.java index edbc863188..8206f2f862 100644 --- a/client/src/main/java/com/vaadin/client/ui/VAbstractTextualDate.java +++ b/client/src/main/java/com/vaadin/client/ui/VAbstractTextualDate.java @@ -121,16 +121,15 @@ public abstract class VAbstractTextualDate<R extends Enum<R>> protected String createFormatString() { if (isYear(getCurrentResolution())) { return "yyyy"; // force full year - } else { - try { - String frmString = LocaleService.getDateFormat(currentLocale); - return cleanFormat(frmString); - } catch (LocaleNotLoadedException e) { - // TODO should die instead? Can the component survive - // without format string? - VConsole.error(e); - return null; - } + } + try { + String frmString = LocaleService.getDateFormat(currentLocale); + return cleanFormat(frmString); + } catch (LocaleNotLoadedException e) { + // TODO should die instead? Can the component survive + // without format string? + VConsole.error(e); + return null; } } @@ -203,7 +202,7 @@ public abstract class VAbstractTextualDate<R extends Enum<R>> /** * Sets the time zone for the field. - * + * * @param timeZone * the new time zone to use * @since 8.2 @@ -243,8 +242,6 @@ public abstract class VAbstractTextualDate<R extends Enum<R>> VConsole.log(e); addStyleName(getStylePrimaryName() + PARSE_ERROR_CLASSNAME); - // this is a hack that may eventually be removed - bufferedInvalidDateString = true; setDate(null); } } else { @@ -255,28 +252,40 @@ public abstract class VAbstractTextualDate<R extends Enum<R>> // always send the date string bufferedDateString = text.getText(); - updateDateVariables(); + updateAndSendBufferedValues(); + } + + /** + * Updates the {@link VDateField#bufferedResolutions bufferedResolutions}, + * then {@link #sendBufferedValues() sends} the values to the server. + * + * @since + */ + protected final void updateAndSendBufferedValues() { + updateBufferedResolutions(); + sendBufferedValues(); } /** - * Updates variables to send a response to the server. + * Updates {@link VDateField#bufferedResolutions bufferedResolutions} before + * sending a response to the server. * <p> * The method can be overridden by subclasses to provide a custom logic for * date variables to avoid overriding the {@link #onChange(ChangeEvent)} * method. - * + * + * <p> + * Note that this method should not send the buffered values, but use + * {@link #updateAndSendBufferedValues()} instead + * * @since */ - protected void updateDateVariables() { - // Update variables - // (only the smallest defining resolution needs to be - // immediate) + protected void updateBufferedResolutions() { Date currentDate = getDate(); - bufferedResolutions.put( - getResolutions().filter(this::isYear).findFirst().get().name(), - currentDate != null ? currentDate.getYear() + 1900 : null); - if (isYear(getCurrentResolution())) { - sendBufferedValues(); + if (currentDate != null) { + bufferedResolutions.put( + getResolutions().filter(this::isYear).findFirst().get(), + currentDate.getYear() + 1900); } } @@ -432,13 +441,12 @@ public abstract class VAbstractTextualDate<R extends Enum<R>> * @since 8.1 */ public void setISODate(String isoDate) { - if (isoDate == null) { - setDate(null); - } else { - Date date = getIsoFormatter().parse(isoDate); - setDate(date); + Date date = null; + if (isoDate != null) { + date = getIsoFormatter().parse(isoDate); } - updateDateVariables(); + setDate(date); + updateAndSendBufferedValues(); } /** @@ -454,16 +462,14 @@ public abstract class VAbstractTextualDate<R extends Enum<R>> Date date = getDate(); if (date == null) { return null; - } else { - return getIsoFormatter().format(date); } + return getIsoFormatter().format(date); } private DateTimeFormat getIsoFormatter() { if (supportsTime()) { return DateTimeFormat.getFormat(ISO_DATE_TIME_PATTERN); - } else { - return DateTimeFormat.getFormat(ISO_DATE_PATTERN); } + return DateTimeFormat.getFormat(ISO_DATE_PATTERN); } } diff --git a/client/src/main/java/com/vaadin/client/ui/VDateField.java b/client/src/main/java/com/vaadin/client/ui/VDateField.java index 971248cee9..af1b018130 100644 --- a/client/src/main/java/com/vaadin/client/ui/VDateField.java +++ b/client/src/main/java/com/vaadin/client/ui/VDateField.java @@ -20,6 +20,7 @@ import java.util.Date; import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.stream.Collectors; import java.util.stream.Stream; import com.google.gwt.user.client.ui.FlowPanel; @@ -66,13 +67,13 @@ public abstract class VDateField<R extends Enum<R>> extends FlowPanel * A temporary holder of the time units (resolutions), which would be sent * to the server through {@link #sendBufferedValues()}. * - * The key is the resolution name e.g. "HOUR", "MINUTE". + * The key is the resolution. * * The value can be {@code null}. * * @since */ - protected Map<String, Integer> bufferedResolutions = new HashMap<>(); + protected Map<R, Integer> bufferedResolutions = new HashMap<>(); /** * A temporary holder of the date string, which would be sent to the server @@ -83,14 +84,6 @@ public abstract class VDateField<R extends Enum<R>> extends FlowPanel protected String bufferedDateString; /** - * A temporary holder of whether the date string was invalid or not, which - * would be sent to the server through {@link #sendBufferedValues()}. - * - * @since - */ - protected boolean bufferedInvalidDateString; - - /** * The date that is displayed the date field before a value is selected. If * null, display the current date. */ @@ -269,16 +262,16 @@ public abstract class VDateField<R extends Enum<R>> extends FlowPanel } /** - * Sends the {@link #bufferedDateString}, {@link #bufferedInvalidDateString} - * and {@link #bufferedResolutions} to the server, and clears their values. + * Sends the {@link #bufferedDateString} and {@link #bufferedResolutions} to + * the server, and clears their values. * * @since */ public void sendBufferedValues() { - rpc.update(bufferedDateString, bufferedInvalidDateString, - new HashMap<>(bufferedResolutions)); + rpc.update(bufferedDateString, + bufferedResolutions.entrySet().stream().collect(Collectors + .toMap(e -> e.getKey().name(), e -> e.getValue()))); bufferedDateString = null; - bufferedInvalidDateString = false; bufferedResolutions.clear(); } diff --git a/client/src/main/java/com/vaadin/client/ui/VDateFieldCalendar.java b/client/src/main/java/com/vaadin/client/ui/VDateFieldCalendar.java index 69e6d923ce..6e727ee640 100644 --- a/client/src/main/java/com/vaadin/client/ui/VDateFieldCalendar.java +++ b/client/src/main/java/com/vaadin/client/ui/VDateFieldCalendar.java @@ -15,6 +15,10 @@ */ package com.vaadin.client.ui; +import static com.vaadin.shared.ui.datefield.DateResolution.DAY; +import static com.vaadin.shared.ui.datefield.DateResolution.MONTH; +import static com.vaadin.shared.ui.datefield.DateResolution.YEAR; + import java.util.Date; import java.util.Map; @@ -31,7 +35,7 @@ public class VDateFieldCalendar extends VAbstractDateFieldCalendar<VDateCalendarPanel, DateResolution> { public VDateFieldCalendar() { - super(GWT.create(VDateCalendarPanel.class), DateResolution.YEAR); + super(GWT.create(VDateCalendarPanel.class), YEAR); } /** @@ -53,16 +57,14 @@ public class VDateFieldCalendar DateResolution resolution = getCurrentResolution(); if (currentDate == null || date2.getTime() != currentDate.getTime()) { setCurrentDate((Date) date2.clone()); - bufferedResolutions.put(DateResolution.YEAR.name(), + bufferedResolutions.put(YEAR, // Java Date uses the year aligned to 1900 (no to zero). // So we should add 1900 to get a correct year aligned to 0. date2.getYear() + 1900); - if (resolution.compareTo(DateResolution.YEAR) < 0) { - bufferedResolutions.put(DateResolution.MONTH.name(), - date2.getMonth() + 1); - if (resolution.compareTo(DateResolution.MONTH) < 0) { - bufferedResolutions.put(DateResolution.DAY.name(), - date2.getDate()); + if (resolution.compareTo(YEAR) < 0) { + bufferedResolutions.put(MONTH, date2.getMonth() + 1); + if (resolution.compareTo(MONTH) < 0) { + bufferedResolutions.put(DAY, date2.getDate()); } } sendBufferedValues(); @@ -71,8 +73,7 @@ public class VDateFieldCalendar @Override public void setCurrentResolution(DateResolution resolution) { - super.setCurrentResolution( - resolution == null ? DateResolution.YEAR : resolution); + super.setCurrentResolution(resolution == null ? YEAR : resolution); } @Override @@ -82,7 +83,7 @@ public class VDateFieldCalendar @Override public boolean isYear(DateResolution resolution) { - return DateResolution.YEAR.equals(resolution); + return YEAR.equals(resolution); } @Override diff --git a/client/src/main/java/com/vaadin/client/ui/VDateTimeFieldCalendar.java b/client/src/main/java/com/vaadin/client/ui/VDateTimeFieldCalendar.java index 6e74bf45e7..a635b8b615 100644 --- a/client/src/main/java/com/vaadin/client/ui/VDateTimeFieldCalendar.java +++ b/client/src/main/java/com/vaadin/client/ui/VDateTimeFieldCalendar.java @@ -15,6 +15,13 @@ */ package com.vaadin.client.ui; +import static com.vaadin.shared.ui.datefield.DateTimeResolution.DAY; +import static com.vaadin.shared.ui.datefield.DateTimeResolution.HOUR; +import static com.vaadin.shared.ui.datefield.DateTimeResolution.MINUTE; +import static com.vaadin.shared.ui.datefield.DateTimeResolution.MONTH; +import static com.vaadin.shared.ui.datefield.DateTimeResolution.SECOND; +import static com.vaadin.shared.ui.datefield.DateTimeResolution.YEAR; + import java.util.Date; import java.util.Map; @@ -32,8 +39,7 @@ public class VDateTimeFieldCalendar extends VAbstractDateFieldCalendar<VDateTimeCalendarPanel, DateTimeResolution> { public VDateTimeFieldCalendar() { - super(GWT.create(VDateTimeCalendarPanel.class), - DateTimeResolution.MINUTE); + super(GWT.create(VDateTimeCalendarPanel.class), MINUTE); } @Override @@ -49,23 +55,17 @@ public class VDateTimeFieldCalendar extends DateTimeResolution resolution = getCurrentResolution(); if (currentDate == null || date2.getTime() != currentDate.getTime()) { setCurrentDate((Date) date2.clone()); - addBufferedResolution(DateTimeResolution.YEAR, - date2.getYear() + 1900); - if (resolution.compareTo(DateTimeResolution.YEAR) < 0) { - addBufferedResolution(DateTimeResolution.MONTH, - date2.getMonth() + 1); - if (resolution.compareTo(DateTimeResolution.MONTH) < 0) { - addBufferedResolution(DateTimeResolution.DAY, - date2.getDate()); - if (resolution.compareTo(DateTimeResolution.DAY) < 0) { - addBufferedResolution(DateTimeResolution.HOUR, - date2.getHours()); - if (resolution.compareTo(DateTimeResolution.HOUR) < 0) { - addBufferedResolution(DateTimeResolution.MINUTE, - date2.getMinutes()); - if (resolution - .compareTo(DateTimeResolution.MINUTE) < 0) { - addBufferedResolution(DateTimeResolution.SECOND, + bufferedResolutions.put(YEAR, date2.getYear() + 1900); + if (resolution.compareTo(YEAR) < 0) { + bufferedResolutions.put(MONTH, date2.getMonth() + 1); + if (resolution.compareTo(MONTH) < 0) { + bufferedResolutions.put(DAY, date2.getDate()); + if (resolution.compareTo(DAY) < 0) { + bufferedResolutions.put(HOUR, date2.getHours()); + if (resolution.compareTo(HOUR) < 0) { + bufferedResolutions.put(MINUTE, date2.getMinutes()); + if (resolution.compareTo(MINUTE) < 0) { + bufferedResolutions.put(SECOND, date2.getSeconds()); } } @@ -76,23 +76,17 @@ public class VDateTimeFieldCalendar extends } } - private void addBufferedResolution(DateTimeResolution resolution, - Integer value) { - bufferedResolutions.put(resolution.name(), value); - } - @Override public String resolutionAsString() { - if (getCurrentResolution().compareTo(DateTimeResolution.DAY) >= 0) { + if (getCurrentResolution().compareTo(DAY) >= 0) { return getResolutionVariable(getCurrentResolution()); - } else { - return "full"; } + return "full"; } @Override public boolean isYear(DateTimeResolution resolution) { - return DateTimeResolution.YEAR.equals(resolution); + return YEAR.equals(resolution); } @Override diff --git a/client/src/main/java/com/vaadin/client/ui/VPopupCalendar.java b/client/src/main/java/com/vaadin/client/ui/VPopupCalendar.java index 65c47f8c6c..970ccfb71a 100644 --- a/client/src/main/java/com/vaadin/client/ui/VPopupCalendar.java +++ b/client/src/main/java/com/vaadin/client/ui/VPopupCalendar.java @@ -15,6 +15,10 @@ */ package com.vaadin.client.ui; +import static com.vaadin.shared.ui.datefield.DateResolution.DAY; +import static com.vaadin.shared.ui.datefield.DateResolution.MONTH; +import static com.vaadin.shared.ui.datefield.DateResolution.YEAR; + import java.util.Date; import java.util.Map; @@ -32,7 +36,7 @@ public class VPopupCalendar extends VAbstractPopupCalendar<VDateCalendarPanel, DateResolution> { public VPopupCalendar() { - super(GWT.create(VDateCalendarPanel.class), DateResolution.YEAR); + super(GWT.create(VDateCalendarPanel.class), YEAR); } @Override @@ -47,24 +51,23 @@ public class VPopupCalendar @Override public void setCurrentResolution(DateResolution resolution) { - super.setCurrentResolution( - resolution == null ? DateResolution.YEAR : resolution); + super.setCurrentResolution(resolution == null ? YEAR : resolution); } public static Date makeDate(Map<DateResolution, Integer> dateValues) { - if (dateValues.get(DateResolution.YEAR) == null) { + if (dateValues.get(YEAR) == null) { return null; } Date date = new Date(2000 - 1900, 0, 1); - Integer year = dateValues.get(DateResolution.YEAR); + Integer year = dateValues.get(YEAR); if (year != null) { date.setYear(year - 1900); } - Integer month = dateValues.get(DateResolution.MONTH); + Integer month = dateValues.get(MONTH); if (month != null) { date.setMonth(month - 1); } - Integer day = dateValues.get(DateResolution.DAY); + Integer day = dateValues.get(DAY); if (day != null) { date.setDate(day); } @@ -73,7 +76,7 @@ public class VPopupCalendar @Override public boolean isYear(DateResolution resolution) { - return DateResolution.YEAR.equals(resolution); + return YEAR.equals(resolution); } @Override @@ -82,31 +85,27 @@ public class VPopupCalendar } @Override - protected void updateDateVariables() { - super.updateDateVariables(); - DateResolution resolution = getCurrentResolution(); - // Update variables - // (only the smallest defining resolution needs to be - // immediate) + protected void updateBufferedResolutions() { + super.updateBufferedResolutions(); Date currentDate = getDate(); - if (resolution.compareTo(DateResolution.MONTH) <= 0) { - bufferedResolutions.put(DateResolution.MONTH.name(), - currentDate != null ? currentDate.getMonth() + 1 : null); - } - if (resolution.compareTo(DateResolution.DAY) <= 0) { - bufferedResolutions.put(DateResolution.DAY.name(), - currentDate != null ? currentDate.getDate() : null); + if (currentDate != null) { + DateResolution resolution = getCurrentResolution(); + if (resolution.compareTo(MONTH) <= 0) { + bufferedResolutions.put(MONTH, currentDate.getMonth() + 1); + } + if (resolution.compareTo(DAY) <= 0) { + bufferedResolutions.put(DAY, currentDate.getDate()); + } } - sendBufferedValues(); } @Override protected String cleanFormat(String format) { // Remove unnecessary d & M if resolution is too low - if (getCurrentResolution().compareTo(DateResolution.DAY) > 0) { + if (getCurrentResolution().compareTo(DAY) > 0) { format = format.replaceAll("d", ""); } - if (getCurrentResolution().compareTo(DateResolution.MONTH) > 0) { + if (getCurrentResolution().compareTo(MONTH) > 0) { format = format.replaceAll("M", ""); } return super.cleanFormat(format); diff --git a/client/src/main/java/com/vaadin/client/ui/VPopupTimeCalendar.java b/client/src/main/java/com/vaadin/client/ui/VPopupTimeCalendar.java index ff740efbca..39ae704651 100644 --- a/client/src/main/java/com/vaadin/client/ui/VPopupTimeCalendar.java +++ b/client/src/main/java/com/vaadin/client/ui/VPopupTimeCalendar.java @@ -15,6 +15,13 @@ */ package com.vaadin.client.ui; +import static com.vaadin.shared.ui.datefield.DateTimeResolution.DAY; +import static com.vaadin.shared.ui.datefield.DateTimeResolution.HOUR; +import static com.vaadin.shared.ui.datefield.DateTimeResolution.MINUTE; +import static com.vaadin.shared.ui.datefield.DateTimeResolution.MONTH; +import static com.vaadin.shared.ui.datefield.DateTimeResolution.SECOND; +import static com.vaadin.shared.ui.datefield.DateTimeResolution.YEAR; + import java.util.Date; import java.util.Map; @@ -36,8 +43,7 @@ public class VPopupTimeCalendar extends VAbstractPopupCalendar<VDateTimeCalendarPanel, DateTimeResolution> { public VPopupTimeCalendar() { - super(GWT.create(VDateTimeCalendarPanel.class), - DateTimeResolution.MINUTE); + super(GWT.create(VDateTimeCalendarPanel.class), MINUTE); } @Override @@ -47,45 +53,43 @@ public class VPopupTimeCalendar extends @Override public String resolutionAsString() { - if (getCurrentResolution().compareTo(DateTimeResolution.DAY) >= 0) { + if (getCurrentResolution().compareTo(DAY) >= 0) { return getResolutionVariable(getCurrentResolution()); - } else { - return "full"; } + return "full"; } @Override public void setCurrentResolution(DateTimeResolution resolution) { - super.setCurrentResolution( - resolution == null ? DateTimeResolution.MINUTE : resolution); + super.setCurrentResolution(resolution == null ? MINUTE : resolution); } public static Date makeDate(Map<DateTimeResolution, Integer> dateValues) { - if (dateValues.get(DateTimeResolution.YEAR) == null) { + if (dateValues.get(YEAR) == null) { return null; } Date date = new Date(2000 - 1900, 0, 1); - Integer year = dateValues.get(DateTimeResolution.YEAR); + Integer year = dateValues.get(YEAR); if (year != null) { date.setYear(year - 1900); } - Integer month = dateValues.get(DateTimeResolution.MONTH); + Integer month = dateValues.get(MONTH); if (month != null) { date.setMonth(month - 1); } - Integer day = dateValues.get(DateTimeResolution.DAY); + Integer day = dateValues.get(DAY); if (day != null) { date.setDate(day); } - Integer hour = dateValues.get(DateTimeResolution.HOUR); + Integer hour = dateValues.get(HOUR); if (hour != null) { date.setHours(hour); } - Integer minute = dateValues.get(DateTimeResolution.MINUTE); + Integer minute = dateValues.get(MINUTE); if (minute != null) { date.setMinutes(minute); } - Integer second = dateValues.get(DateTimeResolution.SECOND); + Integer second = dateValues.get(SECOND); if (second != null) { date.setSeconds(second); } @@ -94,7 +98,7 @@ public class VPopupTimeCalendar extends @Override public boolean isYear(DateTimeResolution resolution) { - return DateTimeResolution.YEAR.equals(resolution); + return YEAR.equals(resolution); } @Override @@ -103,38 +107,27 @@ public class VPopupTimeCalendar extends } @Override - protected void updateDateVariables() { - super.updateDateVariables(); - DateTimeResolution resolution = getCurrentResolution(); - // (only the smallest defining resolution needs to be - // immediate) + protected void updateBufferedResolutions() { + super.updateBufferedResolutions(); Date currentDate = getDate(); - if (resolution.compareTo(DateTimeResolution.MONTH) <= 0) { - addBufferedResolution(DateTimeResolution.MONTH, - currentDate != null ? currentDate.getMonth() + 1 : null); - } - if (resolution.compareTo(DateTimeResolution.DAY) <= 0) { - addBufferedResolution(DateTimeResolution.DAY, - currentDate != null ? currentDate.getDate() : null); - } - if (resolution.compareTo(DateTimeResolution.HOUR) <= 0) { - addBufferedResolution(DateTimeResolution.HOUR, - currentDate != null ? currentDate.getHours() : null); - } - if (resolution.compareTo(DateTimeResolution.MINUTE) <= 0) { - addBufferedResolution(DateTimeResolution.MINUTE, - currentDate != null ? currentDate.getMinutes() : null); - } - if (resolution.compareTo(DateTimeResolution.SECOND) <= 0) { - addBufferedResolution(DateTimeResolution.SECOND, - currentDate != null ? currentDate.getSeconds() : null); + if (currentDate != null) { + DateTimeResolution resolution = getCurrentResolution(); + if (resolution.compareTo(MONTH) <= 0) { + bufferedResolutions.put(MONTH, currentDate.getMonth() + 1); + } + if (resolution.compareTo(DAY) <= 0) { + bufferedResolutions.put(DAY, currentDate.getDate()); + } + if (resolution.compareTo(HOUR) <= 0) { + bufferedResolutions.put(HOUR, currentDate.getHours()); + } + if (resolution.compareTo(MINUTE) <= 0) { + bufferedResolutions.put(MINUTE, currentDate.getMinutes()); + } + if (resolution.compareTo(SECOND) <= 0) { + bufferedResolutions.put(SECOND, currentDate.getSeconds()); + } } - sendBufferedValues(); - } - - private void addBufferedResolution(DateTimeResolution resolutionToAdd, - Integer value) { - bufferedResolutions.put(resolutionToAdd.name(), value); } @Override @@ -144,16 +137,12 @@ public class VPopupTimeCalendar extends super.updateValue(newDate); DateTimeResolution resolution = getCurrentResolution(); if (currentDate == null || newDate.getTime() != currentDate.getTime()) { - if (resolution.compareTo(DateTimeResolution.DAY) < 0) { - bufferedResolutions.put(DateTimeResolution.HOUR.name(), - newDate.getHours()); - if (resolution.compareTo(DateTimeResolution.HOUR) < 0) { - bufferedResolutions.put(DateTimeResolution.MINUTE.name(), - newDate.getMinutes()); - if (resolution.compareTo(DateTimeResolution.MINUTE) < 0) { - bufferedResolutions.put( - DateTimeResolution.SECOND.name(), - newDate.getSeconds()); + if (resolution.compareTo(DAY) < 0) { + bufferedResolutions.put(HOUR, newDate.getHours()); + if (resolution.compareTo(HOUR) < 0) { + bufferedResolutions.put(MINUTE, newDate.getMinutes()); + if (resolution.compareTo(MINUTE) < 0) { + bufferedResolutions.put(SECOND, newDate.getSeconds()); } } } @@ -164,50 +153,45 @@ public class VPopupTimeCalendar extends protected String createFormatString() { if (isYear(getCurrentResolution())) { return "yyyy"; // force full year - } else { - - try { - String frmString = LocaleService.getDateFormat(currentLocale); - frmString = cleanFormat(frmString); - // String delim = LocaleService - // .getClockDelimiter(currentLocale); - if (getCurrentResolution() - .compareTo(DateTimeResolution.HOUR) <= 0) { - if (dts.isTwelveHourClock()) { - frmString += " hh"; - } else { - frmString += " HH"; - } - if (getCurrentResolution() - .compareTo(DateTimeResolution.MINUTE) <= 0) { - frmString += ":mm"; - if (getCurrentResolution() - .compareTo(DateTimeResolution.SECOND) <= 0) { - frmString += ":ss"; - } - } - if (dts.isTwelveHourClock()) { - frmString += " aaa"; + } + try { + String frmString = LocaleService.getDateFormat(currentLocale); + frmString = cleanFormat(frmString); + // String delim = LocaleService + // .getClockDelimiter(currentLocale); + if (getCurrentResolution().compareTo(HOUR) <= 0) { + if (dts.isTwelveHourClock()) { + frmString += " hh"; + } else { + frmString += " HH"; + } + if (getCurrentResolution().compareTo(MINUTE) <= 0) { + frmString += ":mm"; + if (getCurrentResolution().compareTo(SECOND) <= 0) { + frmString += ":ss"; } } - - return frmString; - } catch (LocaleNotLoadedException e) { - // TODO should die instead? Can the component survive - // without format string? - VConsole.error(e); - return null; + if (dts.isTwelveHourClock()) { + frmString += " aaa"; + } } + + return frmString; + } catch (LocaleNotLoadedException e) { + // TODO should die instead? Can the component survive + // without format string? + VConsole.error(e); + return null; } } @Override protected String cleanFormat(String format) { // Remove unnecessary d & M if resolution is too low - if (getCurrentResolution().compareTo(DateTimeResolution.DAY) > 0) { + if (getCurrentResolution().compareTo(DAY) > 0) { format = format.replaceAll("d", ""); } - if (getCurrentResolution().compareTo(DateTimeResolution.MONTH) > 0) { + if (getCurrentResolution().compareTo(MONTH) > 0) { format = format.replaceAll("M", ""); } return super.cleanFormat(format); diff --git a/client/src/main/java/com/vaadin/client/ui/datefield/AbstractDateFieldConnector.java b/client/src/main/java/com/vaadin/client/ui/datefield/AbstractDateFieldConnector.java index 2aad416343..b7849938af 100644 --- a/client/src/main/java/com/vaadin/client/ui/datefield/AbstractDateFieldConnector.java +++ b/client/src/main/java/com/vaadin/client/ui/datefield/AbstractDateFieldConnector.java @@ -54,10 +54,9 @@ public abstract class AbstractDateFieldConnector<R extends Enum<R>> Stream<R> resolutions = widget.getResolutions(); R resolution = widget.getCurrentResolution(); return resolutions.collect(Collectors.toMap(Function.identity(), - res -> res == null ? null - : (resolution.compareTo(res) <= 0) - ? stateResolutions.get(res.name()) - : null)); + res -> resolution.compareTo(res) <= 0 + ? stateResolutions.get(res.name()) + : null)); } /** @@ -68,14 +67,14 @@ public abstract class AbstractDateFieldConnector<R extends Enum<R>> * @since */ protected Map<R, Integer> getDefaultValues() { + VDateField<R> widget = getWidget(); Map<String, Integer> stateResolutions = getState().resolutions; - Stream<R> resolutions = getWidget().getResolutions(); - R resolution = getWidget().getCurrentResolution(); + Stream<R> resolutions = widget.getResolutions(); + R resolution = widget.getCurrentResolution(); return resolutions.collect(Collectors.toMap(Function.identity(), - res -> res == null ? null - : (resolution.compareTo(res) <= 0) - ? stateResolutions.get("default-" + res.name()) - : null)); + res -> resolution.compareTo(res) <= 0 + ? stateResolutions.get("default-" + res.name()) + : null)); } @SuppressWarnings("unchecked") diff --git a/server/src/main/java/com/vaadin/ui/AbstractComponent.java b/server/src/main/java/com/vaadin/ui/AbstractComponent.java index 88b42d5757..7a87230125 100644 --- a/server/src/main/java/com/vaadin/ui/AbstractComponent.java +++ b/server/src/main/java/com/vaadin/ui/AbstractComponent.java @@ -91,7 +91,7 @@ public abstract class AbstractComponent extends AbstractClientConnector /** * The internal error message of the component. */ - private ErrorMessage componentError = null; + private ErrorMessage componentError; /** * Locale of this component. diff --git a/server/src/main/java/com/vaadin/ui/AbstractDateField.java b/server/src/main/java/com/vaadin/ui/AbstractDateField.java index 67067bd070..965c2f652a 100644 --- a/server/src/main/java/com/vaadin/ui/AbstractDateField.java +++ b/server/src/main/java/com/vaadin/ui/AbstractDateField.java @@ -77,10 +77,9 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & private AbstractDateFieldServerRpc rpc = new AbstractDateFieldServerRpc() { @Override - public void update(String newDateString, boolean invalidDateString, + public void update(String newDateString, Map<String, Integer> resolutions) { - Set<String> resolutionNames = getResolutions() - .map(AbstractDateField.this::getResolutionVariable) + Set<String> resolutionNames = getResolutions().map(Enum::name) .collect(Collectors.toSet()); resolutionNames.retainAll(resolutions.keySet()); if (!isReadOnly() @@ -109,7 +108,8 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & if (newDateString == null || newDateString.isEmpty()) { setValue(newDate, true); } else { - if (invalidDateString) { + // invalid date string + if (resolutions.isEmpty()) { Result<T> parsedDate = handleUnparsableDateString( dateString); parsedDate.ifOk(v -> setValue(v, true)); @@ -173,7 +173,7 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & /* Constructors */ /** - * Constructs an empty <code>AbstractDateField</code> with no caption and + * Constructs an empty {@code AbstractDateField} with no caption and * specified {@code resolution}. * * @param resolution @@ -185,10 +185,10 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & } /** - * Constructs an empty <code>AbstractDateField</code> with caption. + * Constructs an empty {@code AbstractDateField} with caption. * * @param caption - * the caption of the datefield. + * the caption of the datefield * @param resolution * initial resolution for the field, not {@code null} */ @@ -198,11 +198,11 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & } /** - * Constructs a new <code>AbstractDateField</code> with the given caption - * and initial text contents. + * Constructs a new {@code AbstractDateField} with the given caption and + * initial text contents. * * @param caption - * the caption <code>String</code> for the editor. + * the caption {@code String} for the editor. * @param value * the date/time value. * @param resolution @@ -227,24 +227,31 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & * Construct a date object from the individual field values received from * the client. * + * @param resolutions + * map of time unit (resolution) name and value, the key is the + * resolution name e.g. "HOUR", "MINUTE", the value can be + * {@code null} + * @param oldDate + * used as a fallback to get needed values if they are not + * defined in the specified {@code resolutions} + * + * @return the date object built from the specified resolutions * @since */ - protected T reconstructDateFromFields(Map<String, Integer> variables, + protected T reconstructDateFromFields(Map<String, Integer> resolutions, T oldDate) { Map<R, Integer> calendarFields = new HashMap<>(); for (R resolution : getResolutionsHigherOrEqualTo(getResolution())) { // Only handle what the client is allowed to send. The same // resolutions that are painted - String variableName = getResolutionVariable(resolution); + String resolutionName = resolution.name(); - Integer newValue = variables.get(variableName); - if (newValue != null) { - calendarFields.put(resolution, newValue); - } else { - calendarFields.put(resolution, - getDatePart(oldDate, resolution)); + Integer newValue = resolutions.get(resolutionName); + if (newValue == null) { + newValue = getDatePart(oldDate, resolution); } + calendarFields.put(resolution, newValue); } return buildDate(calendarFields); } @@ -252,8 +259,8 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & /** * Sets the start range for this component. If the value is set before this * date (taking the resolution into account), the component will not - * validate. If <code>startDate</code> is set to <code>null</code>, any - * value before <code>endDate</code> will be accepted by the range + * validate. If {@code startDate} is set to {@code null}, any value before + * {@code endDate} will be accepted by the range * * @param startDate * - the allowed range's start date @@ -315,12 +322,12 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & /** * Sets the end range for this component. If the value is set after this * date (taking the resolution into account), the component will not - * validate. If <code>endDate</code> is set to <code>null</code>, any value - * after <code>startDate</code> will be accepted by the range. + * validate. If {@code endDate} is set to {@code null}, any value after + * {@code startDate} will be accepted by the range. * * @param endDate - * - the allowed range's end date (inclusive, based on the - * current resolution) + * the allowed range's end date (inclusive, based on the current + * resolution) */ public void setRangeEnd(T endDate) { Date date = convertToDate(endDate); @@ -336,7 +343,7 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & /** * Returns the precise rangeStart used. * - * @return the precise rangeStart used, may be null. + * @return the precise rangeStart used, may be {@code null}. */ public T getRangeStart() { return convertFromDate(getState(false).rangeStart); @@ -345,7 +352,7 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & /** * Returns the precise rangeEnd used. * - * @return the precise rangeEnd used, may be null. + * @return the precise rangeEnd used, may be {@code null}. */ public T getRangeEnd() { return convertFromDate(getState(false).rangeEnd); @@ -423,14 +430,14 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & // Only paint variables for the resolution and up, e.g. Resolution DAY // paints DAY,MONTH,YEAR - for (R res : getResolutionsHigherOrEqualTo(getResolution())) { - String variableName = getResolutionVariable(res); + for (R resolution : getResolutionsHigherOrEqualTo(getResolution())) { + String resolutionName = resolution.name(); - Integer value = getValuePart(currentDate, res); - resolutions.put(variableName, value); + Integer value = getValuePart(currentDate, resolution); + resolutions.put(resolutionName, value); - Integer defaultValuePart = getValuePart(defaultValue, res); - resolutions.put("default-" + variableName, defaultValuePart); + Integer defaultValuePart = getValuePart(defaultValue, resolution); + resolutions.put("default-" + resolutionName, defaultValuePart); } } @@ -501,6 +508,7 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & * default value is set, current date/time is used. * * @param defaultValue + * the default value, may be {@code null} * @since 8.1.2 */ public void setDefaultValue(T defaultValue) { @@ -581,9 +589,11 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & * {@link #handleUnparsableDateString(String)} method is overridden, the * localized message from its exception is used. * + * @param parsingErrorMessage + * the default parsing error message + * * @see #getParseErrorMessage() * @see #handleUnparsableDateString(String) - * @param parsingErrorMessage */ public void setParseErrorMessage(String parsingErrorMessage) { defaultParseErrorMessage = parsingErrorMessage; @@ -628,8 +638,7 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & } /** - * Formats date according to the components locale. To be reimplemented in - * subclasses. + * Formats date according to the components locale. * * @param value * the date or {@code null} @@ -637,9 +646,7 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & * {@code null} * @since 8.1.1 */ - protected String formatDate(T value) { - return Objects.toString(value, ""); - } + protected abstract String formatDate(T value); @Override public void writeDesign(Element design, DesignContext designContext) { @@ -684,11 +691,10 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & this.value = value; // Also set the internal dateString - if (value != null) { - dateString = formatDate(value); - } else { - dateString = formatDate(getEmptyValue()); + if (value == null) { + value = getEmptyValue(); } + dateString = formatDate(value); RangeValidator<T> validator = getRangeValidator();// TODO move range // check to internal // validator? @@ -717,9 +723,10 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & * given {@code resolution}. * * @param date - * the given date + * the given date, can be {@code null} * @param resolution - * the resolution to extract a value from the date by + * the resolution to extract a value from the date by, not + * {@code null} * @return the integer value part of the date by the given resolution */ protected abstract int getDatePart(T date, R resolution); @@ -764,10 +771,6 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & */ protected abstract Date convertToDate(T date); - private String getResolutionVariable(R resolution) { - return resolution.name(); - } - @SuppressWarnings("unchecked") private Stream<R> getResolutions() { Type resolutionType = GenericTypeReflector.getTypeParameter(getClass(), @@ -776,11 +779,10 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & Class<?> clazz = (Class<?>) resolutionType; return Stream.of(clazz.getEnumConstants()) .map(object -> (R) object); - } else { - throw new RuntimeException("Cannot detect resoluton type " - + Optional.ofNullable(resolutionType).map(Type::getTypeName) - .orElse(null)); } + throw new RuntimeException("Cannot detect resoluton type " + + Optional.ofNullable(resolutionType).map(Type::getTypeName) + .orElse(null)); } private Iterable<R> getResolutionsHigherOrEqualTo(R resoution) { diff --git a/server/src/test/java/com/vaadin/tests/server/component/datefield/DateFieldListenersTest.java b/server/src/test/java/com/vaadin/tests/server/component/datefield/DateFieldListenersTest.java index 4edc2a30df..eea1e33137 100644 --- a/server/src/test/java/com/vaadin/tests/server/component/datefield/DateFieldListenersTest.java +++ b/server/src/test/java/com/vaadin/tests/server/component/datefield/DateFieldListenersTest.java @@ -50,6 +50,11 @@ public class DateFieldListenersTest extends AbstractListenerMethodsTestBase { protected Date convertToDate(LocalDateTime date) { return null; } + + @Override + protected String formatDate(LocalDateTime value) { + return null; + } } @Test diff --git a/shared/src/main/java/com/vaadin/shared/ui/datefield/AbstractDateFieldServerRpc.java b/shared/src/main/java/com/vaadin/shared/ui/datefield/AbstractDateFieldServerRpc.java index 2ef8993fb6..cdd8e30815 100644 --- a/shared/src/main/java/com/vaadin/shared/ui/datefield/AbstractDateFieldServerRpc.java +++ b/shared/src/main/java/com/vaadin/shared/ui/datefield/AbstractDateFieldServerRpc.java @@ -33,15 +33,13 @@ public interface AbstractDateFieldServerRpc extends ServerRpc { * the value of the text field part. It enables analyzing invalid * input on the server. {@code null} if the date was chosen with * popup calendar or contains user-typed string - * @param invalidDateString - * Whether the last date string is invalid or not * @param resolutions - * map of time unit (resolution) name and value, name is the - * lower-case resolution name e.g. "hour", "minute", and value - * can be {@code null} + * map of time unit (resolution) name and value, the key is the + * resolution name e.g. "HOUR", "MINUTE", the value can be + * {@code null}. If the map is empty, that means the + * {@code newDateString} is invalid */ - void update(String newDateString, boolean invalidDateString, - Map<String, Integer> resolutions); + void update(String newDateString, Map<String, Integer> resolutions); /** * Indicates to the server that the client-side has lost focus. |