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}