001// Copyright 2006, 2009, 2011 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.commons.util; 016 017import java.util.Locale; 018import java.util.Map; 019 020import org.apache.tapestry5.commons.MessageFormatter; 021import org.apache.tapestry5.commons.Messages; 022import org.apache.tapestry5.commons.internal.util.MessageFormatterImpl; 023 024/** 025 * Abstract implementation of {@link Messages} that doesn't know where values come from (that information is supplied in 026 * a subclass, via the {@link #valueForKey(String)} method). 027 */ 028public abstract class AbstractMessages implements Messages 029{ 030 /** 031 * String key to MF instance. 032 */ 033 private final Map<String, MessageFormatter> cache = CollectionFactory.newConcurrentMap(); 034 035 private final Locale locale; 036 037 protected AbstractMessages(Locale locale) 038 { 039 this.locale = locale; 040 } 041 042 /** 043 * Invoked to provide the value for a particular key. This may be invoked multiple times even for the same key. The 044 * implementation should <em>ignore the case of the key</em>. 045 * 046 * @param key the key to obtain a value for (case insensitive) 047 * @return the value for the key, or null if this instance can not provide the value 048 */ 049 protected abstract String valueForKey(String key); 050 051 052 @Override 053 public boolean contains(String key) 054 { 055 return valueForKey(key) != null; 056 } 057 058 @Override 059 public String get(String key) 060 { 061 if (contains(key)) return valueForKey(key); 062 063 return String.format("[[missing key: %s]]", key); 064 } 065 066 @Override 067 public MessageFormatter getFormatter(String key) 068 { 069 MessageFormatter result = cache.get(key); 070 071 if (result == null) 072 { 073 result = buildMessageFormatter(key); 074 cache.put(key, result); 075 } 076 077 return result; 078 } 079 080 private MessageFormatter buildMessageFormatter(String key) 081 { 082 String format = get(key); 083 084 return new MessageFormatterImpl(format, locale); 085 } 086 087 @Override 088 public String format(String key, Object... args) 089 { 090 return getFormatter(key).format(args); 091 } 092 093}