/* * This file is part of the Wayback archival access software * (http://archive-access.sourceforge.net/projects/wayback/). * * Licensed to the Internet Archive (IA) by one or more individual * contributors. * * The IA 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.archive.wayback.util; import java.text.DateFormat; import java.text.Format; import java.text.MessageFormat; import java.util.Collection; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; import java.util.TimeZone; import org.apache.commons.lang.StringEscapeUtils; /** * An class which assists in UI generation, primarily through Locale-aware * String formatting, and also helps in escaping (hopefully properly) Strings * for use in HTML. * * Note that date formatting done through this class forces all times to the * UTC timezone - at the moment it appears too confusing to attempt to localize * times in any other way.. * * @author brad * @version $Date$, $Revision$ */ public class StringFormatter { private final static TimeZone TZ_UTC = TimeZone.getTimeZone("UTC"); ResourceBundle bundle = null; Locale locale = null; Map<String,MessageFormat> formats = null; /** * Construct a StringFormatter... * @param bundle ResourceBundle to lookup patterns for MessageFormat * objects. * @param locale to use, where applicable with MessageFormat objects */ public StringFormatter(ResourceBundle bundle) { this(null,Locale.getDefault()); } /** * Construct a StringFormatter... * @param bundle ResourceBundle to lookup patterns for MessageFormat * objects. * @param locale to use, where applicable with MessageFormat objects */ public StringFormatter(ResourceBundle bundle, Locale locale) { this.bundle = bundle; this.locale = locale; formats = new HashMap<String,MessageFormat>(); } public MessageFormat getFormat(String pattern) { MessageFormat format = formats.get(pattern); if(format == null) { format = new MessageFormat(pattern,locale); // lets try to make sure any internal DateFormats use UTC: Format[] subFormats = format.getFormats(); if(subFormats != null) { for(Format subFormat : subFormats) { if(subFormat instanceof DateFormat) { DateFormat subDateFormat = (DateFormat) subFormat; subDateFormat.setTimeZone(TZ_UTC); } } } formats.put(pattern,format); } return format; } /** * Access a localized string associated with key from the ResourceBundle, * likely the UI.properties file. * @param key to lookup in the ResourceBundle * @return localized String version of key argument, or key itself if * something goes wrong... */ public String getLocalized(String key) { if(bundle != null) { try { return bundle.getString(key); // String localized = bundle.getString(key); // if((localized != null) && (localized.length() > 0)) { // return localized; // } } catch (Exception e) { } } return key; } private String formatInner(String key, Object objects[]) { try { return getFormat(getLocalized(key)).format(objects); } catch (Exception e) { // TODO: log message //e.printStackTrace(); } return key; } // What gives? This works in the Junit test, but not in jsps... // /** // * @param key String property name in UI.properties file to use as the // * pattern for interpolation // * @param objects array of things to interpolate within the MessageFormat // * described by the pattern in UI.properties for key key // * @return Localized Formatted String for key, interpolated with args // */ // public String format(String key, Object...objects) { // return formatInner(key,objects); // } /** * Localize a string key from the UI.properties file * @param key String property name in UI.properties file to use as the * pattern for the MessageFormat * @return Localized String for key */ public String format(String key) { Object args[] = {}; return formatInner(key,args); } /** * @param key String property name in UI.properties file to use as the * pattern for interpolation * @param o1 thing1 to interpolate within the MessageFormat * described by the pattern in UI.properties for key key * @return Localized Formatted String for key, interpolated with argument objects */ public String format(String key,Object o1) { Object args[] = {o1}; return formatInner(key,args); } /** * @param key String property name in UI.properties file to use as the * pattern for interpolation * @param o1 thing1 to interpolate within the MessageFormat * described by the pattern in UI.properties for key key * @param o2 thing2 to interpolate within the MessageFormat * described by the pattern in UI.properties for key key * @return Localized Formatted String for key, interpolated with argument objects */ public String format(String key,Object o1,Object o2) { Object args[] = {o1,o2}; return formatInner(key,args); } /** * @param key String property name in UI.properties file to use as the * pattern for interpolation * @param o1 thing1 to interpolate within the MessageFormat * described by the pattern in UI.properties for key key * @param o2 thing2 to interpolate within the MessageFormat * described by the pattern in UI.properties for key key * @param o3 thing3 to interpolate within the MessageFormat * described by the pattern in UI.properties for key key * @return Localized Formatted String for key, interpolated with argument objects */ public String format(String key,Object o1,Object o2,Object o3) { Object args[] = {o1,o2,o3}; return formatInner(key,args); } /** * @param key String property name in UI.properties file to use as the * pattern for interpolation * @param o1 thing1 to interpolate within the MessageFormat * described by the pattern in UI.properties for key key * @param o2 thing2 to interpolate within the MessageFormat * described by the pattern in UI.properties for key key * @param o3 thing3 to interpolate within the MessageFormat * described by the pattern in UI.properties for key key * @param o4 thing4 to interpolate within the MessageFormat * described by the pattern in UI.properties for key key * @return Localized Formatted String for key, interpolated with argument objects */ public String format(String key,Object o1,Object o2,Object o3,Object o4) { Object args[] = {o1,o2,o3,o4}; return formatInner(key,args); } /** * handy shortcut to the apache StringEscapeUtils * @param raw string to be escaped * @return the string escaped so it's safe for insertion in HTML */ public String escapeHtml(String raw) { return StringEscapeUtils.escapeHtml(raw); } /** * handy shortcut to the apache StringEscapeUtils * @param raw string to be escaped * @return the string escaped so it's safe for insertion in Javascript */ public String escapeJavaScript(String raw) { return StringEscapeUtils.escapeJavaScript(raw); } /** * Convert... spaces to   * @param input to replace * @return with spaces replaced */ public String spaceToNBSP(String input) { return input.replaceAll(" ", " "); } public static String join(String delim, String...stuff) { int max = stuff.length - 1; int len = delim.length() * max; for(String s : stuff) { len += s.length(); } StringBuilder sb = new StringBuilder(len); for(int i = 0; i < stuff.length; i++) { sb.append(stuff[i]); if(i < max) { sb.append(delim); } } return sb.toString(); } }