com.rapidminer.gui.viewer.metadata.model.AbstractAttributeStatisticsModel.java Source code

Java tutorial

Introduction

Here is the source code for com.rapidminer.gui.viewer.metadata.model.AbstractAttributeStatisticsModel.java

Source

/**
 * Copyright (C) 2001-2015 by RapidMiner and the contributors
 *
 * Complete list of developers available at our web site:
 *
 *      http://rapidminer.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses/.
 */
package com.rapidminer.gui.viewer.metadata.model;

import com.rapidminer.example.Attribute;
import com.rapidminer.example.AttributeRole;
import com.rapidminer.example.ExampleSet;
import com.rapidminer.gui.viewer.metadata.AttributeStatisticsPanel;
import com.rapidminer.gui.viewer.metadata.event.AttributeStatisticsEvent;
import com.rapidminer.gui.viewer.metadata.event.AttributeStatisticsEvent.EventType;
import com.rapidminer.gui.viewer.metadata.event.AttributeStatisticsEventListener;

import java.awt.Font;
import java.lang.ref.WeakReference;

import javax.swing.event.EventListenerList;

import org.jfree.chart.ChartTheme;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;

/**
 * Abstract model for the {@link AttributeStatisticsPanel}. See implementations for details.
 * 
 * @author Marco Boeck
 * 
 */
public abstract class AbstractAttributeStatisticsModel {

    /** the {@link Attribute} for this model */
    private final Attribute attribute;

    /** stores the {@link ExampleSet} as a {@link WeakReference} */
    private final WeakReference<ExampleSet> weakExampleSet;

    /** if not <code>null</code>, the attribute is a special attribute */
    private final String specialAttName;

    /** if true, the panel should be drawn in an alternating color scheme */
    private boolean alternating;

    /** if true, the display should be enlarged */
    private boolean enlarged;

    /** if true, the construction value will be displayed */
    private boolean showConstruction;

    /** the number of missing values */
    protected double missing;

    /** the construction value for the attribute */
    private final String construction;

    /** event listener for this model */
    private final EventListenerList eventListener;

    /**
     * Inits the
     * 
     * @param exampleSet
     * @param attribute
     */
    protected AbstractAttributeStatisticsModel(final ExampleSet exampleSet, final Attribute attribute) {
        this.attribute = attribute;
        this.weakExampleSet = new WeakReference<>(exampleSet);
        this.specialAttName = exampleSet.getAttributes().findRoleByName(attribute.getName()).getSpecialName();
        this.construction = attribute.getConstruction();

        this.eventListener = new EventListenerList();
    }

    /**
     * Adds a {@link AttributeStatisticsEventListener} which will be informed of all changes to this
     * model.
     * 
     * @param listener
     */
    public void registerEventListener(final AttributeStatisticsEventListener listener) {
        eventListener.add(AttributeStatisticsEventListener.class, listener);
    }

    /**
     * Removes the {@link AttributeStatisticsEventListener} from this model.
     * 
     * @param listener
     */
    public void removeEventListener(final AttributeStatisticsEventListener listener) {
        eventListener.remove(AttributeStatisticsEventListener.class, listener);
    }

    /**
     * Sets if this panel should be drawn in an alternating color scheme (slightly darker) to make
     * reading of many rows easier.
     * 
     * @param alternating
     */
    public void setAlternating(final boolean alternating) {
        if (this.alternating != alternating) {
            this.alternating = alternating;

            fireAlternatingChangedEvent();
        }
    }

    /**
     * Returns <code>true</code> if this is an alternating attribute statistics model.
     * 
     * @return
     */
    public boolean isAlternating() {
        return alternating;
    }

    /**
     * Gets the enlarged status which determines how many information to display.
     * 
     * @return
     */
    public boolean isEnlarged() {
        return enlarged;
    }

    /**
     * Sets the enlarged status.
     * 
     * @param enlarged
     */
    public void setEnlarged(final boolean enlarged) {
        this.enlarged = enlarged;
        if (enlarged && getExampleSetOrNull() != null) {
            prepareCharts();
        }

        fireEnlargedChangedEvent();
    }

    /**
     * Gets the show construction status which determines if the construction value is shown.
     * 
     * @return
     */
    public boolean isShowConstruction() {
        return showConstruction;
    }

    /**
     * Sets the show construction status.
     * 
     * @param showConstruction
     */
    public void setShowConstruction(final boolean showConstruction) {
        this.showConstruction = showConstruction;

        fireShowConstructionChangedEvent();
    }

    /**
     * Returns <code>true</code> if this attribute has a special {@link AttributeRole};
     * <code>false</code> otherwise.
     * 
     * @return
     */
    public boolean isSpecialAtt() {
        return specialAttName != null;
    }

    /**
     * Returns the name of the special {@link AttributeRole} for this {@link Attribute}. If this is
     * not a special attribute, returns <code>null</code> .
     * 
     * @return
     */
    public String getSpecialAttName() {
        return specialAttName;
    }

    /**
     * Gets the {@link Attribute} backing this model.
     * 
     * @return
     */
    public Attribute getAttribute() {
        return attribute;
    }

    /**
     * Gets the {@link ExampleSet} backing this model or <code>null</code> if the
     * {@link WeakReference} to it was removed.
     * 
     * @return
     */
    public ExampleSet getExampleSetOrNull() {
        return weakExampleSet.get();
    }

    /**
     * Fire when the show construction status has changed.
     */
    protected void fireShowConstructionChangedEvent() {
        fireEvent(EventType.SHOW_CONSTRUCTION_CHANGED);
    }

    /**
     * Fire when the enlarged status has changed.
     */
    protected void fireEnlargedChangedEvent() {
        fireEvent(EventType.ENLARGED_CHANGED);
    }

    /**
     * Fire when the statistics of an attribute have changed.
     */
    protected void fireStatisticsChangedEvent() {
        fireEvent(EventType.STATISTICS_CHANGED);
    }

    /**
     * Fire when alternation has changed.
     */
    protected void fireAlternatingChangedEvent() {
        fireEvent(EventType.ALTERNATING_CHANGED);
    }

    /**
     * Fires the given {@link EventType}.
     * 
     * @param type
     */
    protected void fireEvent(final EventType type) {
        Object[] listeners = eventListener.getListenerList();
        // Process the listeners last to first
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == AttributeStatisticsEventListener.class) {
                AttributeStatisticsEvent e = new AttributeStatisticsEvent(type);
                ((AttributeStatisticsEventListener) listeners[i + 1]).modelChanged(e);
            }
        }
    }

    /**
     * Updates the statistics of this model via the given {@link ExampleSet}.
     * 
     * @param exampleSet
     *            the {@link ExampleSet} for which the attribute statistics should be updated. No
     *            reference to it is stored to prevent memory leaks.
     */
    public abstract void updateStatistics(ExampleSet exampleSet);

    /**
     * Returns the number of missing values.
     * 
     * @return
     */
    public double getNumberOfMissingValues() {
        return missing;
    }

    /**
     * Returns the construction value for this attribute.
     * 
     * @return
     */
    public String getConstruction() {
        return construction;
    }

    /**
     * Returns the given {@link JFreeChart} for the given index. If the given index is invalid,
     * returns <code>null</code>.
     * 
     * @param index
     * @return
     */
    public abstract JFreeChart getChartOrNull(int index);

    /**
     * Prepares the charts if needed.
     */
    protected abstract void prepareCharts();

    /**
     * Changes the font of {@link JFreeChart}s to Sans Serif. This method uses a
     * {@link StandardChartTheme} to do so, so any changes to the look of the chart must be done
     * after calling this method.
     * 
     * @param chart
     *            the chart to change fonts for
     */
    protected static void setDefaultChartFonts(JFreeChart chart) {
        final ChartTheme chartTheme = StandardChartTheme.createJFreeTheme();

        if (StandardChartTheme.class.isAssignableFrom(chartTheme.getClass())) {
            StandardChartTheme standardTheme = (StandardChartTheme) chartTheme;
            // The default font used by JFreeChart cannot render japanese etc symbols
            final Font oldExtraLargeFont = standardTheme.getExtraLargeFont();
            final Font oldLargeFont = standardTheme.getLargeFont();
            final Font oldRegularFont = standardTheme.getRegularFont();
            final Font oldSmallFont = standardTheme.getSmallFont();

            final Font extraLargeFont = new Font(Font.SANS_SERIF, oldExtraLargeFont.getStyle(),
                    oldExtraLargeFont.getSize());
            final Font largeFont = new Font(Font.SANS_SERIF, oldLargeFont.getStyle(), oldLargeFont.getSize());
            final Font regularFont = new Font(Font.SANS_SERIF, oldRegularFont.getStyle(), oldRegularFont.getSize());
            final Font smallFont = new Font(Font.SANS_SERIF, oldSmallFont.getStyle(), oldSmallFont.getSize());

            standardTheme.setExtraLargeFont(extraLargeFont);
            standardTheme.setLargeFont(largeFont);
            standardTheme.setRegularFont(regularFont);
            standardTheme.setSmallFont(smallFont);

            standardTheme.apply(chart);
        }
    }
}