//#if defined(COGNITIVE)
//@#$LPS-COGNITIVE:GranularityType:Package
// $Id: Critic.java 132 2010-09-26 23:32:33Z marcusvnac $
// 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 java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Observable;
import java.util.Set;
import javax.swing.Icon;
//#if defined(LOGGING)
//@#$LPS-LOGGING:GranularityType:Import
//@#$LPS-LOGGING:Localization:NestedIfdef-COGNITIVE
import org.apache.log4j.Logger;
//#endif
import org.argouml.application.helpers.ApplicationVersion;
import org.argouml.application.helpers.ResourceLoaderWrapper;
import org.argouml.cognitive.critics.SnoozeOrder;
import org.argouml.cognitive.critics.Wizard;
import org.argouml.configuration.Configuration;
import org.argouml.configuration.ConfigurationKey;
/**
* "Abstract" base class for design critics. Each subclass should define
* its own predicate method and define its own relevance tags. <p>
*
* A critic supports design goals and decisions, which can be adjusted
* accordingly. It will post todo items which may or may not be relevant to
* the particular designer.<p>
*
* Steps to follow when adding a critic are listed in the Argo
* cookbook under <a HREF="../cookbook.html#define_critic">
* define_critic</a>.
*
* @author Jason Robbins
*/
public class Critic
extends Observable
implements Poster, Serializable {
//#if defined(LOGGING)
//@#$LPS-LOGGING:GranularityType:Field
//@#$LPS-LOGGING:Localization:NestedIfdef-COGNITIVE
/**
* Logger.
*/
private static final Logger LOG = Logger.getLogger(Critic.class);
//#endif
////////////////////////////////////////////////////////////////
// constants
/**
* PROBLEM_FOUND is used for the result of the check of a critic.
*/
public static final boolean PROBLEM_FOUND = true;
/**
* NO_PROBLEM is used for the result of the check of a critic.
*/
public static final boolean NO_PROBLEM = false;
/**
* The keys of some predefined control records.
*/
private static final String ENABLED = "enabled";
private static final String SNOOZE_ORDER = "snoozeOrder";
/**
* Type of knowledge that critics can deliver.
*/
public static final String KT_DESIGNERS =
Translator.localize("misc.knowledge.designers");
/**
* Type of knowledge that critics can deliver.
*/
public static final String KT_CORRECTNESS =
Translator.localize("misc.knowledge.correctness");
/**
* Type of knowledge that critics can deliver.
*/
public static final String KT_COMPLETENESS =
Translator.localize("misc.knowledge.completeness");
/**
* Type of knowledge that critics can deliver.
*/
public static final String KT_CONSISTENCY =
Translator.localize("misc.knowledge.consistency");
/**
* Type of knowledge that critics can deliver.
*/
public static final String KT_SYNTAX =
Translator.localize("misc.knowledge.syntax");
/**
* Type of knowledge that critics can deliver.
*/
public static final String KT_SEMANTICS =
Translator.localize("misc.knowledge.semantics");
/**
* Type of knowledge that critics can deliver.
*/
public static final String KT_OPTIMIZATION =
Translator.localize("misc.knowledge.optimization");
/**
* Type of knowledge that critics can deliver.
*/
public static final String KT_PRESENTATION =
Translator.localize("misc.knowledge.presentation");
/**
* Type of knowledge that critics can deliver.
*/
public static final String KT_ORGANIZATIONAL =
Translator.localize("misc.knowledge.organizational");
/**
* Type of knowledge that critics can deliver.
*/
public static final String KT_EXPERIENCIAL =
Translator.localize("misc.knowledge.experiential");
/**
* Type of knowledge that critics can deliver.
*/
public static final String KT_TOOL =
Translator.localize("misc.knowledge.tool");
/**
* This function calculates the default URL to describe this critic.
*
* @return the URL in string format
*/
public final String defaultMoreInfoURL() {
String clsName = getClass().getName();
clsName = clsName.substring(clsName.lastIndexOf(".") + 1);
return ApplicationVersion.getManualForCritic()
+ clsName;
}
////////////////////////////////////////////////////////////////
// instance variables
/**
* The priority of the ToDoItem produced.
*/
private int priority;
/**
* The headline of the ToDoItem produced.
*/
private String headline;
/**
* The description of the ToDoItem produced.
*/
private String description;
/**
* The moreInfoURL of the ToDoItem produced.
*/
private String moreInfoURL;
/**
* Arguments used to configure the critic.
* TODO: Could this be removed from the main critics class?
* @deprecated for 0.25.4 by Linus Tolke.
* This way of storing information encourages
* violation of type safety.
* Create member attributes instead.
*/
@Deprecated
private Hashtable<String, Object> args = new Hashtable<String, Object>();
/**
* The icon representing the resource.
*/
public static final Icon DEFAULT_CLARIFIER =
ResourceLoaderWrapper
.lookupIconResource("PostIt0");
private Icon clarifier = DEFAULT_CLARIFIER;
/**
* The decision category that this critic is relevant to. The idea
* of each critic being relevant to exactly one type of decision
* is a very simple one. Subclasses that have more sophisticated
* decision relevance logic should override isRelevantToDecisions.
* You can also define new ControlMech's. <p>
*
* Decision categories are defined in the DecisionModel of a
* particular domain.
*
* @see ControlMech
*/
private String decisionCategory;
private List<Decision> supportedDecisions = new ArrayList<Decision>();
private List<Goal> supportedGoals = new ArrayList<Goal>();
/**
* The decision type of this critic. For example, correctness,
* completeness, consistency, alternative, presentation,
* optimization, organizational, tool critics, etc.
*/
private String criticType;
/**
* Internal flag that stores the end result of all ControlMech
* evaluations of this critic.
*/
private boolean isActive = true;
/**
* Control records used in determining if this Critic should be
* active.
*/
private Hashtable<String, Object> controlRecs =
new Hashtable<String, Object>();
private ListSet<String> knowledgeTypes = new ListSet<String>();
private long triggerMask = 0L;
////////////////////////////////////////////////////////////////
// constructor
/**
* Construct a new critic instance. Typically only one instance of
* each critic class is created and stored in a static variable, as
* per the Singleton pattern. Each domain extension should define
* a static initializer block to make one instance of each critic and
* call {@link Agency#register(Critic, Object)} with that instance.
*/
public Critic() {
/* TODO: THIS IS A HACK.
* A much better way of doing this would be not to start
* the critic in the first place.
*/
if (Configuration.getBoolean(getCriticKey(), true)) {
addControlRec(ENABLED, Boolean.TRUE);
isActive = true;
} else {
addControlRec(ENABLED, Boolean.FALSE);
isActive = false;
}
addControlRec(SNOOZE_ORDER, new SnoozeOrder());
criticType = "correctness";
knowledgeTypes.add(KT_CORRECTNESS);
decisionCategory = "Checking";
moreInfoURL = defaultMoreInfoURL();
description = Translator.localize("misc.critic.no-description");
headline = Translator.messageFormat("misc.critic.default-headline",
new Object[] {getClass().getName()});
priority = ToDoItem.MED_PRIORITY;
}
/**
* Returns the {@link org.argouml.configuration.ConfigurationKey}
* that the critic uses to determine if it is enabled or disabled.<p>
*
* The string resulting from the ConfigurationKey
* <code>argo.critic.critic_category.critic_name</code>.<p>
*
* <code>critic_category</code> would describe the type of critic and is
* taken from {@link #getCriticCategory}.<p>
*
* <code>critic_name</code> would describe the function of the critic
* and is taken from {@link #getCriticName}.<p>
*
* Some examples:<p>
* <ul>
* <li>argo.critic.layout.Overlap
* <li>argo.critic.uml.ReservedWord
* <li>argo.critic.java.ReservedWord
* <li>argo.critic.idl.ReservedWord
* </ul>
*
* @see org.argouml.configuration.Configuration#makeKey(String,
* String, String)
* @see #getCriticCategory
* @see #getCriticName
*
* @since 0.9.4
*
* @return the key
*/
public ConfigurationKey getCriticKey() {
return Configuration.makeKey("critic",
getCriticCategory(),
getCriticName());
}
/**
* Returns a default critic category.
* Critics should override this
* to provide specific classification information.
*
* @since 0.9.4
*
* @return a default category
*/
public String getCriticCategory() {
return Translator.localize("misc.critic.unclassified");
}
/**
* Returns a default critic name.
* By default this is the simple class name.
* Critic implementations should override this
* to provide a better (more descriptive) string.
*
* @since 0.9.4
*
* @return a default critic name
*/
public String getCriticName() {
return getClass().getName()
.substring(getClass().getName().lastIndexOf(".") + 1);
}
////////////////////////////////////////////////////////////////
// critiquing
/**
* Examine the given Object and Designer and, if
* appropriate, produce one or more ToDoItem's and add them to the
* offending design material's and the Designer's ToDoList. By
* default this is basically a simple if-statement that relies on
* predicate() to determine if there is some appropriate feedback,
* and toDoItem() to produce the ToDoItem.
*
* The predicate() and toDoItem() pair of methods is simple and
* convient for many critics. More sophisticated critics that
* produce more than one ToDoItem per critiquing, or that produce
* ToDoItem's that contain information that was already computed in
* the predicate, should override critique. If you override this
* method, you should call super.critique().
*
* @see Critic#predicate
* @see Critic#toDoItem
*
* @param dm the design material
* @param dsgr the designer
*/
public void critique(Object dm, Designer dsgr) {
// The following debug line is now the single most memory consuming
// line in the whole of ArgoUML. It allocates approximately 18% of
// all memory allocated.
// Suggestions for solutions:
// Check if there is a LOG.debug(String, String) method that can
// be used instead.
// Use two calls.
// For now I (Linus) just comment it out.
// LOG.debug("applying critic: " + _headline);
if (predicate(dm, dsgr)) {
// LOG.debug("predicate() returned true, creating ToDoItem");
ToDoItem item = toDoItem(dm, dsgr);
postItem(item, dm, dsgr);
}
}
/**
* @param item the todo item
* @param dm the designmaterial/offender to be informed
* @param dsgr the designer
*/
public void postItem(ToDoItem item, Object dm, Designer dsgr) {
if (dm instanceof Offender) {
((Offender) dm).inform(item);
}
dsgr.inform(item);
}
/**
* Perform the Critic's analysis of the design. Subclasses should test
* the given Object to make sure that it is the type of
* object that is expected. Each object in the design registers its
* own critics with the run-time system. The dm parameter is bound
* to each design object that registered this critic, one per
* call. Returning true means that feedback should be delivered to
* the Designer. By convention, subclasses should return their
* superclass predicate method if their own predicate would
* return false.
*
* @param dm the design material, which is to be checked
* @param dsgr the designer
* @return the critic result
*/
public boolean predicate(Object dm, Designer dsgr) {
return false;
}
/**
* Return true iff the given ToDoItem is still valid and should be
* kept in the given designers ToDoList. Critics that are not
* enabled should always return false so that their ToDoItems will
* be removed. Subclasses of Critic that supply multiple offenders
* should always override this method. <p>
*
* By default this method basically asks the critic to again
* critique the offending Object and then it checks if the
* resulting ToDoItem is the same as the one already posted. This is
* simple and it works fine for light-weight critics. Critics that
* expend a lot of computational effort in making feedback that can
* be easily check to see if it still holds, should override this
* method. <p>
*
* TODO: Maybe ToDoItem should carry some data to make
* this method more efficient.
*
* {@inheritDoc}
*/
public boolean stillValid(ToDoItem i, Designer dsgr) {
if (!isActive()) {
//#if defined(LOGGING)
//@#$LPS-LOGGING:GranularityType:Statement
//@#$LPS-LOGGING:Localization:NestedStatement
//@#$LPS-LOGGING:Localization:NestedIfdef-COGNITIVE
LOG.warn("got to stillvalid while not active");
//#endif
return false;
}
if (i.getOffenders().size() != 1) {
return true;
}
if (predicate(i.getOffenders().get(0), dsgr)) {
// Now we know that this critic is still valid. What we need to
// figure out is if the corresponding to-do item is still valid.
// The to-do item is to be replaced if the name of some offender
// has changed that affects its description or if the contents
// of the list of offenders has changed.
// We check that by creating a new ToDoItem and then verifying
// that it looks exactly the same.
// This really creates a lot of to-do items that goes to waste.
ToDoItem item = toDoItem(i.getOffenders().get(0), dsgr);
return (item.equals(i));
}
return false;
}
/*
* @see org.argouml.cognitive.Poster#supports(org.argouml.cognitive.Decision)
*/
public boolean supports(Decision d) {
return supportedDecisions.contains(d);
}
public List<Decision> getSupportedDecisions() {
return supportedDecisions;
}
/**
* @param d the decision
*/
public void addSupportedDecision(Decision d) {
supportedDecisions.add(d);
}
/*
* @see org.argouml.cognitive.Poster#supports(org.argouml.cognitive.Goal)
*/
public boolean supports(Goal g) {
return supportedGoals.contains(g);
}
public List<Goal> getSupportedGoals() {
return supportedGoals;
}
/**
* @param g the goal
*/
public void addSupportedGoal(Goal g) {
supportedGoals.add(g);
}
/*
* @see org.argouml.cognitive.Poster#containsKnowledgeType(java.lang.String)
*/
public boolean containsKnowledgeType(String type) {
return knowledgeTypes.contains(type);
}
/**
* @param type the knowledgetype
*/
public void addKnowledgeType(String type) {
knowledgeTypes.add(type);
}
/**
* @return the knowledgetypes
*/
public ListSet<String> getKnowledgeTypes() {
return knowledgeTypes;
}
/**
* @param kt the knowledgetypes
*/
public void setKnowledgeTypes(ListSet<String> kt) {
knowledgeTypes = kt;
}
/**
* Reset all knowledgetypes, and add the given one.
*
* @param t1 the only knowledgetype in string format
*/
public void setKnowledgeTypes(String t1) {
knowledgeTypes = new ListSet<String>();
addKnowledgeType(t1);
}
/**
* Reset all knowledgetypes, and add the given ones.
*
* @param t1 a knowledgetype in string format
* @param t2 a knowledgetype in string format
*/
public void setKnowledgeTypes(String t1, String t2) {
knowledgeTypes = new ListSet<String>();
addKnowledgeType(t1);
addKnowledgeType(t2);
}
/**
* Reset all knowledgetypes, and add the given ones.
*
* @param t1 a knowledgetype in string format
* @param t2 a knowledgetype in string format
* @param t3 a knowledgetype in string format
*/
public void setKnowledgeTypes(String t1, String t2, String t3) {
knowledgeTypes = new ListSet<String>();
addKnowledgeType(t1);
addKnowledgeType(t2);
addKnowledgeType(t3);
}
/**
* @param s the reason
* @return the code for the given reason
*/
public static int reasonCodeFor(String s) {
return 1 << (s.hashCode() % 62);
}
/**
* @return the trigger mask
*/
public long getTriggerMask() {
return triggerMask;
}
/**
* @param s the trigger to be added (is ORed into the mask)
*/
public void addTrigger(String s) {
int newCode = reasonCodeFor(s);
triggerMask |= newCode;
}
/**
* @param patternCode the mask to be checked
* @return true if it matches a trigger
*/
public boolean matchReason(long patternCode) {
return (triggerMask == 0) || ((triggerMask & patternCode) != 0);
}
/*
* @see org.argouml.cognitive.Poster#expand(java.lang.String, org.argouml.cognitive.ListSet)
*/
public String expand(String desc, ListSet offs) {
return desc;
}
/*
* @see org.argouml.cognitive.Poster#getClarifier()
*/
public Icon getClarifier() {
return clarifier;
}
////////////////////////////////////////////////////////////////
// criticism control
/**
* Reply true iff this Critic can execute. This fact is normally
* determined by a ControlMech.
*
* @return true iff this Critic can execute
*/
public boolean isActive() { return isActive; }
/**
* Make this critic active. From now on it can be applied to a
* design material in critiquing.
*/
public void beActive() {
if (!isActive) {
Configuration.setBoolean(getCriticKey(), true);
isActive = true;
setChanged();
notifyObservers(this);
}
}
/**
* Make this critic inactive. From now on it will be idle and will
* not be applied to a design material in critiquing.
*/
public void beInactive() {
if (isActive) {
Configuration.setBoolean(getCriticKey(), false);
isActive = false;
setChanged();
notifyObservers(this);
}
}
/**
* Add some attribute used by ControlMech to determine if this
* Critic should be active. Critics store control record so that
* stateful ControlMech's do not need to store a parallel data
* structure. But Critic's do not directy use or modify this
* data.
*
* @param name the key
* @param controlData the value
* @return the previous value of the specified key
* in this hashtable, or <code>null</code>
* if it did not have one
*/
public Object addControlRec(String name, Object controlData) {
return controlRecs.put(name, controlData);
}
/**
* Reply the named control record, or null if not defined.
*
* @param name the key
* @return the value
*/
public Object getControlRec(String name) {
return controlRecs.get(name);
}
/**
* This is a convient method for accessing one well-known control
* record. The enabled control record is a boolean that the user can
* turn on or off to manually enable or disable this Critic. It is
* normally combined with other ControlMech determinations with a
* logic-and.
*
* @return true if enabled
*/
public boolean isEnabled() {
if (this.getCriticName() != null
&& this.getCriticName().equals("CrNoGuard")) {
System.currentTimeMillis();
}
return ((Boolean) getControlRec(ENABLED)).booleanValue();
}
/**
* @param e the value to be set for the key ENABLED
*/
public void setEnabled(boolean e) {
Boolean enabledBool = e ? Boolean.TRUE : Boolean.FALSE;
addControlRec(ENABLED, enabledBool);
}
/**
* Reply the SnoozeOrder that is defined for this critic.
*
* @return the snooze order
*/
public SnoozeOrder snoozeOrder() {
return (SnoozeOrder) getControlRec(SNOOZE_ORDER);
}
/**
* Disable this Critic for the next few minutes.
*/
public void snooze() { snoozeOrder().snooze(); }
/**
* Lift any previous SnoozeOrder.
*/
public void unsnooze() { snoozeOrder().unsnooze(); }
/**
* Checks if the critic is currently snoozed.
* @return true if the critic is snoozed
*/
public boolean isSnoozed() {
return snoozeOrder().getSnoozed();
}
/**
* Reply true if this Critic is relevant to the decisions that
* the Designer is considering. By default just asks the Designer if
* he/she is considering my decisionCategory. Really this is
* something for a ControlMech to compute, but if a subclass of
* Critic encapsulates some information you may need to override
* this method.
*
* @param dsgr the designer
* @return true if relevant
*/
public boolean isRelevantToDecisions(Designer dsgr) {
for (Decision d : getSupportedDecisions()) {
/* TODO: Make use of the constants defined in the ToDoItem class! */
if (d.getPriority() > 0 && d.getPriority() <= getPriority()) {
return true;
}
}
return false;
}
/**
* Reply true iff this Critic is relevant to the goals that the
* Designer is trying to achieve. By default, all Critic's are
* relevant regardless of the GoalModel. Really this is something for a
* ControlMech to compute, but if a subclass of Critic encapsulates
* some information you may need to override this method. <p>
*
* TODO: I would like a better default action, but goals
* are typed and their values must be interperted by critics. They
* are not as generic as the DecisionModel.
*
* @param dsgr the designer
* @return true if relevant
*/
public boolean isRelevantToGoals(Designer dsgr) {
return true;
}
////////////////////////////////////////////////////////////////
// corrective automations, wizards
/**
* Create a new Wizard to help the user fix the identified problem. This
* version assumes subclasses override getWizClass to return the appropriate
* Class of wizard. Critic subclasses that need to initialize their wizard
* might override this to call super.makeWizard() and then work with the
* result.
*
* @param item
* the todo item
* @return the wizard
*/
public Wizard makeWizard(ToDoItem item) {
Class wizClass = getWizardClass(item);
// if wizClass is not a subclass of Wizard, print a warning
if (wizClass != null) {
try {
Wizard w = (Wizard) wizClass.newInstance();
w.setToDoItem(item);
initWizard(w);
return w;
} catch (IllegalAccessException illEx) {
//#if defined(LOGGING)
//@#$LPS-LOGGING:GranularityType:Statement
//@#$LPS-LOGGING:Localization:NestedStatement
//@#$LPS-LOGGING:Localization:NestedIfdef-COGNITIVE
LOG.error("Could not access wizard: ", illEx);
//#endif
} catch (InstantiationException instEx) {
//#if defined(LOGGING)
//@#$LPS-LOGGING:GranularityType:Statement
//@#$LPS-LOGGING:Localization:NestedStatement
//@#$LPS-LOGGING:Localization:NestedIfdef-COGNITIVE
LOG.error("Could not instantiate wizard: ", instEx);
//#endif
}
}
return null;
}
/**
* Return the Class of wizard that can fix the problem identifed by
* this critic.
* This method returns null, subclasses with wizards should override it.
*
* @param item the todo item
* @return null if no wizard is defined.
*/
public Class getWizardClass(ToDoItem item) {
return null;
}
/**
* Initialize a newly created wizard with information found by the
* critic. This is called right after the wizard is made in
* makeWizard() and after the wizard's ToDoItem is set. Any critic
* that supports wizards should probably override this method, and
* call super initWizard() first.
*
* @param w the wizard
*/
public void initWizard(Wizard w) {
}
////////////////////////////////////////////////////////////////
// accessors
/**
* Reply a string used to determine if this critic would be
* relevant to current design decisions. Strings returned from here
* are compared to strings in the DecisionModel.
*
* @return the decision category
*/
public String getDecisionCategory() {
return decisionCategory;
}
/**
* Set the decisionCategory, usually done in the constructor. I
* have not yet thought of a case where dynamically changing the
* Critic's decisionCategory is useful.
*
* @param c the category
*/
protected void setDecisionCategory(String c) {
decisionCategory = c;
}
/**
* Reply a string used to contol critics according to
* type. Examples include: correctness, completeness, consistency,
* optimization, presentation, and alternative.
*
* @return the critic knowledge type
*/
public String getCriticType() {
return criticType;
}
/**
* Reply the headline used in feedback produced by this Critic.
*
* @param dm the design material
* @param dsgr the designer
* @return the headline
*/
public String getHeadline(Object dm, Designer dsgr) {
return getHeadline();
}
/**
* Reply the headline used in feedback produced by this Critic.
*
* @param offenders the set of offenders
* @param dsgr the designer
* @return the headline
*/
public String getHeadline(ListSet offenders, Designer dsgr) {
return getHeadline(offenders.get(0), dsgr);
}
/**
* Reply the headline used in feedback produced by this Critic.
*
* @return the headline
*/
public String getHeadline() {
return headline;
}
/**
* Set the headline used in feedback produced by this Critic.
*
* @param h the headline
*/
public void setHeadline(String h) {
headline = h;
}
/**
* Reply the priority used in feedback produced by this Critic.
*
* @param offenders the offenders
* @param dsgr the designer
* @return the priority
*/
public int getPriority(ListSet offenders, Designer dsgr) {
return priority;
}
/**
* @param p the priority
*/
public void setPriority(int p) {
priority = p;
}
/**
* @return the priority
*/
public int getPriority() {
return priority;
}
/**
* Reply the description used in feedback produced by this Critic.
*
* @param offenders the offenders
* @param dsgr the designer
* @return the description
*/
public String getDescription(ListSet offenders, Designer dsgr) {
return description;
}
/**
* @param d the description
*/
public void setDescription(String d) {
description = d;
}
/**
* @return the description
*/
public String getDescriptionTemplate() {
return description;
}
/**
* Reply the moreInfoURL used in feedback produced by this Critic.
*
* @param offenders the offenders
* @param dsgr the designer
* @return the more-info-url
*/
public String getMoreInfoURL(ListSet offenders, Designer dsgr) {
return moreInfoURL;
}
/**
* @param m the more-info-url
*/
public void setMoreInfoURL(String m) {
moreInfoURL = m;
}
/**
* @return the more-info-url
*/
public String getMoreInfoURL() {
return getMoreInfoURL(null, null);
}
/**
* @param name the key
* @param value the value
* @deprecated for 0.25.4 by Linus Tolke.
* This way of storing information encourages
* violation of type safety.
* Create member attributes instead.
*/
@Deprecated
protected void setArg(String name, Object value) {
args.put(name, value);
}
/**
* @param name the key
* @return the value
* @deprecated for 0.25.4 by Linus Tolke.
* This way of storing information encourages
* violation of type safety.
* Create member attributes instead.
*/
@Deprecated
protected Object getArg(String name) {
return args.get(name);
}
/**
* @return the (key, value) pairs
* @deprecated for 0.25.4 by Linus Tolke.
* This way of storing information encourages
* violation of type safety.
* Create member attributes instead.
*/
@Deprecated
public Hashtable<String, Object> getArgs() {
return args;
}
/**
* @param h the new table of (key, value) pairs
* @deprecated for 0.25.4 by Linus Tolke.
* This way of storing information encourages
* violation of type safety.
* Create member attributes instead.
*/
@Deprecated
public void setArgs(Hashtable<String, Object> h) {
args = h;
}
/**
* Get the design materials to be criticized by this critic
*
* @return the design materials
*/
public Set<Object> getCriticizedDesignMaterials() {
Set<Object> ret = new HashSet<Object>();
return ret;
}
////////////////////////////////////////////////////////////////
// design feedback
/**
* Reply the ToDoItem that the designer should see iff predicate()
* returns true. By default it just fills in the fields of the
* ToDoItem from accessor methods of this Critic. Critic Subclasses
* may override this method or the accessor methods to add computed
* fields to the ToDoItem.
*
* TODO: Critic's may want to add new fields to a
* ToDoItem to make stillValid more efficent.
*
* @see Critic#critique
*
* @param dm the offender
* @param dsgr the designer
* @return ToDoItem
*/
public ToDoItem toDoItem(Object dm, Designer dsgr) {
return new ToDoItem(this, dm, dsgr);
}
////////////////////////////////////////////////////////////////
// issue resolution
/*
* TODO: Not implemented yet. The idea is that some
* problems identified by Critic's can be fixed with certain design
* manipulations (or transforms) that can be applied automatically
* to resolve the problem. This method replies true iff the given
* problem can be fixed. The fixIt() method actually does the fix.
*
* @see org.argouml.cognitive.Poster#canFixIt(org.argouml.cognitive.ToDoItem)
* Also
* @see Critic#fixIt
*/
public boolean canFixIt(ToDoItem item) {
return false;
}
/*
* @see org.argouml.cognitive.Poster#fixIt(org.argouml.cognitive.ToDoItem, java.lang.Object)
*/
public void fixIt(ToDoItem item, Object arg) {
}
/*
* Reply a string that describes this Critic. Identical to getCriticName()
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
//return getCriticName();
return getHeadline();
}
}
//#endif