001    /* ===========================================================
002     * JFreeChart : a free chart library for the Java(tm) platform
003     * ===========================================================
004     *
005     * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors.
006     *
007     * Project Info:  http://www.jfree.org/jfreechart/index.html
008     *
009     * This library is free software; you can redistribute it and/or modify it
010     * under the terms of the GNU Lesser General Public License as published by
011     * the Free Software Foundation; either version 2.1 of the License, or
012     * (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but
015     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017     * License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this library; if not, write to the Free Software
021     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
022     * USA.
023     *
024     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025     * in the United States and other countries.]
026     *
027     * ----------------------
028     * QuarterDateFormat.java
029     * ----------------------
030     * (C) Copyright 2005-2008, by Object Refinery Limited and Contributors.
031     *
032     * Original Author:  David Gilbert (for Object Refinery Limited);
033     * Contributor(s):   -;
034     *
035     * Changes:
036     * --------
037     * 01-Mar-2005 : Version 1 (DG);
038     * 10-May-2005 : Added equals() method, and implemented Cloneable and
039     *               Serializable (DG);
040     * ------------- JFREECHART 1.0.x ---------------------------------------------
041     * 08-Jun-2007 : Added Greek symbols, and support for reversing the date - see
042     *               patch 1577221 (DG);
043     *
044     */
045    
046    package org.jfree.chart.axis;
047    
048    import java.io.Serializable;
049    import java.text.DateFormat;
050    import java.text.FieldPosition;
051    import java.text.NumberFormat;
052    import java.text.ParsePosition;
053    import java.util.Arrays;
054    import java.util.Calendar;
055    import java.util.Date;
056    import java.util.GregorianCalendar;
057    import java.util.TimeZone;
058    
059    /**
060     * A formatter that formats dates to show the year and quarter (for example,
061     * '2004 IV' for the last quarter of 2004.
062     */
063    public class QuarterDateFormat extends DateFormat
064            implements Cloneable, Serializable {
065    
066        /** For serialization. */
067        private static final long serialVersionUID = -6738465248529797176L;
068    
069        /** Symbols for regular quarters. */
070        public static final String[] REGULAR_QUARTERS = new String[] {"1", "2",
071                "3", "4"};
072    
073        /** Symbols for roman numbered quarters. */
074        public static final String[] ROMAN_QUARTERS  = new String[] {"I", "II",
075                "III", "IV"};
076    
077        /**
078         * Symbols for greek numbered quarters.
079         *
080         * @since 1.0.6
081         */
082        public static final String[] GREEK_QUARTERS = new String[] {"\u0391",
083                "\u0392", "\u0393", "\u0394"};
084    
085        /** The strings. */
086        private String[] quarters = REGULAR_QUARTERS;
087    
088        /** A flag that controls whether the quarter or the year goes first. */
089        private boolean quarterFirst;
090    
091        /**
092         * Creates a new instance for the default time zone.
093         */
094        public QuarterDateFormat() {
095            this(TimeZone.getDefault());
096        }
097    
098        /**
099         * Creates a new instance for the specified time zone.
100         *
101         * @param zone  the time zone (<code>null</code> not permitted).
102         */
103        public QuarterDateFormat(TimeZone zone) {
104            this(zone, REGULAR_QUARTERS);
105        }
106    
107        /**
108         * Creates a new instance for the specified time zone.
109         *
110         * @param zone  the time zone (<code>null</code> not permitted).
111         * @param quarterSymbols  the quarter symbols.
112         */
113        public QuarterDateFormat(TimeZone zone, String[] quarterSymbols) {
114            this(zone, quarterSymbols, false);
115        }
116    
117        /**
118         * Creates a new instance for the specified time zone.
119         *
120         * @param zone  the time zone (<code>null</code> not permitted).
121         * @param quarterSymbols  the quarter symbols.
122         * @param quarterFirst  a flag that controls whether the quarter or the
123         *         year is displayed first.
124         *
125         * @since 1.0.6
126         */
127        public QuarterDateFormat(TimeZone zone, String[] quarterSymbols,
128                boolean quarterFirst) {
129            if (zone == null) {
130                throw new IllegalArgumentException("Null 'zone' argument.");
131            }
132            this.calendar = new GregorianCalendar(zone);
133            this.quarters = quarterSymbols;
134            this.quarterFirst = quarterFirst;
135    
136            // the following is never used, but it seems that DateFormat requires
137            // it to be non-null.  It isn't well covered in the spec, refer to
138            // bug parade 5061189 for more info.
139            this.numberFormat = NumberFormat.getNumberInstance();
140    
141        }
142    
143        /**
144         * Formats the given date.
145         *
146         * @param date  the date.
147         * @param toAppendTo  the string buffer.
148         * @param fieldPosition  the field position.
149         *
150         * @return The formatted date.
151         */
152        public StringBuffer format(Date date, StringBuffer toAppendTo,
153                                   FieldPosition fieldPosition) {
154            this.calendar.setTime(date);
155            int year = this.calendar.get(Calendar.YEAR);
156            int month = this.calendar.get(Calendar.MONTH);
157            int quarter = month / 3;
158            if (this.quarterFirst) {
159                toAppendTo.append(this.quarters[quarter]);
160                toAppendTo.append(" ");
161                toAppendTo.append(year);
162            }
163            else {
164                toAppendTo.append(year);
165                toAppendTo.append(" ");
166                toAppendTo.append(this.quarters[quarter]);
167            }
168            return toAppendTo;
169        }
170    
171        /**
172         * Parses the given string (not implemented).
173         *
174         * @param source  the date string.
175         * @param pos  the parse position.
176         *
177         * @return <code>null</code>, as this method has not been implemented.
178         */
179        public Date parse(String source, ParsePosition pos) {
180            return null;
181        }
182    
183        /**
184         * Tests this formatter for equality with an arbitrary object.
185         *
186         * @param obj  the object (<code>null</code> permitted).
187         *
188         * @return A boolean.
189         */
190        public boolean equals(Object obj) {
191            if (obj == this) {
192                return true;
193            }
194            if (!(obj instanceof QuarterDateFormat)) {
195                return false;
196            }
197            QuarterDateFormat that = (QuarterDateFormat) obj;
198            if (!Arrays.equals(this.quarters, that.quarters)) {
199                return false;
200            }
201            if (this.quarterFirst != that.quarterFirst) {
202                return false;
203            }
204            return super.equals(obj);
205        }
206    
207    }