Ptidej-v5.2-master/POM Tests/data/ArgoUML_0.28/src/org/argouml/cognitive/ToDoItem.java
// $Id: ToDoItem.java 15994 2008-11-08 18:50:51Z mvw $
// Copyright (c) 1996-2008 The Regents of the University of California. All
// Rights Reserved. Permission to use, copy, modify, and distribute this
// software and its documentation without fee, and without a written
// agreement is hereby granted, provided that the above copyright notice
// and this paragraph appear in all copies.  This software program and
// documentation are copyrighted by The Regents of the University of
// California. The software program and documentation are supplied "AS
// IS", without any accompanying services from The Regents. The Regents
// does not warrant that the operation of the program will be
// uninterrupted or error-free. The end-user understands that the program
// was developed for research purposes and is advised not to rely
// exclusively on the program for any reason.  IN NO EVENT SHALL THE
// UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
// CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

package org.argouml.cognitive;

import java.io.Serializable;

import javax.swing.Icon;

import org.argouml.cognitive.critics.Wizard;
import org.argouml.cognitive.critics.WizardItem;
import org.argouml.util.CollectionUtil;

/**
 * This class defines the feedback items that can be placed on the
 * Designer's ToDoList.  The main point of a ToDoItem is to inform
 * the Designer of some problem or open design issue.  Additional
 * information in the ToDoItem helps put the designer in a mental
 * context suitable for resolving the issue: ToDoItem's are well tied
 * into the design and design process so that the Designer can see
 * which design material's are the subject of this ToDoItem, and which
 * Critic raised it.  The more info URL helps
 * provide background knowledge of the domain. In the future
 * ToDoItems will include ties back to the design rationale log.
 * Also the run-time system needs to know who posted each ToDoItem so
 * that it can automatically remove it if it is no longer valid.
 */
public class ToDoItem implements Serializable, WizardItem {

    ////////////////////////////////////////////////////////////////
    // constants

    /**
     * The interruptive priority todoitem of 4 levels.
     */
    public static final int INTERRUPTIVE_PRIORITY = 9;

    /**
     * The high priority todoitem of 4 levels.
     */
    public static final int HIGH_PRIORITY = 1;

    /**
     * The medium priority todoitem of 4 levels.
     */
    public static final int MED_PRIORITY = 2;

    /**
     * The lowest priority todoitem of 4 levels.
     */
    public static final int LOW_PRIORITY = 3;

    ////////////////////////////////////////////////////////////////
    // instance variables

    /**
     * Who posted this item (e.g., a Critic, or the designer)?
     */
    private Poster thePoster;

    /**
     * One line description of issue.
     */
    private String theHeadline;

    /**
     * How important is this issue? Enough to interrupt the designer?
     */
    private int thePriority;

    /**
     * One paragraph description of the issue.
     */
    private String theDescription;

    /**
     * URL for background (textbook?) knowledge about the domain.
     */
    private String theMoreInfoURL;

    /**
     * The part of the design this issue affects.
     * <p>
     * Each member is either a model element, a {@link Fig}, or a
     * {@link Diagram}.
     * <p>
     * TODO: Offenders need to be more strongly typed. Because there is not a
     * common supertype for these three types, we can't type this list. We
     * should introduce a common supertype/interface. - tfm 20070630
     * <p>
     * The list of offenders is set once (e.g. by the constructor)
     * and cannot change.
     * <p>
     */
    private ListSet theOffenders;

    private final Wizard theWizard;

    /**
     * The constructor.
     *
     * @param poster the poster
     * @param h the headline
     * @param p the priority
     * @param d the description
     * @param m the more info url
     * @param offs the offenders
     */
    public ToDoItem(Poster poster, String h, int p, String d, String m,
		    ListSet offs) {
        checkOffs(offs);

        thePoster = poster;
        theHeadline = h;
        theOffenders = offs;
        thePriority = p;
        theDescription = d;
        theMoreInfoURL = m;
        theWizard = null;
    }

    /**
     * The constructor.
     *
     * @param poster the poster
     * @param h the headline
     * @param p the priority
     * @param d the description
     * @param m the more info url
     */
    public ToDoItem(Poster poster, String h, int p, String d, String m) {
	thePoster = poster;
	theHeadline = h;
	theOffenders = new ListSet();
	thePriority = p;
	theDescription = d;
	theMoreInfoURL = m;
        theWizard = null;
    }

    /**
     * The constructor.
     *
     * @param c the poster (critic)
     * @param dm A single offender.
     * @param dsgr the designer
     */
    public ToDoItem(Critic c, Object dm, Designer dsgr) {
        checkArgument(dm);

        thePoster = c;
        theHeadline = c.getHeadline(dm, dsgr);
        theOffenders = new ListSet(dm);
        thePriority = c.getPriority(theOffenders, dsgr);
        theDescription = c.getDescription(theOffenders, dsgr);
        theMoreInfoURL = c.getMoreInfoURL(theOffenders, dsgr);
        theWizard = c.makeWizard(this);
    }

    /**
     * The constructor.
     *
     * @param c the poster (critic)
     * @param offs the offenders
     * @param dsgr the designer
     */
    public ToDoItem(Critic c, ListSet offs, Designer dsgr) {
        checkOffs(offs);

        thePoster = c;
        theHeadline = c.getHeadline(offs, dsgr);
        theOffenders = offs;
        thePriority = c.getPriority(theOffenders, dsgr);
        theDescription = c.getDescription(theOffenders, dsgr);
        theMoreInfoURL = c.getMoreInfoURL(theOffenders, dsgr);
        theWizard = c.makeWizard(this);
    }

    /**
     * The constructor.
     *
     * @param c the poster (critic)
     */
    public ToDoItem(Critic c) {
	thePoster = c;
	theHeadline = c.getHeadline();
	theOffenders = new ListSet();
	thePriority = c.getPriority(null, null);
	theDescription = c.getDescription(null, null);
	theMoreInfoURL = c.getMoreInfoURL(null, null);
	theWizard = c.makeWizard(this);
    }

    /**
     * Override in subclass to validate the offender is an expected type.
     * @param dm the offender aka design material
     */
    protected void checkArgument(Object dm) {
    }


    /**
     * Check the offenders.<p>
     *
     * This is called from the constructors where the offenders are given.
     *
     * TODO: Why do we only care about checking the first 2 offenders above?
     * @param offs The offenders.
     */
    private void checkOffs(ListSet offs) {
        if (offs == null) {
            throw new IllegalArgumentException(
                    "A ListSet of offenders must be supplied.");
        }
        Object offender = CollectionUtil.getFirstItemOrNull(offs);
        if (offender != null) {
            checkArgument(offender);
        }

        if (offs.size() >= 2) {
            offender = offs.get(1);
            checkArgument(offender);
        }
    }

    // Cached expansions
    private String cachedExpandedHeadline;
    private String cachedExpandedDescription;

    ////////////////////////////////////////////////////////////////
    // accessors

    /**
     * @return the headline
     */
    public String getHeadline() {
	if (cachedExpandedHeadline == null) {
	    cachedExpandedHeadline =
	        thePoster.expand(theHeadline, theOffenders);
	}
	return cachedExpandedHeadline;
    }

    /**
     * @deprecated in 0.27.2 byb Bob Tarling. A ToDoItem should be immutable
     * to guarantee it can be passed safely between threads. Only use the
     * constructor to set this value.
     * @param h the headline
     */
    @Deprecated
    public void setHeadline(String h) {
	theHeadline = h;
	cachedExpandedHeadline = null;
    }

    /**
     * @return the description
     */
    public String getDescription() {
	if (cachedExpandedDescription == null) {
	    cachedExpandedDescription =
		thePoster.expand(theDescription, theOffenders);
	}
	return cachedExpandedDescription;
    }

    /**
     * @deprecated in 0.27.2 byb Bob Tarling. A ToDoItem should be immutable
     * to guarantee it can be passed safely between threads. Only use the
     * constructor to set this value.
     * @param d the description
     */
    @Deprecated
    public void setDescription(String d) {
	theDescription = d;
	cachedExpandedDescription = null;
    }

    /**
     * @return the more-info-url
     */
    public String getMoreInfoURL() { return theMoreInfoURL; }

    /**
     * @deprecated in 0.27.2 byb Bob Tarling. A ToDoItem should be immutable
     * to guarantee it can be passed safely between threads. Only use the
     * constructor to set this value.
     * @param m the more-info-url
     */
    @Deprecated
    public void setMoreInfoURL(String m) {
        theMoreInfoURL = m;
    }

    /**
     * @return the priority
     */
    public int getPriority() { return thePriority; }

    /**
     * @deprecated in 0.27.2 by Bob Tarling. A ToDoItem should be immutable
     * to guarantee it can be passed safely between threads. Only use the
     * constructor to set this value.
     * @param p the priority
     */
    @Deprecated
    public void setPriority(int p) {
        thePriority = p;
    }

    /**
     * @return the wizard progress. An integer between 0 and 100,
     *         shows percent done.
     */
    public int getProgress() {
	if (theWizard != null) {
	    return theWizard.getProgress();
	}
	return 0;
    }

    /**
     * Reply a Set of design material's that are the subject of this ToDoItem.
     *
     * @return the offenders
     * TODO: Offenders need to be more strongly typed. - tfm 20070630
     */
    public ListSet getOffenders() {
        // TODO: should not be using assert here but I don't want to change to
        // IllegalStateException at lead up to a release as I don't know how
        // much testing is done with assert on.
        assert theOffenders != null;
        return theOffenders;
    }

    /**
     * Set the design material that is subject of this ToDoItem.
     *
     * @param offenders the offenders
     * TODO: Offenders need to be more strongly typed. - tfm 20070630
     * TODO: Provide a constructor argument for this so that the class can
     * become immutable
     * @deprecated in 0.27.2 by Bob Tarling. A ToDoItem should be immutable
     * to guarantee it can be passed safely between threads. Only use the
     * constructor to set this value.
     */
    @Deprecated
    public void setOffenders(ListSet offenders) {
        theOffenders = offenders;
    }

    /**
     * Reply the Critic or Designer that posted this ToDoItem.
     *
     * @return the poster
     */
    public Poster getPoster() {
        return thePoster;
    }

    /**
     * Return a clarifier object that can graphical highlight this
     * error in a design diagram. Return a clarifier for this todoitem,
     * if not found by the poster, or null.
     *
     * @return an Icon or null if none found.
     */
    public Icon getClarifier() {
	return thePoster.getClarifier();
    }

    /**
     * @return the wizard
     */
    public Wizard getWizard() { return theWizard; }

    /**
     * @param type the knowledgetype
     * @return true if the poster contains the given knowledgetype
     */
    public boolean containsKnowledgeType(String type) {
	return getPoster().containsKnowledgeType(type);
    }

    /**
     * @param d the decision
     * @return true if the decision is supported by the poster
     */
    public boolean supports(Decision d) {
	return getPoster().supports(d);
    }

    /**
     * @param g the given goal
     * @return true if the poster supports the given goal
     */
    public boolean supports(Goal g) {
	return getPoster().supports(g);
    }

    /*
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        int code = 0;

        code += getHeadline().hashCode();
        if (getPoster() != null) {
            code += getPoster().hashCode();
        }
        return code;
    }

    /*
     * Is this item a copy?
     *
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object o) {
	if (!(o instanceof ToDoItem)) {
	    return false;
	}
	ToDoItem i = (ToDoItem) o;
	if (!getHeadline().equals(i.getHeadline())) {
	    return false;
	}
	if (!(getPoster() == (i.getPoster()))) {
	    return false;
	}

	// For some reason ListSet.equals() allocates a lot of memory, well
	// some memory at least. Lets try to avoid that when not needed by
	// invoking this test only when the two previous tests are not decisive.
	if (!getOffenders().equals(i.getOffenders())) {
	    return false;
	}
	return true;
    }
    
    

    ////////////////////////////////////////////////////////////////
    // user interface

    /**
     * When a ToDoItem is selected in the UiToDoList window, highlight
     * the "offending" design material's.
     */
    public void select() {
        for (Object dm : getOffenders()) {
	    if (dm instanceof Highlightable) {
	        ((Highlightable) dm).setHighlight(true);
	    }
	}
    }

    /**
     * When a ToDoItem is deselected in the UiToDoList window,
     * unhighlight the "offending" design material's.
     */
    public void deselect() {
        for (Object dm : getOffenders()) {
	    if (dm instanceof Highlightable) {
	        ((Highlightable) dm).setHighlight(false);
	    }
	}
    }

    /**
     * The user has double-clicked or otherwise indicated that they
     * want to do something active with this item. By default, just
     * re-select it, subclasses may choose to do more (e.g., navigate to
     * the offending item if it is not visible).
     */
    public void action() {
        deselect();
        select();
    }

    /**
     * Notify the user interface that this ToDoItem has
     * changed. Currently, this is used to update the progress bar.
     */
    public void changed() {
	ToDoList list = Designer.theDesigner().getToDoList();
	list.fireToDoItemChanged(this);
    }


    ////////////////////////////////////////////////////////////////
    // issue resolutions

    /**
     * Some problems can be automatically fixed, ask the Critic to do
     * it if it can. <p>
     */
    public void fixIt() {
        thePoster.fixIt(this, null);
    }

    /**
     * Some problems can be automatically fixed, ask the Critic to do
     * it if it can.
     *
     * @return true if the critic can automatically fix the problem
     */
    public boolean canFixIt() {
        return thePoster.canFixIt(this);
    }

    /**
     * TODO: this is not done yet. Eventually this will also
     * feed the rational log.
     */
    //   public void resolve(Object reason) {
    //     ToDoList list = Designer.theDesigner().getToDoList();
    //     list.resolve(this, reason);
    //   }

    /**
     * Reply true iff this ToDoItem should be kept on the Designer's
     * ToDoList. This should return false if the poster has been
     * deactivated, or if it can be determined that the problem that
     * raised this issue is no longer present.
     *
     * @param d the given designer
     * @return true if the todoitem is still valid
     */
    public boolean stillValid(Designer d) {
	if (thePoster == null) {
	    return true;
	}
	if (theWizard != null && theWizard.isStarted()
	        && !theWizard.isFinished()) {
	    return true;
	}
	return thePoster.stillValid(this, d);
    }

    /*
     * Reply a string for debugging.
     *
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
	return this.getClass().getName()
	    + "(" + getHeadline() + ") on " + getOffenders().toString();
    }

    /**
     * The UID.
     */
    private static final long serialVersionUID = 3058660098451455153L;
}





