|
|
|
|
||
|
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.
|
||
|
|
|