    001// Copyright 2012 The Apache Software Foundation
    002//
    003// Licensed under the Apache License, Version 2.0 (the "License");
    004// you may not use this file except in compliance with the License.
    005// You may obtain a copy of the License at
    006//
    007// http://www.apache.org/licenses/LICENSE-2.0
    008//
    009// Unless required by applicable law or agreed to in writing, software
    010// distributed under the License is distributed on an "AS IS" BASIS,
    011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012// See the License for the specific language governing permissions and
    013// limitations under the License.
    014
    015package org.apache.tapestry5.internal.services.messages;
    016
    017import org.apache.tapestry5.internal.util.VirtualResource;
    018import org.apache.tapestry5.ioc.Resource;
    019import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
    020import org.apache.tapestry5.ioc.internal.util.InternalUtils;
    021
    022import java.io.IOException;
    023import java.io.InputStream;
    024import java.net.URL;
    025import java.text.DateFormatSymbols;
    026import java.text.DecimalFormatSymbols;
    027import java.util.*;
    028
    029/**
    030 * Provides a number of symbols related to client-side localization; by exposing these in the global message catalog,
    031 * they are available to the client (via the "t5/core/messages" module).
    032 *
    033 * @since 5.4
    034 */
    035public class ClientLocalizationMessageResource extends VirtualResource
    036{
    037    private final Locale locale;
    038
    039    public ClientLocalizationMessageResource()
    040    {
    041        this(null);
    042    }
    043
    044    ClientLocalizationMessageResource(Locale locale)
    045    {
    046        this.locale = locale;
    047    }
    048
    049    @Override
    050    public Resource withExtension(String extension)
    051    {
    052        return this;
    053    }
    054
    055    @Override
    056    public String getPath()
    057    {
    058        return String.format("<Client localization symbols for locale %s>", locale == null ? "(none)" : locale);
    059    }
    060
    061    @Override
    062    public String getFile()
    063    {
    064        return null;
    065    }
    066
    067    @Override
    068    public URL toURL()
    069    {
    070        return null;
    071    }
    072
    073    @Override
    074    public Resource forLocale(Locale locale)
    075    {
    076        return new ClientLocalizationMessageResource(locale);
    077    }
    078
    079    public InputStream openStream() throws IOException
    080    {
    081        DecimalFormatSymbols decimalSymbols = DecimalFormatSymbols.getInstance(locale);
    082
    083        Map<String, Object> symbols = CollectionFactory.newMap();
    084
    085        symbols.put("decimal-symbols.group", decimalSymbols.getGroupingSeparator());
    086        symbols.put("decimal-symbols.minus", decimalSymbols.getMinusSign());
    087        symbols.put("decimal-symbols.decimal", decimalSymbols.getDecimalSeparator());
    088
    089        DateFormatSymbols dateSymbols = new DateFormatSymbols(locale);
    090
    091        List<String> months = Arrays.asList(dateSymbols.getMonths()).subList(0, 12);
    092
    093        // Comma-separated list, starting with January
    094        symbols.put("date-symbols.months", InternalUtils.join(months, ","));
    095
    096        List<String> days = Arrays.asList(dateSymbols.getWeekdays()).subList(1, 8);
    097
    098        // Comma-separated list, starting with Sunday
    099        symbols.put("date-symbols.days", InternalUtils.join(days, ","));
    100
    101        Calendar c = Calendar.getInstance(locale);
    102
    103        // First day of the week, usually 0 for Sunday (e.g., in the US) or 1 for Monday
    104        // (e.g., France).
    105        symbols.put("date-symbols.first-day", c.getFirstDayOfWeek() - 1);
    106
    107
    108        StringBuilder builder = new StringBuilder();
    109
    110        for (Map.Entry<String, Object> entry : symbols.entrySet())
    111        {
    112            write(builder, entry.getKey(), entry.getValue());
    113        }
    114
    115        return toInputStream(builder.toString());
    116    }
    117
    118    private void write(StringBuilder builder, String name, Object value)
    119    {
    120        builder.append(name).append('=').append(value).append('\n');
    121    }
    122}