001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-present, by David Gilbert 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 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 
025 * Other names may be trademarks of their respective owners.]
026 *
027 * --------------------------
028 * OutlierListCollection.java
029 * --------------------------
030 * (C) Copyright 2003-present, by David Browning and Contributors.
031 *
032 * Original Author:  David Browning (for Australian Institute of Marine
033 *                   Science);
034 * Contributor(s):   -;
035 *
036 */
037
038package org.jfree.chart.renderer;
039
040import java.util.ArrayList;
041import java.util.Iterator;
042import java.util.List;
043
044/**
045 * A collection of outlier lists for a box and whisker plot. Each collection is
046 * associated with a single box and whisker entity.
047 *
048 * Outliers are grouped in lists for each entity. Lists contain
049 * one or more outliers, determined by whether overlaps have
050 * occurred. Overlapping outliers are grouped in the same list.
051 *
052 * @see org.jfree.chart.renderer.OutlierList
053 */
054public class OutlierListCollection {
055
056    /** Storage for the outlier lists. */
057    private final List<OutlierList> outlierLists;
058
059    /**
060     * Unbelievably, outliers which are more than 2 * interquartile range are
061     * called far outs...  See Tukey EDA  (a classic one of a kind...)
062     */
063    private boolean highFarOut = false;
064
065    /**
066     * A flag that indicates whether or not the collection contains low far
067     * out values.
068     */
069    private boolean lowFarOut = false;
070
071    /**
072     * Creates a new empty collection.
073     */
074    public OutlierListCollection() {
075        this.outlierLists = new ArrayList<>();
076    }
077
078    /**
079     * A flag to indicate the presence of one or more far out values at the
080     * top end of the range.
081     *
082     * @return A {@code boolean}.
083     */
084    public boolean isHighFarOut() {
085        return this.highFarOut;
086    }
087
088    /**
089     * Sets the flag that indicates the presence of one or more far out values
090     * at the top end of the range.
091     *
092     * @param farOut  the flag.
093     */
094    public void setHighFarOut(boolean farOut) {
095        this.highFarOut = farOut;
096    }
097
098    /**
099     * A flag to indicate the presence of one or more far out values at the
100     * bottom end of the range.
101     *
102     * @return A {@code boolean}.
103     */
104    public boolean isLowFarOut() {
105        return this.lowFarOut;
106    }
107
108    /**
109     * Sets the flag that indicates the presence of one or more far out values
110     * at the bottom end of the range.
111     *
112     * @param farOut  the flag.
113     */
114    public void setLowFarOut(boolean farOut) {
115        this.lowFarOut = farOut;
116    }
117    /**
118     * Appends the specified element as a new {@code OutlierList} to the
119     * end of this list if it does not overlap an outlier in an existing list.
120     *
121     * If it does overlap, it is appended to the outlier list which it overlaps
122     * and that list is updated.
123     *
124     * @param outlier  element to be appended to this list.
125     *
126     * @return {@code true} (as per the general contract of Collection.add).
127     */
128    public boolean add(Outlier outlier) {
129        if (this.outlierLists.isEmpty()) {
130            return this.outlierLists.add(new OutlierList(outlier));
131        }
132        else {
133            boolean updated = false;
134            for (OutlierList list : this.outlierLists) {
135                if (list.isOverlapped(outlier)) {
136                    updated = updateOutlierList(list, outlier);
137                }
138            }
139            if (!updated) {
140                //System.err.print(" creating new outlier list ");
141                updated = this.outlierLists.add(new OutlierList(outlier));
142            }
143            return updated;
144        }
145    }
146
147    /**
148     * Returns an iterator for the outlier lists.
149     *
150     * @return An iterator.
151     */
152    public Iterator<OutlierList> iterator() {
153        return this.outlierLists.iterator();
154    }
155
156
157    /**
158     * Updates the outlier list by adding the outlier to the end of the list and
159     * setting the averaged outlier to the average x and y coordinate values
160     * of the outliers in the list.
161     *
162     * @param list  the outlier list to be updated.
163     * @param outlier  the outlier to be added
164     *
165     * @return <tt>true</tt> (as per the general contract of Collection.add).
166     */
167    private boolean updateOutlierList(OutlierList list, Outlier outlier) {
168        boolean result = list.add(outlier);
169        list.updateAveragedOutlier();
170        list.setMultiple(true);
171        return result;
172    }
173
174}