Plasma GitLab Archive
Projects Blog Knowledge

(*
 * <COPYRIGHT>
 * Copyright 2002 Joachim Schrod Network and Publication Consultance GmbH, Gerd Stolpmann
 *
 * <GPL>
 * This file is part of WDialog.
 *
 * WDialog 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.
 *
 * WDialog 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 WDialog; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * </>
 *)

(* $Id: wd_types.mli,v 3.14 2006-03-08 00:56:45 stolpmann Exp $
 * ----------------------------------------------------------------------
 *
 *)

(** This module defines the fundamental types for WDialog *)

type (+'a) dict = 'a Wd_dictionary.t
  (** The type ['a dict] is just an abbreviation for dictionaries (mappings from
   *  strings to ['a]).
   *)

type event =
    Button of string
  | Image_button of (string * int * int)
  | Indexed_button of (string * string)
  | Indexed_image_button of (string * string * int * int)
  | No_event
  | Popup_request of string (** *)
(** [ ]
 *
 *  Events are generated when the user presses a button, clicks at a hyperlink,
 *  or opens a server-generated popup window.
 *
 * - [Button n]: The button with name [n] has been pressed
 *   ([<ui:button name="n" ...>])
 * - [Image_button (n,x,y)]: The image button with name [n] has been pressed
 *   at the coordinates [(x,y)]. ([<ui:imagebutton name="n" ...>])
 * - [Indexed_button (n,i)]: The button with name [n] and index [i] has been pressed
 *   ([<ui:button name="n" index="i" ...>])
 * - [Indexed_image_button (n,i,x,y)]: The image button with name [n] and index [i]
 *   has been pressed at the coordinates [(x,y)].
 *   ([<ui:imagebutton name="n" index="i" ...>])
 * - [No_event]: This value indicates that there was no event (or no
 *   recognized event)
 * - [Popup_request s]: A server popup window has just popped up, and the contents
 *   for the window have been requested. The argument is the second argument
 *   of the "open" Javascript function that has been generated by the
 *   ui:server-popup element.
 *)


type interactors =
    { mutable ui_buttons :             string option Wd_interactor.t;
      mutable ui_imagebuttons :        string option Wd_interactor.t;
      mutable ui_anchors :             string option Wd_interactor.t;
      mutable ui_indexed_buttons :     string option Wd_interactor.t;
      mutable ui_indexed_imagebuttons :string option Wd_interactor.t;
      mutable ui_indexed_anchors :     string option Wd_interactor.t;
      mutable ui_vars :                unit Wd_interactor.t;
      mutable ui_enumvars :            (string * string option * string) list;
      mutable ui_uploads :             unit Wd_interactor.t;
    }
   (** Values of this type store the mapping from the (name,index) pairs
     * of interactor elements to the real CGI parameter names together
     * with auxiliary components.
     *
     * What's the problem? Interactor elements like [ui:a] allow the programmer
     * to identify these either by a single name (which is an arbitrary
     * string) or by a pair of a "name" and an "index" (i.e. two arbitrary
     * strings). In contrast to this, CGI parameter names are much more
     * restricted. First, these names are only strings; there is no
     * built-in representation for pairs of strings. Second, you cannot
     * use arbitrary characters within these names because of limitations
     * of the transport protocol and because of bugs in browsers. (As
     * the "multipart/form-data" representation used in the transport
     * protocol bases on the RFC 822 mail format, it is neither possible to
     * pass 8 bit values, nor to pass control characters. A known bug
     * in Netscape browsers is that the double-quote and backslash characters
     * are incorrectly represented.)
     *
     * The solution is to generate the CGI parameter names using only
     * unproblematic characters, and to keep the mapping of the original
     * [string] or [string * string] to the generated CGI name. This record
     * stores the mappings for the various namespaces. The mapping is
     * encapsulated in the {!Wd_interactor} module, and the type
     * ['a Wd_interactor.t] (where ['a] is arbitrary) represents such a mapping. The
     * CGI names are simply enumerated, and the [Wd_interactor.t] value stores only
     * the numbers (IDs) of the CGI parameters. The complete CGI name is formed
     * using a prefix and the number stored in [Wd_interactor.t]. For example,
     * ui:buttons without index have the prefix "button_"; and if the
     * ui_button record component contains entries for the IDs 0, 1, and 2,
     * the complete CGI names are "button_0", "button_1", and "button_2",
     * respectively.
     *
     * The type parameter ['a] of ['a Wd_interactor.t] is the type of the
     * auxiliary component stored with every entry. See below for the
     * meanings in every case.
     *
     * The [Wd_interactor.t] structure always maps from pairs [string * string] to
     * numeric IDs. Because of this, there are usually two mappings, one
     * for the (name,index) pairs, and one for the simple names. The record
     * components listed below that have a name with "indexed" are responsible
     * for the pairs, the corresponding component without "indexed" stores
     * the mapping for the simple case.
     *
     * The simple case is represented as [Wd_interactor.t] by using always the
     * empty string [""] as index.
     *
     * {b THE COMPONENTS ARE:}
     *
     * {ol
     * {- {b BUTTON-TYPE INTERACTORS:}
     * {ul
     * {- [ui_buttons]:          Enumerates the [ui:button] interactors
     *                           that have only a name, not an index.
     *                           CGI prefix: "button_".
     * }
     * {- [ui_indexed_buttons]:  Enumerates the [ui:button] interactors
     *                           that have both a name and an index.
     *                           CGI prefix: "xbutton_".
     * }
     * {- [ui_imagebuttons]:     Enumerates the [ui:imagebutton] interactors
     *                           that have only a name, not an index.
     *                           CGI prefix: "imagebutton_".
     * }
     * {- [ui_indexed_imagebuttons]: Enumerates the [ui:imagebutton] interactors
     *                           that have both a name and an index.
     *                           CGI prefix: "ximagebutton_".
     * }
     * {- [ui_anchors]:          Enumerates the [ui:a] interactors
     *                           that have only a name, not an index.
     *                           CGI prefix: "anchor_".
     * }
     * {- [ui_indexed_anchors]:  Enumerates the [ui:a] interactors
     *                           that have both a name and an index.
     *                           CGI prefix: "xanchor_".
     * }
     * }
     *
     * These components use the auxiliary component to store the "goto"
     * attribute of the interactor, if present.
     *
     * }
     * {- {b BOX-LIKE INTERACTORS:}
     * {ul
     * {- [ui_vars]:             Enumerates the interactors that are bound
     *                           to an object variable (i.e. they have a
     *                           [variable] attribute, like [ui:text]).
     *                           As variables allow either only non-indexed
     *                           names or only indexed names, this component
     *                           contains both interactors identified by a simple
     *                           string name and interactors identified by
     *                           (name,index) pairs; it is not possible that
     *                           there are conflicts between the two naming
     *                           methods.
     *                           CGI prefix: "var_".
     *                           This component does not have an auxiliary
     *                           component.
     * }
     * {- [ui_enumvars]:         This list enumerates the simple names
     *                           [(name, None, pg)] or pairs [(name, Some index, pg)]
     *                           that occur in checkbox, radiobutton and select
     *                           list interactors. [pg] is the name of the page
     *                           where the interactor occurs (knowing the page
     *                           is necessary for popup dialogues).
     * }
     * {- [ui_uploads]:          Enumerates the [ui:file] interactors. These
     *                           may only have a simple name.
     *                           CGI prefix: "upload_".
     *                           This component does not have an auxiliary
     *                           component.
     * }
     * }
     * }
     * }
     *)

type head = string array
    (** The head of a table or matrix. The head gives every column a
      * name. The names must be unique for the table/matrix.
     *)


type init_expr =
    [ `String_iexpr of Wd_brexpr.expr_string
    | `Enum_iexpr of Wd_brexpr.expr_string list
    | `Dyn_enum_iexpr of (Wd_brexpr.expr_string * Wd_brexpr.expr_string) list
    | `Alist_iexpr of (Wd_brexpr.expr_string * init_expr) list
    | `Matrix_iexpr of head * Wd_brexpr.expr_string array array
    | `Value_iexpr of Wd_brexpr.expr
    | `Map_iexpr of Wd_brexpr.expr * init_expr list
    | `Dsrc_iexpr of string * Wd_brexpr.expr_string
    ]
  (** The initializing expression for dialog variables. Such an expression
    * may contain $-expressions (but not references to template parameters).
    * Furthermore, it is also possible to denote arbitrary values by giving
    * a $-expression (this includes functions), and to map expressions by
    * applying a function.
   *)

(** A table is an abstract (read-only) view on a data structure with
  * certain access primitives. The table consists of several rows,
  * and every row of several columns. The columns have names, defined
  * in the table head.
  *
  * Tables may be backed by:
  * - WDialog values like dynamic enumerators or matrices
  * - Message catalogs
  * - Arbitrary external data sources like SQL tables or results of
  *   SQL SELECT statements
  *
  * Note that "=", the equality test, checks for object identity rather
  * than structural equality. See [Wd_table.compare] for a reasonable
  * equality function.
  *
  * See [Wd_table] for table functions.
 *)
class type table =
object
  method head : head
    (** Returns the table head *)

  method select : column:string -> string -> table
    (** Returns the sub table where the named [column] has the passed
     * value. The returned table has the same head, i.e. the passed
     * column is still present although all rows have the same value
     * in it.
     *)

  method card : int
    (** Returns the number of rows of the table. This method may be
     * expensive if the rows have to be retrieved from the data source
     * first before they can be counted.
     *)

  method iter : unit -> iterator option
    (** Starts iterating the table in a certain, table-specific order.
      * If the table is empty the function will return [None], otherwise
      * an [iterator] is passed back. The [iterator] represents the 
      * current row and allows the user to get all further rows.
      * Iterators must be closed (by calling [close]) when it is not
      * iterated until the end of the table. This allows implementors
      * of external data sources to free resources.
      *
      * Every invocation of [iter] starts a new query; previously 
      * retrieved chains of [iterator] objects are not cached.
     *)
end

and iterator =
object
  method row : string array
    (** Returns the row this cell of the iterator chain is tied to *)

  method large_row : string Stream.t array
    (** Returns the same values as [row] but also supports large values.
      * Every cell is represented as [string Stream.t], i.e. the value
      * of the cell are the concatenated elements of the stream.
      *
      * If you do not have any idea what this means, just define
      * {[
      * method large_row = Array.map (fun s -> Stream.of_list [s]) self#row
      * ]}
     *)

  method next : iterator option
    (** Returns the next iterator cell of the chain, or [None] if this
     * is the last cell. The next cell is usually computed lazily (on
     * demand only), but once the cell is determined, [next] returns
     * always the same object.
     *)

  method close : unit -> unit
    (** Closes the iterator. This is only allowed for cells where [next]
      * has not yet been called. After being closed, the method [next]
      * returns always [None].
     *)
end


type 'dlg poly_var_value =
    String_value   of string
  | Enum_value     of string list
  | Dialog_value   of 'dlg option
  | Dyn_enum_value of (string * string) list
  | Alist_value    of (string * 'dlg poly_var_value) list
  | Matrix_value   of head * string array array
  | Table_value    of table
  | Function_value of ('dlg -> 
			 'dlg poly_var_value Lazy.t list -> 'dlg poly_var_value)
 (** *)
(** [ ]
 *
 * [poly_var_value] is the type of instance variables of dialogs. There are
 * nine possibilities for [poly_var_value]s:
 * - [String_value s]: The instance variable contains the string [s]
 * - [Enum_value [x1;x2;...]]: The instance variable contains an enumerator
 *   value with the internal items [x1], [x2], etc. (As variables are declared
 *   it is known which items are possible, and whether there are corresponding
 *   external values.)
 * - [Dialog_value None]: The instance variable does not contain a dialog.
 * - [Dialog_value (Some dlg)]: The variable contains the dialog dlg.
 * - [Dyn_enum_value [(x1,y1);(x2,y2);...]]: The variable contains the enumerator
 *   with internal items [x1], [x2],... and the corresponding external values
 *   [y1], [y2], ...
 * - [Alist_value [(i1,v1); (i2,v2); ...]]: The variable contains the associative
 *   list where the index [i1] is mapped to the value [v1], [i2] is mapped to [v2] etc.
 * - [Matrix_value(h,m)]: The value is a sequence of rows, and every row is
 *   a sequence of the same number of columns. The matrix cells are strings.
 *   The columns have names as defined in [h].
 * - [Table_value t]: Table values are abstract (i.e. nothing is said about the
 *   representation), and have only certain read-only access primitives.
 *   Usually a table is only a front-end to some other value or object.
 *   Table values cannot be marshalled and thus cannot be part of 
 *   persistent sessions.
 * - [Function_value f]: Functions can be applied for a certain dialog
 *   and take a list of arguments. The result is again a [poly_var_value].
 *   Function values cannot be marshalled and thus cannot be part of 
 *   persistent sessions.
 *
 * See also {!Wd_types.var_value} below.
 *)


type enum_decl =
    { enum_name : string;
      mutable enum_definition : (string * string) list;
    }
(** The type of an enumeration declaration (i.e. [ui:enumeration]). The component
 *  [enum_name] is the name of the enumeration. The component [enum_definition]
 *  is the list of the pairs of internal and external names, in the right order.
 *)


type var_type_name =
    String_type
  | Enum_type of enum_decl
  | Dialog_type
  | Dyn_enum_type
  | Matrix_type
  | Table_type    (** *)
(** The different variable types *)


type 'dlg poly_var_decl =
    { var_name : string;
      var_type : var_type_name;
      var_init : init_expr option;
      var_temporary : bool;
      var_associative : bool;
      var_protected : bool;
    }
(** This record describes variable declarations. [var_name] contains the name of the
 * variable. [var_type] is the declared type according to the [type] attribute.
 * [var_init] contains either [None], in which case no special initial value is
 * declared, or [Some v], where [v] is the initial value. [var_temporary] corresponds
 * to the [temporary] attribute, [var_associative] to the [associative] attribute,
 * and finally [var_protected] to the [protected] attribute.
 *)


type response_header =
    { mutable rh_status : Nethttp.http_status;
      mutable rh_content_type : string;
      mutable rh_cache : Netcgi.cache_control;
      mutable rh_filename : string option;
      mutable rh_language : string option;
      mutable rh_script_type : string option;
      mutable rh_style_type : string option;
      mutable rh_set_cookie : Nethttp.cookie list;
      mutable rh_fields : (string * string list) list;
    }
(** This record contains the CGI header of the response. It is initialized
 *  quite early and can be modified while executing the request. The fields
 *  correspond to the arguments of the method [set_header] of the class
 *  type [cgi_activation], defined in [Netcgi_types].
 *)

type debug_mode_style =
  [ `Fully_encoded
  | `Partially_encoded
  ]
(** Whether the generated HTML comments do escape HTML meta characters
 *  always ([`Fully_encoded]), or only partially ([`Partially_encoded]).
 *)

type environment =
    { (* Overall way of operation: *)
      debug_mode : bool;
      debug_mode_style : debug_mode_style;
      prototype_mode : bool;
      server_popup_mode : bool;
      (* Web variables *)
      self_url : string;
      response_header : response_header;
      cgi : Netcgi.cgi_activation;
    }
(** This record contains data that may be different for every CGI request. The
 *  [debug_mode] and [prototype_mode] components are true iff the corresponding
 *  mode is switched on. The [server_popup_mode] is true iff the current request
 *  is a popup request. [self_url] is the URL that invokes the CGI recursively.
 *  [cgi] contains the full CGI request. The [request_header] is the 
 *  designated header of the HTTP response.
 *)


type trans_vars =
    { mutable within_popup : bool;
      mutable current_page : string;
      mutable popup_env_initialized : bool;
      mutable condition_code : bool;
              (* last result of <ui:if>, <ui:ifvar>, <ui:iflang> *)
      mutable serialize_session : unit -> string;
    }
(** This record is private for the transformation engine. *)


type ('universe,'dialog,'environment) poly_ds_buf = 
    ('universe,'dialog,'environment) Wd_serialize_types.poly_ds_buf =
    { ds_str : string;         (* String to deserialize *)
      mutable ds_pos : int;    (* Current position *)
      ds_end : int;            (* End position *)
      ds_universe : 'universe;
      ds_environment : 'environment;
      ds_dialogs : (int, 'dialog) Hashtbl.t;   
         (* maps dialog IDs to dialogs *)
    }
(** The deserialization buffer *)


exception Not_found_in_catalog of string * string * string
  (** Raised when a token cannot be translated. The triple is
    * (dialog name, language, token).
   *)


(** A message catalog maps tokens to display strings for a number of
  * languages.
 *)
class type message_catalog =
object
  method domain : string
    (** The domain name of the catalog. For catalogs defined in the scope of
     * dialogs, the domain name is the dialog name unless overridden.
     *)

  method lookup : language:string -> string -> string
    (** Looks up the meaning of a token in the given language. Raises
      * [Not_found_in_catalog] if not found.
     *)

  method uplinks : string list
    (** Returns uplink catalogs, in which one should look also to 
      * translate messages.
     *)

  method as_table : table
    (** Returns the catalog as table. This is a secondary API which is
      * needed to handle catalogs as values, but not to translate tokens.
      * Uplink catalogs are not included in the table, i.e. looking tokens
      * up via the table is not the same as calling [lookup].
      *
      * The table has the three columns [lang], [int], and [ext].
     *)

end


class type extensible_message_catalog =
object
  inherit message_catalog

  method add_message : language:string -> string -> string -> unit
    (** Adds the mapping of a token to a display string for a 
     * given language.
     *)
end


(** This class type contains the dialog declaration *)
class type dialog_decl_type =
object ('self)

  (* PUBLIC *)
  method name : string
    (** The name of the dialog *)

  method enumeration : string -> enum_decl
    (** Returns the declared enumeration *)

  method variable_names : string list
    (** Returns the names of all declared variables *)

  method variable : string -> dialog_type poly_var_decl
    (** Returns a single variable declaration *)

  method page_names : string list
    (** Returns the names of all declared pages *)

  method page : string -> syntax_tree_type
    (** Returns the XML tree of the demanded page (i.e. the [ui:page] node) *)

  method page_is_declared_as_popup : string -> bool
    (** Returns whether the page is declared as popup page (attribute
       *  [popup]
     *)

  method start_page : string
    (** Returns the name of the start page *)

  method default_context : syntax_tree_type dict
    (** Returns the default context of the dialog, i.e. the context parameters
       *  that are declared by the [ui:context] element occurring directly in
       *  the [ui:dialog] element, and not in a certain page.
     *)

  method language_variable : string option
    (** Returns [Some v] if a language variable called [v] is declared, or
       *  [None] if no such variable exists.
     *)

  (* RESTRICTED *)

  (**/**)

  method set_name : string -> unit
  method set_start_page : string -> unit
  method add_enumeration : enum_decl -> unit
  method add_variable : dialog_type poly_var_decl -> unit
  method add_page : string -> syntax_tree_type -> unit
  method set_default_context : syntax_tree_type dict -> unit
  method set_language_variable : string -> unit
end

      (** This class contains the dialog instance *)
and virtual dialog_type =
object ('self)

  method copy : dialog_type
    (** return a copy of the dialog
       *
       * The copy is not attached to a session, even if the original object
       * is.
     *)
  method name : string
    (** return the name of the dialog *)
  method page_name : string
    (** return the name of the current page *)
  method page_names : string list
    (** returns the names of all defined pages of this dialog *)
  method variable : string -> dialog_type poly_var_value
    (** [variable n]: Get the variable with name [n], or raise 
       * [No_such_variable]. The name [n] cannot only refer to variables
       * declared in this dialog, but also to variables of subdialogs
       * using the dot notation: "name1.name2...nameN". Here, [name1]
       * must be a dialog variable, and [name2] a variable of this
       * subdialog, and so on, until the final variable [nameN] is
       * reached, whose value is returned. - The dot notation is accepted
       * by the following methods, too.
     *)
  method variable_decl : string -> dialog_type poly_var_decl
    (* [variable_decl n] returns the declaration of the variable [n].
       * Raises [Not_found] if there is no declaration. Note that the
       * dot notation is allowed in contrast to [declaration # variable n].
     *)
  method initial_variable_value : string -> dialog_type poly_var_value
    (** Returns the initial value of a variable *)
  method string_variable : string -> string
    (** [string_variable n]: Get the contents of the string variable [n].
       * Raise [No_such_variable] if the variable does not exist. [Runtime_error]
       * if the variable is not a string.
     *)
  method enum_variable : string -> string list
    (** [enum_variable n]: Get the contents of the enumerator variable [n].
       * The enumerator must have been declared. The returned list contains
       * only the internal values.
       * Raise [No_such_variable] if the variable does not exist. [Runtime_error]
       * if the variable is not a declared enumerator.
     *)
  method dyn_enum_variable : string -> (string * string) list
    (** [dyn_enum_variable n]: Get the contents of the enumerator variable [n].
       * The enumerator may be dynamic or may be declared. The returned
       * list contains both the internal and the external values.
       * Raise [No_such_variable] if the variable does not exist. [Runtime_error]
       * if the variable is not an enumerator.
     *)
  method dialog_variable : string -> dialog_type option
    (** [dialog_variable n]: Get the contents of the dialog variable [n].
       * Raise [No_such_variable] if the variable does not exist.
       * [Runtime_error] if the variable is not a dialog.
     *)
  method alist_variable : string -> (string * dialog_type poly_var_value) list
    (** [alist_variable n]: Get the contents of the associative variable [n].
       * Raise [No_such_variable] if the variable does not exist.
       * [Runtime_error] if the variable is not an alist.
     *)
  method matrix_variable : string -> head * string array array
    (** [matrix_variable n]: Get the contents of the matrix variable [n].
       * Raise [No_such_variable] if the variable does not exist.
       * [Runtime_error] if the variable is not a matrix.
     *)
  method table_variable : string -> table
    (** [table_variable n]: Get the contents of the table variable [n].
       * Raise [No_such_variable] if the variable does not exist.
       * [Runtime_error] if the variable is not a table.
     *)
  method function_variable : 
    string -> 
    ( dialog_type -> 
	dialog_type poly_var_value Lazy.t list -> 
	  dialog_type poly_var_value )
      (** [function_variable n]: Get the contents of the function variable [n].
       * Raise [No_such_variable] if the variable does not exist.
       * [Runtime_error] if the variable is not a function.
       *)
  method lookup_string_variable : string -> string -> string
  method lookup_enum_variable : string -> string -> string list
  method lookup_dyn_enum_variable : string -> string -> (string * string) list
  method lookup_dialog_variable : string -> string -> dialog_type option
  method lookup_matrix_variable : string -> string -> head * string array array
  method lookup_table_variable : string -> string -> table
  method lookup_function_variable : 
    string ->
    string -> 
    ( dialog_type -> 
	dialog_type poly_var_value Lazy.t list -> 
	  dialog_type poly_var_value )
      (** [lookup_]*[_variable n x]: Get the contents of the associative
       * variable [n] at index [x].
       * [No_such_variable] if the variable does not exist.
       * [Not_found] if the variable is undefined at [x].
       * [Runtime_error] if the variable has the wrong type.
       *)
  method set_variable : string -> dialog_type poly_var_value -> unit
    (** [set_variable n v]: Sets the variable [n] to the value [v]. The value [v]
       * must be compatible to the declared type of the variable.
       * [No_such_variable] if the variable does not exist.
       * [Runtime_error] if the variable is not compatible.
     *)
  method unset_variable : string -> unit
    (** [unset_variable n]: Sets the variable [n] to the declared default
       * value.
       * If the default is not declared, the following default values apply:
       * For strings: the default is the empty string.
       * For enumerators: the default is the empty list.
       * For dialogs: the default is that the value does not exist.
     *)
  method lookup_uploaded_file : string -> Netcgi.cgi_argument option
    (** [lookup_uploaded_file name]:
       * Checks whether the file upload box [name] was used. If so,
       * [Some arg], where [arg] is the transporting CGI argument is returned.
       * If the box was not used, but the box exists, [None] is returned.
       * Raises a [Runtime_error] if the named box does not exist.
       *
       * {b Important note:} Uploaded files are not persistent. This means that
       * they are only existent in the [handle] phase, not during initialization
       * nor the [prepare_page] phase. You get a failure
       * "Upload.get: not initialized" if you try to access uploaded files
       * in the wrong moment.
     *)
  method dump : Format.formatter -> unit
    (** [dump f] output a textual description of the current state into
	 * formatter [f]. (A debugging aid.)
     *)
  method next_page : string
    (** Returns the name of the designated next page. *)
  method set_next_page : string -> unit
    (** Sets the name of the designated next page *)
  method event : event
    (** returns the event that just has happened *)
  method is_server_popup_request : bool
    (** Returns whether someone invoked [set_server_popup_request] before.
       * This is usually done if an dialog is restored for a server-driven
       * popup window (tag [ui:server-popup]).
     *)
  method serialize : (dialog_type,unit) Hashtbl.t -> Buffer.t -> unit
    (** Writes the state of this dialog into the buffer. The hashtable is used
	* in the recursive descent into the object hierarchy to remember which
	* dialogs have already been serialized. Call the method initially with
	* an empty hash table.
     *)
  method unserialize : (universe_type,dialog_type,environment) poly_ds_buf -> unit
    (** Sets the state of this dialog from the deserialization buffer which must contain
       * previously serialized dialog.
     *)

  method enter_session_scope : session_type -> unit
    (** Tells the dialog the current session *)
  method leave_session_scope : unit -> unit
    (** Tells the dialog that it is no longer under control of this session
     *)
  method session : session_type
    (** Returns the current session. Fails when there is no session *)

  method environment : environment
    (** Return the environment of the current CGI activation *)
  method declaration : dialog_decl_type
    (** Return the declaration of this dialog *)
  method application : application_type
    (** Return the application *)
  method universe : universe_type
    (** Return the universe *)

  (*********************************************************************)

  (** {b The following methods must be defined in subclasses:} *)

  method virtual prepare_page : unit -> unit
    (** This method is invoked just before a new output page is generated.
       *
       * {b Preconditions:}
       *
       * The method [page_name] returns the name of this page.
       * The method [event] still returns the action last happened, but
       * the name of the page where this action happened is lost. It may
       * be interesting whether the last event was [No_event] because this
       * indicates that the page is the initial page of the dialog.
       *
       * This method should set any variables which are necessary to
       * generate the new page (mostly variable containing HTML fragments).
       * Furthermore, any state that needs to be saved should be put into
       * variables, too.
     *)
  method virtual handle : unit -> unit
    (** This method is invoked just after the user triggered an event (e.g.
       * pressed a button).
       *
       * {b Preconditions:}
       * The method [page_name] returns the name of the page that was visible
       * while the event was triggered.
       * The method [event] returns the description of the event.
       *
       * {b Postconditions:}
       * The method may set the next page to display by invoking
       * [set_next_page]; if it does not then the default will be used.
       * The default is either specified by the XML element describing
       * the interactor that triggered the event, or the default is
       * otherwise this page again.
       *
       * This method should modify the variables according to the event
       * that happened, and optionally set the next page to display.
       *
       * There is also an alternate way to go to another page: raising
       * the exception Change_page.
       *
       * By raising the exception Change_dialog this method may force to go to
       * another dialog.
     *)

  (*********************************************************************)

  (**/**)

  (* Internal methods *)
  method set_event : event -> unit
    (* set_event e: Sets the current event to e. *)
  method set_server_popup_request : unit -> unit
    (* Sets that this dialog is restored for a server popup window *)
  method init : string -> unit
    (* MOSTLY INTERNAL USE:
       * init p: re-initializes the dialog in order to go to page p.
     *)
  method lock_ia : bool -> unit
    (* ONLY INTERNAL USE *)
  method interactors : interactors
    (* ONLY INTERNAL USE *)

(* -- class [dialog] also has a private method:
     * method private put_tree : string -> Template.tree -> unit
 *)

end

      (** This class represents the whole application *)
      and application_type =
object ('self)
  method start_dialog_name : string
    (** Returns the name of the start dialog *)
  method dialog_names : string list
    (** Returns the names of the declared dialogs *)
  method dialog_declaration : string -> dialog_decl_type
    (** Returns the declaration for the passed dialog *)
  method template_names : string list
    (** Returns the names of the declared templates (including the templates of
       * the core and the standard libraries)
     *)
  method template : string -> template_type
    (** Returns the definition of the passed template *)
  method study : unit -> unit
    (** Studies all defined templates *)
  method output_encoding : string -> (string -> string)
    (** Returns the output encoding as function [string -> string] *)
  method add_output_encoding : string -> (string -> string) -> unit
    (** Adds the output encoding function (second argument) under the
       * passed name (first argument) to the application. It is not
       * possible to redefine existing functions.
     *)
  method var_function : 
    string -> 
    (dialog_type ->
       dialog_type poly_var_value list -> 
	 dialog_type poly_var_value)
      (** Returns the function as O'Caml function.
       * If the function has lazy arguments, this property will be lost when it is
       * returned by this method. Use [lazy_var_function] instead.
       *)
  method lazy_var_function : 
    string -> 
    (dialog_type ->
       dialog_type poly_var_value Lazy.t list -> 
	 dialog_type poly_var_value)
      (** Returns the function as O'Caml function *)
  method dtd : Pxp_dtd.dtd
    (** Returns the DTD of WDialog *)
  method charset : Pxp_types.rep_encoding
    (** Returns the character set used for the internal representation, and for
       *  the generated HTML pages.
     *)
  method debug_mode : bool
    (** Returns whether there is a processing instruction [<?wd-debug-mode?>].
       *  This value is used to initialize the environment.
     *)
  method debug_mode_style : debug_mode_style
    (** Returns the style of the debug mode *)
  method prototype_mode : bool
    (** Returns whether there is a processing instruction [<?wd-prototype-mode?>].
       *  This value is used to initialize the environment.
     *)
  method onstartup_call_handle : bool
    (** Returns whether there is a processing instruction [<?wd-onstartup-call-handle?>].
     *)
  method add_var_function : 
    string -> 
    ( dialog_type -> 
	dialog_type poly_var_value list -> 
	  dialog_type poly_var_value) ->
    unit
      (** Adds a function with eager evaluation *)
  method add_lazy_var_function : 
    string -> 
    ( dialog_type -> 
	dialog_type poly_var_value Lazy.t list -> 
	  dialog_type poly_var_value) ->
    unit
      (** Adds a function with lazy evaluation of its arguments *)

  method catalog : string -> message_catalog
    (** Return the catalog for the domain or raise [Not_found] *)

  method add_catalog : message_catalog -> unit
    (** Add an (external) catalog *)

  method add_extensible_catalog : extensible_message_catalog -> unit
    (** Add an extensible catalog. These can be extended by 
        * ui:catalog elements
     *)

  method add_message : 
    domain:string -> language:string -> string -> string -> unit
    (** Adds a message to the extensible catalog identified by [domain].
     *)

  method lookup_message :
    domain:string -> language:string -> string -> string
    (** Translates the token to [language] starting with the catalog
        * identified by [domain], and proceeding with uplink catalogs
        * if necessary. Raises [Not_found_in_catalog] if no translation
        * is possible.
     *)

  method data_source : string -> data_source
    (** Gets a data source object or raises [Not_found] *)

  method data_sources : data_source list
    (** Get all data source objects *)

  method add_data_source : data_source -> unit
    (** Adds a data source *)

  (**/**)

  method set_start_dialog_name : string -> unit
  method add_dialog_declaration : dialog_decl_type -> unit
  method add_template : ?lib:bool -> string -> template_type -> unit
  method set_debug_mode : bool -> debug_mode_style -> unit
  method set_prototype_mode : bool -> unit
  method set_onstartup_call_handle : bool -> unit
end

      (** This class represents a template definition *)
and template_type =
object

  method study : application_type -> unit
    (** Studies the template for the scope of the passed application *)
  method instantiate :
    ?context: syntax_tree_type dict ->
    ?vars: trans_vars ->
    ?params:  syntax_tree_type dict ->
    dialog_type ->
    syntax_tree_type
      (** Instantiates the template. The parameter [~context] may contain the
	*  context parameters (defaults to the empty set). [~vars] may contain the
	*  transformation variables (defaults to: not available). [~params] may
	*  contains the lexical parameters (defaults to the empty set).
	*  In every case, the current dialog instance must be passed.
	*
	*  The result of the instantiation is the XML tree where all dollar notations
	*  have been replaced by the passed actual parameter values. It is not necessary
	*  that the template is completely expanded, however, i.e. it may contain
	*  [ui:use] elements.
	*
	*  The exception [Instantiation_error] will be raised if something goes
	*  wrong.
       *)
end

      (** This class represents the XML syntax tree *)
      and syntax_tree_type =
object ('self)

  inherit [syntax_tree_type Pxp_document.node] Pxp_document.extension
    (** The syntax tree is an extension of the PXP model for XML trees *)

  inherit template_type
    (** The syntax tree is always a template definition. This has formal
       *  reasons.
     *)

  (** {b Scanner methods}
     *
     * The side-effect of the scanners is to put the result into the passed
     * argument.
   *)
  method scan_application : application_type -> unit
  method scan_dialog : application_type -> dialog_decl_type -> unit
  method scan_enumeration : enum_decl -> unit

  method escaped_data : string
    (** Returns the string contained in the data node after HTML-escaping has
       *  been applied. This string is cached.
     *)

  method to_html :
    ?context: syntax_tree_type dict ->
    ?vars:    trans_vars ->
    dialog_type ->
    Netchannels.out_obj_channel ->
    unit
      (** This method writes the current node and all its children to the passed
       *  output channel. This method is for HTML context, i.e. character data
       *  are to be HTML-escaped, and all elements have to be interpreted.
       *)

  (* TODO: to_xhtml *)
  method to_text :
    ?context: syntax_tree_type dict ->
    ?vars:    trans_vars ->
    dialog_type ->
    Netchannels.out_obj_channel ->
    unit
      (** This method writes the current node and all its children to the passed
       *  output channel. This method is for attribute context, i.e. character data
       *  remain as they are without escaping them, and only the elements are
       *  interpreted that are defined for attribute context.
       *)
end

      (** The universe is the registry of classes and dialogs *)
      and universe_type =
object ('self)

  method application : application_type
    (** Return the application this universe is made for *)
  method register : string -> (universe_type -> string -> environment -> dialog_type) -> unit
    (** Registers that a certain O'Caml class implements the callbacks of the
       *  dialog declared in the UI definition. More precisely,
       *
       *  [u # register name f_new]
       *
       *  registers that the dialog [name] is realized by the objects returned by
       *  the evaluation of the constructing function [f_new]. The arguments passed
       *  to [f_new] are:
       *
       *  [f_new u name env]
       *
       *  where [u] and [name] are the universe and the dialog name, and [env]
       *  is the environment of the current CGI activation. It is legal to store
       *  [env] in the created objects because they are created for every activation
       *  anew.
     *)

  method create : environment -> string -> dialog_type
    (** Creates a new object for the passed environment and dialog name. This method
       *  effectively calls the function [f_new] that has previously been registered.
     *)
end

      (** The session manager creates new sessions, and looks sessions up in the
  *  (possibly fictive) session database
       *)
      and session_manager_type =
object

  method create : dialog_type -> session_type
    (** Creates a new session for this dialog *)

  method unserialize : universe_type -> environment -> string -> session_type
    (** Restores an old session for the passed universe and the passed
	 * environment. The string is the session in serialized form as returned
	 * by the [serialize] method.
     *)
end

      (** This is a single session *)
      and session_type =
object

  method session_id : string
    (** Returns the ID of the session. Fails if the session does not have
       * an ID (e.g. it is not stored in the database)
     *)

  method dialog_name : string
    (** Returns the name of the dialog this session encapsulates *)

  method dialog : dialog_type
    (** Returns the dialog *)

  method commit_changes : unit -> unit
    (** Causes that [serialize] returns the current state of the dialog.
       *  This means that [commit_changes] extracts the state from the dialog,
       *  and prepares the string that will be returned by [serialize].
     *)

  method serialize : string
    (** Returns the state of the dialog at the time of the last [commit_change]
       * or the state of the initial dialog
     *)
  method change_dialog : dialog_type -> unit
    (** Continue with a new dialog. The methods [dialog_name] and [dialog] will
       * immediately reflect the change. However, you have to call [commit_changes]
       * to make [serialize] return the state of the new dialog.
     *)
end

and data_source =
object
  method name : string
    (** The name of the data source, e.g. "sql" *)

  method pre_handle : dialog_type -> unit
  method post_handle : dialog_type -> bool -> unit
  method pre_prepare_page : dialog_type -> unit
  method post_prepare_page : dialog_type -> bool -> unit
    (** Hooks. The [bool] argument is [true] when the method was successful. *)

  method retrieve : string -> table
    (** Retrieves the data for an expression of the data source provider
      * as table (think SQL SELECT statement).
     *)
end




type var_value = dialog_type poly_var_value
  (** [ ]
   *
   * This type is the concrete version of {!Wd_types.poly_var_value} that is
   *  actually used
   *)

type var_decl  = dialog_type poly_var_decl
  (** [ ]
   *
   * This type is the concrete version of {!Wd_types.poly_var_decl} that is
   * actually used
   *)

type ds_buf = (universe_type,dialog_type,environment) poly_ds_buf
  (** [ ]
   *
   * This type is the concrete version of {!Wd_serialize.poly_ds_buf} that is
   * actually used
   *)


exception Change_dialog of dialog_type
  (** The implementation of the [handle] method of a dialog may raise
   * [Change_dialog] to drop the current dialog and continue with another
   * dialog.
   *)

exception Change_page of string
  (** The implementation of the [handle] method of a dialog  may raise
   *  [Change_page] to set the next page to display for the current dialog.
   *)

exception During_action of string * exn
  (** The inner exception occurs in the action described in the string *)

exception Formal_user_error of string
  (** A formal error that happens independently of the current runtime state.
   *  The string argument explains the error.
   *)

exception Runtime_error of string
  (** A certain operation cannot be performed because the current state does
   *  not fulfill the necessary preconditions.
   *  The string argument explains the error.
   *)

exception No_such_variable of string
  (** It has been tried to access a non-declared variable. The string is the
   *  name of the variable.
   *)

exception Instantiation_error of string
  (** An error generated by the [instantiate] method. The caller should
   * catch this exception and report the error from its own view
   *)

exception Eval_error of string
  (** An error generated when evaluating bracket expressions. The caller should
   * catch this exception and report the error from its own view
   *)

exception Eval_error_noloc of string
  (** An error generated when evaluating bracket expressions. The caller should
   * catch this exception and report the error from its own view.
   * In contrast to [Eval_error], this exception does not contain any
   * reference to the location of the failed expression.
   *)


(**/**)

val revision_types : string
  (* Returns the CVS revision string. It is part of the hash value
   * that goes into the serialized objects
   *)

(* ======================================================================
 * History:
 *
 * $Log: wd_types.mli,v $
 * Revision 3.14  2006-03-08 00:56:45  stolpmann
 * Addition of Table_value, Matrix_value and Function_value.
 *
 * New parser for initial expressions. It is now possible to
 * use $[...] in variable initializers.
 *
 * Extended bracket expressions: functions, let expressions,
 * word literals, matrix literals.
 *
 * New type for message catalogs, although not yet implemented.
 *
 * Revision 3.13  2005/12/09 20:02:40  stolpmann
 * Fix in Wd_interactor.unserialize.
 *
 * The [interactors] are now locked in the "handle" stage of processing.
 * Any trial will fail.
 *
 * Revision 3.12  2005/06/11 14:24:14  stolpmann
 * Extension of bracket expressions: many new functions.
 * Functions in bracket expressions may now lazily evaluate their arguments.
 * ui:if and ui:ifvar may refer to any functions defined for bracket
 * expressions.
 * New: ui:ifexpr
 * Parsing of bracket expressions is now done with ulex. Private interfaces
 * of PXP are no longer used for this purpose.
 * Serialization has been rewritten, and it is now safe.
 * Fix: In ui:context there may now be macro references at any location.
 * Also documented all these changes.
 *
 * Revision 3.11  2004/12/12 17:57:32  stolpmann
 * 	Added <q:wd-link> and <q:wd-xlink> to generate links for
 * applications that cannot use Javascript. Limited functionality, however.
 * See stdlib.xml for details.
 *
 * Revision 3.10  2003/03/21 14:23:44  stolpmann
 * 	ocamldoc updated
 *
 * Revision 3.9  2003/02/21 21:58:53  stolpmann
 * 	Changed docs.
 *
 * Revision 3.8  2003/02/16 23:48:15  stolpmann
 * 	Improved wd-debug-mode: there are now two styles
 *
 * Revision 3.7  2003/01/04 21:55:26  stolpmann
 * 	new record response_header
 *
 * Revision 3.6  2002/11/09 11:41:19  stolpmann
 * 	Fix: ui:select accepts dot notation. A new method
 * variable_decl needs to be defined for dialogs. This method
 * returns the var_decl record and interprets the dot notation.
 *
 * Revision 3.5  2002/10/20 19:39:17  stolpmann
 * 	New feature: The brackets $[...] can contain expressions,
 * not only variables
 *
 * Revision 3.4  2002/10/18 20:17:49  stolpmann
 * 	New feature: dot notation to access contents of dialog
 * variables
 *
 * Revision 3.3  2002/04/10 20:04:05  stolpmann
 * 	The CVS revision number is exported.
 *
 * Revision 3.2  2002/02/14 16:15:21  stolpmann
 * 	Added copyright notice.
 *
 * Revision 3.1  2002/02/12 20:29:25  stolpmann
 * 	Initial release at sourceforge.
 *
 * Revision 2.1  2002/02/11 18:27:55  gerd
 * 	Initial revision.
 *
 *
 *)

This web site is published by Informatikbüro Gerd Stolpmann
Powered by Caml