001/*
002 * (C) Copyright 2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Anahide Tchertchian
018 */
019package org.nuxeo.ecm.platform.ui.web.tag.handler;
020
021import java.text.ParseException;
022import java.text.SimpleDateFormat;
023import java.util.Date;
024import java.util.TimeZone;
025
026import javax.faces.view.facelets.ComponentConfig;
027import javax.faces.view.facelets.FaceletContext;
028import javax.faces.view.facelets.MetaRule;
029import javax.faces.view.facelets.MetaRuleset;
030import javax.faces.view.facelets.Metadata;
031import javax.faces.view.facelets.MetadataTarget;
032import javax.faces.view.facelets.TagAttribute;
033import javax.faces.view.facelets.TagAttributes;
034
035import org.apache.commons.logging.Log;
036import org.apache.commons.logging.LogFactory;
037import org.jboss.seam.international.LocaleSelector;
038import org.jboss.seam.international.TimeZoneSelector;
039import org.richfaces.component.UICalendar;
040
041/**
042 * @since 5.4.2
043 */
044public class InputDateTimeTagHandler extends GenericHtmlComponentHandler {
045
046    private static final Log log = LogFactory.getLog(InputDateTimeTagHandler.class);
047
048    protected final String defaultTime;
049
050    /**
051     * @since 5.7.2
052     */
053    protected TagAttributes attributes;
054
055    public InputDateTimeTagHandler(ComponentConfig config) {
056        super(config);
057        attributes = config.getTag().getAttributes();
058        defaultTime = getValue(attributes, "defaultTime", "12:00");
059    }
060
061    protected String getValue(TagAttributes attrs, String name, String defaultValue) {
062        TagAttribute attr = attrs.get(name);
063        if (attr == null) {
064            return defaultValue;
065        }
066        return attr.getValue();
067    }
068
069    @Override
070    @SuppressWarnings("rawtypes")
071    protected MetaRuleset createMetaRuleset(Class type) {
072        MetaRuleset m = super.createMetaRuleset(type);
073
074        // aliases for the old date time component compatibility
075        m.alias("format", "datePattern");
076        // showsTime is not configurable anymore
077        m.ignore("showsTime");
078        // locale ok
079        // timeZone ok, just need to convert string to a TimeZone instance
080        m.addRule(new TimeZoneMetaRule());
081        // do not bind styleClass to inputClass anymore: styleClass can be
082        // taken into account but the datetime widget itself, see NXP-14963.
083        // m.alias("styleClass", "inputClass");
084        m.alias("triggerLabel", "buttonLabel");
085        m.alias("triggerImg", "buttonIcon");
086        m.alias("triggerStyleClass", "buttonClass");
087
088        m.alias("onclick", "oninputclick");
089
090        // setup some default properties
091        m.add(new TagMetaData());
092
093        // onchange and onselect not working anymore, but keep them in case
094        // this is solved one day
095        // m.ignore("onchange");
096        // m.ignore("onselect");
097
098        return m;
099
100    }
101
102    class TimeZoneMetaRule extends MetaRule {
103
104        public Metadata applyRule(String name, TagAttribute attribute, MetadataTarget meta) {
105            if (!"timeZone".equals(name)) {
106                return null;
107            }
108            return new Metadata() {
109                @Override
110                public void applyMetadata(FaceletContext ctx, Object instance) {
111                    Object tz = attribute.getObject(ctx);
112                    if (tz instanceof TimeZone) {
113                        ((UICalendar) instance).setTimeZone((TimeZone) tz);
114                    } else if (tz instanceof String) {
115                        ((UICalendar) instance).setTimeZone(TimeZone.getTimeZone((String) tz));
116                    } else {
117                        throw new IllegalArgumentException("Invalid timezone: " + tz);
118                    }
119                }
120            };
121        }
122    }
123
124    class TagMetaData extends Metadata {
125
126        public TagMetaData() {
127            super();
128        }
129
130        @Override
131        public void applyMetadata(FaceletContext ctx, Object instance) {
132            if (!(instance instanceof UICalendar)) {
133                log.error("Cannot apply date time component metadata, " + "not a HtmlCalendar instance: " + instance);
134                return;
135            }
136            UICalendar c = (UICalendar) instance;
137            TimeZone tz = c.getTimeZone();
138            if (tz == null) {
139                // set default timezone only if not already specified in the component
140                c.setTimeZone(TimeZoneSelector.instance().getTimeZone());
141            }
142            c.setLocale(LocaleSelector.instance().getLocale());
143        }
144    }
145
146    @Override
147    public void setAttributes(FaceletContext ctx, Object instance) {
148        super.setAttributes(ctx, instance);
149        // set default time in timezone
150        UICalendar c = (UICalendar) instance;
151        c.setPopup(Boolean.parseBoolean(getValue(attributes, "popup", "true")));
152        c.setEnableManualInput(Boolean.parseBoolean(getValue(attributes, "enableManualInput", "true")));
153        c.setShowApplyButton(Boolean.parseBoolean(getValue(attributes, "showApplyButton", "false")));
154        c.setZindex(Integer.parseInt(getValue(attributes, "zindex", "1500")));
155        setDefaultTime(c);
156    }
157
158    protected void setDefaultTime(UICalendar instance) {
159        SimpleDateFormat format = new SimpleDateFormat("HH:mm");
160        format.setTimeZone(instance.getTimeZone());
161        Date date;
162        try {
163            date = format.parse(defaultTime);
164        } catch (ParseException e) {
165            return;
166        }
167        instance.setDefaultTime(date);
168    }
169}