Browse Source
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@1319 50f2f4bb-b051-0410-bef5-90022cba6387pull/1/head
13 changed files with 682 additions and 18 deletions
@ -1,4 +1,4 @@
@@ -1,4 +1,4 @@
|
||||
#Thu Dec 18 06:34:20 PST 2008 |
||||
#Sat Jun 06 14:43:50 EDT 2009 |
||||
eclipse.preferences.version=1 |
||||
formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile |
||||
formatter_profile=_Spring |
||||
formatter_settings_version=11 |
||||
|
||||
@ -0,0 +1,87 @@
@@ -0,0 +1,87 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed 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.springframework.ui.message; |
||||
|
||||
import java.util.Locale; |
||||
|
||||
import org.springframework.context.MessageSource; |
||||
import org.springframework.context.MessageSourceResolvable; |
||||
import org.springframework.core.style.ToStringCreator; |
||||
|
||||
class DefaultMessageResolver implements MessageResolver, MessageSourceResolvable { |
||||
|
||||
private Severity severity; |
||||
|
||||
private String[] codes; |
||||
|
||||
private Object[] args; |
||||
|
||||
private String defaultText; |
||||
|
||||
public DefaultMessageResolver(Severity severity, String[] codes, Object[] args, String defaultText) { |
||||
this.severity = severity; |
||||
this.codes = codes; |
||||
this.args = args; |
||||
this.defaultText = defaultText; |
||||
} |
||||
|
||||
// implementing MessageResolver
|
||||
|
||||
public Message resolveMessage(MessageSource messageSource, Locale locale) { |
||||
String text = messageSource.getMessage(this, locale); |
||||
return new TextMessage(severity, text); |
||||
} |
||||
|
||||
// implementing MessageSourceResolver
|
||||
|
||||
public String[] getCodes() { |
||||
return codes; |
||||
} |
||||
|
||||
public Object[] getArguments() { |
||||
return args; |
||||
} |
||||
|
||||
public String getDefaultMessage() { |
||||
return defaultText; |
||||
} |
||||
|
||||
public String toString() { |
||||
return new ToStringCreator(this).append("severity", severity).append("codes", codes).append("args", args).append("defaultText", defaultText).toString(); |
||||
} |
||||
|
||||
static class TextMessage implements Message { |
||||
|
||||
private Severity severity; |
||||
|
||||
private String text; |
||||
|
||||
public TextMessage(Severity severity, String text) { |
||||
this.severity = severity; |
||||
this.text = text; |
||||
} |
||||
|
||||
public Severity getSeverity() { |
||||
return severity; |
||||
} |
||||
|
||||
public String getText() { |
||||
return text; |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author oimport java.io.Serializable; |
||||
|
||||
import org.springframework.core.style.ToStringCreator; |
||||
ou 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.springframework.ui.message; |
||||
|
||||
/** |
||||
* Communicates information about an event to the user. |
||||
* For example, a validation message may inform a web application user a business rule was violated. |
||||
* A message is attached to a receiving element, has text providing the basis for communication, |
||||
* and has severity indicating the priority or intensity of the message for its receiver. |
||||
* |
||||
* @author Keith Donald |
||||
*/ |
||||
public interface Message { |
||||
|
||||
/** |
||||
* The severity of this message. |
||||
* The severity indicates the intensity or priority of the communication. |
||||
* @return the message severity |
||||
*/ |
||||
public Severity getSeverity(); |
||||
|
||||
/** |
||||
* The message text. |
||||
* The text is the message's communication payload. |
||||
* @return the message text |
||||
*/ |
||||
public String getText(); |
||||
|
||||
} |
||||
@ -0,0 +1,158 @@
@@ -0,0 +1,158 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed 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.springframework.ui.message; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.LinkedHashSet; |
||||
import java.util.List; |
||||
import java.util.Set; |
||||
|
||||
import org.springframework.context.MessageSource; |
||||
import org.springframework.context.MessageSourceResolvable; |
||||
import org.springframework.core.style.ToStringCreator; |
||||
|
||||
/** |
||||
* A convenient builder for building {@link MessageResolver} objects programmatically. |
||||
* Often used by model code such as validation logic to conveniently record validation messages. |
||||
* Supports the production of message resolvers that hard-code their message text, |
||||
* as well as message resolvers that retrieve their text from a {@link MessageSource}. |
||||
* |
||||
* Usage example: |
||||
* <p> |
||||
* <pre> |
||||
* new MessageBuilder(). |
||||
* severity(Severity.ERROR). |
||||
* code("invalidFormat"). |
||||
* arg("mathForm.decimalField"). |
||||
* arg("#,###.##"). |
||||
* defaultText("The decimal field must be in format #,####.##"). |
||||
* build(); |
||||
* </pre> |
||||
* </p> |
||||
* @author Keith Donald |
||||
*/ |
||||
public class MessageBuilder { |
||||
|
||||
private Set<String> codes = new LinkedHashSet<String>(); |
||||
|
||||
private Severity severity; |
||||
|
||||
private List<Object> args = new ArrayList<Object>(); |
||||
|
||||
private String defaultText; |
||||
|
||||
/** |
||||
* Records the severity of the message. |
||||
* @return this, for fluent API usage |
||||
*/ |
||||
public MessageBuilder severity(Severity severity) { |
||||
this.severity = severity; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Records that the message being built should try and resolve its text using the code provided. |
||||
* Adds the code to the codes list. Successive calls to this method add additional codes. |
||||
* Codes are applied in the order they are added. |
||||
* @param code the message code |
||||
* @return this, for fluent API usage |
||||
*/ |
||||
public MessageBuilder code(String code) { |
||||
codes.add(code); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Records that the message being built has a variable argument. |
||||
* Adds the arg to the args list. Successive calls to this method add additional args. |
||||
* Args are applied in the order they are added. |
||||
* @param arg the message argument value |
||||
* @return this, for fluent API usage |
||||
*/ |
||||
public MessageBuilder arg(Object arg) { |
||||
args.add(arg); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Records that the message being built has a variable argument, whose display value is also {@link MessageSourceResolvable}. |
||||
* Adds the arg to the args list. Successive calls to this method add additional resolvable args. |
||||
* Args are applied in the order they are added. |
||||
* @param arg the resolvable message argument |
||||
* @return this, for fluent API usage |
||||
*/ |
||||
public MessageBuilder resolvableArg(Object arg) { |
||||
args.add(new ResolvableArgument(arg)); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Records the fallback text of the message being built. |
||||
* If the message has no codes, this will always be used as the text. |
||||
* If the message has codes but none can be resolved, this will always be used as the text. |
||||
* @param text the default text |
||||
* @return this, for fluent API usage |
||||
*/ |
||||
public MessageBuilder defaultText(String text) { |
||||
defaultText = text; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Builds the message that will be resolved. |
||||
* Call after recording builder instructions. |
||||
* @return the built message resolver |
||||
*/ |
||||
public MessageResolver build() { |
||||
if (severity == null) { |
||||
severity = Severity.INFO; |
||||
} |
||||
if (codes == null && defaultText == null) { |
||||
throw new IllegalArgumentException( |
||||
"A message code or the message text is required to build this message resolver"); |
||||
} |
||||
String[] codesArray = (String[]) codes.toArray(new String[codes.size()]); |
||||
Object[] argsArray = args.toArray(new Object[args.size()]); |
||||
return new DefaultMessageResolver(severity, codesArray, argsArray, defaultText); |
||||
} |
||||
|
||||
private static class ResolvableArgument implements MessageSourceResolvable { |
||||
|
||||
private Object arg; |
||||
|
||||
public ResolvableArgument(Object arg) { |
||||
this.arg = arg; |
||||
} |
||||
|
||||
public Object[] getArguments() { |
||||
return null; |
||||
} |
||||
|
||||
public String[] getCodes() { |
||||
return new String[] { arg.toString() }; |
||||
} |
||||
|
||||
public String getDefaultMessage() { |
||||
return arg.toString(); |
||||
} |
||||
|
||||
public String toString() { |
||||
return new ToStringCreator(this).append("arg", arg).toString(); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed 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.springframework.ui.message; |
||||
|
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* A context for recording and retrieving messages for display in a user interface. |
||||
*/ |
||||
public interface MessageContext { |
||||
|
||||
/** |
||||
* Return all messages in this context indexed by the UI element they are associated with. |
||||
* @return the message map |
||||
*/ |
||||
public Map<String, List<Message>> getMessages(); |
||||
|
||||
/** |
||||
* Get all messages on the UI element provided. |
||||
* Returns an empty list if no messages have been recorded against the element. |
||||
* Messages are returned in the order they were added. |
||||
* @param element the id of the element to lookup messages against |
||||
*/ |
||||
public List<Message> getMessages(String element); |
||||
|
||||
/** |
||||
* Add a new message to this context. |
||||
* @param element the id of the UI element the message should be associated with |
||||
* @param messageResolver the resolver that will resolve the message to be added |
||||
*/ |
||||
public void addMessage(String element, MessageResolver messageResolver); |
||||
|
||||
} |
||||
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed 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.springframework.ui.message; |
||||
|
||||
import java.util.Locale; |
||||
|
||||
import org.springframework.context.MessageSource; |
||||
|
||||
/** |
||||
* A factory for a Message. Allows a Message to be internationalized and to be resolved from a |
||||
* {@link MessageSource message resource bundle}. |
||||
* |
||||
* @author Keith Donald |
||||
* @see Message |
||||
* @see MessageSource |
||||
*/ |
||||
public interface MessageResolver { |
||||
|
||||
/** |
||||
* Resolve the message from the message source using the current locale. |
||||
* @param messageSource the message source, an abstraction for a resource bundle |
||||
* @param locale the current locale of this request |
||||
* @return the resolved message |
||||
*/ |
||||
public Message resolveMessage(MessageSource messageSource, Locale locale); |
||||
} |
||||
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed 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.springframework.ui.message; |
||||
|
||||
/** |
||||
* Enum exposing supported message severities. |
||||
* |
||||
* @author Keith Donald |
||||
* @author Jeremy Grelle |
||||
* @see Message |
||||
*/ |
||||
public enum Severity { |
||||
|
||||
/** |
||||
* The "Informational" severity. Used to indicate a successful operation or result. |
||||
*/ |
||||
INFO, |
||||
|
||||
/** |
||||
* The "Warning" severity. Used to indicate there is a minor problem, or to inform the message receiver of possible |
||||
* misuse, or to indicate a problem may arise in the future. |
||||
*/ |
||||
WARNING, |
||||
|
||||
/** |
||||
* The "Error" severity. Used to indicate a significant problem like a business rule violation. |
||||
*/ |
||||
ERROR, |
||||
|
||||
/** |
||||
* The "Fatal" severity. Used to indicate a fatal problem like a system error. |
||||
*/ |
||||
FATAL |
||||
|
||||
} |
||||
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
<html> |
||||
<body> |
||||
<p> |
||||
A system for creating and managing localized messages to display in a UI. |
||||
</p> |
||||
</body> |
||||
</html> |
||||
@ -0,0 +1,147 @@
@@ -0,0 +1,147 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed 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.springframework.ui.message.support; |
||||
|
||||
import java.text.MessageFormat; |
||||
import java.util.ArrayList; |
||||
import java.util.LinkedHashMap; |
||||
import java.util.List; |
||||
import java.util.Locale; |
||||
import java.util.Map; |
||||
|
||||
import org.springframework.context.MessageSource; |
||||
import org.springframework.context.i18n.LocaleContextHolder; |
||||
import org.springframework.context.support.AbstractMessageSource; |
||||
import org.springframework.core.style.ToStringCreator; |
||||
import org.springframework.ui.message.Message; |
||||
import org.springframework.ui.message.MessageContext; |
||||
import org.springframework.ui.message.MessageResolver; |
||||
import org.springframework.ui.message.Severity; |
||||
import org.springframework.util.CachingMapDecorator; |
||||
|
||||
import edu.emory.mathcs.backport.java.util.Collections; |
||||
|
||||
/** |
||||
* The default message context implementation. |
||||
* Uses a {@link MessageSource} to resolve messages that are added by callers. |
||||
* |
||||
* @author Keith Donald |
||||
*/ |
||||
public class DefaultMessageContext implements MessageContext { |
||||
|
||||
private MessageSource messageSource; |
||||
|
||||
@SuppressWarnings("serial") |
||||
private Map<String, ArrayList<Message>> messagesByElement = new CachingMapDecorator<String, ArrayList<Message>>(new LinkedHashMap<String, ArrayList<Message>>()) { |
||||
protected ArrayList<Message> create(String element) { |
||||
return new ArrayList<Message>(); |
||||
} |
||||
}; |
||||
|
||||
/** |
||||
* Creates a new default message context. |
||||
* Defaults to a message source that simply resolves default text and cannot resolve localized message codes. |
||||
*/ |
||||
public DefaultMessageContext() { |
||||
init(null); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new default message context. |
||||
* @param messageSource the message source to resolve messages added to this context |
||||
*/ |
||||
public DefaultMessageContext(MessageSource messageSource) { |
||||
init(messageSource); |
||||
} |
||||
|
||||
/** |
||||
* The message source configured to resolve message text. |
||||
* @return the message source |
||||
*/ |
||||
public MessageSource getMessageSource() { |
||||
return messageSource; |
||||
} |
||||
|
||||
// implementing message context
|
||||
|
||||
@SuppressWarnings("unchecked") |
||||
public Map<String, List<Message>> getMessages() { |
||||
return Collections.unmodifiableMap(messagesByElement); |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
public List<Message> getMessages(String element) { |
||||
List<Message> messages = messagesByElement.get(element); |
||||
if (messages.isEmpty()) { |
||||
return Collections.emptyList(); |
||||
} |
||||
return Collections.unmodifiableList(messages); |
||||
} |
||||
|
||||
public void addMessage(String element, MessageResolver messageResolver) { |
||||
List<Message> messages = messagesByElement.get(element); |
||||
messages.add(new ResolvableMessage(messageResolver)); |
||||
} |
||||
|
||||
public String toString() { |
||||
return new ToStringCreator(this).append("messagesByElement", messagesByElement).toString(); |
||||
} |
||||
|
||||
// internal helpers
|
||||
|
||||
private void init(MessageSource messageSource) { |
||||
setMessageSource(messageSource); |
||||
} |
||||
|
||||
private void setMessageSource(MessageSource messageSource) { |
||||
if (messageSource == null) { |
||||
messageSource = new DefaultTextFallbackMessageSource(); |
||||
} |
||||
this.messageSource = messageSource; |
||||
} |
||||
|
||||
private static class DefaultTextFallbackMessageSource extends AbstractMessageSource { |
||||
protected MessageFormat resolveCode(String code, Locale locale) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
class ResolvableMessage implements Message { |
||||
|
||||
private MessageResolver resolver; |
||||
|
||||
private Message resolvedMessage; |
||||
|
||||
public ResolvableMessage(MessageResolver resolver) { |
||||
this.resolver = resolver; |
||||
} |
||||
|
||||
public Severity getSeverity() { |
||||
return getMessage().getSeverity(); |
||||
} |
||||
|
||||
public String getText() { |
||||
return getMessage().getText(); |
||||
} |
||||
|
||||
public Message getMessage() { |
||||
if (resolvedMessage == null) { |
||||
resolvedMessage = resolver.resolveMessage(messageSource, LocaleContextHolder.getLocale()); |
||||
} |
||||
return resolvedMessage; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
package org.springframework.ui.message; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
|
||||
import java.util.Locale; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.context.support.StaticMessageSource; |
||||
|
||||
public class MessageBuilderTests { |
||||
private MessageBuilder builder = new MessageBuilder(); |
||||
|
||||
@Test |
||||
public void buildMessage() { |
||||
MessageResolver resolver = builder.severity(Severity.ERROR).code("invalidFormat").resolvableArg("mathForm.decimalField") |
||||
.arg("#,###.##").defaultText("Field must be in format #,###.##").build(); |
||||
StaticMessageSource messageSource = new StaticMessageSource(); |
||||
messageSource.addMessage("invalidFormat", Locale.US, "{0} must be in format {1}"); |
||||
messageSource.addMessage("mathForm.decimalField", Locale.US, "Decimal Field"); |
||||
Message message = resolver.resolveMessage(messageSource, Locale.US); |
||||
assertEquals(Severity.ERROR, message.getSeverity()); |
||||
assertEquals("Decimal Field must be in format #,###.##", message.getText()); |
||||
} |
||||
} |
||||
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
package org.springframework.ui.message.support; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
import java.util.List; |
||||
import java.util.Locale; |
||||
import java.util.Map; |
||||
|
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.springframework.context.support.StaticMessageSource; |
||||
import org.springframework.ui.message.Message; |
||||
import org.springframework.ui.message.MessageBuilder; |
||||
import org.springframework.ui.message.MessageResolver; |
||||
import org.springframework.ui.message.Severity; |
||||
|
||||
public class DefaultMessageContextTests { |
||||
|
||||
private DefaultMessageContext context; |
||||
|
||||
@Before |
||||
public void setUp() { |
||||
StaticMessageSource messageSource = new StaticMessageSource(); |
||||
messageSource.addMessage("invalidFormat", Locale.US, "{0} must be in format {1}"); |
||||
messageSource.addMessage("mathForm.decimalField", Locale.US, "Decimal Field"); |
||||
context = new DefaultMessageContext(messageSource); |
||||
} |
||||
|
||||
@Test |
||||
public void addMessage() { |
||||
MessageBuilder builder = new MessageBuilder(); |
||||
MessageResolver message = builder.severity(Severity.ERROR).code("invalidFormat").resolvableArg( |
||||
"mathForm.decimalField").arg("#,###.##").defaultText("Field must be in format #,###.##").build(); |
||||
context.addMessage("mathForm.decimalField", message); |
||||
Map<String, List<Message>> messages = context.getMessages(); |
||||
assertEquals(1, messages.size()); |
||||
assertEquals("Decimal Field must be in format #,###.##", messages.get("mathForm.decimalField").get(0).getText()); |
||||
assertEquals("Decimal Field must be in format #,###.##", context.getMessages("mathForm.decimalField").get(0).getText()); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue