myfaces-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From GitBox <...@apache.org>
Subject [GitHub] henningn closed pull request #12: TOBAGO-1879 tc:date does not support Calendar and DateTime
Date Tue, 18 Sep 2018 16:15:39 GMT
henningn closed pull request #12: TOBAGO-1879 tc:date does not support Calendar and DateTime
URL: https://github.com/apache/myfaces-tobago/pull/12
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/DateTimeConverter.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/DateTimeConverter.java
new file mode 100644
index 000000000..313711677
--- /dev/null
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/DateTimeConverter.java
@@ -0,0 +1,175 @@
+/*
+ * 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.myfaces.tobago.convert;
+
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.ConverterException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAccessor;
+import java.util.Calendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import static org.apache.myfaces.tobago.convert.DateTimeConverter.CONVERTER_ID;
+
+@org.apache.myfaces.tobago.apt.annotation.Converter(id = CONVERTER_ID)
+public class DateTimeConverter extends javax.faces.convert.DateTimeConverter {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DateTimeConverter.class);
+
+  public static final String CONVERTER_ID = "org.apache.myfaces.tobago.DateTime";
+
+  private static final String TYPE_DATE = "date";
+  private static final String TYPE_TIME = "time";
+  private static final String TYPE_BOTH = "both";
+  private static final String TYPE_CALENDAR = "calendar";
+  private static final String TYPE_LOCAL_DATE = "localDate";
+  private static final String TYPE_LOCAL_TIME = "localTime";
+  private static final String TYPE_LOCAL_DATE_TIME = "localDateTime";
+  private static final String TYPE_OFFSET_TIME = "offsetTime";
+  private static final String TYPE_OFFSET_DATE_TIME = "offsetDateTime";
+  private static final String TYPE_ZONED_DATE_TIME = "zonedDateTime";
+
+  @Override
+  public Object getAsObject(FacesContext facesContext, UIComponent component, String string) throws ConverterException {
+    if (StringUtils.isBlank(string)) {
+      return null;
+    } else {
+      final String type = getType();
+      if (TYPE_DATE.equals(type) || TYPE_TIME.equals(type) || TYPE_BOTH.equals(type)) {
+        return super.getAsObject(facesContext, component, string);
+      } else if (TYPE_CALENDAR.equals(type)) {
+        final Locale locale = getLocale();
+        final String pattern = getPattern();
+        final TimeZone timeZone = getTimeZone();
+        final Calendar calendar;
+        if (component instanceof UIInput && ((UIInput) component).getValue() != null) {
+          calendar = (Calendar) ((UIInput) component).getValue();
+        } else {
+          if (timeZone != null && locale != null) {
+            calendar = Calendar.getInstance(timeZone, locale);
+          } else if (locale != null) {
+            calendar = Calendar.getInstance(locale);
+          } else if (timeZone != null) {
+            calendar = Calendar.getInstance(timeZone);
+          } else {
+            calendar = Calendar.getInstance();
+          }
+        }
+
+        SimpleDateFormat sdf = locale != null ? new SimpleDateFormat(pattern, locale) : new SimpleDateFormat(pattern);
+        try {
+          calendar.setTime(sdf.parse(string));
+        } catch (ParseException e) {
+          throw new ConverterException("string='" + string + "'", e);
+        }
+
+        return calendar;
+      } else if (TYPE_LOCAL_DATE.equals(type)) {
+        logMandatoryPatterns("yMd");
+        return getDateTimeFormatter().parse(string, LocalDate::from);
+      } else if (TYPE_LOCAL_TIME.equals(type)) {
+        logMandatoryPatterns("H");
+        return getDateTimeFormatter().parse(string, LocalTime::from);
+      } else if (TYPE_LOCAL_DATE_TIME.equals(type)) {
+        logMandatoryPatterns("yMdH");
+        return getDateTimeFormatter().parse(string, LocalDateTime::from);
+      } else if (TYPE_OFFSET_TIME.equals(type)) {
+        logMandatoryPatterns("HZ");
+        return getDateTimeFormatter().parse(string, OffsetTime::from);
+      } else if (TYPE_OFFSET_DATE_TIME.equals(type)) {
+        logMandatoryPatterns("yMdHZ");
+        return getDateTimeFormatter().parse(string, OffsetDateTime::from);
+      } else if (TYPE_ZONED_DATE_TIME.equals(type)) {
+        logMandatoryPatterns("yMdHZ");
+        return getDateTimeFormatter().parse(string, ZonedDateTime::from);
+      } else {
+        throw new ConverterException("invalid type '" + type + "'");
+      }
+    }
+  }
+
+  @Override
+  public String getAsString(FacesContext facesContext, UIComponent component, Object object) throws ConverterException {
+    if (object == null) {
+      return null;
+    } else {
+      final String type = getType();
+      if (TYPE_DATE.equals(type) || TYPE_TIME.equals(type) || TYPE_BOTH.equals(type)) {
+        return super.getAsString(facesContext, component, object);
+      } else if (TYPE_CALENDAR.equals(type)) {
+        Calendar calendar = (Calendar) object;
+        final Locale locale = getLocale();
+        final String pattern = getPattern();
+
+        SimpleDateFormat sdf = new SimpleDateFormat(pattern, locale);
+        return sdf.format(calendar.getTime());
+      } else if (TYPE_LOCAL_DATE.equals(type)
+          || TYPE_LOCAL_TIME.equals(type)
+          || TYPE_LOCAL_DATE_TIME.equals(type)
+          || TYPE_OFFSET_TIME.equals(type)
+          || TYPE_OFFSET_DATE_TIME.equals(type)
+          || TYPE_ZONED_DATE_TIME.equals(type)) {
+        return getDateTimeFormatter().format((TemporalAccessor) object);
+      } else {
+        throw new ConverterException("invalid type '" + type + "'");
+      }
+    }
+  }
+
+  private void logMandatoryPatterns(String mandatoryChars) {
+    logMandatoryPattern(mandatoryChars, "y", "year");
+    logMandatoryPattern(mandatoryChars, "M", "month");
+    logMandatoryPattern(mandatoryChars, "d", "day");
+    logMandatoryPattern(mandatoryChars, "H", "hour");
+    logMandatoryPattern(mandatoryChars, "Z", "offset");
+  }
+
+  private void logMandatoryPattern(String mandatoryChars, String c, String name) {
+    final String pattern = getPattern();
+    if (pattern != null && mandatoryChars.contains(c) && !pattern.contains(c)) {
+      LOG.error("No char for " + name + " ('" + c + "') in pattern: " + pattern);
+    }
+  }
+
+  private DateTimeFormatter getDateTimeFormatter() {
+    final String pattern = getPattern();
+    if (!StringUtils.isBlank(pattern)) {
+      final Locale locale = getLocale();
+      return locale != null ? DateTimeFormatter.ofPattern(pattern, locale) : DateTimeFormatter.ofPattern(pattern);
+    } else {
+      throw new ConverterException("no pattern set");
+    }
+  }
+}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/ConvertDateTimeHandler.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/ConvertDateTimeHandler.java
new file mode 100644
index 000000000..515933f65
--- /dev/null
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/ConvertDateTimeHandler.java
@@ -0,0 +1,119 @@
+/*
+ * 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.myfaces.tobago.facelets;
+
+import org.apache.myfaces.tobago.convert.DateTimeConverter;
+
+import javax.el.ELException;
+import javax.el.ValueExpression;
+import javax.faces.component.UIComponent;
+import javax.faces.component.ValueHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.view.facelets.ComponentHandler;
+import javax.faces.view.facelets.ConverterConfig;
+import javax.faces.view.facelets.ConverterHandler;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.TagAttribute;
+import javax.faces.view.facelets.TagException;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import static org.apache.myfaces.tobago.internal.util.Deprecation.LOG;
+
+public class ConvertDateTimeHandler extends ConverterHandler {
+
+  private final TagAttribute binding;
+  private final TagAttribute locale;
+  private final TagAttribute pattern;
+  private final TagAttribute timeZone;
+  private final TagAttribute type;
+
+  public ConvertDateTimeHandler(final ConverterConfig config) {
+    super(config);
+    binding = getAttribute("binding");
+    locale = getAttribute("locale");
+    pattern = getAttribute("pattern");
+    timeZone = getAttribute("timeZone");
+    type = getAttribute("type");
+  }
+
+  @Override
+  public void apply(final FaceletContext faceletContext, final UIComponent parent) throws ELException {
+    if (parent instanceof ValueHolder) {
+      if (ComponentHandler.isNew(parent)) {
+        final ValueHolder valueHolder = (ValueHolder) parent;
+        Converter converter = null;
+        ValueExpression valueExpression = null;
+        if (binding != null) {
+          valueExpression = binding.getValueExpression(faceletContext, Converter.class);
+          converter = (Converter) valueExpression.getValue(faceletContext);
+        }
+        if (converter == null) {
+          converter = FacesContext.getCurrentInstance().getApplication().createConverter(DateTimeConverter.CONVERTER_ID);
+          DateTimeConverter dtConverter = (DateTimeConverter) converter;
+
+          if (locale != null) {
+            final Object localeObject = locale.getObject(faceletContext);
+            if (localeObject instanceof Locale) {
+              dtConverter.setLocale((Locale) localeObject);
+            } else {
+              LOG.warn("Could not set local.");
+            }
+          }
+          if (pattern != null) {
+            final Object patternObject = pattern.getObject(faceletContext);
+            if (patternObject instanceof String) {
+              dtConverter.setPattern((String) patternObject);
+            } else {
+              LOG.warn("Could not set pattern.");
+            }
+          }
+          if (timeZone != null) {
+            final Object timeZoneObject = timeZone.getObject(faceletContext);
+            if (timeZoneObject instanceof TimeZone) {
+              dtConverter.setTimeZone((TimeZone) timeZoneObject);
+            } else {
+              LOG.warn("Could not set time zone.");
+            }
+          }
+          if (type != null) {
+            final Object typeObject = type.getObject(faceletContext);
+            if (typeObject instanceof String) {
+              dtConverter.setType((String) typeObject);
+            } else {
+              LOG.warn("Could not set type.");
+            }
+          }
+
+          if (valueExpression != null) {
+            valueExpression.setValue(faceletContext, converter);
+          }
+        }
+        if (converter != null) {
+          valueHolder.setConverter(converter);
+        }
+        // TODO else LOG.warn?
+      }
+    } else {
+      throw new TagException(tag, "Parent is not of type ValueHolder, type is: " + parent);
+    }
+  }
+}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ConvertDateTimeTagDeclaration.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ConvertDateTimeTagDeclaration.java
new file mode 100644
index 000000000..c656722c2
--- /dev/null
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ConvertDateTimeTagDeclaration.java
@@ -0,0 +1,82 @@
+/*
+ * 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.myfaces.tobago.internal.taglib.component;
+
+
+import org.apache.myfaces.tobago.apt.annotation.ConverterTag;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.convert.DateTimeConverter;
+import org.apache.myfaces.tobago.facelets.ConvertDateTimeHandler;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasFor;
+
+import javax.el.ValueExpression;
+
+/**
+ * Register a DateTimeConverter instance on the UIComponent associated with the closest parent UIComponent custom
+ * action.
+ */
+@Tag(name = "convertDateTime")
+@ConverterTag(
+    converterId = DateTimeConverter.CONVERTER_ID,
+    faceletHandler = "org.apache.myfaces.tobago.facelets.ConvertDateTimeHandler")
+public interface ConvertDateTimeTagDeclaration extends HasFor {
+
+  /**
+   * A ValueExpression that evaluates to an instance of {@link ConvertDateTimeHandler}.
+   */
+  @TagAttribute(name = "binding", type = "org.apache.myfaces.tobago.convert.DateTimeConverter")
+  void setBinding(ValueExpression binding);
+
+  /**
+   * Locale whose predefined styles for dates and times are used during formatting or parsing. If not specified, the
+   * Locale returned by FacesContext.getViewRoot().getLocale() will be used. Value must be either a VB expression that
+   * evaluates to a java.util.Locale instance, or a String that is valid to pass as the first argument to the
+   * constructor java.util.Locale(String language, String country). The empty string is passed as the second argument.
+   */
+  @TagAttribute(type = "java.lang.Object")
+  void setLocale(ValueExpression locale);
+
+  /**
+   * Custom formatting pattern which determines how the date/time string should be formatted and parsed.
+   * Pattern chars 'G', 'W', 'F', 'K', 'z' and 'X' are not supported.
+   */
+  @TagAttribute()
+  void setPattern(String pattern);
+
+  /**
+   * Time zone in which to interpret any time information in the date String. Value must be either a VB expression that
+   * evaluates to a java.util.TimeZone instance, or a String that is a timezone ID as described in the javadocs for
+   * java.util.TimeZone.getTimeZone().
+   */
+  @TagAttribute(type = "java.lang.Object")
+  void setTimeZone(ValueExpression timeZone);
+
+
+  /**
+   * Specifies what contents the string value will be formatted to include, or parsed expecting. Valid values are
+   * "date", "time", "both", "calendar", "localDate", "localDateTime", "localTime", "offsetTime", "offsetDateTime", and
+   * "zonedDateTime". The values starting with "local", "offset" and "zoned" correspond to Java SE 8 Date Time API
+   * classes in package java.time with the name derived by upper casing the first letter. For example,
+   * java.time.LocalDate for the value "localDate". Default value is "date".
+   */
+  @TagAttribute()
+  void setType(String type);
+}
diff --git a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ConvertDateTimeController.java b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ConvertDateTimeController.java
new file mode 100644
index 000000000..398db76a3
--- /dev/null
+++ b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ConvertDateTimeController.java
@@ -0,0 +1,172 @@
+/*
+ * 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.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.ZonedDateTime;
+import java.util.Calendar;
+import java.util.Date;
+
+@RequestScoped
+@Named
+public class ConvertDateTimeController {
+
+  private Date myFacesDate;
+  private Date tobagoDate;
+  private Calendar calendar;
+  private LocalDate myFacesLocalDate;
+  private LocalDate tobagoLocalDate;
+  private LocalTime myFacesLocalTime;
+  private LocalTime tobagoLocalTime;
+  private LocalDateTime myFacesLocalDateTime;
+  private LocalDateTime tobagoLocalDateTime;
+  private OffsetTime myFacesOffsetTime;
+  private OffsetTime tobagoOffsetTime;
+  private OffsetDateTime myFacesOffsetDateTime;
+  private OffsetDateTime tobagoOffsetDateTime;
+  private ZonedDateTime myFacesZonedDateTime;
+  private ZonedDateTime tobagoZonedDateTime;
+
+  public Date getMyFacesDate() {
+    return myFacesDate;
+  }
+
+  public void setMyFacesDate(Date myFacesDate) {
+    this.myFacesDate = myFacesDate;
+  }
+
+  public Date getTobagoDate() {
+    return tobagoDate;
+  }
+
+  public void setTobagoDate(Date tobagoDate) {
+    this.tobagoDate = tobagoDate;
+  }
+
+  public Calendar getCalendar() {
+    return calendar;
+  }
+
+  public void setCalendar(Calendar calendar) {
+    this.calendar = calendar;
+  }
+
+  public LocalDate getMyFacesLocalDate() {
+    return myFacesLocalDate;
+  }
+
+  public void setMyFacesLocalDate(LocalDate myFacesLocalDate) {
+    this.myFacesLocalDate = myFacesLocalDate;
+  }
+
+  public LocalDate getTobagoLocalDate() {
+    return tobagoLocalDate;
+  }
+
+  public void setTobagoLocalDate(LocalDate tobagoLocalDate) {
+    this.tobagoLocalDate = tobagoLocalDate;
+  }
+
+  public LocalTime getMyFacesLocalTime() {
+    return myFacesLocalTime;
+  }
+
+  public void setMyFacesLocalTime(LocalTime myFacesLocalTime) {
+    this.myFacesLocalTime = myFacesLocalTime;
+  }
+
+  public LocalTime getTobagoLocalTime() {
+    return tobagoLocalTime;
+  }
+
+  public void setTobagoLocalTime(LocalTime tobagoLocalTime) {
+    this.tobagoLocalTime = tobagoLocalTime;
+  }
+
+  public LocalDateTime getMyFacesLocalDateTime() {
+    return myFacesLocalDateTime;
+  }
+
+  public void setMyFacesLocalDateTime(LocalDateTime myFacesLocalDateTime) {
+    this.myFacesLocalDateTime = myFacesLocalDateTime;
+  }
+
+  public LocalDateTime getTobagoLocalDateTime() {
+    return tobagoLocalDateTime;
+  }
+
+  public void setTobagoLocalDateTime(LocalDateTime tobagoLocalDateTime) {
+    this.tobagoLocalDateTime = tobagoLocalDateTime;
+  }
+
+  public OffsetTime getMyFacesOffsetTime() {
+    return myFacesOffsetTime;
+  }
+
+  public void setMyFacesOffsetTime(OffsetTime myFacesOffsetTime) {
+    this.myFacesOffsetTime = myFacesOffsetTime;
+  }
+
+  public OffsetTime getTobagoOffsetTime() {
+    return tobagoOffsetTime;
+  }
+
+  public void setTobagoOffsetTime(OffsetTime tobagoOffsetTime) {
+    this.tobagoOffsetTime = tobagoOffsetTime;
+  }
+
+  public OffsetDateTime getMyFacesOffsetDateTime() {
+    return myFacesOffsetDateTime;
+  }
+
+  public void setMyFacesOffsetDateTime(OffsetDateTime myFacesOffsetDateTime) {
+    this.myFacesOffsetDateTime = myFacesOffsetDateTime;
+  }
+
+  public OffsetDateTime getTobagoOffsetDateTime() {
+    return tobagoOffsetDateTime;
+  }
+
+  public void setTobagoOffsetDateTime(OffsetDateTime tobagoOffsetDateTime) {
+    this.tobagoOffsetDateTime = tobagoOffsetDateTime;
+  }
+
+  public ZonedDateTime getMyFacesZonedDateTime() {
+    return myFacesZonedDateTime;
+  }
+
+  public void setMyFacesZonedDateTime(ZonedDateTime myFacesZonedDateTime) {
+    this.myFacesZonedDateTime = myFacesZonedDateTime;
+  }
+
+  public ZonedDateTime getTobagoZonedDateTime() {
+    return tobagoZonedDateTime;
+  }
+
+  public void setTobagoZonedDateTime(ZonedDateTime tobagoZonedDateTime) {
+    this.tobagoZonedDateTime = tobagoZonedDateTime;
+  }
+}
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1041-date-tobagoConverter/date-tobagoConverter.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1041-date-tobagoConverter/date-tobagoConverter.test.js
new file mode 100644
index 000000000..11d6020ea
--- /dev/null
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1041-date-tobagoConverter/date-tobagoConverter.test.js
@@ -0,0 +1,227 @@
+/*
+ * 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.
+ */
+
+QUnit.test("Date - f:convertDateTime", function (assert) {
+  let inputFn = jQueryFrameFn("#page\\:mainForm\\:myfacesDateInput\\:\\:field");
+  let datepickerButtonFn = jQueryFrameFn("#page\\:mainForm\\:myfacesDateInput .datepickerbutton");
+  let outputFn = jQueryFrameFn("#page\\:mainForm\\:myfacesDateOutput .tobago-out");
+
+  testConvertDateTime(assert,
+      inputFn, datepickerButtonFn, outputFn,
+      "dd.MM.yyyy HH:mm:ss", true, true,
+      "14.12.2018 12:34:56", "14.12.2018 12:34:56");
+});
+
+QUnit.test("Date - tc:convertDateTime", function (assert) {
+  let inputFn = jQueryFrameFn("#page\\:mainForm\\:tobagoDateInput\\:\\:field");
+  let datepickerButtonFn = jQueryFrameFn("#page\\:mainForm\\:tobagoDateInput .datepickerbutton");
+  let outputFn = jQueryFrameFn("#page\\:mainForm\\:tobagoDateOutput .tobago-out");
+
+  testConvertDateTime(assert,
+      inputFn, datepickerButtonFn, outputFn,
+      "dd.MM.yyyy HH:mm:ss", true, true,
+      "14.12.2018 12:34:56", "14.12.2018 12:34:56");
+});
+
+QUnit.test("Calendar - tc:convertDateTime", function (assert) {
+  let inputFn = jQueryFrameFn("#page\\:mainForm\\:tobagoDateInput\\:\\:field");
+  let datepickerButtonFn = jQueryFrameFn("#page\\:mainForm\\:tobagoDateInput .datepickerbutton");
+  let outputFn = jQueryFrameFn("#page\\:mainForm\\:tobagoDateOutput .tobago-out");
+
+  testConvertDateTime(assert,
+      inputFn, datepickerButtonFn, outputFn,
+      "dd.MM.yyyy HH:mm:ss", true, true,
+      "14.12.2018 12:34:56", "14.12.2018 12:34:56");
+});
+
+QUnit.test("LocalDate - f:convertDateTime", function (assert) {
+  let inputFn = jQueryFrameFn("#page\\:mainForm\\:myfacesLocalDateInput\\:\\:field");
+  let datepickerButtonFn = jQueryFrameFn("#page\\:mainForm\\:myfacesLocalDateInput .datepickerbutton");
+  let outputFn = jQueryFrameFn("#page\\:mainForm\\:myfacesLocalDateOutput .tobago-out");
+
+  if (inputFn().length > 0) {
+    testConvertDateTime(assert,
+        inputFn, datepickerButtonFn, outputFn,
+        "dd.MM.yyyy", true, false,
+        "14.12.2018", "14.12.2018");
+  } else {
+    assert.ok(true, "MyFaces 2.3 not activated");
+  }
+});
+
+QUnit.test("LocalDate - tc:convertDateTime", function (assert) {
+  let inputFn = jQueryFrameFn("#page\\:mainForm\\:tobagoLocalDateInput\\:\\:field");
+  let datepickerButtonFn = jQueryFrameFn("#page\\:mainForm\\:tobagoLocalDateInput .datepickerbutton");
+  let outputFn = jQueryFrameFn("#page\\:mainForm\\:tobagoLocalDateOutput .tobago-out");
+
+  testConvertDateTime(assert,
+      inputFn, datepickerButtonFn, outputFn,
+      "dd.MM.yyyy", true, false,
+      "14.12.2018", "14.12.2018");
+});
+
+QUnit.test("LocalTime - f:convertDateTime", function (assert) {
+  let inputFn = jQueryFrameFn("#page\\:mainForm\\:myfacesLocalTimeInput\\:\\:field");
+  let datepickerButtonFn = jQueryFrameFn("#page\\:mainForm\\:myfacesLocalTimeInput .datepickerbutton");
+  let outputFn = jQueryFrameFn("#page\\:mainForm\\:myfacesLocalTimeOutput .tobago-out");
+
+  if (inputFn().length > 0) {
+    testConvertDateTime(assert,
+        inputFn, datepickerButtonFn, outputFn,
+        "HH:mm:ss", false, true,
+        "12:34:56", "12:34:56");
+  } else {
+    assert.ok(true, "MyFaces 2.3 not activated");
+  }
+});
+
+QUnit.test("LocalTime - tc:convertDateTime", function (assert) {
+  let inputFn = jQueryFrameFn("#page\\:mainForm\\:tobagoLocalTimeInput\\:\\:field");
+  let datepickerButtonFn = jQueryFrameFn("#page\\:mainForm\\:tobagoLocalTimeInput .datepickerbutton");
+  let outputFn = jQueryFrameFn("#page\\:mainForm\\:tobagoLocalTimeOutput .tobago-out");
+
+  testConvertDateTime(assert,
+      inputFn, datepickerButtonFn, outputFn,
+      "HH:mm:ss", false, true,
+      "12:34:56", "12:34:56");
+});
+
+QUnit.test("LocalDateTime - f:convertDateTime", function (assert) {
+  let inputFn = jQueryFrameFn("#page\\:mainForm\\:myfacesLocalDateTimeInput\\:\\:field");
+  let datepickerButtonFn = jQueryFrameFn("#page\\:mainForm\\:myfacesLocalDateTimeInput .datepickerbutton");
+  let outputFn = jQueryFrameFn("#page\\:mainForm\\:myfacesLocalDateTimeOutput .tobago-out");
+
+  if (inputFn().length > 0) {
+    testConvertDateTime(assert,
+        inputFn, datepickerButtonFn, outputFn,
+        "dd.MM.yyyy HH:mm:ss", true, true,
+        "14.12.2018 12:34:56", "14.12.2018 12:34:56");
+  } else {
+    assert.ok(true, "MyFaces 2.3 not activated");
+  }
+});
+
+QUnit.test("LocalDateTime - tc:convertDateTime", function (assert) {
+  let inputFn = jQueryFrameFn("#page\\:mainForm\\:tobagoLocalDateTimeInput\\:\\:field");
+  let datepickerButtonFn = jQueryFrameFn("#page\\:mainForm\\:tobagoLocalDateTimeInput .datepickerbutton");
+  let outputFn = jQueryFrameFn("#page\\:mainForm\\:tobagoLocalDateTimeOutput .tobago-out");
+
+  testConvertDateTime(assert,
+      inputFn, datepickerButtonFn, outputFn,
+      "dd.MM.yyyy HH:mm:ss", true, true,
+      "14.12.2018 12:34:56", "14.12.2018 12:34:56");
+});
+
+QUnit.test("OffsetTime - f:convertDateTime", function (assert) {
+  let inputFn = jQueryFrameFn("#page\\:mainForm\\:myfacesOffsetTimeInput\\:\\:field");
+  let datepickerButtonFn = jQueryFrameFn("#page\\:mainForm\\:myfacesOffsetTimeInput .datepickerbutton");
+  let outputFn = jQueryFrameFn("#page\\:mainForm\\:myfacesOffsetTimeOutput .tobago-out");
+
+  if (inputFn().length > 0) {
+    testConvertDateTime(assert,
+        inputFn, datepickerButtonFn, outputFn,
+        "HH:mm:ss Z", false, true,
+        "12:34:56 +0200", "12:34:56");
+  } else {
+    assert.ok(true, "MyFaces 2.3 not activated");
+  }
+});
+
+QUnit.test("OffsetTime - tc:convertDateTime", function (assert) {
+  let inputFn = jQueryFrameFn("#page\\:mainForm\\:tobagoOffsetTimeInput\\:\\:field");
+  let datepickerButtonFn = jQueryFrameFn("#page\\:mainForm\\:tobagoOffsetTimeInput .datepickerbutton");
+  let outputFn = jQueryFrameFn("#page\\:mainForm\\:tobagoOffsetTimeOutput .tobago-out");
+
+  testConvertDateTime(assert,
+      inputFn, datepickerButtonFn, outputFn,
+      "HH:mm:ss Z", false, true,
+      "12:34:56 +0200", "12:34:56");
+});
+
+QUnit.test("OffsetDateTime - f:convertDateTime", function (assert) {
+  let inputFn = jQueryFrameFn("#page\\:mainForm\\:myfacesOffsetDateTimeInput\\:\\:field");
+  let datepickerButtonFn = jQueryFrameFn("#page\\:mainForm\\:myfacesOffsetDateTimeInput .datepickerbutton");
+  let outputFn = jQueryFrameFn("#page\\:mainForm\\:myfacesOffsetDateTimeOutput .tobago-out");
+
+  if (inputFn().length > 0) {
+    testConvertDateTime(assert,
+        inputFn, datepickerButtonFn, outputFn,
+        "dd.MM.yyyy HH:mm:ss Z", true, true,
+        "14.12.2018 12:34:56 +0200", "14.12.2018 12:34:56");
+  } else {
+    assert.ok(true, "MyFaces 2.3 not activated");
+  }
+});
+
+QUnit.test("OffsetDateTime - tc:convertDateTime", function (assert) {
+  let inputFn = jQueryFrameFn("#page\\:mainForm\\:tobagoOffsetDateTimeInput\\:\\:field");
+  let datepickerButtonFn = jQueryFrameFn("#page\\:mainForm\\:tobagoOffsetDateTimeInput .datepickerbutton");
+  let outputFn = jQueryFrameFn("#page\\:mainForm\\:tobagoOffsetDateTimeOutput .tobago-out");
+
+  testConvertDateTime(assert,
+      inputFn, datepickerButtonFn, outputFn,
+      "dd.MM.yyyy HH:mm:ss Z", true, true,
+      "14.12.2018 12:34:56 +0200", "14.12.2018 12:34:56");
+});
+
+QUnit.test("ZonedDateTime - f:convertDateTime", function (assert) {
+  let inputFn = jQueryFrameFn("#page\\:mainForm\\:myfacesZonedDateTimeInput\\:\\:field");
+  let datepickerButtonFn = jQueryFrameFn("#page\\:mainForm\\:myfacesZonedDateTimeInput .datepickerbutton");
+  let outputFn = jQueryFrameFn("#page\\:mainForm\\:myfacesZonedDateTimeOutput .tobago-out");
+
+  if (inputFn().length > 0) {
+    testConvertDateTime(assert,
+        inputFn, datepickerButtonFn, outputFn,
+        "dd.MM.yyyy HH:mm:ss Z", true, true,
+        "14.12.2018 12:34:56 +0200", "14.12.2018 12:34:56");
+  } else {
+    assert.ok(true, "MyFaces 2.3 not activated");
+  }
+});
+
+QUnit.test("ZonedDateTime - tc:convertDateTime", function (assert) {
+  let inputFn = jQueryFrameFn("#page\\:mainForm\\:tobagoZonedDateTimeInput\\:\\:field");
+  let datepickerButtonFn = jQueryFrameFn("#page\\:mainForm\\:tobagoZonedDateTimeInput .datepickerbutton");
+  let outputFn = jQueryFrameFn("#page\\:mainForm\\:tobagoZonedDateTimeOutput .tobago-out");
+
+  testConvertDateTime(assert,
+      inputFn, datepickerButtonFn, outputFn,
+      "dd.MM.yyyy HH:mm:ss Z", true, true,
+      "14.12.2018 12:34:56 +0200", "14.12.2018 12:34:56");
+});
+
+function testConvertDateTime(assert, inputFn, datepickerButtonFn, outputFn,
+                             expectPattern, expectCalendarIcon, expectClockIcon,
+                             inputValue, expectOutputValue) {
+  let submitButtonFn = jQueryFrameFn("#page\\:mainForm\\:submitButton");
+
+  let TTT = new TobagoTestTools(assert);
+  TTT.asserts(3, function () {
+    assert.equal(inputFn().data("tobago-pattern"), expectPattern);
+    assert.equal(datepickerButtonFn().find(".fa-calendar").length, expectCalendarIcon);
+    assert.equal(datepickerButtonFn().find(".fa-clock-o").length, expectClockIcon);
+  });
+  TTT.action(function () {
+    inputFn().val(inputValue);
+    submitButtonFn().click();
+  });
+  TTT.waitForResponse();
+  TTT.asserts(1, function () {
+    assert.equal(outputFn().text(), expectOutputValue);
+  });
+  TTT.startTest();
+}
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1041-date-tobagoConverter/date-tobagoConverter.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1041-date-tobagoConverter/date-tobagoConverter.xhtml
new file mode 100644
index 000000000..ca36d17f6
--- /dev/null
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1041-date-tobagoConverter/date-tobagoConverter.xhtml
@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:f="http://java.sun.com/jsf/core"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="tc:convertDateTime"/>
+
+  <tc:section label="Date">
+    <tc:segmentLayout extraSmall="6seg">
+      <tc:box label="MyFaces">
+        <tc:date id="myfacesDateInput" label="Date" value="#{convertDateTimeController.myFacesDate}" labelLayout="top">
+          <f:convertDateTime pattern="dd.MM.yyyy HH:mm:ss"/>
+        </tc:date>
+        <tc:out id="myfacesDateOutput" label="Output" value="#{convertDateTimeController.myFacesDate}">
+          <f:convertDateTime pattern="dd.MM.yyyy HH:mm:ss"/>
+        </tc:out>
+      </tc:box>
+      <tc:box label="Tobago">
+        <tc:date id="tobagoDateInput" label="Date" value="#{convertDateTimeController.tobagoDate}" labelLayout="top">
+          <tc:convertDateTime pattern="dd.MM.yyyy HH:mm:ss"/>
+        </tc:date>
+        <tc:out id="tobagoDateOutput" label="Output" value="#{convertDateTimeController.tobagoDate}">
+          <tc:convertDateTime pattern="dd.MM.yyyy HH:mm:ss"/>
+        </tc:out>
+      </tc:box>
+    </tc:segmentLayout>
+  </tc:section>
+
+  <tc:section label="Calendar">
+    <tc:date id="calendarDate" label="Calendar" value="#{convertDateTimeController.calendar}">
+      <tc:convertDateTime pattern="dd.MM.yyyy HH:mm:ss" type="calendar"/>
+    </tc:date>
+    <tc:out label="calendarOutput" value="#{convertDateTimeController.calendar}">
+      <tc:convertDateTime pattern="dd.MM.yyyy HH:mm:ss" type="calendar"/>
+    </tc:out>
+  </tc:section>
+
+  <tc:section label="LocalDate">
+    <tc:segmentLayout extraSmall="6seg">
+      <tc:box label="MyFaces 2.3">
+        <tc:panel rendered="#{version.myfaces and version.version23}">
+          <tc:date id="myfacesLocalDateInput" label="LocalDate" value="#{convertDateTimeController.myFacesLocalDate}"
+                   labelLayout="top">
+            <f:convertDateTime pattern="dd.MM.yyyy" type="localDate"/>
+          </tc:date>
+          <tc:out id="myfacesLocalDateOutput" label="Output" value="#{convertDateTimeController.myFacesLocalDate}">
+            <f:convertDateTime pattern="dd.MM.yyyy" type="localDate"/>
+          </tc:out>
+        </tc:panel>
+        <tc:panel rendered="#{!version.myfaces or !version.version23}">
+          <p>MyFaces 2.3 not activated</p>
+        </tc:panel>
+      </tc:box>
+      <tc:box label="Tobago">
+        <tc:date id="tobagoLocalDateInput" label="LocalDate" value="#{convertDateTimeController.tobagoLocalDate}"
+                 labelLayout="top">
+          <tc:convertDateTime pattern="dd.MM.yyyy" type="localDate"/>
+        </tc:date>
+        <tc:out id="tobagoLocalDateOutput" label="Output" value="#{convertDateTimeController.tobagoLocalDate}">
+          <tc:convertDateTime pattern="dd.MM.yyyy" type="localDate"/>
+        </tc:out>
+      </tc:box>
+    </tc:segmentLayout>
+  </tc:section>
+
+  <tc:section label="LocalTime">
+    <tc:segmentLayout extraSmall="6seg">
+      <tc:box label="MyFaces 2.3">
+        <tc:panel rendered="#{version.myfaces and version.version23}">
+          <tc:date id="myfacesLocalTimeInput" label="LocalTime" value="#{convertDateTimeController.myFacesLocalTime}"
+                   labelLayout="top">
+            <f:convertDateTime pattern="HH:mm:ss" type="localTime"/>
+          </tc:date>
+          <tc:out id="myfacesLocalTimeOutput" label="Output" value="#{convertDateTimeController.myFacesLocalTime}">
+            <f:convertDateTime pattern="HH:mm:ss" type="localTime"/>
+          </tc:out>
+        </tc:panel>
+        <tc:panel rendered="#{!version.myfaces or !version.version23}">
+          <p>MyFaces 2.3 not activated</p>
+        </tc:panel>
+      </tc:box>
+      <tc:box label="Tobago">
+        <tc:date id="tobagoLocalTimeInput" label="LocalTime" value="#{convertDateTimeController.tobagoLocalTime}"
+                 labelLayout="top">
+          <tc:convertDateTime pattern="HH:mm:ss" type="localTime"/>
+        </tc:date>
+        <tc:out id="tobagoLocalTimeOutput" label="Output" value="#{convertDateTimeController.tobagoLocalTime}">
+          <tc:convertDateTime pattern="HH:mm:ss" type="localTime"/>
+        </tc:out>
+      </tc:box>
+    </tc:segmentLayout>
+  </tc:section>
+
+  <tc:section label="LocalDateTime">
+    <tc:segmentLayout extraSmall="6seg">
+      <tc:box label="MyFaces 2.3">
+        <tc:panel rendered="#{version.myfaces and version.version23}">
+          <tc:date id="myfacesLocalDateTimeInput" label="LocalDateTime"
+                   value="#{convertDateTimeController.myFacesLocalDateTime}"
+                   labelLayout="top">
+            <f:convertDateTime pattern="dd.MM.yyyy HH:mm:ss" type="localDateTime"/>
+          </tc:date>
+          <tc:out id="myfacesLocalDateTimeOutput" label="Output"
+                  value="#{convertDateTimeController.myFacesLocalDateTime}">
+            <f:convertDateTime pattern="dd.MM.yyyy HH:mm:ss" type="localDateTime"/>
+          </tc:out>
+        </tc:panel>
+        <tc:panel rendered="#{!version.myfaces or !version.version23}">
+          <p>MyFaces 2.3 not activated</p>
+        </tc:panel>
+      </tc:box>
+      <tc:box label="Tobago">
+        <tc:date id="tobagoLocalDateTimeInput" label="LocalDateTime"
+                 value="#{convertDateTimeController.tobagoLocalDateTime}"
+                 labelLayout="top">
+          <tc:convertDateTime pattern="dd.MM.yyyy HH:mm:ss" type="localDateTime"/>
+        </tc:date>
+        <tc:out id="tobagoLocalDateTimeOutput" label="Output" value="#{convertDateTimeController.tobagoLocalDateTime}">
+          <tc:convertDateTime pattern="dd.MM.yyyy HH:mm:ss" type="localDateTime"/>
+        </tc:out>
+      </tc:box>
+    </tc:segmentLayout>
+  </tc:section>
+
+  <tc:section label="OffsetTime">
+    <tc:segmentLayout extraSmall="6seg">
+      <tc:box label="MyFaces 2.3">
+        <tc:panel rendered="#{version.myfaces and version.version23}">
+          <tc:date id="myfacesOffsetTimeInput" label="OffsetTime" value="#{convertDateTimeController.myFacesOffsetTime}"
+                   labelLayout="top">
+            <f:convertDateTime pattern="HH:mm:ss Z" type="offsetTime"/>
+          </tc:date>
+          <tc:out id="myfacesOffsetTimeOutput" label="Output" value="#{convertDateTimeController.myFacesOffsetTime}">
+            <f:convertDateTime pattern="HH:mm:ss" type="offsetTime"/>
+          </tc:out>
+        </tc:panel>
+        <tc:panel rendered="#{!version.myfaces or !version.version23}">
+          <p>MyFaces 2.3 not activated</p>
+        </tc:panel>
+      </tc:box>
+      <tc:box label="Tobago">
+        <tc:date id="tobagoOffsetTimeInput" label="OffsetTime" value="#{convertDateTimeController.tobagoOffsetTime}"
+                 labelLayout="top">
+          <tc:convertDateTime pattern="HH:mm:ss Z" type="offsetTime"/>
+        </tc:date>
+        <tc:out id="tobagoOffsetTimeOutput" label="Output" value="#{convertDateTimeController.tobagoOffsetTime}">
+          <tc:convertDateTime pattern="HH:mm:ss" type="offsetTime"/>
+        </tc:out>
+      </tc:box>
+    </tc:segmentLayout>
+  </tc:section>
+
+  <tc:section label="OffsetDateTime">
+    <tc:segmentLayout extraSmall="6seg">
+      <tc:box label="MyFaces 2.3">
+        <tc:panel rendered="#{version.myfaces and version.version23}">
+          <tc:date id="myfacesOffsetDateTimeInput" label="OffsetDateTime"
+                   value="#{convertDateTimeController.myFacesOffsetDateTime}"
+                   labelLayout="top">
+            <f:convertDateTime pattern="dd.MM.yyyy HH:mm:ss Z" type="offsetDateTime"/>
+          </tc:date>
+          <tc:out id="myfacesOffsetDateTimeOutput" label="Output"
+                  value="#{convertDateTimeController.myFacesOffsetDateTime}">
+            <f:convertDateTime pattern="dd.MM.yyyy HH:mm:ss" type="offsetDateTime"/>
+          </tc:out>
+        </tc:panel>
+        <tc:panel rendered="#{!version.myfaces or !version.version23}">
+          <p>MyFaces 2.3 not activated</p>
+        </tc:panel>
+      </tc:box>
+      <tc:box label="Tobago">
+        <tc:date id="tobagoOffsetDateTimeInput" label="OffsetDateTime"
+                 value="#{convertDateTimeController.tobagoOffsetDateTime}"
+                 labelLayout="top">
+          <tc:convertDateTime pattern="dd.MM.yyyy HH:mm:ss Z" type="offsetDateTime"/>
+        </tc:date>
+        <tc:out id="tobagoOffsetDateTimeOutput" label="Output"
+                value="#{convertDateTimeController.tobagoOffsetDateTime}">
+          <tc:convertDateTime pattern="dd.MM.yyyy HH:mm:ss" type="offsetDateTime"/>
+        </tc:out>
+      </tc:box>
+    </tc:segmentLayout>
+  </tc:section>
+
+  <tc:section label="ZonedDateTime">
+    <tc:segmentLayout extraSmall="6seg">
+      <tc:box label="MyFaces 2.3">
+        <tc:panel rendered="#{version.myfaces and version.version23}">
+          <tc:date id="myfacesZonedDateTimeInput" label="ZonedDateTime"
+                   value="#{convertDateTimeController.myFacesZonedDateTime}"
+                   labelLayout="top">
+            <f:convertDateTime pattern="dd.MM.yyyy HH:mm:ss Z" type="zonedDateTime"/>
+          </tc:date>
+          <tc:out id="myfacesZonedDateTimeOutput" label="Output"
+                  value="#{convertDateTimeController.myFacesZonedDateTime}">
+            <f:convertDateTime pattern="dd.MM.yyyy HH:mm:ss" type="zonedDateTime"/>
+          </tc:out>
+        </tc:panel>
+        <tc:panel rendered="#{!version.myfaces or !version.version23}">
+          <p>MyFaces 2.3 not activated</p>
+        </tc:panel>
+      </tc:box>
+      <tc:box label="Tobago">
+        <tc:date id="tobagoZonedDateTimeInput" label="ZonedDateTime"
+                 value="#{convertDateTimeController.tobagoZonedDateTime}"
+                 labelLayout="top">
+          <tc:convertDateTime pattern="dd.MM.yyyy HH:mm:ss Z" type="zonedDateTime"/>
+        </tc:date>
+        <tc:out id="tobagoZonedDateTimeOutput" label="Output" value="#{convertDateTimeController.tobagoZonedDateTime}">
+          <tc:convertDateTime pattern="dd.MM.yyyy HH:mm:ss" type="zonedDateTime"/>
+        </tc:out>
+      </tc:box>
+    </tc:segmentLayout>
+  </tc:section>
+
+  <tc:button id="submitButton" label="Submit"/>
+</ui:composition>
diff --git a/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/ConverterTag.java b/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/ConverterTag.java
new file mode 100644
index 000000000..1de8a21b4
--- /dev/null
+++ b/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/ConverterTag.java
@@ -0,0 +1,12 @@
+package org.apache.myfaces.tobago.apt.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(value = RetentionPolicy.SOURCE)
+public @interface ConverterTag {
+
+  String converterId();
+
+  String faceletHandler() default "";
+}
diff --git a/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/CheckstyleConfigGenerator.java b/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/CheckstyleConfigGenerator.java
index b80a65acb..ff7bfe74a 100644
--- a/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/CheckstyleConfigGenerator.java
+++ b/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/CheckstyleConfigGenerator.java
@@ -23,6 +23,7 @@
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.myfaces.tobago.apt.AnnotationUtils;
+import org.apache.myfaces.tobago.apt.annotation.ConverterTag;
 import org.apache.myfaces.tobago.apt.annotation.SimpleTag;
 import org.apache.myfaces.tobago.apt.annotation.Tag;
 import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
@@ -150,7 +151,8 @@ protected void appendTag(
       checkDuplicates(annotationTag.name());
       // TODO configure replacement
       final String className;
-      if (typeElement.getAnnotation(SimpleTag.class) != null || typeElement.getAnnotation(ValidatorTag.class) != null) {
+      if (typeElement.getAnnotation(SimpleTag.class) != null || typeElement.getAnnotation(ValidatorTag.class) != null
+          || typeElement.getAnnotation(ConverterTag.class) != null) {
         className = AnnotationUtils.generatedTagName(typeElement);
       } else if (typeElement.getAnnotation(UIComponentTag.class) != null) {
         className = "org.apache.myfaces.tobago.internal.taglib." + StringUtils.capitalize(annotationTag.name())
diff --git a/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/TaglibGenerator.java b/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/TaglibGenerator.java
index ae22bf29d..348e81722 100644
--- a/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/TaglibGenerator.java
+++ b/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/TaglibGenerator.java
@@ -22,6 +22,7 @@
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.myfaces.tobago.apt.AnnotationUtils;
+import org.apache.myfaces.tobago.apt.annotation.ConverterTag;
 import org.apache.myfaces.tobago.apt.annotation.Facet;
 import org.apache.myfaces.tobago.apt.annotation.Markup;
 import org.apache.myfaces.tobago.apt.annotation.Preliminary;
@@ -498,6 +499,16 @@ protected void addTagContent(
       addLeafTextElement(simpleTag.faceletHandler(), "handler-class", tagElement, document);
     }
 
+    final ConverterTag converterTag = typeElement.getAnnotation(ConverterTag.class);
+    if (converterTag != null) {
+      final Element converterElement = document.createElement("converter");
+      tagElement.appendChild(converterElement);
+      addLeafTextElement(converterTag.converterId(), "converter-id", converterElement, document);
+      if (StringUtils.isNotBlank(converterTag.faceletHandler())) {
+        addLeafTextElement(converterTag.faceletHandler(), "handler-class", converterElement, document);
+      }
+    }
+
     final ValidatorTag validatorTag = typeElement.getAnnotation(ValidatorTag.class);
     if (validatorTag != null) {
       final Element validatorElement = document.createElement("validator");


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

Mime
View raw message