You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2013/12/13 15:03:45 UTC

[1/4] git commit: ISIS-636: guard added to BookmarkServiceDefault

Updated Branches:
  refs/heads/master 71018db0a -> 192b6b229


ISIS-636: guard added to BookmarkServiceDefault

... to guard against NPE for null Bookmark


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/cdfccdc3
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/cdfccdc3
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/cdfccdc3

Branch: refs/heads/master
Commit: cdfccdc3197433ca40d9ffc3c0c2626c0ea31589
Parents: 71018db
Author: Dan Haywood <da...@apache.org>
Authored: Fri Dec 13 00:45:31 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Dec 13 00:45:31 2013 +0100

----------------------------------------------------------------------
 .../core/metamodel/services/bookmarks/BookmarkServiceDefault.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/cdfccdc3/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/bookmarks/BookmarkServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/bookmarks/BookmarkServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/bookmarks/BookmarkServiceDefault.java
index b504efc..c039ce5 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/bookmarks/BookmarkServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/bookmarks/BookmarkServiceDefault.java
@@ -52,7 +52,7 @@ public class BookmarkServiceDefault implements BookmarkService, DomainObjectServ
     @NotContributed(As.ASSOCIATION)
     public Object lookup(final BookmarkHolder bookmarkHolder) {
         Bookmark bookmark = bookmarkHolder.bookmark();
-        return lookup(bookmark);
+        return bookmark != null? lookup(bookmark): null;
     }
 
     /**


[2/4] git commit: ISIS-632: further minor tweaks.

Posted by da...@apache.org.
ISIS-632: further minor tweaks.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/dca5c3e8
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/dca5c3e8
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/dca5c3e8

Branch: refs/heads/master
Commit: dca5c3e8c9f71bbcfbacd0fea623a0247fe47466
Parents: cdfccdc
Author: Dan Haywood <da...@apache.org>
Authored: Fri Dec 13 00:52:51 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Dec 13 00:52:51 2013 +0100

----------------------------------------------------------------------
 .../wicket/ui/components/widgets/Select2ChoiceUtil.java       | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/dca5c3e8/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/Select2ChoiceUtil.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/Select2ChoiceUtil.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/Select2ChoiceUtil.java
index 221b527..8738a80 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/Select2ChoiceUtil.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/Select2ChoiceUtil.java
@@ -25,12 +25,15 @@ import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 
 public final class Select2ChoiceUtil  {
-    
+
     private Select2ChoiceUtil(){}
 
     // a guesstimate to convert a single character into 'em' units
     private static final double CHAR_TO_EM_MULTIPLIER = 0.8;
     
+    // a further fudge, add some additional characters prior to multiplication.
+    private static final int ADDITIONAL_CHARS = 3;
+    
     public static Select2Choice<ObjectAdapterMemento> newSelect2Choice(String id, final IModel<ObjectAdapterMemento> modelObject, ScalarModel scalarModel) {
         Select2Choice<ObjectAdapterMemento> select2Choice = new Select2Choice<ObjectAdapterMemento>(id, modelObject);
         int typicalLength = scalarModel.getTypicalLength(); 
@@ -39,7 +42,7 @@ public final class Select2ChoiceUtil  {
     }
 
     private static String asCssStyleWidth(int numChars) {
-        return "width: " + ((numChars+2) * CHAR_TO_EM_MULTIPLIER) + "em;";
+        return "width: " + ((numChars+ADDITIONAL_CHARS) * CHAR_TO_EM_MULTIPLIER) + "em;";
     }
 
 }


[4/4] git commit: ISIS-630: also reimplemented VSP for Joda LocalDateTime

Posted by da...@apache.org.
ISIS-630: also reimplemented VSP for Joda LocalDateTime

... so it too no longer has any dependencies on the concept of UTC.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/192b6b22
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/192b6b22
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/192b6b22

Branch: refs/heads/master
Commit: 192b6b229ab21ca9a0a6f3a893fc90272898942a
Parents: b87c2a9
Author: Dan Haywood <da...@apache.org>
Authored: Fri Dec 13 14:03:18 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Dec 13 14:03:18 2013 +0000

----------------------------------------------------------------------
 .../progmodel/facets/value/JodaFunctions.java   |  55 +++++
 .../value/datejodalocal/JodaLocalDateUtil.java  | 127 ++++++++++
 .../JodaLocalDateValueSemanticsProvider.java    | 221 ++++--------------
 .../JodaLocalDateTimeUtil.java                  | 124 ++++++++++
 ...JodaLocalDateTimeValueSemanticsProvider.java | 232 +++++++++++++++++--
 ...lDateTimeValueSemanticsProviderAbstract.java | 118 ----------
 6 files changed, 574 insertions(+), 303 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/192b6b22/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/JodaFunctions.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/JodaFunctions.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/JodaFunctions.java
new file mode 100644
index 0000000..2ff05e3
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/JodaFunctions.java
@@ -0,0 +1,55 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.apache.isis.core.progmodel.facets.value;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+
+import org.joda.time.LocalDate;
+import org.joda.time.format.DateTimeFormatter;
+
+import org.apache.isis.applib.profiles.Localization;
+import org.apache.isis.core.metamodel.facets.object.parseable.TextEntryParseException;
+
+public final class JodaFunctions  {
+
+    private JodaFunctions(){}
+    
+    public static Function<DateTimeFormatter, DateTimeFormatter> withLocale(final Localization localization) {
+        return new Function<DateTimeFormatter, DateTimeFormatter>() {
+            @Override
+            public DateTimeFormatter apply(DateTimeFormatter input) {
+                if (localization == null) {
+                    return input;
+                } 
+                final Locale locale = localization.getLocale();
+                if (locale == null) {
+                    return input;
+                } 
+                return input.withLocale(locale);
+            }
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/192b6b22/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateUtil.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateUtil.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateUtil.java
new file mode 100644
index 0000000..ebcd901
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateUtil.java
@@ -0,0 +1,127 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.apache.isis.core.progmodel.facets.value.datejodalocal;
+
+import java.util.List;
+import java.util.StringTokenizer;
+
+import com.google.common.collect.Iterables;
+
+import org.joda.time.LocalDate;
+import org.joda.time.format.DateTimeFormatter;
+
+import org.apache.isis.applib.profiles.Localization;
+import org.apache.isis.core.metamodel.facets.object.parseable.TextEntryParseException;
+import org.apache.isis.core.progmodel.facets.value.JodaFunctions;
+
+public final class JodaLocalDateUtil  {
+
+    private JodaLocalDateUtil(){}
+    
+    static LocalDate parseDate(final String dateStr, final Localization localization, List<DateTimeFormatter> parseFormatters) {
+        Iterable<DateTimeFormatter> elements = Iterables.transform(parseFormatters, JodaFunctions.withLocale(localization));
+        LocalDate parsedDate = parseDate(dateStr, elements);
+        return parsedDate;
+    }
+
+    
+    private static LocalDate parseDate(String dateStr, Iterable<DateTimeFormatter> formatters) {
+        for(DateTimeFormatter formatter: formatters) {
+            try {
+                return formatter.parseLocalDate(dateStr);
+            } catch (final IllegalArgumentException e) {
+                // continue to next
+            }
+        }
+        throw new TextEntryParseException("Not recognised as a date: " + dateStr);
+    }
+
+    // //////////////////////////////////////
+
+    static LocalDate relativeDate(final LocalDate contextDate, final String str, final boolean add) {
+        LocalDate relativeDate = contextDate;
+        if (str.equals("")) {
+            return contextDate;
+        }
+
+        try {
+            final StringTokenizer st = new StringTokenizer(str.substring(1), " ");
+            while (st.hasMoreTokens()) {
+                final String token = st.nextToken();
+                relativeDate = adjustDate(relativeDate, token, add);
+            }
+            return relativeDate;
+        } catch (final Exception e) {
+            return contextDate;
+        }
+    }
+
+    private static LocalDate adjustDate(final LocalDate contextDate, String str, final boolean add) {
+        int hours = 0;
+        int minutes = 0;
+        int days = 0;
+        int months = 0;
+        int years = 0;
+
+        if (str.endsWith("H")) {
+            str = str.substring(0, str.length() - 1);
+            hours = Integer.valueOf(str).intValue();
+        } else if (str.endsWith("M")) {
+            str = str.substring(0, str.length() - 1);
+            minutes = Integer.valueOf(str).intValue();
+        } else if (str.endsWith("w")) {
+            str = str.substring(0, str.length() - 1);
+            days = 7 * Integer.valueOf(str).intValue();
+        } else if (str.endsWith("y")) {
+            str = str.substring(0, str.length() - 1);
+            years = Integer.valueOf(str).intValue();
+        } else if (str.endsWith("m")) {
+            str = str.substring(0, str.length() - 1);
+            months = Integer.valueOf(str).intValue();
+        } else if (str.endsWith("d")) {
+            str = str.substring(0, str.length() - 1);
+            days = Integer.valueOf(str).intValue();
+        } else {
+            days = Integer.valueOf(str).intValue();
+        }
+
+        if (add) {
+            return add(contextDate, years, months, days, hours, minutes);
+        } else {
+            return add(contextDate, -years, -months, -days, -hours, -minutes);
+        }
+    }
+
+    private static LocalDate add(final LocalDate original, final int years, final int months, final int days, final int hours, final int minutes) {
+        if(hours != 0 || minutes != 0) {
+            throw new IllegalArgumentException("cannot add non-zero hours or minutes to a LocalDate");
+        }
+        return original.plusYears(years).plusMonths(months).plusDays(days);
+    }
+
+
+    // //////////////////////////////////////
+
+    public static String titleString(final DateTimeFormatter formatter, final LocalDate date) {
+        return date == null ? "" : formatter.print(date);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/192b6b22/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateValueSemanticsProvider.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateValueSemanticsProvider.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateValueSemanticsProvider.java
index 16ed066..27ab588 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateValueSemanticsProvider.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateValueSemanticsProvider.java
@@ -19,13 +19,13 @@
 
 package org.apache.isis.core.progmodel.facets.value.datejodalocal;
 
-import java.text.SimpleDateFormat;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.StringTokenizer;
 
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
@@ -55,18 +55,18 @@ public class JodaLocalDateValueSemanticsProvider extends ValueSemanticsProviderA
      * <p>
      * REVIEW: This seems only to have any effect if 'propertyType' is set to 'date'.
      * 
-     * @see #setPatternOverride(String)
+     * @see #setTitlePatternOverride(String)
      * @deprecated - because 'propertyType' parameter is never used
      */
     @Deprecated
     public static void setFormat(final String propertyType, final String pattern) {
-        setPatternOverride(pattern);
+        setTitlePatternOverride(pattern);
     }
     /**
      * A replacement for {@link #setFormat(String, String)}.
      */
-    public static void setPatternOverride(final String pattern) {
-        OVERRIDE_PATTERN.set(pattern);
+    public static void setTitlePatternOverride(final String pattern) {
+        OVERRIDE_TITLE_PATTERN.set(pattern);
     }
     
     /**
@@ -80,9 +80,9 @@ public class JodaLocalDateValueSemanticsProvider extends ValueSemanticsProviderA
      * 
      * <p>
      * A pre-determined list of values is available, specifically 'iso_encoding', 'iso' and 'medium' (see 
-     * {@link #NAMED_FORMATTERS}).  Alternatively,  can also specify a mask, eg <tt>dd-MMM-yyyy</tt>.
+     * {@link #NAMED_TITLE_FORMATTERS}).  Alternatively,  can also specify a mask, eg <tt>dd-MMM-yyyy</tt>.
      * 
-     * @see #NAMED_FORMATTERS  
+     * @see #NAMED_TITLE_FORMATTERS  
      */
     public final static String CFG_FORMAT_KEY = ConfigurationConstants.ROOT + "value.format.date";
     
@@ -91,20 +91,33 @@ public class JodaLocalDateValueSemanticsProvider extends ValueSemanticsProviderA
      * Keys represent the values which can be configured, and which are used for the rendering of dates.
      * 
      */
-    private static Map<String, DateTimeFormatter> NAMED_FORMATTERS = Maps.newHashMap();
+    private static Map<String, DateTimeFormatter> NAMED_TITLE_FORMATTERS = Maps.newHashMap();
     static {
-        NAMED_FORMATTERS.put("iso_encoding", DateTimeFormat.forPattern("yyyyMMdd"));
-        NAMED_FORMATTERS.put("iso", DateTimeFormat.forPattern("yyyy-MM-dd"));
-        NAMED_FORMATTERS.put("medium", DateTimeFormat.forStyle("M-"));
+        NAMED_TITLE_FORMATTERS.put("iso_encoding", DateTimeFormat.forPattern("yyyyMMdd"));
+        NAMED_TITLE_FORMATTERS.put("iso", DateTimeFormat.forPattern("yyyy-MM-dd"));
+        NAMED_TITLE_FORMATTERS.put("long", DateTimeFormat.forStyle("L-"));
+        NAMED_TITLE_FORMATTERS.put("medium", DateTimeFormat.forStyle("M-"));
+        NAMED_TITLE_FORMATTERS.put("short", DateTimeFormat.forStyle("S-"));
     }
     
-    private final static ThreadLocal<String> OVERRIDE_PATTERN = new ThreadLocal<String>() {
+    private final static ThreadLocal<String> OVERRIDE_TITLE_PATTERN = new ThreadLocal<String>() {
         @Override
         protected String initialValue() {
             return null;
         }
     };
 
+    
+    private final static List<DateTimeFormatter> PARSE_FORMATTERS = Lists.newArrayList();
+    static {
+        PARSE_FORMATTERS.add(DateTimeFormat.forStyle("L-"));
+        PARSE_FORMATTERS.add(DateTimeFormat.forStyle("M-"));
+        PARSE_FORMATTERS.add(DateTimeFormat.forStyle("S-"));
+        PARSE_FORMATTERS.add(DateTimeFormat.forPattern("yyyy-MM-dd"));
+        PARSE_FORMATTERS.add(DateTimeFormat.forPattern("yyyyMMdd"));
+    }
+    
+
 
     public static Class<? extends Facet> type() {
         return JodaLocalDateValueFacet.class;
@@ -115,8 +128,9 @@ public class JodaLocalDateValueSemanticsProvider extends ValueSemanticsProviderA
     private static final LocalDate DEFAULT_VALUE = null;
 
 
-    private final DateTimeFormatter encodingFormatter;
-    protected DateTimeFormatter titleStringFormatter;
+    private final DateTimeFormatter encodingFormatter = DateTimeFormat.forPattern("yyyyMMdd");
+    
+    private DateTimeFormatter titleStringFormatter;
     private String titleStringFormatNameOrPattern;
 
     
@@ -139,15 +153,13 @@ public class JodaLocalDateValueSemanticsProvider extends ValueSemanticsProviderA
             final FacetHolder holder, final IsisConfiguration configuration, final ValueSemanticsProviderContext context) {
         super(type(), holder, LocalDate.class, 12, Immutability.IMMUTABLE, EqualByContent.HONOURED, DEFAULT_VALUE, configuration, context);
 
-        encodingFormatter = DateTimeFormat.forPattern("yyyyMMdd");
-        
         String configuredNameOrPattern = getConfiguration().getString(CFG_FORMAT_KEY, "medium").toLowerCase().trim();
         updateTitleStringFormatter(configuredNameOrPattern);
     }
 
 
     private void updateTitleStringFormatter(String titleStringFormatNameOrPattern) {
-        titleStringFormatter = NAMED_FORMATTERS.get(titleStringFormatNameOrPattern);
+        titleStringFormatter = NAMED_TITLE_FORMATTERS.get(titleStringFormatNameOrPattern);
         if (titleStringFormatter == null) {
             titleStringFormatter = DateTimeFormat.forPattern(titleStringFormatNameOrPattern);
         }
@@ -161,24 +173,23 @@ public class JodaLocalDateValueSemanticsProvider extends ValueSemanticsProviderA
 
     @Override
     protected LocalDate doParse(final Object context, final String entry, final Localization localization) {
-        
+
         updateTitleStringFormatterIfOverridden();
+        
+        LocalDate contextDate = (LocalDate) context;
 
-        final String dateString = entry.trim();
-        final String str = dateString.toLowerCase();
-        if (str.equals("today") || str.equals("now")) {
-            return now();
-        } else if (dateString.startsWith("+")) {
-            return relativeDate(context == null ? now() : context, dateString, true);
-        } else if (dateString.startsWith("-")) {
-            return relativeDate(context == null ? now() : context, dateString, false);
+        final String dateString = entry.trim().toUpperCase();
+        if (dateString.startsWith("+") && contextDate != null) {
+            return JodaLocalDateUtil.relativeDate(contextDate, dateString, true);
+        } else if (dateString.startsWith("-")  && contextDate != null) {
+            return JodaLocalDateUtil.relativeDate(contextDate, dateString, false);
         } else {
-            return parseDate(dateString, context == null ? now() : context, localization);
+            return parseDate(dateString, contextDate, localization);
         }
     }
 
     private void updateTitleStringFormatterIfOverridden() {
-        final String overridePattern = OVERRIDE_PATTERN.get();
+        final String overridePattern = OVERRIDE_TITLE_PATTERN.get();
         if (overridePattern == null || 
             titleStringFormatNameOrPattern.equals(overridePattern)) {
             return;
@@ -188,78 +199,10 @@ public class JodaLocalDateValueSemanticsProvider extends ValueSemanticsProviderA
         updateTitleStringFormatter(overridePattern);
     }
 
-    private LocalDate parseDate(final String dateString, final Object original, final Localization localization) {
-        List<DateTimeFormatter> elements = formatsToTry(localization);
-        LocalDate parsedDate = parseDate(dateString, elements.iterator());
-        return setDate(parsedDate);
-    }
-
-    private LocalDate parseDate(final String dateString, final Iterator<DateTimeFormatter> iterator) {
-        final DateTimeFormatter format = iterator.next();
-        try {
-            return format.parseLocalDate(dateString);
-        } catch (final IllegalArgumentException e) {
-            if (iterator.hasNext()) {
-                return parseDate(dateString, iterator);
-            } else {
-                throw new TextEntryParseException("Not recognised as a date: " + dateString);
-            }
-        }
-    }
-
-    private LocalDate relativeDate(final Object object, final String str, final boolean add) {
-        if (str.equals("")) {
-            return now();
-        }
-
-        try {
-            LocalDate date = (LocalDate) object;
-            final StringTokenizer st = new StringTokenizer(str.substring(1), " ");
-            while (st.hasMoreTokens()) {
-                final String token = st.nextToken();
-                date = relativeDate2(date, token, add);
-            }
-            return date;
-        } catch (final Exception e) {
-            return now();
-        }
-    }
-
-    private LocalDate relativeDate2(final LocalDate original, String str, final boolean add) {
-        int hours = 0;
-        int minutes = 0;
-        int days = 0;
-        int months = 0;
-        int years = 0;
-
-        if (str.endsWith("H")) {
-            str = str.substring(0, str.length() - 1);
-            hours = Integer.valueOf(str).intValue();
-        } else if (str.endsWith("M")) {
-            str = str.substring(0, str.length() - 1);
-            minutes = Integer.valueOf(str).intValue();
-        } else if (str.endsWith("w")) {
-            str = str.substring(0, str.length() - 1);
-            days = 7 * Integer.valueOf(str).intValue();
-        } else if (str.endsWith("y")) {
-            str = str.substring(0, str.length() - 1);
-            years = Integer.valueOf(str).intValue();
-        } else if (str.endsWith("m")) {
-            str = str.substring(0, str.length() - 1);
-            months = Integer.valueOf(str).intValue();
-        } else if (str.endsWith("d")) {
-            str = str.substring(0, str.length() - 1);
-            days = Integer.valueOf(str).intValue();
-        } else {
-            days = Integer.valueOf(str).intValue();
-        }
-
-        if (add) {
-            return add(original, years, months, days, hours, minutes);
-        } else {
-            return add(original, -years, -months, -days, -hours, -minutes);
-        }
+    private LocalDate parseDate(final String dateStr, final Object original, final Localization localization) {
+        return JodaLocalDateUtil.parseDate(dateStr, localization, PARSE_FORMATTERS);
     }
+    
 
     // ///////////////////////////////////////////////////////////////////////////
     // TitleProvider
@@ -270,23 +213,20 @@ public class JodaLocalDateValueSemanticsProvider extends ValueSemanticsProviderA
         if (value == null) {
             return null;
         }
-        final LocalDate date = dateValue(value);
+        final LocalDate date = (LocalDate) value;
         DateTimeFormatter f = titleStringFormatter;
         if (localization != null) {
-            f = format(localization);
+            f = titleStringFormatter.withLocale(localization.getLocale());
         }
-        return titleString(f, date);
+        return JodaLocalDateUtil.titleString(f, date);
     }
 
     @Override
     public String titleStringWithMask(final Object value, final String usingMask) {
-        final LocalDate date = dateValue(value);
-        return titleString(new SimpleDateFormat(usingMask), date);
+        final LocalDate date = (LocalDate) value;
+        return JodaLocalDateUtil.titleString(DateTimeFormat.forPattern(usingMask), date);
     }
 
-    private String titleString(final DateTimeFormatter formatter, final LocalDate date) {
-        return date == null ? "" : formatter.print(date);
-    }
 
     // //////////////////////////////////////////////////////////////////
     // EncoderDecoder
@@ -294,7 +234,7 @@ public class JodaLocalDateValueSemanticsProvider extends ValueSemanticsProviderA
 
     @Override
     protected String doEncode(final Object object) {
-        final LocalDate date = dateValue(object);
+        final LocalDate date = (LocalDate) object;
         return encode(date);
     }
 
@@ -330,72 +270,11 @@ public class JodaLocalDateValueSemanticsProvider extends ValueSemanticsProviderA
     }
 
 
-    // //////////////////////////////////////////////////////////////////
-    // temporal-specific stuff
-    // //////////////////////////////////////////////////////////////////
-
-    protected boolean isEmpty() {
-        return false;
-    }
-
-
-
-    
-    // //////////////////////////////////////////////////////////////////
-    // temporal-specific stuff
-    // //////////////////////////////////////////////////////////////////
-
-    protected DateTimeFormatter format(final Localization localization) {
-        return DateTimeFormat.forStyle("M-").withLocale(localization.getLocale());
-    }
-
-    protected List<DateTimeFormatter> formatsToTry(Localization localization) {
-        List<DateTimeFormatter> formats = Lists.newArrayList();
-        
-        formats.add(withLocale(DateTimeFormat.forStyle("L-"), localization));
-        formats.add(withLocale(DateTimeFormat.forStyle("M-"), localization));
-        formats.add(withLocale(DateTimeFormat.forStyle("S-"), localization));
-        formats.add(withLocale(DateTimeFormat.forPattern("yyyy-MM-dd"), localization));
-        formats.add(withLocale(DateTimeFormat.forPattern("yyyyMMdd"), localization));
-
-        return formats;
-    }
-
-
-    private static DateTimeFormatter withLocale(DateTimeFormatter formatter, Localization localization) {
-        if(localization != null) {
-            Locale locale2 = localization.getLocale();
-            formatter.withLocale(locale2);
-        }
-        return formatter;
-    }
-
-    // //////////////////////////////////////
-
-    protected LocalDate add(final LocalDate original, final int years, final int months, final int days, final int hours, final int minutes) {
-        if(hours != 0 || minutes != 0) {
-            throw new IllegalArgumentException("cannot add non-zero hours or minutes to a LocalDate");
-        }
-        return original.plusYears(years).plusMonths(months).plusDays(days);
-    }
-
-    protected LocalDate now() {
-        return new LocalDate();
-    }
-
-    protected LocalDate dateValue(final Object value) {
-        return (LocalDate) value;
-    }
-
-    protected LocalDate setDate(final LocalDate date) {
-        return date;
-    }
-
     // //////////////////////////////////////
     
     @Override
     public String toString() {
-        return "DateValueSemanticsProvider: " + titleStringFormatter;
+        return "JodaLocalDateValueSemanticsProvider: " + titleStringFormatter;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/192b6b22/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datetimejodalocal/JodaLocalDateTimeUtil.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datetimejodalocal/JodaLocalDateTimeUtil.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datetimejodalocal/JodaLocalDateTimeUtil.java
new file mode 100644
index 0000000..7038f47
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datetimejodalocal/JodaLocalDateTimeUtil.java
@@ -0,0 +1,124 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.apache.isis.core.progmodel.facets.value.datetimejodalocal;
+
+import java.util.List;
+import java.util.StringTokenizer;
+
+import com.google.common.collect.Iterables;
+
+import org.joda.time.LocalDateTime;
+import org.joda.time.format.DateTimeFormatter;
+
+import org.apache.isis.applib.profiles.Localization;
+import org.apache.isis.core.metamodel.facets.object.parseable.TextEntryParseException;
+import org.apache.isis.core.progmodel.facets.value.JodaFunctions;
+
+public final class JodaLocalDateTimeUtil  {
+
+    private JodaLocalDateTimeUtil(){}
+    
+    static LocalDateTime parseDate(final String dateStr, final Localization localization, List<DateTimeFormatter> parseFormatters) {
+        Iterable<DateTimeFormatter> elements = Iterables.transform(parseFormatters, JodaFunctions.withLocale(localization));
+        return parseDateTime(dateStr, elements);
+    }
+
+    
+    private static LocalDateTime parseDateTime(String dateStr, Iterable<DateTimeFormatter> formatters) {
+        for(DateTimeFormatter formatter: formatters) {
+            try {
+                return formatter.parseLocalDateTime(dateStr);
+            } catch (final IllegalArgumentException e) {
+                // continue to next
+            }
+        }
+        throw new TextEntryParseException("Not recognised as a date: " + dateStr);
+    }
+
+    // //////////////////////////////////////
+
+    
+    static LocalDateTime relativeDateTime(final LocalDateTime contextDate, final String str, final boolean add) {
+        LocalDateTime relativeDate = contextDate;
+        if (str.equals("")) {
+            return contextDate;
+        }
+
+        try {
+            final StringTokenizer st = new StringTokenizer(str.substring(1), " ");
+            while (st.hasMoreTokens()) {
+                final String token = st.nextToken();
+                relativeDate = adjustDateTime(relativeDate, token, add);
+            }
+            return relativeDate;
+        } catch (final Exception e) {
+            return contextDate;
+        }
+    }
+
+    private static LocalDateTime adjustDateTime(final LocalDateTime contextDateTime, String str, final boolean add) {
+        int hours = 0;
+        int minutes = 0;
+        int days = 0;
+        int months = 0;
+        int years = 0;
+
+        if (str.endsWith("H")) {
+            str = str.substring(0, str.length() - 1);
+            hours = Integer.valueOf(str).intValue();
+        } else if (str.endsWith("M")) {
+            str = str.substring(0, str.length() - 1);
+            minutes = Integer.valueOf(str).intValue();
+        } else if (str.endsWith("w")) {
+            str = str.substring(0, str.length() - 1);
+            days = 7 * Integer.valueOf(str).intValue();
+        } else if (str.endsWith("y")) {
+            str = str.substring(0, str.length() - 1);
+            years = Integer.valueOf(str).intValue();
+        } else if (str.endsWith("m")) {
+            str = str.substring(0, str.length() - 1);
+            months = Integer.valueOf(str).intValue();
+        } else if (str.endsWith("d")) {
+            str = str.substring(0, str.length() - 1);
+            days = Integer.valueOf(str).intValue();
+        } else {
+            days = Integer.valueOf(str).intValue();
+        }
+
+        if (add) {
+            return add(contextDateTime, years, months, days, hours, minutes);
+        } else {
+            return add(contextDateTime, -years, -months, -days, -hours, -minutes);
+        }
+    }
+
+    private static LocalDateTime add(final LocalDateTime original, final int years, final int months, final int days, final int hours, final int minutes) {
+        return original.plusYears(years).plusMonths(months).plusDays(days).plusHours(hours).plusMinutes(minutes);
+    }
+
+
+    // //////////////////////////////////////
+
+    public static String titleString(final DateTimeFormatter formatter, final LocalDateTime date) {
+        return date == null ? "" : formatter.print(date);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/192b6b22/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datetimejodalocal/JodaLocalDateTimeValueSemanticsProvider.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datetimejodalocal/JodaLocalDateTimeValueSemanticsProvider.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datetimejodalocal/JodaLocalDateTimeValueSemanticsProvider.java
index a7b9165..d3f1cee 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datetimejodalocal/JodaLocalDateTimeValueSemanticsProvider.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datetimejodalocal/JodaLocalDateTimeValueSemanticsProvider.java
@@ -19,22 +19,121 @@
 
 package org.apache.isis.core.progmodel.facets.value.datetimejodalocal;
 
-import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 
 import org.joda.time.LocalDateTime;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+import org.joda.time.format.ISODateTimeFormat;
 
 import org.apache.isis.applib.adapters.EncoderDecoder;
+import org.apache.isis.applib.adapters.EncodingException;
 import org.apache.isis.applib.adapters.Parser;
+import org.apache.isis.applib.profiles.Localization;
+import org.apache.isis.core.commons.config.ConfigurationConstants;
 import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.progmodel.facets.object.value.ValueSemanticsProviderAndFacetAbstract;
 import org.apache.isis.core.progmodel.facets.object.value.ValueSemanticsProviderContext;
 
-public class JodaLocalDateTimeValueSemanticsProvider extends JodaLocalDateTimeValueSemanticsProviderAbstract<LocalDateTime> {
+public class JodaLocalDateTimeValueSemanticsProvider extends ValueSemanticsProviderAndFacetAbstract<LocalDateTime> implements JodaLocalDateTimeValueFacet {
+
+    
+    /**
+     * Introduced to allow BDD tests to provide a different format string "mid-flight".
+     * 
+     * <p>
+     * REVIEW: This seems only to have any effect if 'propertyType' is set to 'date'.
+     * 
+     * @see #setTitlePatternOverride(String)
+     * @deprecated - because 'propertyType' parameter is never used
+     */
+    @Deprecated
+    public static void setFormat(final String propertyType, final String pattern) {
+        setTitlePatternOverride(pattern);
+    }
+    /**
+     * A replacement for {@link #setFormat(String, String)}.
+     */
+    public static void setTitlePatternOverride(final String pattern) {
+        OVERRIDE_TITLE_PATTERN.set(pattern);
+    }
+    
+    /**
+     * Key to indicate how LocalDateTime should be parsed/rendered.
+     * 
+     * <p>
+     * eg:
+     * <pre>
+     * isis.value.format.datetime=iso
+     * </pre>
+     * 
+     * <p>
+     * A pre-determined list of values is available, specifically 'iso_encoding', 'iso' and 'medium' (see 
+     * {@link #NAMED_TITLE_FORMATTERS}).  Alternatively,  can also specify a mask, eg <tt>dd-MMM-yyyy</tt>.
+     * 
+     * @see #NAMED_TITLE_FORMATTERS  
+     */
+    public final static String CFG_FORMAT_KEY = ConfigurationConstants.ROOT + "value.format.datetime";
+    
+    
+    /**
+     * Keys represent the values which can be configured, and which are used for the rendering of dates.
+     * 
+     */
+    private static Map<String, DateTimeFormatter> NAMED_TITLE_FORMATTERS = Maps.newHashMap();
+    static {
+        NAMED_TITLE_FORMATTERS.put("iso_encoding", ISODateTimeFormat.basicDateTime());
+        NAMED_TITLE_FORMATTERS.put("iso", ISODateTimeFormat.basicDateTimeNoMillis());
+        NAMED_TITLE_FORMATTERS.put("long", DateTimeFormat.forStyle("LL"));
+        NAMED_TITLE_FORMATTERS.put("medium", DateTimeFormat.forStyle("MM"));
+        NAMED_TITLE_FORMATTERS.put("short", DateTimeFormat.forStyle("SS"));
+    }
+    
+    private final static ThreadLocal<String> OVERRIDE_TITLE_PATTERN = new ThreadLocal<String>() {
+        @Override
+        protected String initialValue() {
+            return null;
+        }
+    };
+
+    
+    private final static List<DateTimeFormatter> PARSE_FORMATTERS = Lists.newArrayList();
+    static {
+        PARSE_FORMATTERS.add(DateTimeFormat.forStyle("LL"));
+        PARSE_FORMATTERS.add(DateTimeFormat.forStyle("MM"));
+        PARSE_FORMATTERS.add(DateTimeFormat.forStyle("SS"));
+        PARSE_FORMATTERS.add(ISODateTimeFormat.basicDateTimeNoMillis());
+        PARSE_FORMATTERS.add(ISODateTimeFormat.basicDateTime());
+    }
+    
+
+
+    public static Class<? extends Facet> type() {
+        return JodaLocalDateTimeValueFacet.class;
+    }
+
 
     // no default
     private static final LocalDateTime DEFAULT_VALUE = null;
 
 
+    private final DateTimeFormatter encodingFormatter = ISODateTimeFormat.basicDateTime();
+    
+    private DateTimeFormatter titleStringFormatter;
+    private String titleStringFormatNameOrPattern;
+
+    
+    // //////////////////////////////////////
+    // constructor
+    // //////////////////////////////////////
+
     /**
      * Required because implementation of {@link Parser} and
      * {@link EncoderDecoder}.
@@ -43,30 +142,135 @@ public class JodaLocalDateTimeValueSemanticsProvider extends JodaLocalDateTimeVa
         this(null, null, null);
     }
 
-    public JodaLocalDateTimeValueSemanticsProvider(final FacetHolder holder, final IsisConfiguration configuration, final ValueSemanticsProviderContext context) {
-        super(holder, LocalDateTime.class, DEFAULT_VALUE, configuration, context);
+    /**
+     * Uses {@link #type()} as the facet type.
+     */
+    public JodaLocalDateTimeValueSemanticsProvider(
+            final FacetHolder holder, final IsisConfiguration configuration, final ValueSemanticsProviderContext context) {
+        super(type(), holder, LocalDateTime.class, 12, Immutability.IMMUTABLE, EqualByContent.HONOURED, DEFAULT_VALUE, configuration, context);
+
+        String configuredNameOrPattern = getConfiguration().getString(CFG_FORMAT_KEY, "medium").toLowerCase().trim();
+        updateTitleStringFormatter(configuredNameOrPattern);
     }
 
+
+    private void updateTitleStringFormatter(String titleStringFormatNameOrPattern) {
+        titleStringFormatter = NAMED_TITLE_FORMATTERS.get(titleStringFormatNameOrPattern);
+        if (titleStringFormatter == null) {
+            titleStringFormatter = DateTimeFormat.forPattern(titleStringFormatNameOrPattern);
+        }
+        this.titleStringFormatNameOrPattern = titleStringFormatNameOrPattern; 
+    }
+    
+
+    // //////////////////////////////////////////////////////////////////
+    // Parsing
+    // //////////////////////////////////////////////////////////////////
+
     @Override
-    protected LocalDateTime add(final LocalDateTime original, final int years, final int months, final int days, final int hours, final int minutes) {
-        if(hours != 0 || minutes != 0) {
-            throw new IllegalArgumentException("cannot add non-zero hours or minutes to a LocalDateTime");
+    protected LocalDateTime doParse(final Object context, final String entry, final Localization localization) {
+
+        updateTitleStringFormatterIfOverridden();
+        
+        LocalDateTime contextDateTime = (LocalDateTime) context;
+
+        final String dateString = entry.trim().toUpperCase();
+        if (dateString.startsWith("+") && contextDateTime != null) {
+            return JodaLocalDateTimeUtil.relativeDateTime(contextDateTime, dateString, true);
+        } else if (dateString.startsWith("-")  && contextDateTime != null) {
+            return JodaLocalDateTimeUtil.relativeDateTime(contextDateTime, dateString, false);
+        } else {
+            return parseDateTime(dateString, contextDateTime, localization);
+        }
+    }
+
+    private void updateTitleStringFormatterIfOverridden() {
+        final String overridePattern = OVERRIDE_TITLE_PATTERN.get();
+        if (overridePattern == null || 
+            titleStringFormatNameOrPattern.equals(overridePattern)) {
+            return;
+        } 
+        
+        // (re)create format
+        updateTitleStringFormatter(overridePattern);
+    }
+
+    private LocalDateTime parseDateTime(final String dateStr, final Object original, final Localization localization) {
+        return JodaLocalDateTimeUtil.parseDate(dateStr, localization, PARSE_FORMATTERS);
+    }
+    
+
+    // ///////////////////////////////////////////////////////////////////////////
+    // TitleProvider
+    // ///////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public String titleString(final Object value, final Localization localization) {
+        if (value == null) {
+            return null;
+        }
+        final LocalDateTime dateTime = (LocalDateTime) value;
+        DateTimeFormatter f = titleStringFormatter;
+        if (localization != null) {
+            f = titleStringFormatter.withLocale(localization.getLocale());
+        }
+        return JodaLocalDateTimeUtil.titleString(f, dateTime);
+    }
+
+    @Override
+    public String titleStringWithMask(final Object value, final String usingMask) {
+        final LocalDateTime dateTime = (LocalDateTime) value;
+        return JodaLocalDateTimeUtil.titleString(DateTimeFormat.forPattern(usingMask), dateTime);
+    }
+
+
+    // //////////////////////////////////////////////////////////////////
+    // EncoderDecoder
+    // //////////////////////////////////////////////////////////////////
+
+    @Override
+    protected String doEncode(final Object object) {
+        final LocalDateTime date = (LocalDateTime) object;
+        return encode(date);
+    }
+
+    private synchronized String encode(final LocalDateTime date) {
+        return encodingFormatter.print(date);
+    }
+
+    @Override
+    protected LocalDateTime doRestore(final String data) {
+        try {
+            return parse(data);
+        } catch (final IllegalArgumentException e) {
+            throw new EncodingException(e);
         }
-        return original.plusYears(years).plusMonths(months).plusDays(days);
     }
 
+    private synchronized LocalDateTime parse(final String data) {
+        return encodingFormatter.parseLocalDateTime(data);
+    }
+
+    // //////////////////////////////////////////////////////////////////
+    // JodaLocalDateValueFacet
+    // //////////////////////////////////////////////////////////////////
+
     @Override
-    protected LocalDateTime now() {
-        return new LocalDateTime();
+    public final LocalDateTime dateValue(final ObjectAdapter object) {
+        return (LocalDateTime) (object == null ? null : object.getObject());
     }
 
     @Override
-    protected Date dateValue(final Object value) {
-        return ((LocalDateTime) value).toDateTime().toDate();
+    public final ObjectAdapter createValue(final LocalDateTime date) {
+        return getAdapterManager().adapterFor(date);
     }
 
+
+    // //////////////////////////////////////
+    
     @Override
-    protected LocalDateTime setDate(final Date date) {
-        return new LocalDateTime(date.getTime());
+    public String toString() {
+        return "JodaLocalDateValueSemanticsProvider: " + titleStringFormatter;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/192b6b22/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datetimejodalocal/JodaLocalDateTimeValueSemanticsProviderAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datetimejodalocal/JodaLocalDateTimeValueSemanticsProviderAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datetimejodalocal/JodaLocalDateTimeValueSemanticsProviderAbstract.java
deleted file mode 100644
index dc94786..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datetimejodalocal/JodaLocalDateTimeValueSemanticsProviderAbstract.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you 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 org.apache.isis.core.progmodel.facets.value.datetimejodalocal;
-
-import java.text.DateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import com.google.common.collect.Maps;
-
-import org.apache.isis.applib.profiles.Localization;
-import org.apache.isis.core.commons.config.ConfigurationConstants;
-import org.apache.isis.core.commons.config.IsisConfiguration;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.progmodel.facets.object.value.ValueSemanticsProviderContext;
-import org.apache.isis.core.progmodel.facets.value.ValueSemanticsProviderAbstractTemporal;
-
-public abstract class JodaLocalDateTimeValueSemanticsProviderAbstract<T> extends ValueSemanticsProviderAbstractTemporal<T> {
-
-    private static Map<String, DateFormat> formats = Maps.newHashMap();
-
-    static {
-        formats.put(ISO_ENCODING_FORMAT, createDateEncodingFormat("yyyyMMdd"));
-        formats.put("iso", createDateFormat("yyyy-MM-dd"));
-        formats.put("medium", DateFormat.getDateInstance(DateFormat.MEDIUM));
-    }
-
-    public JodaLocalDateTimeValueSemanticsProviderAbstract(final FacetHolder holder, final Class<T> adaptedClass, final T defaultValue, final IsisConfiguration configuration, final ValueSemanticsProviderContext context) {
-        super("date", holder, adaptedClass, 12, Immutability.IMMUTABLE, EqualByContent.HONOURED, defaultValue, configuration, context);
-
-        final String formatRequired = configuration.getString(ConfigurationConstants.ROOT + "value.format.date");
-        if (formatRequired == null) {
-            format = formats().get(defaultFormat());
-        } else {
-            setMask(formatRequired);
-        }
-    }
-
-
-    // //////////////////////////////////////////////////////////////////
-    // temporal-specific stuff
-    // //////////////////////////////////////////////////////////////////
-
-    @Override
-    protected void clearFields(final Calendar cal) {
-        cal.set(Calendar.HOUR, 0);
-        cal.set(Calendar.HOUR_OF_DAY, 0);
-        cal.set(Calendar.MINUTE, 0);
-        cal.set(Calendar.SECOND, 0);
-        cal.set(Calendar.AM_PM, 0);
-        cal.set(Calendar.MILLISECOND, 0);
-    }
-
-    @Override
-    protected String defaultFormat() {
-        return "medium";
-    }
-
-    @Override
-    protected boolean ignoreTimeZone() {
-        return true;
-    }
-
-    @Override
-    protected Map<String, DateFormat> formats() {
-        return formats;
-    }
-
-    @Override
-    public String toString() {
-        return "DateValueSemanticsProvider: " + format;
-    }
-
-    @Override
-    protected DateFormat format(final Localization localization) {
-        final DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM, localization.getLocale());
-        dateFormat.setTimeZone(UTC_TIME_ZONE);
-        return dateFormat;
-    }
-
-    protected List<DateFormat> formatsToTry(Localization localization) {
-        List<DateFormat> formats = new ArrayList<DateFormat>();
-
-        Locale locale = localization == null ? Locale.getDefault() : localization.getLocale();
-        formats.add(DateFormat.getDateInstance(DateFormat.LONG, locale));
-        formats.add(DateFormat.getDateInstance(DateFormat.MEDIUM, locale));
-        formats.add(DateFormat.getDateInstance(DateFormat.SHORT, locale));
-        formats.add(createDateFormat("yyyy-MM-dd"));
-        formats.add(createDateFormat("yyyyMMdd"));
-
-        for (DateFormat format : formats) {
-            format.setTimeZone(UTC_TIME_ZONE);
-        }
-
-        return formats;
-    }
-
-}


[3/4] git commit: ISIS-630: fix parsing of joda LocalDate, and defaults in action prompt

Posted by da...@apache.org.
ISIS-630: fix parsing of joda LocalDate, and defaults in action prompt

Reworked implementation of JodaLocalDateValueSemanticsProvider, no longer converts to an underlying java.util.Date

Also, ensured that action prompt's args are cleared on cancel, so that defaults for action args are always obtained
if an action prompt dialog is shown, cancelled, then shown again.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/b87c2a9d
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/b87c2a9d
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/b87c2a9d

Branch: refs/heads/master
Commit: b87c2a9dcce23a0ede235584fa8ea493556081c9
Parents: dca5c3e
Author: Dan Haywood <da...@apache.org>
Authored: Fri Dec 13 00:49:55 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Dec 13 12:47:25 2013 +0000

----------------------------------------------------------------------
 .../wicket/viewer/IsisWicketApplication.java    |   3 -
 .../actions/ActionParametersFormPanel.java      |   7 +-
 .../JodaLocalDateValueSemanticsProvider.java    | 349 ++++++++++++++++++-
 ...LocalDateValueSemanticsProviderAbstract.java | 118 -------
 4 files changed, 344 insertions(+), 133 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/b87c2a9d/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
index 4b75e8b..d164be3 100644
--- a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
+++ b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
@@ -19,7 +19,6 @@
 
 package org.apache.isis.viewer.wicket.viewer;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -53,7 +52,6 @@ import org.apache.wicket.markup.html.IHeaderResponseDecorator;
 import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.request.Request;
 import org.apache.wicket.request.Response;
-import org.apache.wicket.request.mapper.parameter.UrlPathPageParametersEncoder;
 import org.apache.wicket.request.resource.CssResourceReference;
 import org.apache.wicket.settings.IRequestCycleSettings.RenderStrategy;
 import org.slf4j.Logger;
@@ -98,7 +96,6 @@ import org.apache.isis.viewer.wicket.ui.pages.BookmarkedPagesModelProvider;
 import org.apache.isis.viewer.wicket.ui.pages.PageClassList;
 import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistry;
 import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistryAccessor;
-import org.apache.isis.viewer.wicket.ui.pages.entity.EntityPage;
 import org.apache.isis.viewer.wicket.ui.panels.PanelUtil;
 import org.apache.isis.viewer.wicket.viewer.integration.isis.DeploymentTypeWicketAbstract;
 import org.apache.isis.viewer.wicket.viewer.integration.isis.WicketServer;

http://git-wip-us.apache.org/repos/asf/isis/blob/b87c2a9d/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.java
index d713589..baf7be1 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersFormPanel.java
@@ -84,7 +84,11 @@ public class ActionParametersFormPanel extends PanelAbstract<ActionModel> {
     }
 
     private void buildGui() {
-        add(new ActionParameterForm("inputForm", getModel()));
+        ActionModel model = getModel();
+        // in case previously used, eg prompt displayed then cancelled
+        model.clearArguments();
+        
+        add(new ActionParameterForm("inputForm", model));
     }
 
     class ActionParameterForm extends Form<ObjectAdapter> implements ScalarModelSubscriber  {
@@ -206,7 +210,6 @@ public class ActionParametersFormPanel extends PanelAbstract<ActionModel> {
                 @Override
                 public void onSubmit(final AjaxRequestTarget target, Form<?> form) {
                     if(actionPromptIfAny != null) {
-                        getActionModel().clearArguments();
                         actionPromptIfAny.close(target);
                     }
                 };

http://git-wip-us.apache.org/repos/asf/isis/blob/b87c2a9d/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateValueSemanticsProvider.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateValueSemanticsProvider.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateValueSemanticsProvider.java
index eaea72c..16ed066 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateValueSemanticsProvider.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateValueSemanticsProvider.java
@@ -19,22 +19,111 @@
 
 package org.apache.isis.core.progmodel.facets.value.datejodalocal;
 
-import java.util.Date;
+import java.text.SimpleDateFormat;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 
 import org.joda.time.LocalDate;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
 
 import org.apache.isis.applib.adapters.EncoderDecoder;
+import org.apache.isis.applib.adapters.EncodingException;
 import org.apache.isis.applib.adapters.Parser;
+import org.apache.isis.applib.profiles.Localization;
+import org.apache.isis.core.commons.config.ConfigurationConstants;
 import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.object.parseable.TextEntryParseException;
+import org.apache.isis.core.progmodel.facets.object.value.ValueSemanticsProviderAndFacetAbstract;
 import org.apache.isis.core.progmodel.facets.object.value.ValueSemanticsProviderContext;
 
-public class JodaLocalDateValueSemanticsProvider extends JodaLocalDateValueSemanticsProviderAbstract<LocalDate> {
+public class JodaLocalDateValueSemanticsProvider extends ValueSemanticsProviderAndFacetAbstract<LocalDate> implements JodaLocalDateValueFacet {
+
+    
+    /**
+     * Introduced to allow BDD tests to provide a different format string "mid-flight".
+     * 
+     * <p>
+     * REVIEW: This seems only to have any effect if 'propertyType' is set to 'date'.
+     * 
+     * @see #setPatternOverride(String)
+     * @deprecated - because 'propertyType' parameter is never used
+     */
+    @Deprecated
+    public static void setFormat(final String propertyType, final String pattern) {
+        setPatternOverride(pattern);
+    }
+    /**
+     * A replacement for {@link #setFormat(String, String)}.
+     */
+    public static void setPatternOverride(final String pattern) {
+        OVERRIDE_PATTERN.set(pattern);
+    }
+    
+    /**
+     * Key to indicate how LocalDate should be parsed/rendered.
+     * 
+     * <p>
+     * eg:
+     * <pre>
+     * isis.value.format.date=iso
+     * </pre>
+     * 
+     * <p>
+     * A pre-determined list of values is available, specifically 'iso_encoding', 'iso' and 'medium' (see 
+     * {@link #NAMED_FORMATTERS}).  Alternatively,  can also specify a mask, eg <tt>dd-MMM-yyyy</tt>.
+     * 
+     * @see #NAMED_FORMATTERS  
+     */
+    public final static String CFG_FORMAT_KEY = ConfigurationConstants.ROOT + "value.format.date";
+    
+    
+    /**
+     * Keys represent the values which can be configured, and which are used for the rendering of dates.
+     * 
+     */
+    private static Map<String, DateTimeFormatter> NAMED_FORMATTERS = Maps.newHashMap();
+    static {
+        NAMED_FORMATTERS.put("iso_encoding", DateTimeFormat.forPattern("yyyyMMdd"));
+        NAMED_FORMATTERS.put("iso", DateTimeFormat.forPattern("yyyy-MM-dd"));
+        NAMED_FORMATTERS.put("medium", DateTimeFormat.forStyle("M-"));
+    }
+    
+    private final static ThreadLocal<String> OVERRIDE_PATTERN = new ThreadLocal<String>() {
+        @Override
+        protected String initialValue() {
+            return null;
+        }
+    };
+
+
+    public static Class<? extends Facet> type() {
+        return JodaLocalDateValueFacet.class;
+    }
+
 
     // no default
     private static final LocalDate DEFAULT_VALUE = null;
 
 
+    private final DateTimeFormatter encodingFormatter;
+    protected DateTimeFormatter titleStringFormatter;
+    private String titleStringFormatNameOrPattern;
+
+    
+    // //////////////////////////////////////
+    // constructor
+    // //////////////////////////////////////
+
     /**
      * Required because implementation of {@link Parser} and
      * {@link EncoderDecoder}.
@@ -43,11 +132,246 @@ public class JodaLocalDateValueSemanticsProvider extends JodaLocalDateValueSeman
         this(null, null, null);
     }
 
-    public JodaLocalDateValueSemanticsProvider(final FacetHolder holder, final IsisConfiguration configuration, final ValueSemanticsProviderContext context) {
-        super(holder, LocalDate.class, DEFAULT_VALUE, configuration, context);
+    /**
+     * Uses {@link #type()} as the facet type.
+     */
+    public JodaLocalDateValueSemanticsProvider(
+            final FacetHolder holder, final IsisConfiguration configuration, final ValueSemanticsProviderContext context) {
+        super(type(), holder, LocalDate.class, 12, Immutability.IMMUTABLE, EqualByContent.HONOURED, DEFAULT_VALUE, configuration, context);
+
+        encodingFormatter = DateTimeFormat.forPattern("yyyyMMdd");
+        
+        String configuredNameOrPattern = getConfiguration().getString(CFG_FORMAT_KEY, "medium").toLowerCase().trim();
+        updateTitleStringFormatter(configuredNameOrPattern);
+    }
+
+
+    private void updateTitleStringFormatter(String titleStringFormatNameOrPattern) {
+        titleStringFormatter = NAMED_FORMATTERS.get(titleStringFormatNameOrPattern);
+        if (titleStringFormatter == null) {
+            titleStringFormatter = DateTimeFormat.forPattern(titleStringFormatNameOrPattern);
+        }
+        this.titleStringFormatNameOrPattern = titleStringFormatNameOrPattern; 
+    }
+    
+
+    // //////////////////////////////////////////////////////////////////
+    // Parsing
+    // //////////////////////////////////////////////////////////////////
+
+    @Override
+    protected LocalDate doParse(final Object context, final String entry, final Localization localization) {
+        
+        updateTitleStringFormatterIfOverridden();
+
+        final String dateString = entry.trim();
+        final String str = dateString.toLowerCase();
+        if (str.equals("today") || str.equals("now")) {
+            return now();
+        } else if (dateString.startsWith("+")) {
+            return relativeDate(context == null ? now() : context, dateString, true);
+        } else if (dateString.startsWith("-")) {
+            return relativeDate(context == null ? now() : context, dateString, false);
+        } else {
+            return parseDate(dateString, context == null ? now() : context, localization);
+        }
+    }
+
+    private void updateTitleStringFormatterIfOverridden() {
+        final String overridePattern = OVERRIDE_PATTERN.get();
+        if (overridePattern == null || 
+            titleStringFormatNameOrPattern.equals(overridePattern)) {
+            return;
+        } 
+        
+        // (re)create format
+        updateTitleStringFormatter(overridePattern);
+    }
+
+    private LocalDate parseDate(final String dateString, final Object original, final Localization localization) {
+        List<DateTimeFormatter> elements = formatsToTry(localization);
+        LocalDate parsedDate = parseDate(dateString, elements.iterator());
+        return setDate(parsedDate);
+    }
+
+    private LocalDate parseDate(final String dateString, final Iterator<DateTimeFormatter> iterator) {
+        final DateTimeFormatter format = iterator.next();
+        try {
+            return format.parseLocalDate(dateString);
+        } catch (final IllegalArgumentException e) {
+            if (iterator.hasNext()) {
+                return parseDate(dateString, iterator);
+            } else {
+                throw new TextEntryParseException("Not recognised as a date: " + dateString);
+            }
+        }
+    }
+
+    private LocalDate relativeDate(final Object object, final String str, final boolean add) {
+        if (str.equals("")) {
+            return now();
+        }
+
+        try {
+            LocalDate date = (LocalDate) object;
+            final StringTokenizer st = new StringTokenizer(str.substring(1), " ");
+            while (st.hasMoreTokens()) {
+                final String token = st.nextToken();
+                date = relativeDate2(date, token, add);
+            }
+            return date;
+        } catch (final Exception e) {
+            return now();
+        }
+    }
+
+    private LocalDate relativeDate2(final LocalDate original, String str, final boolean add) {
+        int hours = 0;
+        int minutes = 0;
+        int days = 0;
+        int months = 0;
+        int years = 0;
+
+        if (str.endsWith("H")) {
+            str = str.substring(0, str.length() - 1);
+            hours = Integer.valueOf(str).intValue();
+        } else if (str.endsWith("M")) {
+            str = str.substring(0, str.length() - 1);
+            minutes = Integer.valueOf(str).intValue();
+        } else if (str.endsWith("w")) {
+            str = str.substring(0, str.length() - 1);
+            days = 7 * Integer.valueOf(str).intValue();
+        } else if (str.endsWith("y")) {
+            str = str.substring(0, str.length() - 1);
+            years = Integer.valueOf(str).intValue();
+        } else if (str.endsWith("m")) {
+            str = str.substring(0, str.length() - 1);
+            months = Integer.valueOf(str).intValue();
+        } else if (str.endsWith("d")) {
+            str = str.substring(0, str.length() - 1);
+            days = Integer.valueOf(str).intValue();
+        } else {
+            days = Integer.valueOf(str).intValue();
+        }
+
+        if (add) {
+            return add(original, years, months, days, hours, minutes);
+        } else {
+            return add(original, -years, -months, -days, -hours, -minutes);
+        }
+    }
+
+    // ///////////////////////////////////////////////////////////////////////////
+    // TitleProvider
+    // ///////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public String titleString(final Object value, final Localization localization) {
+        if (value == null) {
+            return null;
+        }
+        final LocalDate date = dateValue(value);
+        DateTimeFormatter f = titleStringFormatter;
+        if (localization != null) {
+            f = format(localization);
+        }
+        return titleString(f, date);
+    }
+
+    @Override
+    public String titleStringWithMask(final Object value, final String usingMask) {
+        final LocalDate date = dateValue(value);
+        return titleString(new SimpleDateFormat(usingMask), date);
+    }
+
+    private String titleString(final DateTimeFormatter formatter, final LocalDate date) {
+        return date == null ? "" : formatter.print(date);
+    }
+
+    // //////////////////////////////////////////////////////////////////
+    // EncoderDecoder
+    // //////////////////////////////////////////////////////////////////
+
+    @Override
+    protected String doEncode(final Object object) {
+        final LocalDate date = dateValue(object);
+        return encode(date);
+    }
+
+    private synchronized String encode(final LocalDate date) {
+        return encodingFormatter.print(date);
     }
 
     @Override
+    protected LocalDate doRestore(final String data) {
+        try {
+            return parse(data);
+        } catch (final IllegalArgumentException e) {
+            throw new EncodingException(e);
+        }
+    }
+
+    private synchronized LocalDate parse(final String data) {
+        return encodingFormatter.parseLocalDate(data);
+    }
+
+    // //////////////////////////////////////////////////////////////////
+    // JodaLocalDateValueFacet
+    // //////////////////////////////////////////////////////////////////
+
+    @Override
+    public final LocalDate dateValue(final ObjectAdapter object) {
+        return (LocalDate) (object == null ? null : object.getObject());
+    }
+
+    @Override
+    public final ObjectAdapter createValue(final LocalDate date) {
+        return getAdapterManager().adapterFor(date);
+    }
+
+
+    // //////////////////////////////////////////////////////////////////
+    // temporal-specific stuff
+    // //////////////////////////////////////////////////////////////////
+
+    protected boolean isEmpty() {
+        return false;
+    }
+
+
+
+    
+    // //////////////////////////////////////////////////////////////////
+    // temporal-specific stuff
+    // //////////////////////////////////////////////////////////////////
+
+    protected DateTimeFormatter format(final Localization localization) {
+        return DateTimeFormat.forStyle("M-").withLocale(localization.getLocale());
+    }
+
+    protected List<DateTimeFormatter> formatsToTry(Localization localization) {
+        List<DateTimeFormatter> formats = Lists.newArrayList();
+        
+        formats.add(withLocale(DateTimeFormat.forStyle("L-"), localization));
+        formats.add(withLocale(DateTimeFormat.forStyle("M-"), localization));
+        formats.add(withLocale(DateTimeFormat.forStyle("S-"), localization));
+        formats.add(withLocale(DateTimeFormat.forPattern("yyyy-MM-dd"), localization));
+        formats.add(withLocale(DateTimeFormat.forPattern("yyyyMMdd"), localization));
+
+        return formats;
+    }
+
+
+    private static DateTimeFormatter withLocale(DateTimeFormatter formatter, Localization localization) {
+        if(localization != null) {
+            Locale locale2 = localization.getLocale();
+            formatter.withLocale(locale2);
+        }
+        return formatter;
+    }
+
+    // //////////////////////////////////////
+
     protected LocalDate add(final LocalDate original, final int years, final int months, final int days, final int hours, final int minutes) {
         if(hours != 0 || minutes != 0) {
             throw new IllegalArgumentException("cannot add non-zero hours or minutes to a LocalDate");
@@ -55,18 +379,23 @@ public class JodaLocalDateValueSemanticsProvider extends JodaLocalDateValueSeman
         return original.plusYears(years).plusMonths(months).plusDays(days);
     }
 
-    @Override
     protected LocalDate now() {
         return new LocalDate();
     }
 
-    @Override
-    protected Date dateValue(final Object value) {
-        return ((LocalDate) value).toDateTimeAtCurrentTime().toDate();
+    protected LocalDate dateValue(final Object value) {
+        return (LocalDate) value;
     }
 
+    protected LocalDate setDate(final LocalDate date) {
+        return date;
+    }
+
+    // //////////////////////////////////////
+    
     @Override
-    protected LocalDate setDate(final Date date) {
-        return new LocalDate(date.getTime());
+    public String toString() {
+        return "DateValueSemanticsProvider: " + titleStringFormatter;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/b87c2a9d/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateValueSemanticsProviderAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateValueSemanticsProviderAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateValueSemanticsProviderAbstract.java
deleted file mode 100644
index 08c85b1..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/value/datejodalocal/JodaLocalDateValueSemanticsProviderAbstract.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you 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 org.apache.isis.core.progmodel.facets.value.datejodalocal;
-
-import java.text.DateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import com.google.common.collect.Maps;
-
-import org.apache.isis.applib.profiles.Localization;
-import org.apache.isis.core.commons.config.ConfigurationConstants;
-import org.apache.isis.core.commons.config.IsisConfiguration;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.progmodel.facets.object.value.ValueSemanticsProviderContext;
-import org.apache.isis.core.progmodel.facets.value.ValueSemanticsProviderAbstractTemporal;
-
-public abstract class JodaLocalDateValueSemanticsProviderAbstract<T> extends ValueSemanticsProviderAbstractTemporal<T> {
-
-    private static Map<String, DateFormat> formats = Maps.newHashMap();
-
-    static {
-        formats.put(ISO_ENCODING_FORMAT, createDateEncodingFormat("yyyyMMdd"));
-        formats.put("iso", createDateFormat("yyyy-MM-dd"));
-        formats.put("medium", DateFormat.getDateInstance(DateFormat.MEDIUM));
-    }
-
-    public JodaLocalDateValueSemanticsProviderAbstract(final FacetHolder holder, final Class<T> adaptedClass, final T defaultValue, final IsisConfiguration configuration, final ValueSemanticsProviderContext context) {
-        super("date", holder, adaptedClass, 12, Immutability.IMMUTABLE, EqualByContent.HONOURED, defaultValue, configuration, context);
-
-        final String formatRequired = configuration.getString(ConfigurationConstants.ROOT + "value.format.date");
-        if (formatRequired == null) {
-            format = formats().get(defaultFormat());
-        } else {
-            setMask(formatRequired);
-        }
-    }
-
-
-    // //////////////////////////////////////////////////////////////////
-    // temporal-specific stuff
-    // //////////////////////////////////////////////////////////////////
-
-    @Override
-    protected void clearFields(final Calendar cal) {
-        cal.set(Calendar.HOUR, 0);
-        cal.set(Calendar.HOUR_OF_DAY, 0);
-        cal.set(Calendar.MINUTE, 0);
-        cal.set(Calendar.SECOND, 0);
-        cal.set(Calendar.AM_PM, 0);
-        cal.set(Calendar.MILLISECOND, 0);
-    }
-
-    @Override
-    protected String defaultFormat() {
-        return "medium";
-    }
-
-    @Override
-    protected boolean ignoreTimeZone() {
-        return true;
-    }
-
-    @Override
-    protected Map<String, DateFormat> formats() {
-        return formats;
-    }
-
-    @Override
-    public String toString() {
-        return "DateValueSemanticsProvider: " + format;
-    }
-
-    @Override
-    protected DateFormat format(final Localization localization) {
-        final DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM, localization.getLocale());
-        dateFormat.setTimeZone(UTC_TIME_ZONE);
-        return dateFormat;
-    }
-
-    protected List<DateFormat> formatsToTry(Localization localization) {
-        List<DateFormat> formats = new ArrayList<DateFormat>();
-
-        Locale locale = localization == null ? Locale.getDefault() : localization.getLocale();
-        formats.add(DateFormat.getDateInstance(DateFormat.LONG, locale));
-        formats.add(DateFormat.getDateInstance(DateFormat.MEDIUM, locale));
-        formats.add(DateFormat.getDateInstance(DateFormat.SHORT, locale));
-        formats.add(createDateFormat("yyyy-MM-dd"));
-        formats.add(createDateFormat("yyyyMMdd"));
-
-        for (DateFormat format : formats) {
-            format.setTimeZone(UTC_TIME_ZONE);
-        }
-
-        return formats;
-    }
-
-}