//     $Id: Node.java,v 3.2 1998/12/14 22:23:03 te3d Exp $    
 ////////////////////////////////////////////////////////////////////////////
 //
 // File: Node.java
 //
 // Purpose: A Node represents a functional requirement (FR) or a
 //          design parameter (DP).  We currently treat FRs and DPs
 //        the same.  Each Node has a stability, a recovery
 //          probability, a destabilization probability, and a
 //          name associated with it.
 //
 //          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.
 //   03-NOV-1998  jpg  Added Serialize methods
 //   06-NOV-1998  rgb  Added version control header info
 //   06-NOV-1998  txe  Added Valid(), Verbose()
 //   06-NOV-1998  jpg  implements Serializable
 //   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
 //
 //   30-NOV-1998  txe  (v3) Added destab, improved layout, removed version
 //   14-DEC-1998  txe  Disabled paranoid test
 //
 ////////////////////////////////////////////////////////////////////////////
 import java.util.*;
 public class Node implements java.io.Serializable {
   protected boolean stable;        // if true, the Node is stable
   protected double recovery;        // probability of recovery during cycle
   protected double destab;          // destabilization probability
   protected String name;            // name of the Node
   private String delim = " ";        // token deliminator for serialization
   private boolean paranoid = false; // if true, check against ToSerial()
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Node  [constructor]
   //
   // Purpose: Default constructor, you shouldn't use it.
   //          
   ///////////////////////////////////////////////////////////////////
   public Node () {}
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Node  [constructor]
   //
   // Purpose: This creates a new Node which is a copy of the
   //          specified Node.
   //
   ///////////////////////////////////////////////////////////////////
   public Node (Node new_node)
   throws BoundsException, NullException {
     Copy (new_node);
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Node  [constructor]
   //
   // Purpose: This creates a new Node with the specified stability
   //          and recovery probability.
   //
   // Note:    Please switch to using the constructor with the name.
   //          
   ///////////////////////////////////////////////////////////////////
   public Node (boolean new_stable, double new_recovery)
   throws BoundsException, NullException {
     this (new_stable, new_recovery, 0.2, "NO_NAME");
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Node  [constructor]
   //
   // Purpose: This creates a new Node with the specified stability,
   //          recovery probability, and name.
   //
   ///////////////////////////////////////////////////////////////////
   public Node (boolean new_stable, double new_recovery,
            double  new_destab, String new_name)
   throws BoundsException, NullException {
     SetStable   (new_stable);
     SetRecovery (new_recovery);
     SetDestab   (new_destab);
     SetName     (new_name);
     Validate ();
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Node  [constructor]
   //
   // Purpose: This creates a new Node from the specified string.
   //          
   ///////////////////////////////////////////////////////////////////
   public Node (String source)
   throws BoundsException, EqualityException, NullException, ParsingException {
     if (source == null) {
       throw new NullException ("source");
     }
     try {
       StringTokenizer st = new StringTokenizer (source, delim);
       SetName     (st.nextToken());
       SetStable   (st.nextToken().equalsIgnoreCase ("t"));
       SetRecovery (new Double (st.nextToken()).doubleValue());
       SetDestab   (new Double (st.nextToken()).doubleValue());
     }
     catch (BoundsException e) {
       throw e;
     }
     catch (NullException e) {
       throw e;
     }
     catch (Exception e) {
       throw new ParsingException ("Node string", source);
     }
     // check that output format is consistent with input format:
     if (paranoid) {
       String output = ToSerial ();
       if (!source.equalsIgnoreCase (output)) {
     throw new EqualityException ("Node string", source, output);
       }
     }
     Validate ();
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Copy
   //
   // Purpose: Copies the specified Node's data into the current Node.
   //   
   ///////////////////////////////////////////////////////////////////
   public void Copy (Node new_node)
   throws BoundsException, NullException {
     if (new_node == null) {
       throw new NullException ("new_node");
     }
     new_node.Validate ();
     SetName     (new_node.GetName ());
     SetStable   (new_node.IsStable ());
     SetRecovery (new_node.GetRecovery ());
     SetDestab   (new_node.GetDestab ());
     Validate ();
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  GetDestab
   //
   // Purpose: Returns the current destabilization probability for the
   //          Node.
   //   
   ///////////////////////////////////////////////////////////////////
   public double GetDestab () {
     return destab;
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  GetName
   //
   // Purpose: Returns the name of the Node.
   //   
   ///////////////////////////////////////////////////////////////////
   public String GetName () {
     return name;
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  GetRecovery
   //
   // Purpose: Returns the current recovery probability for the Node.
   //   
   ///////////////////////////////////////////////////////////////////
   public double GetRecovery () {
     return recovery;
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  IsStable
   //
   // Purpose: Returns whether or not the Node is currently stable.
   //   
   ///////////////////////////////////////////////////////////////////
   public boolean IsStable () {
     return stable;
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  SetDestab
   //
   // Purpose: This sets the destabilization probability for the Node.
   //          It makes sure the probability is between 0 and 1.
   //   
   ///////////////////////////////////////////////////////////////////
   public void SetDestab (double new_destab)
   throws BoundsException {
     if (new_destab < 0 || new_destab > 1) {
       throw new BoundsException ("new_destab", new_destab, 0, 1);
     }
     destab = new_destab;
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  SetName
   //
   // Purpose: This sets the Node'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:  SetRecovery
   //
   // Purpose: This sets the recovery probability for the Node.
   //          It makes sure the probability is between 0 and 1.
   //   
   ///////////////////////////////////////////////////////////////////
   public void SetRecovery (double new_recovery)
   throws BoundsException {
     if (new_recovery < 0 || new_recovery > 1) {
       throw new BoundsException ("new_recovery", new_recovery, 0, 1);
     }
     recovery = new_recovery;
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  SetStable
   //
   // Purpose: This sets the stability value for the Node.
   //   
   ///////////////////////////////////////////////////////////////////
   public void SetStable (boolean new_stable) {
     stable = new_stable;
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  ToSerial
   //
   // Purpose: Returns a String representation of the Node.
   //   
   ///////////////////////////////////////////////////////////////////
   public String ToSerial() {
     return name + delim + (stable ? "t" : "f") + delim + recovery
            + delim + destab;
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Valid
   //
   // Purpose: Returns true if Node is valid, false otherwise.
   //   
   ///////////////////////////////////////////////////////////////////
   public boolean Valid () {
     try {
       Validate();
       return true;
     }
     catch (Exception e) {
       return false;
     }
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Validate
   //
   // Purpose: Throws an exception if Node is invalid.
   //   
   ///////////////////////////////////////////////////////////////////
   public void Validate ()
   throws BoundsException, NullException {
     if (recovery < 0 || recovery > 1) {
       throw new BoundsException ("recovery", recovery, 0, 1);
     }
     if (destab < 0 || destab > 1) {
       throw new BoundsException ("destab", destab, 0, 1);
     }
     if (name == null) {
       throw new NullException ("name");
     }
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Verbose
   //
   // Purpose: Returns a human-readable String representation of Node.
   //   
   ///////////////////////////////////////////////////////////////////
   public String Verbose () {
     return name + ": " + (stable ? "stable" : "unstable")
            + ", rec " + recovery + ", des " + destab;
   }
 }
 ////////////////////////////////////////////////////////////////////////////