ETHZ_Logo RAMSES_Logo_Right   RAMSES   RAMSES_Logo_Left Systems Ecology  
Start    search button      Modules:   A-Z   Function   Layer        QuickRefs:   DM   AuxLib   AuxLibE   SciLib   EasyMW   MW   ISIS   RMSLib

DEFINITION MODULE SysVariants;

  (*******************************************************************

    Module  SysVariants     (ISIS_Version_1.2)

      Copyright (c) 1997-2006 by Andreas Fischlin and ETH Zurich.

    Purpose   Support the management of subsystem variants,
              e.g. of model equation versions or of changing
              data structures.

    Remarks   Specifically useful while working with complex,
              structured systems.

              This module belongs to ISIS
              Integrative Systems Implementation Software.


    Programming

      o Design
        Andreas Fischlin          17/01/1997

      o Implementation
        Andreas Fischlin          17/01/1997


    ETH Zurich
    Systems Ecology
    CHN E 35.1
    Universitaetstrasse 16
    8092 Zurich
    SWITZERLAND

    URLs:
        <mailto:RAMSES@env.ethz.ch>
        <http://www.sysecol.ethz.ch>
        <http://www.sysecol.ethz.ch/SimSoftware/RAMSES>


    Last revision of definition:  18/06/1998  AF

  *******************************************************************)


  FROM SYSTEM IMPORT ADDRESS;

  (******************************)
  (*#####   Variant Sets   #####*)
  (******************************)

  TYPE
    VariantSet;
    VariantOrd = INTEGER;
    VariantAttribute = ADDRESS;

    VSRemoveHandler = PROCEDURE (VariantSet);
    VRemoveHandler = PROCEDURE (VariantAttribute);
      (* optional handler used to notify a client upon
      removal of a variant *)


  VAR
    unknownVariantSet: VariantSet; (* read only *)

  CONST
    undefVariant = 0; (* VariantOrd of a non existing variant *)
    variDelim = "|";  (* delimiter used to separate variants in a list *)


  PROCEDURE CreateVariantSet(VAR vs: VariantSet; vsDescr: ARRAY OF CHAR);
    (*
      This routine creates a group (set) of enumeratable
      variants, e.g.  used to characterize model variants,
      which exclude each other.  Variant sets are a sort of
      dynamic enumeration types, which can be defined at run
      time.  vsDescr describes the variant set, e.g.
      "Evapotranspiration".  You may create any number of
      variant sets which can then be used simultaneously to
      define complex structures, called combinations.  A
      particular combination is given by a n-tupel, which
      consists of the particular variant of each involved
      variant set.
    *)


  PROCEDURE DiscardVariantSet(VAR vs: VariantSet);

  PROCEDURE VariantSetExists(vs: VariantSet): BOOLEAN;
  PROCEDURE GetVariantSetDescr(vs: VariantSet; VAR vsDescr: ARRAY OF CHAR);


  (*****************************************************)
  (*#####   Variants = Elements in Variant Sets   #####*)
  (*****************************************************)

  (*---------------------------*)
  (*=====   Declaration   =====*)
  (*---------------------------*)

  PROCEDURE AddVariant(vs: VariantSet; VAR vord: VariantOrd;
                       vIdent,variDescr: ARRAY OF CHAR);
    (*
      Declares (adds) a specific variant to a variant set vs,
      previously declared by procedure CreateVariantSet.  A variant is
      characterized by the string (need not be an identifier) vIdent
      E.g. "Thornthwaite-Mather" or "PET by Penman-Monteith".
      Alternatively a particular variant can be denoted by its order
      vord.  AddVariant assigns a globally (within and among all
      variant sets) unique value to vord.  The sequence in which
      variants are declared determines the order of the variants
      within the set vs (cf.  procedures VSMin, VSMax, VSSucc,
      VSPred).  Note: Calling AddVariant several times with the same
      vIdent for the same vs has no effect, in particular vord is
      preserved as assigned during the very first call to AddVariant.
      Consequently, within a given set vs vIdent is unique, but the
      same vIdent can be added to several sets.  vIdent may not be the
      empty string or AddVariant fails.  In the latter case AddVariant
      returns vord = undefVariant.
    *)

  PROCEDURE VariantExists (vs: VariantSet; vIdent: ARRAY OF CHAR): BOOLEAN;
  PROCEDURE DiscardVariant(vord: VariantOrd);
  PROCEDURE RemoveVariant (vs: VariantSet; vIdent: ARRAY OF CHAR);
    (*
       Discards resp.  removes the variant denoted by vord or
       alternatively by vIdent from the set vs.
     *)

 (*-------------------------------------------*)
 (*=====   Ordinals (VOrd) of Variants   =====*)
 (*-------------------------------------------*)

 (*
   IMPORTANT NOTE: Ordinals (VOrd) are an integer number
   denoting uniquely a single variant, regardless of its
   variant set.  This number must not be confounded with the
   ordination number a variant has within its variant set.  This
   supports a random access of any variant, a feature which is
   necessary for several algorithms used by ISIS.
  *)

  PROCEDURE VOrd(vs: VariantSet; vIdent: ARRAY OF CHAR): VariantOrd;
    (*
      Inverse of GetVVal: Returns the order of a particular
      variant vIdent belonging to the set vs.  Note: The
      returned value is globally unique and different from the
      ordination number of vIdent within vs (cf.  procedures
      OrdInVS and CurOrdInVS).  Having a globally unique number
      denoting any vIdent regardless to which variant set it
      belongs, is e.g. useful for procedure LegalVCombination.
      If vIdent does not belong to any variant set currently
      known, the value undefVariant is returned.
    *)

 (*-------------------------------------*)
 (*=====   Manipulating Variants   =====*)
 (*-------------------------------------*)

  PROCEDURE GetVVal(vord: VariantOrd;
                    VAR vs: VariantSet; VAR vIdent: ARRAY OF CHAR);
    (*
      Inverse of VOrd: Returns the variant identifier vIdent
      with order vord plus the variant set to which vIdent
      belongs.
    *)

  PROCEDURE OrdInVS (vs: VariantSet; vord: VariantOrd): INTEGER;
    (*
      Returns the ordination number (0, 1, ...) of the variant
      denoted by vord within the variant set vs. Returns <0
      in case the vord is not present in vs.
    *)

  PROCEDURE GetNthSubString(VAR(*speed-up*) string: ARRAY OF CHAR;
                            n: INTEGER; VAR subs: ARRAY OF CHAR);
    (*
      Returns in subs the n'th substring (n= 1, 2,...) found in
      string, assuming substrings are separated by "|"
      (variDelim).  This string handling routine is provided for
      your convenience only.
    *)

  PROCEDURE GetVDescriptor (vord: VariantOrd; VAR vDescr: ARRAY OF CHAR);
    (*
      Returns the descriptor vDescr of variant with order vord.
      Returns emtpy string if variant does not exist.
    *)


  (*------------------------------------------------*)
  (*=====   Current Variant of a Variant Set   =====*)
  (*------------------------------------------------*)

  (*
    Each variant set can remember a current variant.  You can ask this
    module to remember the current variant (SetCurVariant, SetCurV) or
    what the current variant is (GetCurVariant,CurVOrd), or to perform
    a relational operation, i.e. to test if the current variant is
    equal to any given variant.  In all cases you have to pass an
    existing variant set.  There are several ways of accessing the
    current variant in a set, either via the identifier
    (SetCurVariant, GetCurVariant, IsCurV) or its unique ordinal
    number (SetCurV, CurVOrd, IsCurVOrd).  Both methods can be
    combined in anyway to your liking.  Finally the current variant
    can also be returned as an ordination number within the set
    (CurOrdInVS, CurOr1stOrd).  Note, in case you have never set the
    current variant, all routines return an undefined value such as
    undefVariant (CurVOrd), the empty string (GetCurVariant), a
    negative ordination number (CurOrdInVS), or zero (CurOr1stOrd).
  *)

  PROCEDURE SetCurVariant (vs: VariantSet;     vIdent: ARRAY OF CHAR);
  PROCEDURE SetCurV       (vs: VariantSet; vord: VariantOrd);

  PROCEDURE GetCurVariant (vs: VariantSet; VAR vIdent: ARRAY OF CHAR);
  PROCEDURE CurVOrd       (vs: VariantSet): VariantOrd;

  PROCEDURE IsCurV ( vIdent: ARRAY OF CHAR; invs: VariantSet): BOOLEAN;
  PROCEDURE IsCurVOrd    (vord: VariantOrd; invs: VariantSet): BOOLEAN;

  PROCEDURE CurOrdInVS    (vs: VariantSet): INTEGER; (* can return <0 *)
  PROCEDURE CurOr1stOrd (invs: VariantSet): CARDINAL;
    (*
      CurOr1stOrd returns the ordination number, 0,1,2..  etc., of the
      current variant in the set 'invs'.  In case no current has ever
      been set for 'invs', CurOr1stOrd returns the ordination number
      of the first variant, i.e. 0, to avoid any range errors.  The
      latter behavior differs from that of CurOrdInVS, which, in this
      case, would return a non-defined ordination number, i.e. a
      negative number like -1.
    *)


  (***********************************************************************)
  (*#####   Grouping Variant Sets to Form Combination of Variants   #####*)
  (***********************************************************************)

  PROCEDURE VListToVCombination(vlist: ARRAY OF CHAR;
                                VAR combination: ARRAY OF VariantOrd);
    (*
      Interprets and translates a combination as given by vlist
      into a combination. Individual variants within vlist have to
      be separated by "|" (variDelim). If the vlist denotes a
      currently illegal combination (see procedure
      LegalVCombination), combination holds only undefVariant
      values. IMPLEMENTATION Restriction: Well defined behavior is
      not warranted unless the client makes sure all variant
      identifiers are globally unique.  Otherwise this routine will
      interpret a variant as valid upon the first match (in
      sequence of declaration), regardless of the variant set and
      whether another variant with the same identifier exists also
      in another variant set.
    *)

  PROCEDURE VCombinationToVList(combination: ARRAY OF VariantOrd;
                                VAR vlist: ARRAY OF CHAR);
    (*
      Returns a list of variant identifiers separated by "|"
      (variDelim) corresponding to combination. If the combination
      is illegal, only the empty string is returned in vlist.
    *)


  PROCEDURE ForbidVCombination(combination: ARRAY OF VariantOrd);
  PROCEDURE AllowVCombination(combination: ARRAY OF VariantOrd);
    (*
      By default any combination of declared variants is legal.
      Calling this procedure makes the combination of variants
      (all belonging to different variantsets) illegal.  Array
      combination holds the orders of the variants.  Has no
      effect if any of the arguments are invalid or not all
      orders denote a variant belonging to a different variant
      set.  Procedure AllowVCombination reverses the effect
      of ForbidVCombination.  Procedure LegalVCombination
      provides a mean to inquire current legal status of a
      given combination of variants.
    *)


  PROCEDURE LegalVCombination (combination: ARRAY OF VariantOrd): BOOLEAN;
    (*
      Returns whether the combination of variants (all
      belonging to different variantsets) is legal.  Array
      combination holds the orders of the variants.  Note:
      Returns also FALSE in case of wrong arguments, e..g if
      any of the variants or variant sets is unknown (an
      element of combination holds undefVariant or a
      variant set has never been declared) or if vs1 is not
      different from vs2.  However, an entirely empty
      combination, characterized by holding undefVariant
      in its first element, is as an exception considered to be
      legal.
    *)

  (***************************)
  (*#####   Utilities   #####*)
  (***************************)

  (*-----------------------*)
  (*=====   Looping   =====*)
  (*-----------------------*)

  PROCEDURE VSDim(vs: VariantSet): INTEGER;
    (* Returns current dimension of variant set vs *)

  PROCEDURE VSMin(vs: VariantSet): VariantOrd;
    (* Returns order of first (minimum) variant in range of variant set vs *)
  PROCEDURE VSMax(vs: VariantSet): VariantOrd;
    (* Returns order of last (maximum) variant in range of variant set vs *)

  PROCEDURE VSucc(vs: VariantSet; vord: VariantOrd): VariantOrd;
    (*
      Returns order of next (successor) variant following
      variant vord in variant set vs.  Order is given by
      sequence of declaration.
    *)
  PROCEDURE VPred(vs: VariantSet; vord: VariantOrd): VariantOrd;
    (*
      Returns order of previous (predecessor) variant
      preceeding variant vord in variant set vs.  Order is
      given by sequence of declaration.
    *)

  PROCEDURE FirstVS(): VariantSet;
  PROCEDURE PrevVS(vs: VariantSet): VariantSet;
  PROCEDURE NextVS(vs: VariantSet): VariantSet;
  PROCEDURE LastVS(): VariantSet;
    (*
      Makes it possible to access all currently instantiated
      variant sets in the sequence they have been declared by
      CreateVariantSet.
    *)


  (*------------------------*)
  (*=====   Handlers   =====*)
  (*------------------------*)

  PROCEDURE AddVSRemoveHandler(vs: VariantSet; rmh: VSRemoveHandler);
  PROCEDURE VoidVSRemoveHandler(vs: VariantSet; rmh: VSRemoveHandler);
    (*
      Adds (voids) a (previously added) remove handler rmh to
      (from) the variant set vs.  The remove handler rmh is
      called when a variant set ceases to exist, i.e.  when
      DiscardVariantSet is called; this occurrs at a moment
      when the variant set's data are still intact and all
      routines (except DiscardVariantSet) from this module are
      still fully functional.
    *)


  PROCEDURE AddVRemoveHandler(vord: VariantOrd; rmh: VRemoveHandler);
  PROCEDURE VoidVRemoveHandler(vord: VariantOrd; rmh: VRemoveHandler);
    (*
      Adds (voids) a (previously added) remove handler rmh to
      (from) the variant denoted by the order vord.  The remove
      handler rmh is called when a variant ceases to exist,
      i.e.  when DiscardVariant or RemoveVariant are called;
      this occurrs at a moment when the variant's data are
      still intact and all routines (except DiscardVariant or
      RemoveVariant) from this module are still fully
      functional.
    *)


  (*--------------------------*)
  (*=====   Attributes   =====*)
  (*--------------------------*)

  PROCEDURE AttachVAttr (vord: VariantOrd; va: VariantAttribute);
  PROCEDURE VAttr (vord: VariantOrd): VariantAttribute;
    (*
      Attaches respectively returns the previously attached
      attribute va to the variant denoted by the order vord.
      An attribute is typically a pointer to a client data
      structure associated with the variant.
    *)



END SysVariants.

  Contact RAMSES@env.ethz.ch Last updated: 25-Jul-2011 [Top of page]