001    /*
002     *  jDTAUS Core API
003     *  Copyright (c) 2005 Christian Schulte
004     *
005     *  Christian Schulte, Haldener Strasse 72, 58095 Hagen, Germany
006     *  <schulte2005@users.sourceforge.net> (+49 2331 3543887)
007     *
008     *  This library is free software; you can redistribute it and/or
009     *  modify it under the terms of the GNU Lesser General Public
010     *  License as published by the Free Software Foundation; either
011     *  version 2.1 of the License, or any later version.
012     *
013     *  This library is distributed in the hope that it will be useful,
014     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
015     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
016     *  Lesser General Public License for more details.
017     *
018     *  You should have received a copy of the GNU Lesser General Public
019     *  License along with this library; if not, write to the Free Software
020     *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
021     *
022     */
023    package org.jdtaus.core.text;
024    
025    import java.io.Serializable;
026    import java.rmi.server.UID;
027    import java.util.Comparator;
028    import java.util.Locale;
029    
030    /**
031     * Application message.
032     * <p>Application messages consist of at least the two properties
033     * {@code timestamp} and {@code formatArguments}. The {@code timestamp} property
034     * will be initialized during instantiation to hold the timestamp of instance
035     * creation. Property {@code formatArguments} holds the arguments to use
036     * for formatting message text. It is recommended that subclasses of this class
037     * are declared {@code final} so that calling {@code getClass()} on a message
038     * instance always returns a type uniquely identifying a message type in the
039     * system.</p>
040     *
041     * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a>
042     * @version $Id: Message.java 8044 2009-07-02 01:29:05Z schulte2005 $
043     *
044     * @see MessageEvent
045     */
046    public abstract class Message implements Cloneable, Serializable
047    {
048        //--Constants---------------------------------------------------------------
049    
050        /**
051         * Comparator for sorting messages in ascending order of occurence.
052         * <p><b>Note:</b><br/>
053         * This comparator imposes orderings that are inconsistent with equals.</p>
054         */
055        public static final Comparator ASCENDING =
056            new AscendingMessageComparator();
057    
058        /**
059         * Comparator for sorting messages in descending order of occurence.
060         * <p><b>Note:</b><br/>
061         * This comparator imposes orderings that are inconsistent with equals.</p>
062         */
063        public static final Comparator DESCENDING =
064            new DescendingMessageComparator();
065    
066        /** Serial version UID for backwards compatibility with 1.0.x classes. */
067        private static final long serialVersionUID = -5747726994506247015L;
068    
069        //---------------------------------------------------------------Constants--
070        //--Constructors------------------------------------------------------------
071    
072        /** Creates a new {@code Message} instance. */
073        public Message()
074        {
075            super();
076            this.timestamp = System.currentTimeMillis();
077            this.uid = new UID();
078        }
079    
080        //------------------------------------------------------------Constructors--
081        //--Message-----------------------------------------------------------------
082    
083        /**
084         * Unique message identifier.
085         * @serial
086         */
087        private UID uid;
088    
089        /**
090         * The timestamp this message got created.
091         * @serial
092         */
093        private long timestamp;
094    
095        /**
096         * Getter for property {@code timestamp}.
097         *
098         * @return the timestamp this message got created.
099         */
100        public final long getTimestamp()
101        {
102            return this.timestamp;
103        }
104    
105        /**
106         * Getter for property {@code formatArguments}.
107         *
108         * @param locale the locale to be used for the arguments to return.
109         *
110         * @return the arguments to use when formatting the message text.
111         */
112        public abstract Object[] getFormatArguments( Locale locale );
113    
114        /**
115         * Gets the formatted message text.
116         *
117         * @param locale the locale to be used for the text to return.
118         *
119         * @return the text of the message for {@code locale}.
120         */
121        public abstract String getText( Locale locale );
122    
123        /**
124         * Creates a string representing the properties of the instance.
125         *
126         * @return a string representing the properties of the instance.
127         */
128        private String internalString()
129        {
130            final StringBuffer buf = new StringBuffer( 500 );
131    
132            buf.append( "\n\ttimestamp=" ).append( this.timestamp ).
133                append( "\n\tuid=" ).append( this.uid ).
134                append( "\n\ttext=" ).append( this.getText( Locale.getDefault() ) );
135    
136            final Object[] args = this.getFormatArguments( Locale.getDefault() );
137            for ( int i = 0; i < args.length; i++ )
138            {
139                buf.append( "\n\tformatArguments[" ).append( i ).append( "]=" ).
140                    append( args[i] );
141    
142            }
143    
144            return buf.toString();
145        }
146    
147        //-----------------------------------------------------------------Message--
148        //--Object------------------------------------------------------------------
149    
150        /**
151         * Returns a string representation of the object.
152         *
153         * @return a string representation of the object.
154         */
155        public String toString()
156        {
157            return super.toString() + this.internalString();
158        }
159    
160        /**
161         * Returns a hash code value for this object.
162         *
163         * @return a hash code value for this object.
164         */
165        public final int hashCode()
166        {
167            return this.uid.hashCode();
168        }
169    
170        /**
171         * Indicates whether some other object is equal to this one.
172         * <p>Messages internally cary a UID which is created during instantiation.
173         * This UID is used for comparing {@code o} with the instance.</p>
174         *
175         * @param o the reference object with which to compare.
176         *
177         * @return {@code true} if this object is the same as {@code o};
178         * {@code false} otherwise.
179         *
180         * @see UID
181         */
182        public final boolean equals( final Object o )
183        {
184            return o == this || ( o instanceof Message &&
185                ( ( Message ) o ).uid.equals( this.uid ) );
186    
187        }
188    
189        /**
190         * Creates and returns a copy of this object.
191         *
192         * @return a clone of this instance.
193         */
194        public Object clone()
195        {
196            try
197            {
198                return super.clone();
199            }
200            catch ( CloneNotSupportedException e )
201            {
202                throw new AssertionError( e );
203            }
204        }
205    
206        //------------------------------------------------------------------Object--
207    }
208    
209    /**
210     * Comparator for sorting messages in ascending order of occurence.
211     * <p><b>Note:</b><br/>
212     * This comparator imposes orderings that are inconsistent with equals.</p>
213     *
214     * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a>
215     * @version $Id: Message.java 8044 2009-07-02 01:29:05Z schulte2005 $
216     */
217    class AscendingMessageComparator implements Comparator, Serializable
218    {
219        //--Comparator--------------------------------------------------------------
220    
221        /**
222         * {@inheritDoc}
223         *
224         * @throws NullPointerException if either {@code o1} or {@code o2} is
225         * {@code null}.
226         * @throws ClassCastException if either {@code o1} or {@code o2} is
227         * not an instance of {@code Message}.
228         */
229        public int compare( final Object o1, final Object o2 )
230        {
231            if ( o1 == null )
232            {
233                throw new NullPointerException( "o1" );
234            }
235            if ( o2 == null )
236            {
237                throw new NullPointerException( "o2" );
238            }
239            if ( !( o1 instanceof Message ) )
240            {
241                throw new ClassCastException( o1.getClass().getName() );
242            }
243            if ( !( o2 instanceof Message ) )
244            {
245                throw new ClassCastException( o2.getClass().getName() );
246            }
247    
248            // TODO JDK 1.5 Long.valueOf(long)
249            final Long l1 = new Long( ( ( Message ) o1 ).getTimestamp() );
250            final Long l2 = new Long( ( ( Message ) o2 ).getTimestamp() );
251            return l1.compareTo( l2 );
252        }
253    
254        //--------------------------------------------------------------Comparator--
255    }
256    
257    /**
258     * Comparator for sorting messages in descending order of occurence.
259     * <p><b>Note:</b><br/>
260     * This comparator imposes orderings that are inconsistent with equals.</p>
261     *
262     * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a>
263     * @version $Id: Message.java 8044 2009-07-02 01:29:05Z schulte2005 $
264     */
265    class DescendingMessageComparator
266        extends AscendingMessageComparator
267    {
268        //--Comparator--------------------------------------------------------------
269    
270        /**
271         * {@inheritDoc}
272         *
273         * @throws NullPointerException if either {@code o1} or {@code o2} is
274         * {@code null}.
275         * @throws ClassCastException if either {@code o1} or {@code o2} is
276         * not an instance of {@code Message}.
277         */
278        public int compare( final Object o1, final Object o2 )
279        {
280            return super.compare( o2, o1 );
281        }
282    
283        //--------------------------------------------------------------Comparator--
284    }