org.processmining.analysis.decisionmining.DecisionAttributeForAuLdg.java Source code

Java tutorial

Introduction

Here is the source code for org.processmining.analysis.decisionmining.DecisionAttributeForAuLdg.java

Source

/**
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 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 General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *    Copyright (c) 2003-2006 TU/e Eindhoven
 *    by Eindhoven University of Technology
 *    Department of Information Systems
 *    http://is.tm.tue.nl
 *
 ************************************************************************/

package org.processmining.analysis.decisionmining;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;

import org.apache.commons.math.stat.descriptive.SummaryStatistics;
import org.processmining.framework.log.LogEvent;
import org.processmining.framework.models.hlprocess.HLActivity;
import org.processmining.framework.models.hlprocess.HLAttribute;
import org.processmining.framework.models.hlprocess.HLProcess;
import org.processmining.framework.models.hlprocess.HLTypes.AttributeType;
import org.processmining.framework.models.hlprocess.att.HLAttributeManager;
import org.processmining.framework.models.hlprocess.att.HLNominalAttribute;
import org.processmining.framework.models.hlprocess.att.HLNumericAttribute;
import org.processmining.framework.models.hlprocess.hlmodel.HLPetriNet;
import org.processmining.framework.models.petrinet.PetriNet;
import org.processmining.framework.models.petrinet.Transition;
import org.processmining.framework.util.GUIPropertyListWithoutGlue;
import org.processmining.framework.util.GuiNotificationTarget;

import weka.core.Attribute;
import weka.core.FastVector;

/**
 * Represents a case attribute as it has been observed in the log. <br>
 * Maintains the corresponding GUI panel where the attribute may be included or
 * excluded from analysis, and the proper attribute type may be chosen (such as
 * numeric or nominal). <br>
 * Furthermore it creates a link to the data mining application (see
 * #getWekaAttribute getWekaAttribute).
 * 
 * @author arozinat
 */
public class DecisionAttributeForAuLdg implements GuiNotificationTarget {

    /** numeric value statistics (may be empty) */
    // private SummaryStatistics myNumericValues = SummaryStatistics.newInstance();
    /** which tasks have written this attribute */
    private HashSet<LogEvent> myLogEvents = new HashSet<LogEvent>();

    private HLPetriNet hlPetriNet;
    /**
     * simulation model attributes (need to be updated as soon as attribute is,
     * e.g., deselected)
     */
    private HLProcess hlProcess;
    /** the high level attribute linked to this decision attribute */
    protected HLAttribute hlAttribute;
    protected HLNominalAttribute nominalBackup;

    private JPanel myPanel;
    private JCheckBox myNameCheckBox;
    private GUIPropertyListWithoutGlue myTypeGuiRepresenation;

    /**
     * Default constructor.
     * 
     * @param name
     *          the name of the attribute
     * @param values
     *          the set of values observed in the log
     */
    public DecisionAttributeForAuLdg(String name, HLPetriNet highLevelPN) {
        hlAttribute = new HLNominalAttribute(name, highLevelPN.getHLProcess());
        hlPetriNet = highLevelPN;
        hlProcess = highLevelPN.getHLProcess();
    }

    /**
     * Returns the name of this attribute.
     * 
     * @return the name of this attribute
     */
    public String getName() {
        return hlAttribute.getName();
    }

    /**
     * Adds the passed value to the values already held for this attribute.
     * Duplicate values will not be added twice, so the collection of values
     * corresponds to a set semantics.
     * 
     * @param newValues
     *          the new value to be added
     */
    public void addValue(String newValue) {
        // add value to enumerated values
        if (newValue != null) {
            ((HLNominalAttribute) hlAttribute).addPossibleValue(newValue);
            // if is numeric also add value to statistics
            try {
                long numericValue = Long.parseLong(newValue);
                //myNumericValues.addValue(numericValue);
            } catch (NumberFormatException ex) {
                // do nothing as value is simply not numeric
            }
        }
    }

    /**
     * Adds the given log event to the list of log events held for this attribute.
     * This is to keep track on which tasks have written this attribute.
     * 
     * @param logEvent
     *          the log event to be added
     */
    public void addLogEvent(LogEvent logEvent) {
        if (logEvent != null) {
            myLogEvents.add(logEvent);
        }
    }

    /**
     * Determines whether this attribute was attached to audit trail entries which
     * are associated to the given log event.
     * 
     * @param logEvent
     *          the log event to be checked
     * @return <code>true</code> if this attribute was observed for at least one
     *         audit trail entry associated to the given log event,
     *         <code>false</code> otherwise
     */
    public boolean hasBeenObservedBy(LogEvent logEvent) {
        if (myLogEvents.contains(logEvent) == true) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Retrieves the set of log events that have provided this attribute.
     * 
     * @return the set of log events that specified this attribute in the given
     *         log
     */
    public Set<LogEvent> getLogEvents() {
        return myLogEvents;
    }

    /**
     * Retrieves this attribute as a weka attribute (regardless whether it was
     * selected by the user or not).
     * 
     * @return the weka attribute corresponding to this attribute
     */
    public Attribute getWekaAttribute() {
        DecisionAttributeTypeForAuLdg myType = getAttributeType();
        // if no type has been chosen yet
        if (myType == null) {
            return null;
        }
        Attribute result = null;
        // build nominal attribute
        if (myType.equals(DecisionAttributeTypeForAuLdg.NOMINAL)) {
            List<String> values = ((HLNominalAttribute) hlAttribute).getPossibleValues().getValues();
            FastVector my_nominal_values = new FastVector(values.size());
            for (String attValue : values) {
                my_nominal_values.addElement(attValue);
            }
            // add vector to attribute
            result = new Attribute(hlAttribute.getName(), my_nominal_values);
        } else if (myType.equals(DecisionAttributeTypeForAuLdg.NUMERIC)) {
            // make attribute a numeric one
            result = new Attribute(hlAttribute.getName());
        }
        return result;
    }

    /**
     * Creates (and adds) a new data attribute object in the simulation model. <br>
     * Adds the given simulation attribute to all high level activities in the
     * associated simulation model that have provided this attribute at least once
     * in the log.
     * 
     * @return the new high level data attribute for this decision attribute
     */
    public void createSimulationAttribute() {
        AttributeType type = getAttributeType().getHighLevelAttributeType();
        // create nominal high level attribute
        if (type == AttributeType.Nominal && hlAttribute instanceof HLNumericAttribute) {
            ArrayList<String> valList = new ArrayList<String>();
            Iterator it = nominalBackup.getPossibleValues().getValues().iterator();
            while (it.hasNext()) {
                String val = (String) it.next();
                int freq = nominalBackup.getPossibleValues().getFrequencyPossibleValueNominal(val);
                for (int i = 0; i < freq; i++) {
                    valList.add(val);
                }
            }
            // initial value is the first value in list (can be changed before export)
            HLAttribute previousAtt = hlAttribute;
            hlAttribute = new HLNominalAttribute(getName(), valList, hlProcess);
            hlProcess.replaceAttribute(previousAtt.getID(), hlAttribute);
        }
        // create numeric high level attribute
        else if (type == AttributeType.Numeric && hlAttribute instanceof HLNominalAttribute) {
            nominalBackup = (HLNominalAttribute) hlAttribute;
            hlAttribute = HLAttributeManager.autoChangeType((HLNominalAttribute) hlAttribute);
        }
        // add the same attribute to all activities (in the simulation model)
        // that have written the attribute
        Iterator<LogEvent> logEventIt = getLogEvents().iterator();
        while (logEventIt.hasNext()) {
            LogEvent le = logEventIt.next();
            // find associated transitions in the process model
            PetriNet pn = (PetriNet) hlPetriNet.getProcessModel();
            Iterator transIt = pn.findTransitions(le).iterator();
            while (transIt.hasNext()) {
                Transition trans = (Transition) transIt.next();
                HLActivity hlTrans = hlPetriNet.findActivity(trans);
                hlTrans.addOutputDataAttribute(hlAttribute.getID());
            }
        }
    }

    /**
     * Returns currently held simulation attribute. Note that as soon as the type
     * of the attribute changes, a new simulation attribute object will be created
     * and assigned to this decision attribute.
     * 
     * @return the current simulation attribute object
     */
    public HLAttribute getSimulationAttribute() {
        return hlAttribute;
    }

    /**
     * Retrieves the corresponding GUI panel for this attribute. If it has not
     * been built yet, it will be built now.
     * 
     * @return the panel belonging to this attribute
     */
    public JPanel getAttributePanel() {
        if (myPanel == null) {
            buildAttributePanel();
        }
        return myPanel;
    }

    /**
     * Determines the selection state of the belonging check box item (i.e.,
     * whether the user has or has not chosen the respective attribute to be
     * included into analysis).
     */
    public boolean isIncluded() {
        boolean result = false;
        if (myNameCheckBox != null) {
            result = myNameCheckBox.isSelected();
        }
        return result;
    }

    /**
     * Overridden to specify when two DecisionAttribute objects are considered to
     * be equal.
     * 
     * @param o
     *          the <code>DecisionAttribute</code> to be compared with
     * @return <code>true</code> if the identifiers are the same,
     *         <code>false</code> otherwise.
     */
    public boolean equals(Object o) {
        // check object identity first
        if (this == o) {
            return true;
        }
        // check type (which includes check for null)
        return (o instanceof DecisionAttributeForAuLdg)
                && hlAttribute.getID().equals(((DecisionAttributeForAuLdg) o).hlAttribute.getID());
    }

    /**
     * Overridden to produce the same hash code for equal objects.
     * 
     * @return the hash code calculated
     */
    public int hashCode() {
        // simple recipe for generating hashCode given by
        // Effective Java (Addison-Wesley, 2001)
        int result = 17;
        result = 37 * result + hlAttribute.getID().hashCode();
        return result;
    }

    /*
     * This method is called as soon as the attribute type changes.
     * 
     * (non-Javadoc)
     * 
     * @see org.processmining.framework.util.GuiNotificationTarget#updateGUI()
     */
    public void updateGUI() {
        // remove old simulation attribute
        // (automatically removes attribute from contained activities)
        HLAttribute oldAtt = getSimulationAttribute();
        hlProcess.removeAttribute(oldAtt.getID());
        // create new simulation attribute (with new attribute type)
        // and add to related activities
        createSimulationAttribute();
    }

    // //////////////////// Private methods
    // //////////////////////////////////////////////

    /**
     * Retrieves the current type of this attribute (i.e., numeric or nominal).
     * 
     * @return the attribute type if the graphical representation has been built
     *         already, <code>null</code> otherwise
     */
    protected DecisionAttributeTypeForAuLdg getAttributeType() {
        DecisionAttributeTypeForAuLdg result = null;
        if (myTypeGuiRepresenation != null) {
            result = (DecisionAttributeTypeForAuLdg) myTypeGuiRepresenation.getValue();
        } else {
            result = DecisionAttributeTypeForAuLdg.NOMINAL;
        }
        return result;
    }

    /**
     * Sets the specified attribut type if possible.
     * 
     * @param type
     *          the new type
     */
    protected void setDecisionAttributeType(DecisionAttributeTypeForAuLdg type) {
        if (myTypeGuiRepresenation == null) {
            createAttributeTypeGui();
        }
        myTypeGuiRepresenation.setValue(type);
    }

    /**
     * Builds a panel containing a checkbox to include or exclude this attribute,
     * and a combobox in order to chose an attribute type.
     */
    private void buildAttributePanel() {
        myPanel = new JPanel();
        myPanel.setLayout(new BoxLayout(myPanel, BoxLayout.LINE_AXIS));
        JLabel myNameLabel = new JLabel("Attribute name: ");
        myNameLabel.setForeground(new Color(100, 100, 100));
        myPanel.add(myNameLabel);
        myNameCheckBox = new JCheckBox(getName());
        // per default select everything
        myNameCheckBox.setSelected(true);

        // register check/uncheck action
        myNameCheckBox.addActionListener(new ActionListener() {
            // specify action when the attribute selection scope is changed
            public void actionPerformed(ActionEvent e) {
                JCheckBox cb = (JCheckBox) e.getSource();
                HLAttribute simAtt = getSimulationAttribute();
                if (cb.isSelected() == true) {
                    myTypeGuiRepresenation.enable();
                    // add attribute to simulation model
                    // and to related activities
                    createSimulationAttribute();
                } else {
                    myTypeGuiRepresenation.disable();
                    // remove attribute from simulation model
                    // (automatically removes attribute from contained activities)
                    hlProcess.removeAttribute(simAtt.getID());
                }
            }
        });

        myPanel.add(myNameCheckBox);
        myPanel.add(Box.createHorizontalGlue());

        createAttributeTypeGui();
        // ArrayList<DecisionAttributeType> attributeTypes = new
        // ArrayList<DecisionAttributeType>();
        // // per default set "nominal"
        // attributeTypes.add(DecisionAttributeType.NOMINAL);
        // attributeTypes.add(DecisionAttributeType.NUMERIC);
        // myTypeGuiRepresenation = new
        // GUIPropertyListWithoutGlue("Attribute type:",
        // "Please determine the type of the attribute", attributeTypes, this);

        myPanel.add(myTypeGuiRepresenation.getPropertyPanel());
    }

    private void createAttributeTypeGui() {
        ArrayList<DecisionAttributeTypeForAuLdg> attributeTypes = new ArrayList<DecisionAttributeTypeForAuLdg>();
        // per default set "nominal"
        attributeTypes.add(DecisionAttributeTypeForAuLdg.NOMINAL);
        attributeTypes.add(DecisionAttributeTypeForAuLdg.NUMERIC);
        myTypeGuiRepresenation = new GUIPropertyListWithoutGlue("Attribute type:",
                "Please determine the type of the attribute", attributeTypes, this);
    }

}