001    /*
002     * Copyright 2002-2004 the original author or authors.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005     * use this file except in compliance with the License. You may obtain a copy of
006     * the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012     * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013     * License for the specific language governing permissions and limitations under
014     * the License.
015     */
016    package org.springframework.richclient.core;
017    
018    import java.io.Serializable;
019    
020    import javax.swing.Icon;
021    import javax.swing.JComponent;
022    import javax.swing.JLabel;
023    import javax.swing.text.JTextComponent;
024    
025    import org.springframework.core.style.ToStringCreator;
026    import org.springframework.richclient.application.ApplicationServicesLocator;
027    import org.springframework.richclient.image.IconSource;
028    import org.springframework.richclient.image.NoSuchImageResourceException;
029    import org.springframework.richclient.util.LabelUtils;
030    import org.springframework.util.ObjectUtils;
031    
032    /**
033     * The default implementation of the {@link Message} interface. This class is
034     * capable of rendering itself on {@link JTextComponent}s and {@link JLabel}s.
035     * In the case of labels, it is also able to lookup an icon to be displayed on
036     * the label.
037     *
038     * @see #getIcon()
039     *
040     */
041    public class DefaultMessage implements Message, Serializable {
042    
043        private static final long serialVersionUID = -6524078363891514995L;
044    
045            private final long timestamp;
046    
047        private final String message;
048    
049        private final Severity severity;
050    
051        /**
052         * A convenience instance representing an empty message. i.e. The message text
053         * is empty and there is no associated severity.
054         */
055        public static final DefaultMessage EMPTY_MESSAGE = new DefaultMessage("", null);
056    
057        /**
058         * Creates a new {@code DefaultMessage} with the given text and a default
059         * severity of {@link Severity#INFO}.
060         *
061         * @param text The message text.
062         */
063        public DefaultMessage(String text) {
064            this(text, Severity.INFO);
065        }
066    
067        /**
068         * Creates a new {@code DefaultMessage} with the given text and severity.
069         *
070         * @param message The message text.
071         * @param severity The severity of the message. May be null.
072         */
073        public DefaultMessage(String message, Severity severity) {
074            if (message == null) {
075                message = "";
076            }
077            this.timestamp = System.currentTimeMillis();
078            this.message = message;
079            this.severity = severity;
080        }
081    
082        public long getTimestamp() {
083            return timestamp;
084        }
085    
086        public String getMessage() {
087            return message;
088        }
089    
090        public Severity getSeverity() {
091            return severity;
092        }
093    
094        /**
095         * Renders this message on the given GUI component. This implementation only
096         * supports components of type {@link JTextComponent} or {@link JLabel}.
097         *
098         * @throws IllegalArgumentException if {@code component} is not a {@link JTextComponent}
099         * or a {@link JLabel}.
100         */
101        public void renderMessage(JComponent component) {
102            if (component instanceof JTextComponent) {
103                ((JTextComponent)component).setText(getMessage());
104            }
105            else if (component instanceof JLabel) {
106                JLabel label = (JLabel)component;
107                label.setText(LabelUtils.htmlBlock(getMessage()));
108                label.setIcon(getIcon());
109            }
110            else {
111                throw new IllegalArgumentException("Unsupported component type " + component);
112            }
113        }
114    
115        /**
116         * Returns the icon associated with this instance's severity. The icon is
117         * expected to be retrieved using a key {@code severity.<SEVERITY_LABEL>}.
118         *
119         * @return The icon associated with this instance's severity, or null if the
120         * instance has no specified severity, or the icon could not be found.
121         *
122         * @see Severity#getLabel()
123         * @see IconSource#getIcon(String)
124         */
125        public Icon getIcon() {
126            if (severity == null) {
127                return null;
128            }
129            try {
130                IconSource iconSource = (IconSource)ApplicationServicesLocator.services().getService(IconSource.class);
131                return iconSource.getIcon("severity." + severity.getLabel());
132            }
133            catch (NoSuchImageResourceException e) {
134                return null;
135            }
136        }
137    
138        public boolean equals(Object o) {
139            if (!(o instanceof DefaultMessage)) {
140                return false;
141            }
142            DefaultMessage other = (DefaultMessage)o;
143            return this.message.equals(other.message) && ObjectUtils.nullSafeEquals(this.severity, other.severity);
144        }
145    
146        public int hashCode() {
147            return message.hashCode() + (severity != null ? severity.hashCode() : 0);
148        }
149    
150        public String toString() {
151            return new ToStringCreator(this).append("message", message).append("severity", severity).toString();
152        }
153    }