Browse Source

AbstractDateField.formatDate() to be abstract (#10186)

* AbstractDateField.formatDate to be abstract

Remove invalidDateString paramter, as it can be deduced

* Fix test

* Remove AbstractDateField.getResolutionVariable

VAbstractTextualDate: rename updateDateVariables() to updateBufferedResolutions()

* Revert to use fixed value of MONDAY.

* release notes

* updateAndSendBufferedValues()

* Missed call to updateAndSendBufferedValues();

* release note
tags/8.2.0.alpha3
Ahmed Ashour 6 years ago
parent
commit
3929d0ac6f

+ 2
- 0
all/src/main/templates/release-notes.html View File

@@ -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>

+ 0
- 1
client/src/main/java/com/vaadin/client/DateTimeService.java View File

@@ -602,7 +602,6 @@ public class DateTimeService {
}

return date;

}

private static Logger getLogger() {

+ 9
- 18
client/src/main/java/com/vaadin/client/LocaleService.java View File

@@ -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) {

+ 6
- 14
client/src/main/java/com/vaadin/client/ui/AbstractConnector.java View File

@@ -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();
}

/*

+ 3
- 4
client/src/main/java/com/vaadin/client/ui/VAbstractPopupCalendar.java View File

@@ -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());
}
}

+ 41
- 35
client/src/main/java/com/vaadin/client/ui/VAbstractTextualDate.java View File

@@ -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);
}
}

+ 8
- 15
client/src/main/java/com/vaadin/client/ui/VDateField.java View File

@@ -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
@@ -82,14 +83,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();
}


+ 12
- 11
client/src/main/java/com/vaadin/client/ui/VDateFieldCalendar.java View File

@@ -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

+ 22
- 28
client/src/main/java/com/vaadin/client/ui/VDateTimeFieldCalendar.java View File

@@ -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

+ 23
- 24
client/src/main/java/com/vaadin/client/ui/VPopupCalendar.java View File

@@ -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);

+ 72
- 88
client/src/main/java/com/vaadin/client/ui/VPopupTimeCalendar.java View File

@@ -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);

+ 9
- 10
client/src/main/java/com/vaadin/client/ui/datefield/AbstractDateFieldConnector.java View File

@@ -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")

+ 1
- 1
server/src/main/java/com/vaadin/ui/AbstractComponent.java View File

@@ -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.

+ 54
- 52
server/src/main/java/com/vaadin/ui/AbstractDateField.java View File

@@ -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) {

+ 5
- 0
server/src/test/java/com/vaadin/tests/server/component/datefield/DateFieldListenersTest.java View File

@@ -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

+ 5
- 7
shared/src/main/java/com/vaadin/shared/ui/datefield/AbstractDateFieldServerRpc.java View File

@@ -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.

Loading…
Cancel
Save