// $Id: Module.java,v 3.2 1998/12/14 22:23:03 te3d Exp $
////////////////////////////////////////////////////////////////////////////
//
// File: Module.java
//
// Purpose: A Module consists of a number of Nodes, which represent
// design parameters (DPs) or functional requirements (FRs).
// The "boss" Module (e.g., modules[0]) contains the FRs,
// while the other, "developer" Modules contain DPs.
// Modules also have names.
//
// This is a base class, and can used by several modules.
// For that reason, we don't specify the invoking modules.
//
// Authors:
// txe Travis Emmitt emmitt@virginia.edu
// jpg James P. Gunderson gunders@virginia.edu
//
// Modifications:
// 28-OCT-1998 txe (v1) Initial creation
// 03-NOV-1998 txe Added comments, removed unused methods.
// 04-NOV-1998 jpg Added Serialization methods
// 06-NOV-1998 rgb Added version control header info
// 06-NOV-1998 txe Added SetStable(), Valid(), Verbose(), debugging
// 06-NOV-1998 jpg implements Serialiizable
// 09-NOV-1998 jpg cleaned up style
//
// 13-NOV-1998 txe (v2) Removed Die, added name, exceptions
// 15-NOV-1998 txe Improved Exceptions, comments, add version, paranoid
// 19-NOV-1998 txe Added random constructor
//
// 30-NOV-1998 txe (v3) SetStable(false) now uses destab, improved look,
// removed version
// 14-DEC-1998 txe Disabled paranoid test
//
////////////////////////////////////////////////////////////////////////////
import java.util.*;
public class Module implements java.io.Serializable {
protected int num_nodes; // number of Nodes in module
protected Node nodes[]; // set of Nodes (DPs and FRs)
protected String name; // name of the module
private String delim = "|"; // token deliminator for serialization
private boolean paranoid = false; // if true, check against ToSerial()
///////////////////////////////////////////////////////////////////
//
// Method: Module [constructor]
//
// Purpose: Default constructor, you shouldn't use it.
//
///////////////////////////////////////////////////////////////////
public Module () {}
///////////////////////////////////////////////////////////////////
//
// Method: Module [constructor]
//
// Purpose: This creates a new Module which is a copy of the
// specified Module.
//
///////////////////////////////////////////////////////////////////
public Module (Module new_module)
throws BoundsException, IndexException, NewException, NullException {
Copy (new_module);
}
///////////////////////////////////////////////////////////////////
//
// Method: Module [constructor]
//
// Purpose: This creates a new Module containing the specified
// Nodes. Note that the Nodes must have been created
// prior to the creation of this Module.
//
// Note: Please use the constructor with the name instead.
//
///////////////////////////////////////////////////////////////////
public Module (int new_num_nodes, Node new_nodes[])
throws BoundsException, IndexException, NewException, NullException {
this (new_num_nodes, new_nodes, "NO_NAME");
}
///////////////////////////////////////////////////////////////////
//
// Method: Module [constructor]
//
// Purpose: This creates a new Module with the specified name,
// containing the specified Nodes. Note that the Nodes
// must have been created prior to the creation of this
// Module.
//
///////////////////////////////////////////////////////////////////
public Module (int new_num_nodes, Node new_nodes[], String new_name)
throws BoundsException, IndexException, NewException, NullException {
if (new_num_nodes < 0) {
throw new BoundsException ("new_num_nodes", new_num_nodes, 0);
}
if (new_num_nodes > 0 && new_nodes == null) {
throw new NullException ("new_nodes");
}
num_nodes = 0;
try {
nodes = new Node [new_num_nodes];
}
catch (Exception e) {
throw new NewException ("nodes", new_num_nodes);
}
SetName (new_name);
for (int i = 0; i < new_num_nodes; i++) {
AddNode (new_nodes[i]);
}
Validate ();
}
///////////////////////////////////////////////////////////////////
//
// Method: Module [constructor]
//
// Purpose: This creates a new Module from the specified String
//
///////////////////////////////////////////////////////////////////
public Module (String source)
throws BoundsException, EqualityException, IndexException,
NullException, ParsingException {
if (source == null) {
throw new NullException ("source");
}
try {
StringTokenizer st = new StringTokenizer (source, delim);
SetName (st.nextToken ());
int count = new Integer (st.nextToken()).intValue();
nodes = new Node [count];
for (int i = 0; i < count; i++) {
AddNode (new Node (st.nextToken()));
}
}
catch (BoundsException e) {
throw e;
}
catch (IndexException e) {
throw e;
}
catch (NullException e) {
throw e;
}
catch (Exception e) {
throw new ParsingException ("Module string", source);
}
// check that output format is consistent with input format:
if (paranoid) {
String output = ToSerial ();
if (!source.equalsIgnoreCase (output)) {
throw new EqualityException ("Module string", source, output);
}
}
Validate ();
}
///////////////////////////////////////////////////////////////////
//
// Method: Module [constructor]
//
// Purpose: This creates a random module with the specified
// name and max size.
//
///////////////////////////////////////////////////////////////////
public Module (String new_name, int max_size)
throws BoundsException, IndexException, NewException, NullException {
if (max_size < 1) {
throw new BoundsException ("max_size", max_size, 1);
}
num_nodes = 0;
int new_num_nodes = 1 + (int) Math.min (Math.random() * max_size, max_size - 1);
try {
nodes = new Node [new_num_nodes];
}
catch (Exception e) {
throw new NewException ("nodes", new_num_nodes);
}
SetName (new_name);
for (int i = 0; i < new_num_nodes; i++) {
int rec_int = 1 + (int) Math.min (Math.random() * 10.0, 9.0);
double recovery = (double) rec_int / 10.0;
int des_int = 1 + (int) Math.min (Math.random() * 10.0, 9.0);
double destab = (double) des_int / 10.0;
AddNode (new Node (Math.random() < 0.5, recovery, destab, "Node" + i));
}
Validate ();
}
///////////////////////////////////////////////////////////////////
//
// Method: AddNode
//
// Purpose: This adds a Node to the Module.
//
///////////////////////////////////////////////////////////////////
public void AddNode (Node new_node)
throws BoundsException, IndexException, NullException {
if (new_node == null) {
throw new NullException ("new_node");
}
nodes[num_nodes] = new_node;
num_nodes++;
Validate ();
}
///////////////////////////////////////////////////////////////////
//
// Method: Copy
//
// Purpose: Copies the specified Module's data into this Module.
//
///////////////////////////////////////////////////////////////////
public void Copy (Module new_module)
throws BoundsException, IndexException, NewException, NullException {
if (new_module == null) {
throw new NullException ("new_module");
}
new_module.Validate ();
SetName (new_module.GetName ());
num_nodes = new_module.GetNumNodes ();
try {
nodes = new Node [num_nodes];
}
catch (Exception e) {
throw new NewException ("nodes", num_nodes);
}
for (int i = 0; i < num_nodes; i++) {
nodes[i] = new Node (new_module.GetNode (i));
}
Validate ();
}
///////////////////////////////////////////////////////////////////
//
// Method: GetName
//
// Purpose: Returns the name of the Module.
//
///////////////////////////////////////////////////////////////////
public String GetName () {
return name;
}
///////////////////////////////////////////////////////////////////
//
// Method: GetNode
//
// Purpose: This returns a reference to the Node specified by the
// index.
//
///////////////////////////////////////////////////////////////////
public Node GetNode (int node_id)
throws BoundsException, IndexException, NullException {
if (!NodeExists (node_id)) {
throw new IndexException ("nodes", node_id);
}
return nodes[node_id];
}
///////////////////////////////////////////////////////////////////
//
// Method: GetNumNodes
//
// Purpose: This returns the current number of Nodes in the Module.
//
///////////////////////////////////////////////////////////////////
public int GetNumNodes () {
return num_nodes;
}
///////////////////////////////////////////////////////////////////
//
// Method: IsStable
//
// Purpose: This returns true if all the Nodes in the Module are
// stable, false otherwise.
//
///////////////////////////////////////////////////////////////////
public boolean IsStable ()
throws BoundsException, IndexException, NullException {
for (int i = 0; i < num_nodes; i++) {
if (!nodes[i].IsStable ()) {
return false;
}
}
return true;
}
///////////////////////////////////////////////////////////////////
//
// Method: NodeExists
//
// Purpose: This returns true if the specified Node exists in
// the Module, false otherwise.
//
///////////////////////////////////////////////////////////////////
public boolean NodeExists (int node_id)
throws BoundsException, IndexException, NullException {
if (node_id < 0 || node_id >= num_nodes) {
return false;
}
return (nodes[node_id] != null);
}
///////////////////////////////////////////////////////////////////
//
// Method: SetName
//
// Purpose: This sets the Module's name to the specified string.
//
///////////////////////////////////////////////////////////////////
public void SetName (String new_name)
throws NullException {
if (new_name == null) {
throw new NullException ("new_name");
}
name = new_name;
}
///////////////////////////////////////////////////////////////////
//
// Method: SetStable
//
// Purpose: Sets the stability of all the Nodes in the Module to
// the specified value.
//
///////////////////////////////////////////////////////////////////
public void SetStable (boolean new_stable)
throws BoundsException, IndexException, NullException {
for (int i = 0; i < num_nodes; i++) {
Node node = nodes[i];
node.SetStable (new_stable || (Math.random() > node.GetDestab()));
}
}
///////////////////////////////////////////////////////////////////
//
// Method: ToSerial
//
// Purpose: Returns a String representation of the Module.
//
///////////////////////////////////////////////////////////////////
public String ToSerial ()
throws BoundsException, IndexException, NullException {
String temp = name + delim + num_nodes;
for (int i = 0; i < num_nodes; i++) {
temp += delim + nodes[i].ToSerial();
}
return temp;
}
///////////////////////////////////////////////////////////////////
//
// Method: Valid
//
// Purpose: Returns true if Module is valid, false otherwise.
//
///////////////////////////////////////////////////////////////////
public boolean Valid () {
try {
Validate();
return true;
}
catch (Exception e) {
return false;
}
}
///////////////////////////////////////////////////////////////////
//
// Method: Validate
//
// Purpose: Throws an exception if Module is invalid.
//
///////////////////////////////////////////////////////////////////
public void Validate ()
throws BoundsException, IndexException, NullException {
if (num_nodes < 0) {
throw new BoundsException ("num_nodes", num_nodes, 0);
}
for (int i = 0; i < num_nodes; i++) {
Node node = null;
try {
node = nodes[i];
}
catch (Exception e) {
throw new IndexException ("nodes", i);
}
if (node == null) {
throw new NullException ("nodes", i);
}
node.Validate ();
}
}
///////////////////////////////////////////////////////////////////
//
// Method: Verbose
//
// Purpose: Returns a human-readable String representation of Module.
//
///////////////////////////////////////////////////////////////////
public String Verbose () {
String temp = name + ": [" + num_nodes + " nodes]\n";
for (int i = 0; i < num_nodes; i++) {
temp += " [" + i + "] ";
try {
temp += nodes[i].Verbose() + "\n";
}
catch (Exception e) {
temp += "INVALID\n";
}
}
return temp;
}
}
////////////////////////////////////////////////////////////////////////////