package org.jboss.seam.international;
import static org.jboss.seam.international.StatusMessage.Severity.INFO;
import static org.jboss.seam.international.StatusMessage.Severity.WARN;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.validation.ConstraintViolation;
import org.jboss.seam.Component;
import org.jboss.seam.international.StatusMessage.Severity;
/**
* Abstract base class for providing status messages. View layers should provide
* a concrete implementation.
*
* @author Pete Muir
*
*/
public abstract class StatusMessages implements Serializable
{
private static final long serialVersionUID = -5395975397632138270L;
public static final String COMPONENT_NAME = "org.jboss.seam.international.statusMessages";
private List<StatusMessage> messages = new ArrayList<StatusMessage>();
private Map<String, List<StatusMessage>> keyedMessages = new HashMap<String, List<StatusMessage>>();
private transient List<Runnable> tasks;
protected List<StatusMessage> getMessages()
{
return messages;
}
protected Map<String, List<StatusMessage>> getKeyedMessages()
{
return keyedMessages;
}
/**
* Clear all status messages
*/
public void clear()
{
messages.clear();
keyedMessages.clear();
}
public void clearKeyedMessages(String id)
{
keyedMessages.remove(id);
}
public void clearGlobalMessages()
{
messages.clear();
}
/**
* Add a status message, looking up the message in the resource bundle
* using the provided key. If the message is found, it is used, otherwise,
* the defaultMessageTemplate will be used.
*
* You can also specify the severity, and parameters to be interpolated
*/
public void add(Severity severity, String key, String detailKey, String messageTemplate, String messageDetailTemplate, final Object... params)
{
final StatusMessage message = new StatusMessage(severity, key, detailKey, messageTemplate, messageDetailTemplate);
if (!message.isEmpty())
{
messages.add(message);
getTasks().add(
new Runnable()
{
public void run()
{
message.interpolate(params);
}
}
);
}
}
/**
* Add a status message, looking up the message in the resource bundle
* using the provided key. If the message is found, it is used, otherwise,
* the defaultMessageTemplate will be used.
*
* The message will be added to the widget specified by the ID. The algorithm
* used determine which widget the id refers to is determined by the view
* layer implementation in use.
*
* You can also specify the severity, and parameters to be interpolated
*
*/
public void addToControl(String id, Severity severity, String key, String messageTemplate, final Object... params)
{
final StatusMessage message = new StatusMessage(severity, key, null, messageTemplate, null);
if (!message.isEmpty())
{
if (keyedMessages.containsKey(id))
{
keyedMessages.get(id).add(message);
}
else
{
List<StatusMessage> list = new ArrayList<StatusMessage>();
list.add(message);
keyedMessages.put(id, list);
}
getTasks().add(
new Runnable()
{
public void run()
{
message.interpolate(params);
}
}
);
}
}
/**
* Create a new status message, with the messageTemplate is as the message.
*
* A severity of INFO will be used, and you can specify paramters to be
* interpolated
*/
public void add(String messageTemplate, Object... params)
{
add(INFO, messageTemplate, params);
}
/**
* Create a new status message, with the messageTemplate is as the message.
*
* You can also specify the severity, and parameters to be interpolated
*
*/
public void add(Severity severity, String messageTemplate, Object... params)
{
add(severity, null, null, messageTemplate, null, params);
}
/**
* Create a new status message, with the messageTemplate is as the message.
*
* The message will be added to the widget specified by the ID. The algorithm
* used determine which widget the id refers to is determined by the view
* layer implementation in use.
*
* A severity of INFO will be used, and you can specify parameters to be
* interpolated
*
*/
public void addToControl(String id, String messageTemplate, Object... params)
{
addToControl(id, INFO, null, messageTemplate, params);
}
/**
* Create a new status message, with the messageTemplate is as the message.
*
* The message will be added to the widget specified by the ID. The algorithm
* used determine which widget the id refers to is determined by the view
* layer implementation in use.
*
* You can also specify the severity, and parameters to be interpolated
*
*/
public void addToControl(String id, Severity severity, String messageTemplate, Object... params)
{
addToControl(id, severity, null, messageTemplate, params);
}
/**
* Add a status message, looking up the message in the resource bundle
* using the provided key. If the message is found, it is used, otherwise,
* the defaultMessageTemplate will be used.
*
* A severity of INFO will be used, and you can specify parameters to be
* interpolated
*/
public void addFromResourceBundle(String key, Object... params)
{
addFromResourceBundle(INFO, key, params);
}
/**
* Add a status message, looking up the message in the resource bundle
* using the provided key.
*
* You can also specify the severity, and parameters to be interpolated
*
*/
public void addFromResourceBundle(Severity severity, String key, Object... params)
{
addFromResourceBundleOrDefault(severity, key, key, params);
}
/**
* Add a status message, looking up the message in the resource bundle
* using the provided key. If the message is found, it is used, otherwise,
* the defaultMessageTemplate will be used.
*
* A severity of INFO will be used, and you can specify parameters to be
* interpolated
*
*/
public void addFromResourceBundleOrDefault(String key, String defaultMessageTemplate, Object... params)
{
addFromResourceBundleOrDefault(INFO, key, defaultMessageTemplate, params);
}
/**
* Add a status message, looking up the message in the resource bundle
* using the provided key. If the message is found, it is used, otherwise,
* the defaultMessageTemplate will be used.
*
* You can also specify the severity, and parameters to be interpolated
*
*/
public void addFromResourceBundleOrDefault(Severity severity, String key, String defaultMessageTemplate, Object... params)
{
add(severity, key, null, defaultMessageTemplate, null, params);
}
/**
* Create a new status message, looking up the message in the resource bundle
* using the provided key.
*
* The message will be added to the widget specified by the ID. The algorithm
* used determine which widget the id refers to is determined by the view
* layer implementation in use.
*
* A severity of INFO will be used, and you can specify parameters to be
* interpolated
*
*/
public void addToControlFromResourceBundle(String id, String key, Object... params)
{
addToControlFromResourceBundle(id, INFO, key, params);
}
/**
* Create a new status message, looking up the message in the resource bundle
* using the provided key.
*
* The message will be added to the widget specified by the ID. The algorithm
* used determine which widget the id refers to is determined by the view
* layer implementation in use.
*
* You can also specify the severity, and parameters to be interpolated
*
*/
public void addToControlFromResourceBundle(String id, Severity severity, String key, Object... params)
{
addToControlFromResourceBundleOrDefault(id, severity, key, key, params);
}
/**
* Add a status message, looking up the message in the resource bundle
* using the provided key. If the message is found, it is used, otherwise,
* the defaultMessageTemplate will be used.
*
* The message will be added to the widget specified by the ID. The algorithm
* used determine which widget the id refers to is determined by the view
* layer implementation in use.
*
* A severity of INFO will be used, and you can specify parameters to be
* interpolated
*
*/
public void addToControlFromResourceBundleOrDefault(String id, String key, String defaultMessageTemplate, Object... params)
{
addToControlFromResourceBundleOrDefault(id, INFO, key, defaultMessageTemplate, params);
}
/**
* Add a status message, looking up the message in the resource bundle
* using the provided key. If the message is found, it is used, otherwise,
* the defaultMessageTemplate will be used.
*
* The message will be added to the widget specified by the ID. The algorithm
* used determine which widget the id refers to is determined by the view
* layer implementation in use.
*
* You can also specify the severity, and parameters to be interpolated
*
*/
public void addToControlFromResourceBundleOrDefault(String id, Severity severity, String key, String defaultMessageTemplate, Object... params)
{
addToControl(id, severity, key, defaultMessageTemplate, params);
}
/**
* Add an array of InvalidValues from Hibernate Validator. Each message will
* be added with a severity of WARN.
*/
public void add(Set<ConstraintViolation<Object>> ivs)
{
for (ConstraintViolation<Object> iv: ivs)
{
add(iv);
}
}
/**
* Add an array of InvalidValues from Hibernate Validator. Each message will
* be added with a severity of WARN.
*
* The name of the property that was validated will be used as the widget ID
*/
/*public void addToControls(Set<ConstraintViolation<Object>> ivs)
{
for (ConstraintViolation<Object> iv: ivs)
{
addToControl(iv);
}
}*/
/**
* Add an InvalidValue from Hibernate Validator. The message will
* be added with a severity of WARN.
*/
public void add(ConstraintViolation<Object> iv)
{
add( WARN, iv.getMessage() );
}
/**
* Add an InvalidValue from Hibernate Validator. The message will
* be added with a severity of WARN.
*
* The name of the property that was validated will be used as the widget ID
*/
/*public void addToControl(ConstraintViolation<Object> iv)
{
addToControl( iv.getInvalidValue().toString(), iv );
}*/
/**
* Add an InvalidValue from Hibernate Validator. The message will
* be added with a severity of WARN.
*
* You can also specify the id of the widget to add the message to
*/
public void addToControl(String id, ConstraintViolation<Object> iv)
{
addToControl( id, WARN, iv.getMessage() );
}
private List<Runnable> getTasks()
{
if (tasks == null)
{
tasks = new ArrayList<Runnable>();
}
return tasks;
}
protected static void runTasks()
{
Component component = Component.forName(StatusMessages.COMPONENT_NAME);
if( component != null && !component.getScope().isContextActive() )
{
return;
}
//Attempting to get the instance anyway for backwards compatibility with some potential hack situations.
StatusMessages statusMessages = instance();
if ( statusMessages != null )
{
statusMessages.doRunTasks();
}
}
protected void doRunTasks()
{
if (tasks!=null)
{
for (Runnable task: tasks) task.run();
tasks.clear();
}
}
public static StatusMessages instance()
{
Component component = Component.forName(StatusMessages.COMPONENT_NAME);
if(component != null && !component.getScope().isContextActive())
{
throw new IllegalStateException("No active "+component.getScope().name()+" context");
}
//Attempting to get the instance anyway for backwards compatibility with some potential hack situations.
return (StatusMessages) Component.getInstance(COMPONENT_NAME);
}
}