diff options
author | Denis <denis@vaadin.com> | 2017-01-10 12:22:34 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-10 12:22:34 +0200 |
commit | 3ef30789d6ac773eed7346dcaa670426fa6f662c (patch) | |
tree | 2e5aee20b96e3a66088aa6cde13796256ec2bcf1 /server | |
parent | b4af93bebf1b7e51d33330c42e3c89d5e3e4fd45 (diff) | |
download | vaadin-framework-3ef30789d6ac773eed7346dcaa670426fa6f662c.tar.gz vaadin-framework-3ef30789d6ac773eed7346dcaa670426fa6f662c.zip |
Refactor AbstractDateField. (#8146)
First round for #8132.
Diffstat (limited to 'server')
13 files changed, 448 insertions, 159 deletions
diff --git a/server/src/main/java/com/vaadin/ui/AbstractComponent.java b/server/src/main/java/com/vaadin/ui/AbstractComponent.java index 88bdc6f3dc..03a7c14eb5 100644 --- a/server/src/main/java/com/vaadin/ui/AbstractComponent.java +++ b/server/src/main/java/com/vaadin/ui/AbstractComponent.java @@ -1223,9 +1223,10 @@ public abstract class AbstractComponent extends AbstractClientConnector /** * Returns a collection of attributes that should not be handled by the - * basic implementation of the {@link #readDesign(Element, DesignContext)} and {@link #writeDesign(Element, DesignContext)} - * methods. Typically these are handled in a custom way in the overridden - * versions of the above methods + * basic implementation of the {@link #readDesign(Element, DesignContext)} + * and {@link #writeDesign(Element, DesignContext)} methods. Typically these + * are handled in a custom way in the overridden versions of the above + * methods * * @since 7.4 * diff --git a/server/src/main/java/com/vaadin/ui/AbstractDateField.java b/server/src/main/java/com/vaadin/ui/AbstractDateField.java index 53415f45a6..0a6cf8fc51 100644 --- a/server/src/main/java/com/vaadin/ui/AbstractDateField.java +++ b/server/src/main/java/com/vaadin/ui/AbstractDateField.java @@ -15,24 +15,31 @@ */ package com.vaadin.ui; +import java.io.Serializable; +import java.lang.reflect.Type; import java.text.SimpleDateFormat; -import java.time.Instant; import java.time.LocalDate; -import java.time.ZoneOffset; +import java.time.temporal.Temporal; +import java.time.temporal.TemporalAdjuster; import java.util.Calendar; import java.util.Date; import java.util.EventObject; import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.logging.Logger; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.jsoup.nodes.Element; +import com.googlecode.gentyref.GenericTypeReflector; import com.vaadin.data.Result; import com.vaadin.data.ValidationResult; import com.vaadin.data.ValueContext; -import com.vaadin.data.validator.DateRangeValidator; +import com.vaadin.data.validator.RangeValidator; import com.vaadin.event.FieldEvents.BlurEvent; import com.vaadin.event.FieldEvents.BlurListener; import com.vaadin.event.FieldEvents.BlurNotifier; @@ -43,9 +50,9 @@ import com.vaadin.server.PaintException; import com.vaadin.server.PaintTarget; import com.vaadin.server.UserError; import com.vaadin.shared.Registration; +import com.vaadin.shared.ui.datefield.AbstractDateFieldState; import com.vaadin.shared.ui.datefield.DateFieldConstants; -import com.vaadin.shared.ui.datefield.Resolution; -import com.vaadin.shared.ui.datefield.TextualDateFieldState; +import com.vaadin.shared.ui.datefield.DateResolution; import com.vaadin.ui.declarative.DesignAttributeHandler; import com.vaadin.ui.declarative.DesignContext; @@ -55,20 +62,26 @@ import com.vaadin.ui.declarative.DesignContext; * @author Vaadin Ltd * * @since 8.0 - * + * + * @param <T> + * type of date ({@code LocalDate} or {@code LocalDateTime}). + * @param <R> + * resolution enumeration type + * */ -public abstract class AbstractDateField extends AbstractField<LocalDate> +public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & Serializable & Comparable<? super T>, R extends Enum<R>> + extends AbstractField<T> implements LegacyComponent, FocusNotifier, BlurNotifier { /** * Value of the field. */ - private LocalDate value; + private T value; /** * Specified smallest modifiable unit for the date field. */ - private Resolution resolution = Resolution.DAY; + private R resolution; /** * Overridden format string @@ -94,8 +107,6 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> private String defaultParseErrorMessage = "Date format not recognized"; - private static Map<Resolution, String> variableNameForResolution = new HashMap<>(); - private String dateOutOfRangeMessage = "Date is out of allowed range"; /** @@ -105,42 +116,46 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> */ private boolean preventValueChangeEvent; - static { - variableNameForResolution.put(Resolution.DAY, "day"); - variableNameForResolution.put(Resolution.MONTH, "month"); - variableNameForResolution.put(Resolution.YEAR, "year"); - } - /* Constructors */ /** - * Constructs an empty <code>DateField</code> with no caption. + * Constructs an empty <code>AbstractDateField</code> with no caption and + * specified {@code resolution}. + * + * @param resolution + * initial resolution for the field */ - public AbstractDateField() { + public AbstractDateField(R resolution) { + this.resolution = resolution; } /** - * Constructs an empty <code>DateField</code> with caption. + * Constructs an empty <code>AbstractDateField</code> with caption. * * @param caption * the caption of the datefield. + * @param resolution + * initial resolution for the field */ - public AbstractDateField(String caption) { + public AbstractDateField(String caption, R resolution) { + this(resolution); setCaption(caption); } /** - * Constructs a new <code>DateField</code> with the given caption and - * initial text contents. + * Constructs a new <code>AbstractDateField</code> with the given caption + * and initial text contents. * * @param caption * the caption <code>String</code> for the editor. * @param value - * the LocalDate value. + * the date/time value. + * @param resolution + * initial resolution for the field */ - public AbstractDateField(String caption, LocalDate value) { + public AbstractDateField(String caption, T value, R resolution) { + this(caption, resolution); setValue(value); - setCaption(caption); } /* Component basic features */ @@ -174,17 +189,16 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> * app or refresh. */ - final LocalDate currentDate = getValue(); + final T currentDate = getValue(); // Only paint variables for the resolution and up, e.g. Resolution DAY // paints DAY,MONTH,YEAR - for (Resolution res : Resolution - .getResolutionsHigherOrEqualTo(resolution)) { + for (R res : getResolutionsHigherOrEqualTo(getResolution())) { int value = -1; if (currentDate != null) { - value = getDateValue(currentDate, res); + value = getDatePart(currentDate, res); } - target.addVariable(this, variableNameForResolution.get(res), value); + target.addVariable(this, getResolutionVariable(res), value); } } @@ -195,15 +209,15 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> */ @Override public void changeVariables(Object source, Map<String, Object> variables) { - - if (!isReadOnly() && (variables.containsKey("year") - || variables.containsKey("month") - || variables.containsKey("day") + Set<String> resolutionNames = getResolutions() + .map(this::getResolutionVariable).collect(Collectors.toSet()); + resolutionNames.retainAll(variables.keySet()); + if (!isReadOnly() && (!resolutionNames.isEmpty() || variables.containsKey("dateString"))) { // Old and new dates - final LocalDate oldDate = getValue(); - LocalDate newDate = null; + final T oldDate = getValue(); + T newDate = null; // this enables analyzing invalid input on the server final String newDateString = (String) variables.get("dateString"); @@ -211,15 +225,15 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> // Gets the new date in parts boolean hasChanges = false; - Map<Resolution, Integer> calendarFields = new HashMap<>(); + Map<R, Integer> calendarFields = new HashMap<>(); - for (Resolution resolution : Resolution - .getResolutionsHigherOrEqualTo(getResolution())) { + for (R resolution : getResolutionsHigherOrEqualTo( + getResolution())) { // Only handle what the client is allowed to send. The same // resolutions that are painted - String variableName = variableNameForResolution.get(resolution); + String variableName = getResolutionVariable(resolution); - Integer value = getDateValue(oldDate, resolution); + int value = getDatePart(oldDate, resolution); if (variables.containsKey(variableName)) { Integer newValue = (Integer) variables.get(variableName); if (newValue >= 0) { @@ -234,15 +248,12 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> if (!hasChanges) { newDate = null; } else { - newDate = LocalDate.of(calendarFields.get(Resolution.YEAR), - calendarFields.getOrDefault(Resolution.MONTH, 1), - calendarFields.getOrDefault(Resolution.DAY, 1)); + newDate = buildDate(calendarFields); } if (newDate == null && dateString != null && !dateString.isEmpty()) { - Result<LocalDate> parsedDate = handleUnparsableDateString( - dateString); + Result<T> parsedDate = handleUnparsableDateString(dateString); if (parsedDate.isError()) { /* @@ -332,8 +343,8 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> * @param startDate * - the allowed range's start date */ - public void setRangeStart(LocalDate startDate) { - Date date = convertLocalDate(startDate); + public void setRangeStart(T startDate) { + Date date = convertToDate(startDate); if (date != null && getState().rangeEnd != null && date.after(getState().rangeEnd)) { throw new IllegalStateException( @@ -367,21 +378,21 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> /** * Gets the resolution. * - * @return int + * @return the date/time field resolution */ - public Resolution getResolution() { + public R getResolution() { return resolution; } /** * Sets the resolution of the DateField. * - * The default resolution is {@link Resolution#DAY} since Vaadin 7.0. + * The default resolution is {@link DateResolution#DAY} since Vaadin 7.0. * * @param resolution - * the resolution to set. + * the resolution to set, not {@code null} */ - public void setResolution(Resolution resolution) { + public void setResolution(R resolution) { this.resolution = resolution; markAsDirty(); } @@ -396,8 +407,8 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> * - the allowed range's end date (inclusive, based on the * current resolution) */ - public void setRangeEnd(LocalDate endDate) { - Date date = convertLocalDate(endDate); + public void setRangeEnd(T endDate) { + Date date = convertToDate(endDate); if (date != null && getState().rangeStart != null && getState().rangeStart.after(date)) { throw new IllegalStateException( @@ -412,8 +423,8 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> * * @return the precise rangeStart used, may be null. */ - public LocalDate getRangeStart() { - return convertDate(getState(false).rangeStart); + public T getRangeStart() { + return convertFromDate(getState(false).rangeStart); } /** @@ -421,8 +432,8 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> * * @return the precise rangeEnd used, may be null. */ - public LocalDate getRangeEnd() { - return convertDate(getState(false).rangeEnd); + public T getRangeEnd() { + return convertFromDate(getState(false).rangeEnd); } /** @@ -482,7 +493,7 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> } @Override - public LocalDate getValue() { + public T getValue() { return value; } @@ -494,7 +505,7 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> * the new value, may be {@code null} */ @Override - public void setValue(LocalDate value) { + public void setValue(T value) { /* * First handle special case when the client side component have a date * string but value is null (e.g. unparsable date string typed in by the @@ -580,17 +591,28 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> } @Override + @SuppressWarnings("unchecked") public void readDesign(Element design, DesignContext designContext) { super.readDesign(design, designContext); if (design.hasAttr("value") && !design.attr("value").isEmpty()) { - LocalDate date = DesignAttributeHandler.getFormatter() - .parse(design.attr("value"), LocalDate.class); - // formatting will return null if it cannot parse the string - if (date == null) { - Logger.getLogger(AbstractDateField.class.getName()).info( - "cannot parse " + design.attr("value") + " as date"); + Type dateType = GenericTypeReflector.getTypeParameter(getClass(), + AbstractDateField.class.getTypeParameters()[0]); + if (dateType instanceof Class<?>) { + Class<?> clazz = (Class<?>) dateType; + T date = (T) DesignAttributeHandler.getFormatter() + .parse(design.attr("value"), clazz); + // formatting will return null if it cannot parse the string + if (date == null) { + Logger.getLogger(AbstractDateField.class.getName()) + .info("cannot parse " + design.attr("value") + + " as date"); + } + doSetValue(date); + } else { + throw new RuntimeException("Cannot detect resoluton type " + + Optional.ofNullable(dateType).map(Type::getTypeName) + .orElse(null)); } - doSetValue(date); } } @@ -629,22 +651,22 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> * date string to handle * @return result that contains parsed Date as a value or an error */ - protected Result<LocalDate> handleUnparsableDateString(String dateString) { + protected Result<T> handleUnparsableDateString(String dateString) { return Result.error(getParseErrorMessage()); } @Override - protected TextualDateFieldState getState() { - return (TextualDateFieldState) super.getState(); + protected AbstractDateFieldState getState() { + return (AbstractDateFieldState) super.getState(); } @Override - protected TextualDateFieldState getState(boolean markAsDirty) { - return (TextualDateFieldState) super.getState(markAsDirty); + protected AbstractDateFieldState getState(boolean markAsDirty) { + return (AbstractDateFieldState) super.getState(markAsDirty); } @Override - protected void doSetValue(LocalDate value) { + protected void doSetValue(T value) { // Also set the internal dateString if (value != null) { dateString = value.toString(); @@ -659,10 +681,7 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> uiHasValidDateString = true; setComponentError(new UserError(currentParseErrorMessage)); } else { - DateRangeValidator validator = new DateRangeValidator( - getDateOutOfRangeMessage(), - getDate(getRangeStart(), getResolution()), - getDate(getRangeEnd(), getResolution())); + RangeValidator<T> validator = getRangeValidator(); ValidationResult result = validator.apply(value, new ValueContext(this)); if (result.isError()) { @@ -671,50 +690,80 @@ public abstract class AbstractDateField extends AbstractField<LocalDate> } } - private LocalDate getDate(LocalDate date, Resolution forResolution) { - if (date == null) { - return null; - } - if (forResolution == Resolution.YEAR) { - return date.withDayOfYear(1); - } else if (forResolution == Resolution.MONTH) { - return date.withDayOfMonth(1); - } else { - return date; - } - } + /** + * Returns a date integer value part for the given {@code date} for the + * given {@code resolution}. + * + * @param date + * the given date + * @param resolution + * the resolution to extract a value from the date by + * @return the integer value part of the date by the given resolution + */ + protected abstract int getDatePart(T date, R resolution); - private int getDateValue(LocalDate date, Resolution resolution) { - LocalDate value = date; - if (value == null) { - value = LocalDate.of(1, 1, 1); - } - switch (resolution) { - case DAY: - return value.getDayOfMonth(); - case MONTH: - return value.getMonthValue(); - case YEAR: - return value.getYear(); - default: - assert false : "Unexpected resolution argument " + resolution; - return -1; - } + /** + * Builds date by the given {@code resolutionValues} which is a map whose + * keys are resolution and integer values. + * <p> + * This is the opposite to {@link #getDatePart(Temporal, Enum)}. + * + * @param resolutionValues + * date values to construct a date + * @return date built from the given map of date values + */ + protected abstract T buildDate(Map<R, Integer> resolutionValues); + + /** + * Returns a custom date range validator which is applicable for the type + * {@code T}. + * + * @return the date range validator + */ + protected abstract RangeValidator<T> getRangeValidator(); + + /** + * Converts {@link Date} to date type {@code T}. + * + * @param date + * a date to convert + * @return object of type {@code T} representing the {@code date} + */ + protected abstract T convertFromDate(Date date); + + /** + * Converts the object of type {@code T} to {@link Date}. + * <p> + * This is the opposite to {@link #convertFromDate(Date)}. + * + * @param date + * the date of type {@code T} + * @return converted date of type {@code Date} + */ + protected abstract Date convertToDate(T date); + + private String getResolutionVariable(R resolution) { + return resolution.name().toLowerCase(Locale.ENGLISH); } - private Date convertLocalDate(LocalDate date) { - if (date == null) { - return null; + @SuppressWarnings("unchecked") + private Stream<R> getResolutions() { + Type resolutionType = GenericTypeReflector.getTypeParameter(getClass(), + AbstractDateField.class.getTypeParameters()[1]); + if (resolutionType instanceof Class<?>) { + 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)); } - return Date.from(date.atStartOfDay(ZoneOffset.UTC).toInstant()); } - private LocalDate convertDate(Date date) { - if (date == null) { - return null; - } - return Instant.ofEpochMilli(date.getTime()).atZone(ZoneOffset.UTC) - .toLocalDate(); + private Iterable<R> getResolutionsHigherOrEqualTo(R resoution) { + return getResolutions().skip(resolution.ordinal()) + .collect(Collectors.toList()); } } diff --git a/server/src/main/java/com/vaadin/ui/AbstractLocalDateField.java b/server/src/main/java/com/vaadin/ui/AbstractLocalDateField.java new file mode 100644 index 0000000000..ab99fe0f28 --- /dev/null +++ b/server/src/main/java/com/vaadin/ui/AbstractLocalDateField.java @@ -0,0 +1,139 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.ui; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneOffset; +import java.util.Date; +import java.util.Map; + +import com.vaadin.data.validator.DateRangeValidator; +import com.vaadin.data.validator.RangeValidator; +import com.vaadin.shared.ui.datefield.AbstractTextualDateFieldState; +import com.vaadin.shared.ui.datefield.DateResolution; + +/** + * @author Vaadin Ltd + * + */ +public abstract class AbstractLocalDateField + extends AbstractDateField<LocalDate, DateResolution> { + + /** + * Constructs an empty <code>AbstractLocalDateField</code> with no caption. + */ + public AbstractLocalDateField() { + super(DateResolution.DAY); + } + + /** + * Constructs an empty <code>AbstractLocalDateField</code> with caption. + * + * @param caption + * the caption of the datefield. + */ + public AbstractLocalDateField(String caption) { + super(caption, DateResolution.DAY); + } + + /** + * Constructs a new <code>AbstractLocalDateField</code> with the given + * caption and initial text contents. + * + * @param caption + * the caption <code>String</code> for the editor. + * @param value + * the LocalDate value. + */ + public AbstractLocalDateField(String caption, LocalDate value) { + super(caption, value, DateResolution.DAY); + } + + @Override + protected int getDatePart(LocalDate date, DateResolution resolution) { + LocalDate value = date; + if (value == null) { + value = LocalDate.of(1, 1, 1); + } + switch (resolution) { + case DAY: + return value.getDayOfMonth(); + case MONTH: + return value.getMonthValue(); + case YEAR: + return value.getYear(); + default: + assert false : "Unexpected resolution argument " + resolution; + return -1; + } + } + + @Override + protected LocalDate buildDate( + Map<DateResolution, Integer> resolutionValues) { + return LocalDate.of(resolutionValues.get(DateResolution.YEAR), + resolutionValues.getOrDefault(DateResolution.MONTH, 1), + resolutionValues.getOrDefault(DateResolution.DAY, 1)); + } + + @Override + protected RangeValidator<LocalDate> getRangeValidator() { + return new DateRangeValidator(getDateOutOfRangeMessage(), + getDate(getRangeStart(), getResolution()), + getDate(getRangeEnd(), getResolution())); + } + + @Override + protected AbstractTextualDateFieldState getState() { + return (AbstractTextualDateFieldState) super.getState(); + } + + @Override + protected AbstractTextualDateFieldState getState(boolean markAsDirty) { + return (AbstractTextualDateFieldState) super.getState(markAsDirty); + } + + @Override + protected LocalDate convertFromDate(Date date) { + if (date == null) { + return null; + } + return Instant.ofEpochMilli(date.getTime()).atZone(ZoneOffset.UTC) + .toLocalDate(); + } + + @Override + protected Date convertToDate(LocalDate date) { + if (date == null) { + return null; + } + return Date.from(date.atStartOfDay(ZoneOffset.UTC).toInstant()); + } + + private LocalDate getDate(LocalDate date, DateResolution forResolution) { + if (date == null) { + return null; + } + if (forResolution == DateResolution.YEAR) { + return date.withDayOfYear(1); + } else if (forResolution == DateResolution.MONTH) { + return date.withDayOfMonth(1); + } else { + return date; + } + } +} diff --git a/server/src/main/java/com/vaadin/ui/AbstractLocalDateTimeField.java b/server/src/main/java/com/vaadin/ui/AbstractLocalDateTimeField.java new file mode 100644 index 0000000000..9be77444c6 --- /dev/null +++ b/server/src/main/java/com/vaadin/ui/AbstractLocalDateTimeField.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.ui; + +import java.time.LocalDateTime; + +import com.vaadin.shared.ui.datefield.DateTimeResolution; +import com.vaadin.shared.ui.datefield.LocalDateTimeFieldState; + +/** + * @author Vaadin Ltd + * + */ +public abstract class AbstractLocalDateTimeField + extends AbstractDateField<LocalDateTime, DateTimeResolution> { + + /** + * Constructs an empty <code>AbstractLocalDateTimeField</code> with no + * caption. + */ + public AbstractLocalDateTimeField() { + super(DateTimeResolution.MINUTE); + } + + /** + * Constructs an empty <code>AbstractLocalDateTimeField</code> with caption. + * + * @param caption + * the caption of the datefield. + */ + public AbstractLocalDateTimeField(String caption) { + super(caption, DateTimeResolution.MINUTE); + } + + @Override + protected LocalDateTimeFieldState getState() { + return (LocalDateTimeFieldState) super.getState(); + } + + @Override + protected LocalDateTimeFieldState getState(boolean markAsDirty) { + return (LocalDateTimeFieldState) super.getState(markAsDirty); + } + +} diff --git a/server/src/main/java/com/vaadin/ui/DateField.java b/server/src/main/java/com/vaadin/ui/DateField.java index fd241f7504..2ee1c478d9 100644 --- a/server/src/main/java/com/vaadin/ui/DateField.java +++ b/server/src/main/java/com/vaadin/ui/DateField.java @@ -17,17 +17,17 @@ package com.vaadin.ui; import java.time.LocalDate; -import com.vaadin.shared.ui.datefield.DateFieldState; +import com.vaadin.shared.ui.datefield.LocalDateFieldState; /** * A date entry component, which displays the actual date selector as a popup. * - * @see AbstractDateField + * @see AbstractLocalDateField * @see InlineDateField * @author Vaadin Ltd. * @since 8.0 */ -public class DateField extends AbstractDateField { +public class DateField extends AbstractLocalDateField { /** * Constructs an empty <code>DateField</code> with no caption. @@ -81,13 +81,13 @@ public class DateField extends AbstractDateField { } @Override - protected DateFieldState getState() { - return (DateFieldState) super.getState(); + protected LocalDateFieldState getState() { + return (LocalDateFieldState) super.getState(); } @Override - protected DateFieldState getState(boolean markAsDirty) { - return (DateFieldState) super.getState(markAsDirty); + protected LocalDateFieldState getState(boolean markAsDirty) { + return (LocalDateFieldState) super.getState(markAsDirty); } /** diff --git a/server/src/main/java/com/vaadin/ui/InlineDateField.java b/server/src/main/java/com/vaadin/ui/InlineDateField.java index cf5017bf34..2db9d7f1db 100644 --- a/server/src/main/java/com/vaadin/ui/InlineDateField.java +++ b/server/src/main/java/com/vaadin/ui/InlineDateField.java @@ -22,12 +22,12 @@ import com.vaadin.shared.ui.datefield.InlineDateFieldState; /** * A date entry component, which displays the actual date selector inline. * - * @see AbstractDateField + * @see AbstractLocalDateField * @see DateField * @author Vaadin Ltd. * @since 8.0 */ -public class InlineDateField extends AbstractDateField { +public class InlineDateField extends AbstractLocalDateField { /** * Constructs an empty <code>InlineDateField</code> with no caption. diff --git a/server/src/main/java/com/vaadin/ui/declarative/DesignAttributeHandler.java b/server/src/main/java/com/vaadin/ui/declarative/DesignAttributeHandler.java index 4c7a2da9a8..42ffe303ef 100644 --- a/server/src/main/java/com/vaadin/ui/declarative/DesignAttributeHandler.java +++ b/server/src/main/java/com/vaadin/ui/declarative/DesignAttributeHandler.java @@ -21,6 +21,7 @@ import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.io.Serializable; import java.lang.reflect.Method; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -36,6 +37,7 @@ import org.jsoup.nodes.Attributes; import org.jsoup.nodes.Element; import org.jsoup.nodes.Node; +import com.googlecode.gentyref.GenericTypeReflector; import com.vaadin.data.Converter; import com.vaadin.data.ValueContext; import com.vaadin.shared.ui.AlignmentInfo; @@ -115,8 +117,9 @@ public class DesignAttributeHandler implements Serializable { success = false; } else { // we have a value from design attributes, let's use that - Object param = getFormatter().parse(value, - setter.getParameterTypes()[0]); + Type[] types = GenericTypeReflector + .getExactParameterTypes(setter, target.getClass()); + Object param = getFormatter().parse(value, (Class<?>) types[0]); setter.invoke(target, param); success = true; } @@ -208,7 +211,9 @@ public class DesignAttributeHandler implements Serializable { Object value = getter.invoke(component); Object defaultValue = getter.invoke(defaultInstance); writeAttribute(attribute, attr, value, defaultValue, - (Class) getter.getReturnType(), context); + (Class) GenericTypeReflector.getExactReturnType(getter, + component.getClass()), + context); } catch (Exception e) { getLogger().log(Level.SEVERE, "Failed to invoke getter for attribute " + attribute, diff --git a/server/src/test/java/com/vaadin/tests/server/component/abstractdatefield/AbstractDateFieldDeclarativeTest.java b/server/src/test/java/com/vaadin/tests/server/component/abstractdatefield/AbstractLocalDateFieldDeclarativeTest.java index dcda449615..80040804cd 100644 --- a/server/src/test/java/com/vaadin/tests/server/component/abstractdatefield/AbstractDateFieldDeclarativeTest.java +++ b/server/src/test/java/com/vaadin/tests/server/component/abstractdatefield/AbstractLocalDateFieldDeclarativeTest.java @@ -20,9 +20,9 @@ import java.util.Locale; import org.junit.Test; -import com.vaadin.shared.ui.datefield.Resolution; +import com.vaadin.shared.ui.datefield.DateResolution; import com.vaadin.tests.server.component.abstractfield.AbstractFieldDeclarativeTest; -import com.vaadin.ui.AbstractDateField; +import com.vaadin.ui.AbstractLocalDateField; /** * Abstract test class which contains tests for declarative format for @@ -36,7 +36,7 @@ import com.vaadin.ui.AbstractDateField; * @author Vaadin Ltd * */ -public abstract class AbstractDateFieldDeclarativeTest<T extends AbstractDateField> +public abstract class AbstractLocalDateFieldDeclarativeTest<T extends AbstractLocalDateField> extends AbstractFieldDeclarativeTest<T, LocalDate> { @Override @@ -60,7 +60,7 @@ public abstract class AbstractDateFieldDeclarativeTest<T extends AbstractDateFie LocalDate end = LocalDate.of(2019, 01, 15); LocalDate start = LocalDate.of(2001, 02, 11); String dateOutOfRange = "test date out of range"; - Resolution resolution = Resolution.MONTH; + DateResolution resolution = DateResolution.MONTH; String dateFormat = "test format"; boolean lenient = true; String parseErrorMsg = "test parse error"; diff --git a/server/src/test/java/com/vaadin/tests/server/component/datefield/DateFieldDeclarativeTest.java b/server/src/test/java/com/vaadin/tests/server/component/datefield/DateFieldDeclarativeTest.java index ea7971b84e..7b55015717 100644 --- a/server/src/test/java/com/vaadin/tests/server/component/datefield/DateFieldDeclarativeTest.java +++ b/server/src/test/java/com/vaadin/tests/server/component/datefield/DateFieldDeclarativeTest.java @@ -17,7 +17,7 @@ package com.vaadin.tests.server.component.datefield; import org.junit.Test; -import com.vaadin.tests.server.component.abstractdatefield.AbstractDateFieldDeclarativeTest; +import com.vaadin.tests.server.component.abstractdatefield.AbstractLocalDateFieldDeclarativeTest; import com.vaadin.ui.DateField; /** @@ -27,7 +27,7 @@ import com.vaadin.ui.DateField; * @author Vaadin Ltd */ public class DateFieldDeclarativeTest - extends AbstractDateFieldDeclarativeTest<DateField> { + extends AbstractLocalDateFieldDeclarativeTest<DateField> { @Test public void remainingAttributes() 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 990fd9ceba..cab1addf58 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 @@ -1,7 +1,14 @@ package com.vaadin.tests.server.component.datefield; +import java.io.Serializable; +import java.time.temporal.Temporal; +import java.time.temporal.TemporalAdjuster; +import java.util.Date; +import java.util.Map; + import org.junit.Test; +import com.vaadin.data.validator.RangeValidator; import com.vaadin.event.FieldEvents.BlurEvent; import com.vaadin.event.FieldEvents.BlurListener; import com.vaadin.event.FieldEvents.FocusEvent; @@ -11,7 +18,37 @@ import com.vaadin.ui.AbstractDateField; public class DateFieldListenersTest extends AbstractListenerMethodsTestBase { - public static class TestDateField extends AbstractDateField { + public static class TestDateField<T extends Temporal & TemporalAdjuster & Serializable & Comparable<? super T>, R extends Enum<R>> + extends AbstractDateField<T, R> { + + public TestDateField() { + super(null); + } + + @Override + protected int getDatePart(T date, R resolution) { + return 0; + } + + @Override + protected T buildDate(Map<R, Integer> resolutionValues) { + return null; + } + + @Override + protected RangeValidator<T> getRangeValidator() { + return null; + } + + @Override + protected T convertFromDate(Date date) { + return null; + } + + @Override + protected Date convertToDate(T date) { + return null; + } } diff --git a/server/src/test/java/com/vaadin/tests/server/component/datefield/InlineDateFieldDeclarativeTest.java b/server/src/test/java/com/vaadin/tests/server/component/datefield/InlineDateFieldDeclarativeTest.java index 4e056d3c63..116bc43c9c 100644 --- a/server/src/test/java/com/vaadin/tests/server/component/datefield/InlineDateFieldDeclarativeTest.java +++ b/server/src/test/java/com/vaadin/tests/server/component/datefield/InlineDateFieldDeclarativeTest.java @@ -21,7 +21,7 @@ import java.time.LocalDate; import org.junit.Test; -import com.vaadin.tests.server.component.abstractdatefield.AbstractDateFieldDeclarativeTest; +import com.vaadin.tests.server.component.abstractdatefield.AbstractLocalDateFieldDeclarativeTest; import com.vaadin.ui.AbstractDateField; import com.vaadin.ui.InlineDateField; import com.vaadin.ui.declarative.Design; @@ -34,7 +34,7 @@ import com.vaadin.ui.declarative.Design; * @author Vaadin Ltd */ public class InlineDateFieldDeclarativeTest - extends AbstractDateFieldDeclarativeTest<InlineDateField> { + extends AbstractLocalDateFieldDeclarativeTest<InlineDateField> { @Test public void testInlineDateFieldToFromDesign() throws Exception { diff --git a/server/src/test/java/com/vaadin/tests/server/component/datefield/ResolutionTest.java b/server/src/test/java/com/vaadin/tests/server/component/datefield/ResolutionTest.java index cb8b6f4914..0db8fbe86f 100644 --- a/server/src/test/java/com/vaadin/tests/server/component/datefield/ResolutionTest.java +++ b/server/src/test/java/com/vaadin/tests/server/component/datefield/ResolutionTest.java @@ -4,39 +4,39 @@ import java.util.ArrayList; import org.junit.Test; -import com.vaadin.shared.ui.datefield.Resolution; +import com.vaadin.shared.ui.datefield.DateResolution; import com.vaadin.tests.util.TestUtil; public class ResolutionTest { @Test public void testResolutionHigherOrEqualToYear() { - Iterable<Resolution> higherOrEqual = Resolution - .getResolutionsHigherOrEqualTo(Resolution.YEAR); - ArrayList<Resolution> expected = new ArrayList<>(); - expected.add(Resolution.YEAR); + Iterable<DateResolution> higherOrEqual = DateResolution + .getResolutionsHigherOrEqualTo(DateResolution.YEAR); + ArrayList<DateResolution> expected = new ArrayList<>(); + expected.add(DateResolution.YEAR); TestUtil.assertIterableEquals(expected, higherOrEqual); } @Test public void testResolutionHigherOrEqualToDay() { - Iterable<Resolution> higherOrEqual = Resolution - .getResolutionsHigherOrEqualTo(Resolution.DAY); - ArrayList<Resolution> expected = new ArrayList<>(); - expected.add(Resolution.DAY); - expected.add(Resolution.MONTH); - expected.add(Resolution.YEAR); + Iterable<DateResolution> higherOrEqual = DateResolution + .getResolutionsHigherOrEqualTo(DateResolution.DAY); + ArrayList<DateResolution> expected = new ArrayList<>(); + expected.add(DateResolution.DAY); + expected.add(DateResolution.MONTH); + expected.add(DateResolution.YEAR); TestUtil.assertIterableEquals(expected, higherOrEqual); } @Test public void testResolutionLowerThanYear() { - Iterable<Resolution> higherOrEqual = Resolution - .getResolutionsLowerThan(Resolution.YEAR); - ArrayList<Resolution> expected = new ArrayList<>(); - expected.add(Resolution.MONTH); - expected.add(Resolution.DAY); + Iterable<DateResolution> higherOrEqual = DateResolution + .getResolutionsLowerThan(DateResolution.YEAR); + ArrayList<DateResolution> expected = new ArrayList<>(); + expected.add(DateResolution.MONTH); + expected.add(DateResolution.DAY); TestUtil.assertIterableEquals(expected, higherOrEqual); } diff --git a/server/src/test/java/com/vaadin/ui/DateFieldTestCase.java b/server/src/test/java/com/vaadin/ui/DateFieldTestCase.java index 8abb16af6c..e67d7bde13 100644 --- a/server/src/test/java/com/vaadin/ui/DateFieldTestCase.java +++ b/server/src/test/java/com/vaadin/ui/DateFieldTestCase.java @@ -12,12 +12,12 @@ import org.junit.Test; public class DateFieldTestCase { - private AbstractDateField dateField; + private AbstractLocalDateField dateField; private LocalDate date; @Before public void setup() { - dateField = new AbstractDateField() { + dateField = new AbstractLocalDateField() { }; date = LocalDate.now(); } |