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_application.ml,v 3.9 2005-06-11 14:24:14 stolpmann Exp $
 * ----------------------------------------------------------------------
 *
 *)

open Wd_types

class application init_dtd : application_type =
  object (self)

    val mutable start_dialog_name =
	    (None : string option)
    val mutable dialogs =
	    (Hashtbl.create 20 : (string, dialog_decl_type) Hashtbl.t)
    val mutable dialog_names =
	    []
    val mutable templates =
	    (Hashtbl.create 20 : (string, template_type) Hashtbl.t)
    val mutable templates_libflag =
	    (Hashtbl.create 20 : (string, bool) Hashtbl.t)
    val mutable template_names =
	    []
    val mutable output_encodings =
	    (Hashtbl.create 10 : (string, string->string) Hashtbl.t)
    val mutable var_functions =
            (Hashtbl.create 10 : 
	       (string, dialog_type -> var_value Lazy.t list -> var_value) Hashtbl.t)
    val mutable dtd =
	    init_dtd
    val mutable debug_mode =
	    false
    val mutable debug_mode_style =
	    `Partially_encoded
    val mutable prototype_mode =
	    false
    val mutable onstartup_call_handle =
	    false

    initializer
      (* Add some standard encodings: *)
      let enc = init_dtd # encoding in
      self # add_output_encoding "html" Wd_encoding.encode_as_html;
      self # add_output_encoding "pre"  Wd_encoding.encode_as_pre;
      self # add_output_encoding "para" Wd_encoding.encode_as_para;
      self # add_output_encoding "js"     Wd_encoding.encode_as_js_string;
      self # add_output_encoding "jslong" 
	       (Wd_encoding.encode_as_js_longstring ~enc);
      (* Add the standard functions: *)
      self # add_var_function "id"      Wd_var_functions.id;
      self # add_var_function "length"  Wd_var_functions.length;
      self # add_var_function "card"    Wd_var_functions.card;
      self # add_var_function "size"    Wd_var_functions.size;
      self # add_var_function "add"     Wd_var_functions.add;
      self # add_var_function "sub"     Wd_var_functions.sub;
      self # add_var_function "mul"     Wd_var_functions.mul;
      self # add_var_function "div"     Wd_var_functions.div;
      self # add_var_function "modulo"  Wd_var_functions.modulo;
      self # add_var_function "assoc"   Wd_var_functions.assoc;
      self # add_var_function "nth"     Wd_var_functions.nth;
      self # add_var_function "contains"      Wd_var_functions.contains;
      self # add_var_function "mentions"      Wd_var_functions.mentions;
      self # add_var_function "translate"     Wd_var_functions.translate;
      self # add_var_function "rev_translate" Wd_var_functions.rev_translate; (* legacy *)
      self # add_var_function "rev-translate" Wd_var_functions.rev_translate;

      self # add_var_function "eq"      Wd_var_functions.eq;
      self # add_var_function "ne"      Wd_var_functions.ne;
      self # add_var_function "match"   Wd_var_functions.match_;
      self # add_var_function "nomatch" Wd_var_functions.nomatch;
      self # add_var_function "substring" Wd_var_functions.substring;
      self # add_var_function "concat"  Wd_var_functions.concat;

      self # add_var_function "int-eq"  Wd_var_functions.int_eq;
      self # add_var_function "int-ne"  Wd_var_functions.int_ne;
      self # add_var_function "int-lt"  Wd_var_functions.int_lt;
      self # add_var_function "int-le"  Wd_var_functions.int_le;
      self # add_var_function "int-gt"  Wd_var_functions.int_gt;
      self # add_var_function "int-ge"  Wd_var_functions.int_ge;
      self # add_var_function "int-min" Wd_var_functions.int_min;
      self # add_var_function "int-max" Wd_var_functions.int_max;
      self # add_var_function "int-abs" Wd_var_functions.int_abs;
      self # add_var_function "int-sign" Wd_var_functions.int_sign;

      self # add_var_function "card-eq" Wd_var_functions.card_eq;
      self # add_var_function "card-ne" Wd_var_functions.card_ne;
      self # add_var_function "card-lt" Wd_var_functions.card_lt;
      self # add_var_function "card-le" Wd_var_functions.card_le;
      self # add_var_function "card-gt" Wd_var_functions.card_gt;
      self # add_var_function "card-ge" Wd_var_functions.card_ge;
      self # add_var_function "size-eq" Wd_var_functions.card_eq;  (* legacy name *)
      self # add_var_function "size-ne" Wd_var_functions.card_ne;  (* legacy name *)
      self # add_var_function "size-lt" Wd_var_functions.card_lt;  (* legacy name *)
      self # add_var_function "size-le" Wd_var_functions.card_le;  (* legacy name *)
      self # add_var_function "size-gt" Wd_var_functions.card_gt;  (* legacy name *)
      self # add_var_function "size-ge" Wd_var_functions.card_ge;  (* legacy name *)

      self # add_var_function "height" Wd_var_functions.height;
      self # add_var_function "width"  Wd_var_functions.width;
      self # add_var_function "dialog-exists" Wd_var_functions.dialog_exists;

      self # add_lazy_var_function "and"    Wd_var_functions.and_;
      self # add_lazy_var_function "or"     Wd_var_functions.or_;
      self # add_var_function      "not"    Wd_var_functions.not_;
      self # add_var_function      "true"   Wd_var_functions.true_;
      self # add_var_function      "false"  Wd_var_functions.false_;
      self # add_lazy_var_function "if"     Wd_var_functions.if_;

      self # add_var_function "var"    Wd_var_functions.var;
      self # add_var_function "dialog" Wd_var_functions.dialog;
      self # add_var_function "self"   Wd_var_functions.self;
      self # add_var_function "page"   Wd_var_functions.page;
      self # add_var_function "language"  Wd_var_functions.language;
      self # add_var_function "self_base_url" Wd_var_functions.self_base_url; (* legacy *)
      self # add_var_function "self-base-url" Wd_var_functions.self_base_url;
      self # add_var_function "session_id" Wd_var_functions.session_id; (* legacy *)
      self # add_var_function "session-id" Wd_var_functions.session_id;
      self # add_var_function "create_anchor_event" Wd_var_functions.create_anchor_event; (* legacy *)
      self # add_var_function "create-anchor-event" Wd_var_functions.create_anchor_event;
      self # add_var_function "create_xanchor_event" Wd_var_functions.create_xanchor_event;
      self # add_var_function "create-xanchor-event" Wd_var_functions.create_xanchor_event; (* legacy *)
      (* There are also the following, magically defined functions:
       * - type
       * - is_associative/is-associative
       * - default
       * - enum
       * - words
       *)
      

    (* ------------------------ Public --------------------------- *)

    method start_dialog_name =
      match start_dialog_name with
	  Some n -> n
	| None -> failwith "application # start_dialog_name"

    method dialog_names =
      dialog_names

    method dialog_declaration obj_name =
      Hashtbl.find dialogs obj_name

    method template_names =
      template_names

    method template tmpl_name =
      Hashtbl.find templates tmpl_name

    method study () =
      Hashtbl.iter
	(fun _ t -> t # study (self :> application_type))
	templates

    method output_encoding name =
      Hashtbl.find output_encodings name

    method lazy_var_function name =
      Hashtbl.find var_functions name

    method var_function name =
      let f = self # lazy_var_function name in
      (fun dlg args -> f dlg (List.map (fun arg -> lazy arg) args))

    method dtd = dtd

    method charset = dtd # encoding

    method debug_mode = debug_mode

    method debug_mode_style = debug_mode_style

    method prototype_mode = prototype_mode

    method onstartup_call_handle = onstartup_call_handle

    (* -------------------- Restricted use only ------------------- *)

    method set_start_dialog_name n =
      start_dialog_name <- Some n

    method add_dialog_declaration obj =
      (* fails if 'obj_name' already used *)
      let obj_name = obj # name in
      if Hashtbl.mem dialogs obj_name then
	raise (Formal_user_error ("ui:dialog `" ^ obj_name ^
				  "' is declared twice"));
      Hashtbl.add dialogs obj_name obj;
      dialog_names <- obj_name :: dialog_names;

    method add_template ?(lib = false) tmpl_name tmpl =
      (* fails if 'tmpl_name' already used, but:
       * a non-library template is allowed to override a library template.
       *)
      let old_libflag =
	try
	  Some(Hashtbl.find templates_libflag tmpl_name)
	with
	    Not_found -> None
      in
      begin match old_libflag with
	  Some true when not lib -> ()
	| None -> ()
	| _ ->
	    raise (Formal_user_error ("ui:template `" ^ tmpl_name ^
				      "' is declared twice"));
      end;
      Hashtbl.add templates tmpl_name tmpl;
      Hashtbl.add templates_libflag tmpl_name lib;
      template_names <- tmpl_name :: template_names;

    method add_output_encoding enc_name enc =
      (* fails if 'enc_name' already used *)
      if Hashtbl.mem output_encodings enc_name then
	failwith ("This output encoding already exists: " ^ enc_name );
      Hashtbl.add output_encodings enc_name enc;

    method add_var_function fn_name fn =
      (* fails if 'fn_name' already used *)
      if Hashtbl.mem var_functions fn_name then
	failwith ("This variable function already exists: " ^ fn_name );
      Hashtbl.add var_functions fn_name 
	(fun dlg lazy_args -> 
	   let args = List.map Lazy.force lazy_args in
	   fn dlg args)

    method add_lazy_var_function fn_name fn =
      (* fails if 'fn_name' already used *)
      if Hashtbl.mem var_functions fn_name then
	failwith ("This variable function already exists: " ^ fn_name );
      Hashtbl.add var_functions fn_name fn

    method set_debug_mode b style = 
      debug_mode <- b;
      debug_mode_style <- style

    method set_prototype_mode b = prototype_mode <- b

    method set_onstartup_call_handle b = onstartup_call_handle <- b

  end
;;

(* ======================================================================
 * History:
 *
 * $Log: wd_application.ml,v $
 * Revision 3.9  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.8  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.7  2003/03/21 12:50:31  stolpmann
 * 	Fix: encode_as_js_longstring can cope with UTF8-encoded strings
 *
 * Revision 3.6  2003/02/16 23:48:14  stolpmann
 * 	Improved wd-debug-mode: there are now two styles
 *
 * Revision 3.5  2002/11/03 21:17:48  stolpmann
 * 	New functions: type, is_associative, default
 *
 * Revision 3.4  2002/11/03 20:56:56  stolpmann
 * 	New functions: translate, rev_translate
 *
 * Revision 3.3  2002/10/20 19:39:16  stolpmann
 * 	New feature: The brackets $[...] can contain expressions,
 * not only variables
 *
 * Revision 3.2  2002/02/14 16:15:21  stolpmann
 * 	Added copyright notice.
 *
 * Revision 3.1  2002/02/12 20:28:59  stolpmann
 * 	Initial release at sourceforge.
 *
 * Revision 1.8  2002/02/07 18:49:59  gerd
 * 	Standard library
 *
 * Revision 1.7  2002/02/05 18:46:08  gerd
 * 	New: methods [set_]debug_mode, prototype_mode, onstartup_call_handle
 *
 * Revision 1.6  2002/01/30 15:11:11  gerd
 * 	The method [study] gets now the application object as argument.
 *
 * Revision 1.5  2002/01/28 02:12:54  gerd
 * 	Added support for output encodings.
 *
 * Revision 1.4  2002/01/26 22:35:53  gerd
 * 	Using hashtables instead of associative lists
 *
 * Revision 1.3  2002/01/24 23:34:54  gerd
 * 	Implemented [study].
 *
 * Revision 1.2  2002/01/14 15:03:23  gerd
 * 	Major change: Typing has been completely revised, and almost
 * every tiny thing has now a new type. Also renamed a lot.
 *
 * Revision 1.1  2000/04/13 17:42:58  gerd
 * 	Initial revision.
 *
 *
 *)

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