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.commons.Resource;
018import org.apache.tapestry5.commons.util.CollectionFactory;
019import org.apache.tapestry5.internal.util.VirtualResource;
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}