You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2022/01/03 19:57:06 UTC
[isis] branch master updated: ISIS-2882: configurable canonical temporal parsing (UI)
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push:
new 7eaa035 ISIS-2882: configurable canonical temporal parsing (UI)
7eaa035 is described below
commit 7eaa03520145e34cb2525391e7aceeeeddfd147d
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Jan 3 20:56:56 2022 +0100
ISIS-2882: configurable canonical temporal parsing (UI)
---
.../modules/ROOT/pages/2021/2.0.0-M7/mignotes.adoc | 4 +-
.../value/semantics/TemporalValueSemantics.java | 79 +++++
.../value/semantics/ValueSemanticsAbstract.java | 32 +-
.../apache/isis/core/config/IsisConfiguration.java | 358 +--------------------
.../temporal/TemporalValueSemanticsProvider.java | 72 ++++-
.../JavaUtilDateValueSemanticsProviderTest.java | 50 ++-
.../wicket/model/isis/WicketViewerSettings.java | 10 -
.../services/WicketViewerSettingsDefault.java | 10 -
8 files changed, 199 insertions(+), 416 deletions(-)
diff --git a/antora/components/relnotes/modules/ROOT/pages/2021/2.0.0-M7/mignotes.adoc b/antora/components/relnotes/modules/ROOT/pages/2021/2.0.0-M7/mignotes.adoc
index cd5589a..ccc69eb 100644
--- a/antora/components/relnotes/modules/ROOT/pages/2021/2.0.0-M7/mignotes.adoc
+++ b/antora/components/relnotes/modules/ROOT/pages/2021/2.0.0-M7/mignotes.adoc
@@ -153,12 +153,12 @@ or globally via `ValueSemanticsProvider<org.joda.time.DateTime>`
| `isis.viewer.wicket.date-pattern` (removed)
| defaults to (canonical) `yyyy-MM-dd` editing format,
-use `isis.value-types.temporal.date-pattern` instead or
+use `isis.value-types.temporal.editing.date-pattern` instead or
customize via `ValueSemanticsProvider<T>`
| `isis.viewer.wicket.date-time-pattern` (removed)
| defaults to concatenation of `date-pattern` with a blank `" "` and with a `time-pattern` editing format,
-use `isis.value-types.temporal.*-pattern` instead or
+use `isis.value-types.temporal.editing.*-pattern` instead or
customize via `ValueSemanticsProvider<T>`
|===
diff --git a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/TemporalValueSemantics.java b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/TemporalValueSemantics.java
index 33fb86d..bf0a285 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/TemporalValueSemantics.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/TemporalValueSemantics.java
@@ -21,6 +21,15 @@ package org.apache.isis.applib.value.semantics;
import java.time.Duration;
import java.time.temporal.Temporal;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+import org.apache.isis.commons.internal.exceptions._Exceptions;
+
+import lombok.Data;
+import lombok.NonNull;
+import lombok.val;
+
/**
* Common base for {@link java.time.temporal.Temporal} value types.
*
@@ -71,4 +80,74 @@ extends
TemporalCharacteristic getTemporalCharacteristic();
OffsetCharacteristic getOffsetCharacteristic();
+ @Data
+ public static class TemporalEditingPattern {
+
+ /**
+ * The locale-independent (canonical) pattern used for editing dates in the UI.
+ */
+ @NotNull @NotEmpty
+ private String datePattern = "yyyy-MM-dd";
+
+ /**
+ * The locale-independent (canonical) pattern used for editing time in the UI.
+ * <p>
+ * When editing, omitting nano-seconds, seconds or minutes will use zeros instead.
+ */
+ @NotNull @NotEmpty
+ private String timePattern = "HH:mm:ss"; //FIXME[ISIS-2882] support omitted parts on input "HH[:mm[:ss[.SSSSSSSSS]]]"
+
+ /**
+ * The locale-independent (canonical) pattern used for editing time-zone in the UI.
+ */
+ @NotNull @NotEmpty
+ private String zonePattern = "x";
+
+ /**
+ * The locale-independent (canonical) pattern used for editing date and time in the UI.
+ * <p>
+ * Uses {@code String.format(dateTimeJoiningPattern, datePattern, timePattern)}
+ * to interpolate the effective date-time format.
+ * @see String#format(String, Object...)
+ */
+ @NotNull @NotEmpty
+ private String dateTimeJoiningPattern = "%1$s %2$s";
+
+ /**
+ * The locale-independent (canonical) pattern used for editing zoned temporals
+ * (date, time or date-time) in the UI.
+ * <p>
+ * Uses {@code String.format(zoneJoiningPattern, temporalPattern, zonePattern)}
+ * to interpolate the effective zoned temporal format.
+ * @see String#format(String, Object...)
+ */
+ @NotNull @NotEmpty
+ private String zoneJoiningPattern = "%1$s %2$s";
+
+ public String getEditingFormatAsPattern(
+ final @NonNull TemporalCharacteristic temporalCharacteristic,
+ final @NonNull OffsetCharacteristic offsetCharacteristic) {
+
+ switch (temporalCharacteristic) {
+ case DATE_TIME:
+ val dateTimePattern =
+ String.format(getDateTimeJoiningPattern(), getDatePattern(), getTimePattern());
+ return offsetCharacteristic.isLocal()
+ ? dateTimePattern
+ : String.format(getZoneJoiningPattern(), dateTimePattern, getZonePattern());
+ case DATE_ONLY:
+ return offsetCharacteristic.isLocal()
+ ? getDatePattern()
+ : String.format(getZoneJoiningPattern(), getDatePattern(), getZonePattern());
+ case TIME_ONLY:
+ return offsetCharacteristic.isLocal()
+ ? getTimePattern()
+ : String.format(getZoneJoiningPattern(), getTimePattern(), getZonePattern());
+ default:
+ throw _Exceptions.unmatchedCase(temporalCharacteristic);
+ }
+ }
+
+ }
+
}
diff --git a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsAbstract.java b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsAbstract.java
index 112e836..3d1fc16 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsAbstract.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsAbstract.java
@@ -36,6 +36,7 @@ import org.springframework.lang.Nullable;
import org.apache.isis.applib.exceptions.recoverable.TextEntryParseException;
import org.apache.isis.applib.locale.UserLocale;
import org.apache.isis.applib.services.iactnlayer.InteractionContext;
+import org.apache.isis.applib.value.semantics.TemporalValueSemantics.TemporalEditingPattern;
import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.commons.internal.exceptions._Exceptions;
@@ -214,12 +215,10 @@ implements
final @Nullable ValueSemanticsProvider.Context context,
final @NonNull TemporalValueSemantics.TemporalCharacteristic temporalCharacteristic,
final @NonNull TemporalValueSemantics.OffsetCharacteristic offsetCharacteristic,
- final @NonNull String datePattern,
- final @NonNull String timePattern,
- final @NonNull String zonePattern) {
+ final @NonNull TemporalEditingPattern editingPattern) {
return getEditingFormatAsBuilder(
- temporalCharacteristic, offsetCharacteristic, datePattern, timePattern, zonePattern)
+ temporalCharacteristic, offsetCharacteristic, editingPattern)
.parseLenient()
.parseCaseInsensitive()
.toFormatter(getUserLocale(context).getTimeFormatLocale());
@@ -228,34 +227,33 @@ implements
protected DateTimeFormatterBuilder getEditingFormatAsBuilder(
final @NonNull TemporalValueSemantics.TemporalCharacteristic temporalCharacteristic,
final @NonNull TemporalValueSemantics.OffsetCharacteristic offsetCharacteristic,
- final @NonNull String datePattern,
- final @NonNull String timePattern,
- final @NonNull String zonePattern) {
+ final @NonNull TemporalEditingPattern editingPattern) {
return new DateTimeFormatterBuilder()
- .appendPattern(getEditingFormatAsPattern(temporalCharacteristic, offsetCharacteristic, datePattern, timePattern, zonePattern));
+ .appendPattern(getEditingFormatAsPattern(
+ temporalCharacteristic, offsetCharacteristic, editingPattern));
}
protected String getEditingFormatAsPattern(
final @NonNull TemporalValueSemantics.TemporalCharacteristic temporalCharacteristic,
final @NonNull TemporalValueSemantics.OffsetCharacteristic offsetCharacteristic,
- final @NonNull String datePattern,
- final @NonNull String timePattern,
- final @NonNull String zonePattern) {
+ final @NonNull TemporalEditingPattern editingPattern) {
switch (temporalCharacteristic) {
case DATE_TIME:
+ val dateTimePattern =
+ String.format(editingPattern.getDateTimeJoiningPattern(), editingPattern.getDatePattern(), editingPattern.getTimePattern());
return offsetCharacteristic.isLocal()
- ? datePattern + " " + timePattern
- : datePattern + " " + timePattern + " " + zonePattern;
+ ? dateTimePattern
+ : String.format(editingPattern.getZoneJoiningPattern(), dateTimePattern, editingPattern.getZonePattern());
case DATE_ONLY:
return offsetCharacteristic.isLocal()
- ? datePattern
- : datePattern + " " + zonePattern;
+ ? editingPattern.getDatePattern()
+ : String.format(editingPattern.getZoneJoiningPattern(), editingPattern.getDatePattern(), editingPattern.getZonePattern());
case TIME_ONLY:
return offsetCharacteristic.isLocal()
- ? timePattern
- : timePattern + " " + zonePattern;
+ ? editingPattern.getTimePattern()
+ : String.format(editingPattern.getZoneJoiningPattern(), editingPattern.getTimePattern(), editingPattern.getZonePattern());
default:
throw _Exceptions.unmatchedCase(temporalCharacteristic);
}
diff --git a/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java b/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java
index dc6b3a6..3703d22 100644
--- a/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java
+++ b/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java
@@ -66,9 +66,10 @@ import org.apache.isis.applib.services.publishing.spi.EntityPropertyChangeSubscr
import org.apache.isis.applib.services.userreg.EmailNotificationService;
import org.apache.isis.applib.services.userreg.UserRegistrationService;
import org.apache.isis.applib.services.userui.UserMenu;
+import org.apache.isis.applib.value.semantics.TemporalValueSemantics.TemporalEditingPattern;
import org.apache.isis.commons.internal.base._NullSafe;
import org.apache.isis.commons.internal.context._Context;
-import org.apache.isis.core.config.IsisConfiguration.Viewer;
+import org.apache.isis.core.config.IsisConfiguration.Core;
import org.apache.isis.core.config.metamodel.facets.DefaultViewConfiguration;
import org.apache.isis.core.config.metamodel.facets.EditingObjectsConfiguration;
import org.apache.isis.core.config.metamodel.facets.PublishingPolicies.ActionPublishingPolicy;
@@ -78,12 +79,6 @@ import org.apache.isis.core.config.metamodel.services.ApplicationFeaturesInitCon
import org.apache.isis.core.config.metamodel.specloader.IntrospectionMode;
import org.apache.isis.core.config.viewer.web.DialogMode;
-import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@@ -1936,34 +1931,6 @@ public class IsisConfiguration {
private boolean clearOriginalDestination = false;
/**
- * The pattern used for rendering and parsing dates.
- *
- * <p>
- * Each Date scalar panel will use {@link #getDatePattern()} or {@link #getDateTimePattern()} depending on its
- * date type. In the case of panels with a date picker, the pattern will be dynamically adjusted so that it can be
- * used by the <a href="https://github.com/Eonasdan/bootstrap-datetimepicker">Bootstrap Datetime Picker</a>
- * component (which uses <a href="http://momentjs.com/docs/#/parsing/string-format/">Moment.js formats</a>, rather
- * than those of regular Java code).
- */
- @NotNull @NotEmpty
- private String datePattern = "dd-MM-yyyy";
-
- /**
- * The pattern used for rendering and parsing date/times.
- *
- * <p>
- * Each Date scalar panel will use {@link #getDatePattern()} or {@link #getDateTimePattern()}
- * depending on its date type. In the case of panels with a date time picker, the pattern will be
- * dynamically adjusted so that it can be
- * used by the <a href="https://github.com/Eonasdan/bootstrap-datetimepicker">Bootstrap Datetime Picker</a>
- * component (which uses <a href="http://momentjs.com/docs/#/parsing/string-format/">Moment.js formats</a>, rather
- * than those of regular Java code).
- * </p>
- */
- @NotNull @NotEmpty
- private String dateTimePattern = "dd-MM-yyyy HH:mm";
-
- /**
* Whether the dialog mode rendered when invoking actions on domain objects should be to use
* the sidebar (the default) or to use a modal dialog.
*
@@ -2573,295 +2540,14 @@ public class IsisConfiguration {
@Data
public static class ValueTypes {
- private final Primitives primitives = new Primitives();
- @Data
- public static class Primitives {
-
- // capitalized to avoid clash with keyword
- private final Int Int = new Int();
- @Data
- public static class Int {
- /**
- * Configures the number format understood by <code>IntValueSemanticsProviderAbstract</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format;
- }
- }
-
- private final JavaLang javaLang = new JavaLang();
+ private final Temporal temporal = new Temporal();
@Data
- public static class JavaLang {
-
- // capitalized to avoid clash with keyword
- private final Byte Byte = new Byte();
- @Data
- public static class Byte {
- /**
- * Configures the number format understood by <code>ByteValueSemanticsProviderAbstract</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format;
- }
-
- // capitalized to avoid clash with keyword
- private final Double Double = new Double();
- @Data
- public static class Double {
- /**
- * Configures the number format understood by <code>DoubleValueSemanticsProviderAbstract</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format;
- }
+ public static class Temporal {
- // capitalized to avoid clash with keyword
- private final Float Float = new Float();
- @Data
- public static class Float {
- /**
- * Configures the number format understood by <code>FloatValueSemanticsProviderAbstract</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format;
- }
+ private final TemporalEditingPattern editing = new TemporalEditingPattern();
- // capitalized to avoid clash with keyword
- private final Long Long = new Long();
- @Data
- public static class Long {
- /**
- * Configures the number format understood by <code>LongValueSemanticsProviderAbstract</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format;
- }
-
- // capitalized to avoid clash with keyword
- private final Short Short = new Short();
- @Data
- public static class Short {
- /**
- * Configures the number format understood by <code>ShortValueSemanticsProviderAbstract</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format;
- }
}
- private final JavaMath javaMath = new JavaMath();
- @Data
- public static class JavaMath {
- private final BigInteger bigInteger = new BigInteger();
- @Data
- public static class BigInteger {
- /**
- * Configures the number format understood by <code>BigIntegerValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format;
- }
-
- private final BigDecimal bigDecimal = new BigDecimal();
- @Data
- public static class BigDecimal {
- /**
- * Configures the number format understood by <code>BigDecimalValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format;
- }
- }
-
- private final JavaTime javaTime = new JavaTime();
- @Data
- public static class JavaTime {
- private final LocalDateTime localDateTime = new LocalDateTime();
- @Data
- public static class LocalDateTime {
- /**
- * Configures the formats understood by <code>LocalDateTimeValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format = "medium";
- }
-
- private final OffsetDateTime offsetDateTime = new OffsetDateTime();
- @Data
- public static class OffsetDateTime {
- /**
- * Configures the formats understood by <code>OffsetDateTimeValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format = "medium";
- }
-
- private final OffsetTime offsetTime = new OffsetTime();
- @Data
- public static class OffsetTime {
- /**
- * Configures the formats understood by <code>OffsetTimeValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format = "medium";
- }
-
- private final LocalDate localDate = new LocalDate();
- @Data
- public static class LocalDate {
- /**
- * Configures the formats understood by <code>LocalDateValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format = "medium";
- }
-
- private final LocalTime localTime = new LocalTime();
- @Data
- public static class LocalTime {
- /**
- * Configures the formats understood by <code>LocalTimeValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format = "medium";
- }
-
- private final ZonedDateTime zonedDateTime = new ZonedDateTime();
- @Data
- public static class ZonedDateTime {
- /**
- * Configures the formats understood by <code>ZonedDateTimeValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format = "medium";
- }
- }
-
- private final JavaUtil javaUtil = new JavaUtil();
- @Data
- public static class JavaUtil {
-
- private final Date date = new Date();
- @Data
- public static class Date {
- /**
- * Configures the formats understood by <code>JavaUtilDateValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format = "medium";
- }
-
- }
-
- private final JavaSql javaSql = new JavaSql();
- @Data
- public static class JavaSql {
- private final Date date = new Date();
- @Data
- public static class Date {
- /**
- * Configures the formats understood by <code>JavaSqlDateValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format = "medium";
- }
- private final Time time = new Time();
- @Data
- public static class Time {
- /**
- * Configures the formats understood by <code>JavaSqlTimeValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format = "short";
- }
-
- private final Timestamp timestamp = new Timestamp();
- @Data
- public static class Timestamp {
- /**
- * Configures the formats understood by <code>JavaSqlTimeStampValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format = "short";
- }
-
- }
-
- private final Joda joda = new Joda();
- @Data
- public static class Joda {
- private final LocalDateTime localDateTime = new LocalDateTime();
- @Data
- public static class LocalDateTime {
- /**
- * Configures the formats understood by <code>JodaLocalDateTimeValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format = "medium";
- }
-
- private final LocalDate localDate = new LocalDate();
- @Data
- public static class LocalDate {
- /**
- * Configures the formats understood by <code>JodaLocalDateValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format = "medium";
- }
-
- private final DateTime dateTime = new DateTime();
- @Data
- public static class DateTime {
- /**
- * Configures the formats understood by <code>JodaDateTimeValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format = "medium";
- }
- }
}
private final Testing testing = new Testing();
@@ -3023,40 +2709,6 @@ public class IsisConfiguration {
}
}
- private final Legacy legacy = new Legacy();
- @Data
- public static class Legacy {
-
- private final ValueTypes valueTypes = new ValueTypes();
- @Data
- public static class ValueTypes {
- private final Percentage percentage = new Percentage();
- @Data
- public static class Percentage {
- /**
- * Configures the formats understood by <code>PercentageValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private String format;
- }
-
- private final Money money = new Money();
- @Data
- public static class Money {
- /**
- * Configures the default currency code used by <code>MoneyValueSemanticsProvider</code>.
- *
- * @deprecated
- */
- @Deprecated
- private Optional<String> currency = Optional.empty();
- }
- }
- }
-
-
private final Extensions extensions = new Extensions();
@Data
public static class Extensions {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/TemporalValueSemanticsProvider.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/TemporalValueSemanticsProvider.java
index 9205ea2..67db9da 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/TemporalValueSemanticsProvider.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/TemporalValueSemanticsProvider.java
@@ -29,18 +29,22 @@ import java.util.function.BiFunction;
import javax.inject.Inject;
+import org.springframework.lang.Nullable;
+
import org.apache.isis.applib.exceptions.recoverable.TextEntryParseException;
import org.apache.isis.applib.value.semantics.EncodingException;
import org.apache.isis.applib.value.semantics.TemporalValueSemantics;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.applib.value.semantics.ValueSemanticsProvider;
import org.apache.isis.commons.internal.base._Strings;
+import org.apache.isis.core.config.IsisConfiguration;
+import org.apache.isis.core.metamodel.context.MetaModelContext;
import org.apache.isis.core.metamodel.facets.objectvalue.temporalformatstyle.DateFormatStyleFacet;
import org.apache.isis.core.metamodel.facets.objectvalue.temporalformatstyle.TimeFormatStyleFacet;
-import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
import lombok.Getter;
import lombok.NonNull;
+import lombok.Value;
import lombok.val;
import lombok.experimental.Accessors;
@@ -56,7 +60,7 @@ public abstract class TemporalValueSemanticsProvider<T extends Temporal>
extends ValueSemanticsAbstract<T>
implements TemporalValueSemantics<T> {
- @Inject protected SpecificationLoader specLoader;
+ @Inject protected MetaModelContext mmc;
@Getter(onMethod_ = {@Override}) protected final TemporalCharacteristic temporalCharacteristic;
@Getter(onMethod_ = {@Override}) protected final OffsetCharacteristic offsetCharacteristic;
@@ -186,21 +190,12 @@ implements TemporalValueSemantics<T> {
*/
protected DateTimeFormatter getRenderingFormat(final ValueSemanticsProvider.Context context) {
- val featureIfAny = Optional.ofNullable(specLoader) //JUnit support
- .flatMap(specLdr->specLdr.loadFeature(context.getFeatureIdentifier()));
-
- val dateFormatStyle = featureIfAny
- .flatMap(feature->feature.lookupFacet(DateFormatStyleFacet.class))
- .map(DateFormatStyleFacet::getDateFormatStyle)
- .orElse(FormatStyle.MEDIUM);
-
- val timeFormatStyle = featureIfAny
- .flatMap(feature->feature.lookupFacet(TimeFormatStyleFacet.class))
- .map(TimeFormatStyleFacet::getTimeFormatStyle)
- .orElse(FormatStyle.MEDIUM);
+ val dateAndTimeFormatStyle = DateAndTimeFormatStyle.forContext(mmc, context);
return getTemporalRenderingFormat(
- context, temporalCharacteristic, offsetCharacteristic, dateFormatStyle, timeFormatStyle);
+ context, temporalCharacteristic, offsetCharacteristic,
+ dateAndTimeFormatStyle.getDateFormatStyle(),
+ dateAndTimeFormatStyle.getTimeFormatStyle());
}
/**
@@ -208,13 +203,13 @@ implements TemporalValueSemantics<T> {
*/
protected DateTimeFormatter getEditingFormat(final ValueSemanticsProvider.Context context) {
return getEditingFormat(context, temporalCharacteristic, offsetCharacteristic,
- "yyyy-MM-dd", "HH:mm:ss", "x");
+ temporalEditingPattern());
}
@Override
public String getPattern(final ValueSemanticsProvider.Context context) {
return getEditingFormatAsPattern(temporalCharacteristic, offsetCharacteristic,
- "yyyy-MM-dd", "HH:mm:ss", "x");
+ temporalEditingPattern());
}
/**
@@ -224,5 +219,48 @@ implements TemporalValueSemantics<T> {
return getTemporalIsoFormat(temporalCharacteristic, offsetCharacteristic);
}
+ // -- HELPER
+
+ @Value(staticConstructor = "of")
+ static class DateAndTimeFormatStyle {
+ @Nullable FormatStyle dateFormatStyle;
+ @Nullable FormatStyle timeFormatStyle;
+
+ static DateAndTimeFormatStyle forContext(
+ final @Nullable MetaModelContext mmc, // nullable .. JUnit support
+ final @Nullable ValueSemanticsProvider.Context context) {
+
+ val featureIfAny = Optional.ofNullable(mmc)
+ .map(MetaModelContext::getSpecificationLoader)
+ .flatMap(specLoader->specLoader.loadFeature(
+ Optional.ofNullable(context)
+ .map(ValueSemanticsProvider.Context::getFeatureIdentifier)
+ .orElse(null)));
+
+ val dateFormatStyle = featureIfAny
+ .flatMap(feature->feature.lookupFacet(DateFormatStyleFacet.class))
+ .map(DateFormatStyleFacet::getDateFormatStyle)
+ .orElse(FormatStyle.MEDIUM);
+
+ val timeFormatStyle = featureIfAny
+ .flatMap(feature->feature.lookupFacet(TimeFormatStyleFacet.class))
+ .map(TimeFormatStyleFacet::getTimeFormatStyle)
+ .orElse(FormatStyle.MEDIUM);
+
+ return of(dateFormatStyle, timeFormatStyle);
+ }
+
+ }
+
+ private org.apache.isis.core.config.IsisConfiguration.ValueTypes.Temporal temporalConfig() {
+ return Optional.ofNullable(mmc) // nullable .. JUnit support
+ .map(MetaModelContext::getConfiguration)
+ .map(conf->conf.getValueTypes().getTemporal())
+ .orElseGet(IsisConfiguration.ValueTypes.Temporal::new);
+ }
+
+ private TemporalEditingPattern temporalEditingPattern() {
+ return temporalConfig().getEditing();
+ }
}
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/JavaUtilDateValueSemanticsProviderTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/JavaUtilDateValueSemanticsProviderTest.java
index 56656b6..07bb8ca 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/JavaUtilDateValueSemanticsProviderTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/JavaUtilDateValueSemanticsProviderTest.java
@@ -22,8 +22,12 @@ import java.time.LocalDateTime;
import java.util.Locale;
import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
import org.apache.isis.applib.exceptions.recoverable.TextEntryParseException;
import org.apache.isis.applib.locale.UserLocale;
import org.apache.isis.applib.services.iactnlayer.InteractionContext;
@@ -32,16 +36,13 @@ import org.apache.isis.applib.value.semantics.ValueSemanticsProvider.Context;
import org.apache.isis.core.metamodel.valuesemantics.temporal.LocalDateTimeValueSemantics;
import org.apache.isis.core.metamodel.valuesemantics.temporal.legacy.JavaUtilDateValueSemantics;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.fail;
-
import lombok.val;
class JavaUtilDateValueSemanticsProviderTest
extends ValueSemanticsProviderAbstractTestCase {
@SuppressWarnings("deprecation")
- private final java.util.Date date = new java.util.Date(2013-1900, 03-1, 13, 17, 59);
+ private final java.util.Date date = new java.util.Date(2013-1900, 03-1, 13, 17, 59, 03);
private JavaUtilDateValueSemantics valueSemantics;
@BeforeEach
@@ -75,14 +76,49 @@ extends ValueSemanticsProviderAbstractTestCase {
@Test
public void testRendering() {
val _context = Context.of(null, InteractionContext.builder().locale(UserLocale.valueOf(Locale.ENGLISH)).build());
- assertEquals("Mar 13, 2013, 5:59:00 PM", valueSemantics.simpleTextPresentation(_context , date));
+ assertEquals("Mar 13, 2013, 5:59:03 PM", valueSemantics.simpleTextPresentation(_context , date));
+ }
+
+ //FIXME[ISIS-2882] support omitted parts on input
+ @Test @Disabled
+ public void testParseNoMinutes() throws Exception {
+ val _context = Context.of(null, InteractionContext.builder().locale(UserLocale.valueOf(Locale.ENGLISH)).build());
+ val parsedDate = valueSemantics.parseTextRepresentation(_context, "2013-03-13 17");
+ assertEquals(date.getTime() - 3540_000L - 3000L, parsedDate.getTime());
+ }
+
+ //FIXME[ISIS-2882] support omitted parts on input
+ @Test @Disabled
+ public void testParseNoSeconds() throws Exception {
+ val _context = Context.of(null, InteractionContext.builder().locale(UserLocale.valueOf(Locale.ENGLISH)).build());
+ val parsedDate = valueSemantics.parseTextRepresentation(_context, "2013-03-13 17:59");
+ assertEquals(date.getTime() - 3000L, parsedDate.getTime());
}
@Test
- public void testParse() throws Exception {
+ public void testParseSeconds() throws Exception {
val _context = Context.of(null, InteractionContext.builder().locale(UserLocale.valueOf(Locale.ENGLISH)).build());
- val parsedDate = valueSemantics.parseTextRepresentation(_context, "2013-03-13 17:59:00");
+ val parsedDate = valueSemantics.parseTextRepresentation(_context, "2013-03-13 17:59:03");
assertEquals(date.getTime(), parsedDate.getTime());
}
+ //FIXME[ISIS-2882] support omitted parts on input
+ /**
+ * @see https://stackoverflow.com/questions/30103167/jsr-310-parsing-seconds-fraction-with-variable-length
+ */
+ @Test @Disabled("cannot find a format pattern that can handle both millis and nanos")
+ public void testParseMillis() throws Exception {
+ val _context = Context.of(null, InteractionContext.builder().locale(UserLocale.valueOf(Locale.ENGLISH)).build());
+ val parsedDate = valueSemantics.parseTextRepresentation(_context, "2013-03-13 17:59:03.123");
+ assertEquals(date.getTime() + 123L, parsedDate.getTime());
+ }
+
+ //FIXME[ISIS-2882] support omitted parts on input
+ @Test @Disabled
+ public void testParseNanos() throws Exception {
+ val _context = Context.of(null, InteractionContext.builder().locale(UserLocale.valueOf(Locale.ENGLISH)).build());
+ val parsedDate = valueSemantics.parseTextRepresentation(_context, "2013-03-13 17:59:03.123456789");
+ assertEquals(date.getTime() + 123L, parsedDate.getTime());
+ }
+
}
diff --git a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/isis/WicketViewerSettings.java b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/isis/WicketViewerSettings.java
index 6385718..b7d250b 100644
--- a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/isis/WicketViewerSettings.java
+++ b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/isis/WicketViewerSettings.java
@@ -35,16 +35,6 @@ public interface WicketViewerSettings extends Serializable {
int getMaxTitleLengthInParentedTables();
/**
- * As per {@link org.apache.isis.core.config.IsisConfiguration.Viewer.Wicket#setDatePattern(String)}
- */
- String getDatePattern();
-
- /**
- * As per {@link org.apache.isis.core.config.IsisConfiguration.Viewer.Wicket#setDateTimePattern(String)}
- */
- String getDateTimePattern();
-
- /**
* As per {@link org.apache.isis.core.config.IsisConfiguration.Viewer.Wicket#setReplaceDisabledTagWithReadonlyTag(boolean)}
*/
boolean isReplaceDisabledTagWithReadonlyTag();
diff --git a/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/services/WicketViewerSettingsDefault.java b/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/services/WicketViewerSettingsDefault.java
index 51d8058..b5f0901 100644
--- a/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/services/WicketViewerSettingsDefault.java
+++ b/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/services/WicketViewerSettingsDefault.java
@@ -52,16 +52,6 @@ public class WicketViewerSettingsDefault implements WicketViewerSettings {
}
@Override
- public String getDatePattern() {
- return getConfiguration().getViewer().getWicket().getDatePattern();
- }
-
- @Override
- public String getDateTimePattern() {
- return getConfiguration().getViewer().getWicket().getDateTimePattern();
- }
-
- @Override
public boolean isReplaceDisabledTagWithReadonlyTag() {
return getConfiguration().getViewer().getWicket().isReplaceDisabledTagWithReadonlyTag();
}