package org.marketcetera.util.l10n;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.marketcetera.util.except.I18NException;
import org.marketcetera.util.log.I18NBoundMessage1P;
import org.marketcetera.util.log.I18NMessageProvider;
import org.marketcetera.util.misc.ClassVersion;
/**
* Holder of meta-information about a properties file that maps
* message keys to message text.
*
* @see org.marketcetera.util.log
*
* @author tlerios@marketcetera.com
* @since 0.6.0
* @version $Id: PropertiesFileInfo.java 16154 2012-07-14 16:34:05Z colin $
*/
/* $License$ */
@ClassVersion("$Id: PropertiesFileInfo.java 16154 2012-07-14 16:34:05Z colin $")
public class PropertiesFileInfo
implements MessageInfoProvider
{
// CLASS DATA.
private static final Pattern PARAM_PATTERN=
Pattern.compile("\\{(\\d+)"); //$NON-NLS-1$
// INSTANCE DATA.
private I18NMessageProvider mProvider;
private Locale mLocale;
private List<MessageInfo> mMessageInfo;
// CONSTRUCTORS.
/**
* Creates a new meta-information holder for the properties file
* associated with the given provider and locale.
*
* @param provider The provider.
* @param locale The locale. Use {@link Locale#ROOT} for the
* fallback properties file.
*
* @throws I18NException Thrown if there is an I/O error while
* attempting to read the properties file.
*/
public PropertiesFileInfo
(I18NMessageProvider provider,
Locale locale)
throws I18NException
{
mProvider=provider;
mLocale=locale;
// Build file name.
StringBuilder builder=new StringBuilder();
builder.append(getProvider().getProviderId());
builder.append(I18NMessageProvider.MESSAGE_FILE_EXTENSION);
if (getLocale()!=Locale.ROOT) {
builder.append('_'); //$NON-NLS-1$
builder.append(getLocale().toString());
}
builder.append(".properties"); //$NON-NLS-1$
String fileName=builder.toString();
// Load file as a resource.
InputStream stream=getProvider().getClass().getClassLoader().
getResourceAsStream(fileName);
if (stream==null) {
throw new I18NException(new I18NBoundMessage1P
(Messages.NONEXISTENT_RESOURCE,fileName));
}
Properties properties=new Properties();
try {
properties.load(stream);
} catch (IOException ex) {
throw new I18NException
(ex,new I18NBoundMessage1P(Messages.LOADING_FAILED,fileName));
}
// Analyze file entries.
mMessageInfo=new LinkedList<MessageInfo>();
for (String key:properties.stringPropertyNames()) {
String messageText=properties.getProperty(key);
try {
new MessageFormat(messageText,getLocale());
} catch (IllegalArgumentException ex) {
throw new I18NException
(ex,new I18NBoundMessage1P(Messages.BAD_TEXT,messageText));
}
Matcher matcher=PARAM_PATTERN.matcher(messageText);
int maxIndex=-1;
while (matcher.find()) {
int index=Integer.valueOf(matcher.group(1));
if (index>maxIndex) {
maxIndex=index;
}
}
mMessageInfo.add
(new PropertyMessageInfo(key,maxIndex+1,messageText));
}
}
/**
* Creates a new meta-information holder for the fallback
* properties file associated with the given provider.
*
* @param provider The provider.
*
* @throws I18NException Thrown if there is an I/O error while
* attempting to read the properties file.
*/
public PropertiesFileInfo
(I18NMessageProvider provider)
throws I18NException
{
this(provider,Locale.ROOT);
}
// INSTANCE METHODS.
/**
* Returns the receiver's message provider.
*
* @return The provider.
*/
public I18NMessageProvider getProvider()
{
return mProvider;
}
/**
* Returns the receiver's locale.
*
* @return The locale. It is null for the fallback properties
* file.
*/
public Locale getLocale()
{
return mLocale;
}
// MessageInfoProvider.
@Override
public List<MessageInfo> getMessageInfo()
{
return mMessageInfo;
}
}