You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
444 lines
12 KiB
444 lines
12 KiB
//==============================================================================
|
|
//
|
|
// Copyright (c) 2002-
|
|
// Authors:
|
|
// * Andrew Hinton <ug60axh@cs.bham.ac.uk> (University of Birmingham)
|
|
// * Dave Parker <david.parker@comlab.ox.ac.uk> (University of Oxford, formerly University of Birmingham)
|
|
// * Mark Kattenbelt <mark.kattenbelt@comlab.ox.ac.uk> (University of Oxford, formerly University of Birmingham)
|
|
// * Vojtech Forejt <vojtech.forejt@cs.ox.ac.uk> (University of Oxford)
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// This file is part of PRISM.
|
|
//
|
|
// PRISM 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.
|
|
//
|
|
// PRISM 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 PRISM; if not, write to the Free Software Foundation,
|
|
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
//
|
|
//==============================================================================
|
|
|
|
package userinterface.properties;
|
|
|
|
import java.util.Vector;
|
|
|
|
import javax.swing.*;
|
|
|
|
import userinterface.GUIPrism;
|
|
import param.BigRational;
|
|
import parser.*;
|
|
import parser.ast.*;
|
|
import parser.type.TypeVoid;
|
|
import prism.*;
|
|
|
|
/**
|
|
* Encapsulates a property in the list in the GUI "Properties" tab.
|
|
*/
|
|
public class GUIProperty
|
|
{
|
|
//Constants
|
|
|
|
/** A property state constant image */
|
|
public static final ImageIcon IMAGE_NOT_DONE = GUIPrism.getIconFromImage("smallFilePrism.png");
|
|
/** A property state constant image */
|
|
public static final ImageIcon IMAGE_DOING = GUIPrism.getIconFromImage("smallClockAnim1.png");
|
|
/** A property state constant image */
|
|
public static final ImageIcon IMAGE_TICK = GUIPrism.getIconFromImage("smallTick.png");
|
|
/** A property state constant image */
|
|
public static final ImageIcon IMAGE_CROSS = GUIPrism.getIconFromImage("smallCross.png");
|
|
/** A property state constant image */
|
|
public static final ImageIcon IMAGE_ERROR = GUIPrism.getIconFromImage("smallError.png");
|
|
/** A property state constant image */
|
|
public static final ImageIcon IMAGE_INVALID = GUIPrism.getIconFromImage("smallWarning.png");
|
|
/** A property state constant image */
|
|
public static final ImageIcon IMAGE_NUMBER = GUIPrism.getIconFromImage("smallCompute.png");
|
|
/** A property state constant image */
|
|
public static final ImageIcon IMAGE_PARETO = GUIPrism.getIconFromImage("smallPareto.png");
|
|
|
|
/** Property status */
|
|
public static final int STATUS_NOT_DONE = 0;
|
|
/** Property status */
|
|
public static final int STATUS_DOING = 1;
|
|
/** Property status */
|
|
public static final int STATUS_PARSE_ERROR = 2;
|
|
/** Property status */
|
|
public static final int STATUS_RESULT_ERROR = 3;
|
|
/** Property status */
|
|
public static final int STATUS_RESULT_TRUE = 4;
|
|
/** Property status */
|
|
public static final int STATUS_RESULT_FALSE = 5;
|
|
/** Property status */
|
|
public static final int STATUS_RESULT_NUMBER = 6;
|
|
/** Property status */
|
|
public static final int STATUS_RESULT_PARETO = 7;
|
|
|
|
//ATTRIBUTES
|
|
|
|
private Prism prism; // Required for parsing
|
|
|
|
private String id; // Unique ID
|
|
private int status; // Status - see constants above
|
|
private ImageIcon doingImage; // Image when in DOING state - can be modified externally for animations
|
|
private boolean beingEdited; // Is this property currently being edited?
|
|
|
|
private String propString; // String representing the property
|
|
private Expression expr; // The parsed property (null if invalid)
|
|
private String comment; // The property's comment
|
|
|
|
private Result result; // Result of model checking etc. (if done, null if not)
|
|
private int numberOfWarnings; // Result of model checking etc. (if done, null if not)
|
|
private String parseError; // Parse error (if property is invalid)
|
|
|
|
private String method; // Method used (verification, simulation)
|
|
private String constantsString; // Constant values used
|
|
private String name;
|
|
private Vector<String> referencedNames;
|
|
|
|
private GUIPropertiesList propList; // to be able to get named properties
|
|
|
|
/** Creates a new instance of GUIProperty */
|
|
public GUIProperty(Prism prism, GUIPropertiesList propList, String id, String propString, String name, String comment)
|
|
{
|
|
this.prism = prism;
|
|
this.propList = propList;
|
|
|
|
this.id = id;
|
|
status = STATUS_NOT_DONE;
|
|
doingImage = IMAGE_DOING;
|
|
beingEdited = false;
|
|
|
|
this.propString = propString;
|
|
expr = null;
|
|
this.comment = comment;
|
|
this.name = name;
|
|
|
|
result = null;
|
|
parseError = "";
|
|
method = "<none>";
|
|
constantsString = "<none>";
|
|
}
|
|
|
|
//ACCESS METHODS
|
|
|
|
public String getID()
|
|
{
|
|
return id;
|
|
}
|
|
|
|
public int getStatus()
|
|
{
|
|
return status;
|
|
}
|
|
|
|
public ImageIcon getImage()
|
|
{
|
|
switch (status) {
|
|
case STATUS_NOT_DONE:
|
|
return IMAGE_NOT_DONE;
|
|
case STATUS_DOING:
|
|
return doingImage;
|
|
case STATUS_PARSE_ERROR:
|
|
return IMAGE_INVALID;
|
|
case STATUS_RESULT_ERROR:
|
|
return IMAGE_ERROR;
|
|
case STATUS_RESULT_TRUE:
|
|
return IMAGE_TICK;
|
|
case STATUS_RESULT_FALSE:
|
|
return IMAGE_CROSS;
|
|
case STATUS_RESULT_NUMBER:
|
|
return IMAGE_NUMBER;
|
|
case STATUS_RESULT_PARETO:
|
|
return IMAGE_PARETO;
|
|
default:
|
|
return IMAGE_NOT_DONE;
|
|
}
|
|
}
|
|
|
|
public boolean isBeingEdited()
|
|
{
|
|
return beingEdited;
|
|
}
|
|
|
|
public String getPropString()
|
|
{
|
|
return propString;
|
|
}
|
|
|
|
/**
|
|
* Returns the name of this property, or {@code null} if the property
|
|
* has no name.
|
|
*/
|
|
public String getName()
|
|
{
|
|
return this.name;
|
|
}
|
|
|
|
/**
|
|
* If the property is valid (see {@link #isValid()}), returns a
|
|
* (potentialy empty) vector containing names of properties
|
|
* this property references.
|
|
* <p/>
|
|
* If the property is not valid, returns {@code null}.
|
|
*/
|
|
public Vector<String> getReferencedNames()
|
|
{
|
|
return this.referencedNames;
|
|
}
|
|
|
|
public Expression getProperty()
|
|
{
|
|
return expr;
|
|
}
|
|
|
|
public String getComment()
|
|
{
|
|
return comment;
|
|
}
|
|
|
|
/**
|
|
* Is this property valid? i.e. Did it parse OK last time it was parsed?
|
|
*/
|
|
public boolean isValid()
|
|
{
|
|
return expr != null;
|
|
}
|
|
|
|
/**
|
|
* Forgets the validity state of the property, i.e. {@link #isValid()} will
|
|
* be returning {@code false} until property is parsed OK again.
|
|
* @return
|
|
*/
|
|
public void makeInvalid() {
|
|
this.expr = null;
|
|
this.referencedNames = null;
|
|
}
|
|
|
|
/**
|
|
* Is this property both valid (i.e. parsed OK last time it was checked)
|
|
* and suitable approximate verification through simulation?
|
|
*/
|
|
public boolean isValidForSimulation()
|
|
{
|
|
return isValid() && prism.isPropertyOKForSimulation(expr);
|
|
}
|
|
|
|
public Result getResult()
|
|
{
|
|
return result;
|
|
}
|
|
|
|
public int getNumberOfWarnings()
|
|
{
|
|
return this.numberOfWarnings;
|
|
}
|
|
|
|
|
|
public String getResultString()
|
|
{
|
|
return result == null ? "Unknown" : result.getResultString();
|
|
}
|
|
|
|
public String getToolTipText()
|
|
{
|
|
switch (status) {
|
|
case STATUS_DOING:
|
|
return "In progress...";
|
|
case STATUS_PARSE_ERROR:
|
|
return "Invalid property: " + parseError;
|
|
case STATUS_RESULT_ERROR:
|
|
return getResultString();
|
|
default:
|
|
return "<html>Result: " + getResultString().replaceAll("\n", "<br/>") + "</html>";
|
|
}
|
|
}
|
|
|
|
public String getConstantsString()
|
|
{
|
|
return constantsString;
|
|
}
|
|
|
|
public String getMethodString()
|
|
{
|
|
return method;
|
|
}
|
|
|
|
public String toString()
|
|
{
|
|
return ((this.name != null) ? ("\"" + this.name + "\" : ") : "") + propString;
|
|
}
|
|
|
|
//UPDATE METHODS
|
|
|
|
public void setStatus(int status)
|
|
{
|
|
this.status = status;
|
|
}
|
|
|
|
public void setDoingImage(ImageIcon image)
|
|
{
|
|
doingImage = image;
|
|
}
|
|
|
|
public void setPropStringAndName(String propString, String name, ModulesFile m, String constantsString, String labelString)
|
|
{
|
|
this.propString = propString;
|
|
this.name = name;
|
|
setStatus(STATUS_NOT_DONE);
|
|
propList.validateProperties();
|
|
}
|
|
|
|
public void setComment(String comment)
|
|
{
|
|
this.comment = comment;
|
|
}
|
|
|
|
public void setBeingEdited(boolean beingEdited)
|
|
{
|
|
this.beingEdited = beingEdited;
|
|
}
|
|
|
|
public void setResult(Result res)
|
|
{
|
|
result = res;
|
|
if (result.getResult() instanceof Boolean) {
|
|
if (((Boolean) result.getResult()).booleanValue()) {
|
|
setStatus(STATUS_RESULT_TRUE);
|
|
} else {
|
|
setStatus(STATUS_RESULT_FALSE);
|
|
}
|
|
} else if (result.getResult() instanceof Integer) {
|
|
setStatus(STATUS_RESULT_NUMBER);
|
|
} else if (result.getResult() instanceof Double) {
|
|
setStatus(STATUS_RESULT_NUMBER);
|
|
} else if (result.getResult() instanceof BigRational) {
|
|
setStatus(STATUS_RESULT_NUMBER);
|
|
} else if (result.getResult() instanceof Interval) {
|
|
setStatus(STATUS_RESULT_NUMBER);
|
|
} else if (result.getResult() instanceof Exception) {
|
|
setStatus(STATUS_RESULT_ERROR);
|
|
} else if (result.getResult() instanceof TileList) {
|
|
setStatus(STATUS_RESULT_PARETO);
|
|
} else {
|
|
setStatus(STATUS_NOT_DONE);
|
|
result = null;
|
|
}
|
|
}
|
|
|
|
public void setNumberOfWarnings(int n)
|
|
{
|
|
this.numberOfWarnings = n;
|
|
}
|
|
|
|
public void setMethodString(String method)
|
|
{
|
|
this.method = (method == null) ? "<none>" : method;
|
|
}
|
|
|
|
public void setConstants(Values mfConstants, Values pfConstants)
|
|
{
|
|
if (mfConstants != null && mfConstants.getNumValues() > 0) {
|
|
constantsString = mfConstants.toString();
|
|
if (pfConstants != null && pfConstants.getNumValues() > 0)
|
|
constantsString += ", " + pfConstants.toString();
|
|
} else if (pfConstants != null && pfConstants.getNumValues() > 0) {
|
|
constantsString = pfConstants.toString();
|
|
} else {
|
|
constantsString = "<none>";
|
|
}
|
|
}
|
|
|
|
public void parse(ModulesFile m, String constantsString, String labelString)
|
|
{
|
|
if (propString == null || constantsString == null || labelString == null) {
|
|
expr = null;
|
|
setStatus(STATUS_PARSE_ERROR);
|
|
parseError = "(Unexpected) Properties, constants or labels are null";
|
|
return;
|
|
}
|
|
try {
|
|
//Parse constants and labels
|
|
boolean couldBeNoConstantsOrLabels = false;
|
|
PropertiesFile fConLab = null;
|
|
try {
|
|
fConLab = prism.parsePropertiesString(m, constantsString + "\n" + labelString);
|
|
} catch (PrismException e) {
|
|
couldBeNoConstantsOrLabels = true;
|
|
}
|
|
|
|
String namedString = "";
|
|
int namedCount = 0;
|
|
//Add named properties
|
|
for (GUIProperty namedProp : this.propList.getAllNamedProperties()) {
|
|
|
|
if (namedProp.isValid() &&
|
|
(this.name == null || !this.name.equals(namedProp.getName()))) {
|
|
namedCount++;
|
|
namedString += "\"" + namedProp.getName() + "\" : " + namedProp.getPropString() + "\n";
|
|
}
|
|
}
|
|
|
|
//Parse all together
|
|
String withConsLabs = constantsString + "\n" + labelString + "\n" + namedString + propString;
|
|
PropertiesFile ff = prism.parsePropertiesString(m, withConsLabs);
|
|
|
|
//Validation of number of properties
|
|
if (ff.getNumProperties() <= namedCount)
|
|
throw new PrismException("Empty Property");
|
|
else if (ff.getNumProperties() > namedCount + 1)
|
|
throw new PrismException("Contains Multiple Properties");
|
|
|
|
//Validation of constants and labels
|
|
if (!couldBeNoConstantsOrLabels) {
|
|
if (ff.getConstantList().size() != fConLab.getConstantList().size())
|
|
throw new PrismException("Contains constants");
|
|
if (ff.getLabelList().size() != fConLab.getLabelList().size())
|
|
throw new PrismException("Contains labels");
|
|
} else {
|
|
if (ff.getConstantList().size() != 0)
|
|
throw new PrismException("Contains constants");
|
|
if (ff.getLabelList().size() != 0)
|
|
throw new PrismException("Contains labels");
|
|
}
|
|
//Now set the property
|
|
expr = ff.getProperty(namedCount);
|
|
parseError = "(Unexpected) no error!";
|
|
// if status was previously a parse error, reset status.
|
|
// otherwise, don't set status - reparse doesn't mean existing results should be lost
|
|
if (getStatus() == STATUS_PARSE_ERROR)
|
|
setStatus(STATUS_NOT_DONE);
|
|
|
|
// get the referenced names
|
|
this.referencedNames = ff.getPropertyObject(namedCount).getAllPropRefsRecursively(ff);
|
|
|
|
} catch (PrismException ex) {
|
|
this.expr = null;
|
|
this.referencedNames = null;
|
|
setStatus(STATUS_PARSE_ERROR);
|
|
parseError = ex.getMessage();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int hashCode()
|
|
{
|
|
return (this.propString != null) ? this.propString.length() : 0;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object obj)
|
|
{
|
|
if (!(obj instanceof GUIProperty))
|
|
return false;
|
|
|
|
return this.id.equals(((GUIProperty) obj).id);
|
|
}
|
|
}
|