P5EEx-Blue-0.01

P5EEx::Blue::Context


NAME

P5EEx::Blue::Context - context in which we are currently running


SYNOPSIS

   # ... official way to get a Context object ...
   use P5EEx::Blue::P5EE;
   $context = P5EEx::Blue::P5EE->context();
   $config = $context->config();   # get the configuration
   $config->dispatch_events();     # dispatch events
   # any of the following named parameters may be specified
   $context = P5EEx::Blue::P5EE->context(
       contextClass => "P5EEx::Blue::Context::CGI",
       configClass => "P5EEx::Blue::Config::File",   # or any Config args
   );
   # ... alternative way (used internally) ...
   use P5EEx::Blue::Context;
   $context = P5EEx::Blue::Context->new();


DESCRIPTION

A Context class models the environment (aka ``context'') in which the current process is running.

The role of the Context class is to abstract the details of the various runtime environments (or Platforms) (including their event loops) so that the basic programming model for the developer is uniform.

Since the Context objects are the objects that initiate events in the P5EE universe, they must be sure to wrap those event handlers with try/catch blocks (i.e. ``eval{};if($@){}'' blocks).

The main functions of the Context class are to

    * load the Config data,
    * dispatch events from the Context event loop, and
    * manage Session data.

The Context object is always a singleton per process (except in rare cases like debugging during development).

Conceptually, the Context may be associated with many Config's (one per authenticated user) and Sessions (one per unique session_id) in a single process (ModPerl). However, in practice, it is often associated with only one Config or Session throughout the lifetime of the process (CGI, Cmd).


Class Group: Context

The following classes might be a part of the Context Class Group.


Attributes, Constants, Global Variables, Class Variables

Master Data Structure Map

 $context
 $context->{debugscope}{$class}          Debugging all methods in class
 $context->{debugscope}{$class.$method}  Debugging a single method
 $context->{initconfig}    Args that Context was created with
 $context->{used}{$class}  Similar to %INC, keeps track of what classes used
 $context->{cgi}           (Context::CGI only) the CGI object
 $context->{Config}{$user} Info from config file
 [$context->{config}]
    $config->{$type}{$name}              Read-only service config
 $context->{Session}{$session_id}
 [$context->{session}]
    $session->{store}{$type}{$name}      Runtime state which is stored
    $session->{cache}{$type}{$name}      Instances of services


Constructor Methods:

new()

The P5EEx::Blue::Context->new() method is rarely called directly. That is because a $context should always be instantiated by calling P5EEx::Blue::P5EE->context(). This allows for caching of the $context as a singleton and the autodetection of what type of Context subclass should in fact be instantiated.

    * Signature: $context = P5EEx::Blue::P5EE->new(%named);
    * Param:  contextClass class  [in]
    * Param:  configClass  class  [in]
    * Param:  configFile   string [in]
    * Return: $context     P5EEx::Blue::Context
    * Throws: Exception::Class::Context
    * Since:  0.01
    Sample Usage:
    $context = P5EEx::Blue::Context->new();
    $context = P5EEx::Blue::Context->new(
        contextClass => 'P5EEx::Blue::Context::CGI',
        configClass  => 'P5EEx::Blue::Config::File',
        configFile   => 'config.xml',
    );


Protected Methods:

The following methods are intended to be called by subclasses of the current class (or environmental, ``main'' code).

init()

The init() method is called from within the standard Context constructor. The init() method in this class does nothing. It allows subclasses of the Context to customize the behavior of the constructor by overriding the init() method.

    * Signature: $context->init($args)
    * Param:     $args            {}    [in]
    * Return:    void
    * Throws:    P5EEx::Blue::Exception
    * Since:     0.01
    Sample Usage:
    $context->init($args);


Public Methods: Services

service()

The service() method returns a named object of a certain service type.

    * Signature: $service = $context->service($type);
    * Signature: $service = $context->service($type,$name);
    * Signature: $service = $context->service($type,$name,%named);
    * Param:  $type        string  [in]
    * Param:  $name        string  [in]
    * Return: $service     P5EEx::Blue::Service
    * Throws: P5EE::Blue::Exception
    * Since:  0.01
    Sample Usage:
    $user = $context->service("Widget","db.user.spadkins");
    $gobutton = $context->service("Widget","gobutton");

There are many services available within a P5EE application. Each service is identified by two pieces of information: it's type and its name.

The following service types are standard in P5EE. Others can be developed by deriving a class from the P5EEx::Blue::Service class. All service types must start with a capital letter.

    * Repository
    * Security
    * Widget
    * TemplateEngine
    * Messaging
    * Procedure
    * LogChannel

Within each service type, each individual service is identified by its name. The name of a service, if not specified, is assumed to be ``default''.

Whenever a service is requested from the Context via this service() method, the service cache in the Session is checked first. If it exists, it is generally returned immediately without modification by the named parameters. (Parameters *are* taken into account if the ``override'' parameter is supplied.)

If it does not exist, it must be created and stored in the cache.

The name of a service, if not specified, is assumed to be ``default''.

The named parameters (%named or $named), if supplied, are considered defaults. They are ignored if the values already exist in the service config. However, the additional named parameter, ``override'', may be supplied. In that case, all of the values in the named parameters will accepted into the service config.

Every service (i.e. $config->{Repository}{default}) starts as a simple hash which is populated with attributes from several complementary sources. If we imagine that a service is requested with type $type and name $name, we can envision the following additional derived variables.

  $type           = "Repository";
  $name           = "sysdb";
  $lcf_type       = "repository";  # lower-case first letter
  $config         = $context->config();
  $repositoryType = $config->{Repository}{sysdb}{repositoryType};

The following sources are consulted to populate the service attributes.

  1. config of the service (in Config)
     i.e. $config->{Repository}{sysdb}
  2. optional config of the service's service_type (in Config)
     i.e. $config->{RepositoryType}{$repositoryType}
  3. named parameters to the service() call

All service configuration happens before instantiation this allows you to override the ``serviceClass'' in the configuration in time for instantiation

session()

repository()

security()

widget()

template_engine()

messaging()

procedure()

log_channel()

shared_datastore()

shared_resource_set()

These are all convenience methods, which simply turn around and call the service() method with the service type as the first argument.

    * Signature: $session = $context->session();
    * Signature: $session = $context->session($name);
    * Signature: $session = $context->session($name,%named);
    * Param:  $name        string  [in]
    * Return: $service     P5EEx::Blue::Service
    * Throws: P5EE::Blue::Exception
    * Since:  0.01
    Sample Usage:
    $session             = $context->session();
    $repository          = $context->repository();
    $security            = $context->security();
    $template_engine     = $context->template_engine();
    $log_channel         = $context->log_channel();
    $shared_datastore    = $context->shared_datastore();
    $shared_resource_set = $context->shared_resource_set();

widget_exists()

    * Signature: $exists = $context->widget_exists($widget_name);
    * Param:  $widget_name     string
    * Return: $exists          boolean
    * Throws: <none>
    * Since:  0.01
    Sample Usage:
    if ($context->widget_exists($widget_name)) {
        # do something
    }

The widget_exists() returns whether or not a widget is already known to the Context. This is true if

 * it exists in the Session's widget cache, or
   (i.e. it has already been referenced and instantiated in the cache),
 * it exists in the Session's store, or
   (i.e. it was referenced in an earlier request in this session)
 * it exists in the Config

If this method returns FALSE (undef), then any call to the widget() method must specify the widgetClass (at a minimum) and may not simply call it with the $widget_name.

This is useful particularly for volatile widgets which generate events (such as image buttons). The $context->dispatch_events() method can check that the widget has not yet been defined and automatically passes the event to the widget's container (implied by the name) for handling.


Public Methods: Accessors

iget()

    * Signature: $value = $context->iget($var, $default);
    * Param:  $var             string
    * Param:  $attribute       string
    * Return: $value           string
    * Throws: <none>
    * Since:  0.01
    Sample Usage:
    $script_url_dir = $context->iget("scriptUrlDir", "/cgi-bin");

The iget() returns the value of an Initialization Config variable (or the ``default'' value if not set).

This is an alternative to getting the reference of the entire hash of Initialization Config variables with $self->initconfig().

wget()

The wget() returns the attribute of a widget.

    * Signature: $value = $context->wget($widgetname, $attribute);
    * Param:  $widgetname      string
    * Param:  $attribute       string
    * Return: $value           string,ref
    * Throws: <none>
    * Since:  0.01
    Sample Usage:
    $wname = $context->wget("session", "wname");
    $width = $context->wget("main.app.toolbar.calc", "width");

wset()

The wset() sets an attribute of a widget in the Session.

    * Signature: $context->wset($widgetname, $attribute, $value);
    * Param:  $widgetname      string
    * Param:  $attribute       string
    * Param:  $value           string,ref
    * Return: void
    * Throws: <none>
    * Since:  0.01
    Sample Usage:
    $context->wset("session", "wname", "main_screen");
    $context->wset("main.app.toolbar.calc", "width", 50);
    $context->wset("xyz", "{arr}[1][2]",  14);
    $context->wset("xyz", "{arr.totals}", 14);

wdelete()

The wdelete() deletes an attribute of a widget in the Session.

    * Signature: $context->wdelete($widgetname, $attribute);
    * Param:  $widgetname      string
    * Param:  $attribute       string
    * Return: void
    * Throws: <none>
    * Since:  0.01
    Sample Usage:
    $context->wdelete("session", "wname");
    $context->wdelete("main.app.toolbar.calc", "width");
    $context->wdelete("xyz", "{arr}[1][2]");
    $context->wdelete("xyz", "{arr.totals}");


Public Methods: Miscellaneous

add_message()

The add_message() method stores a string (the concatenated list of @args) in the Context until it can be viewed by and acted upon by the user.

    * Signature: $context->add_message($msg);
    * Param:  $msg         string  [in]
    * Return: void
    * Throws: <none>
    * Since:  0.01
    Sample Usage:
    $context->add_message("Data was not saved. Try again.");

log()

The log() method writes a string (the concatenated list of @args) to the default log channel.

    * Signature: $context->log(@args);
    * Param:  @args        string  [in]
    * Return: void
    * Throws: <none>
    * Since:  0.01
    Sample Usage:
    $context->log("oops, a bug happened");

user()

The user() method returns the username of the authenticated user. The special name, ``guest'', refers to the unauthenticated (anonymous) user.

    * Signature: $username = $context->user();
    * Param:  void
    * Return: string
    * Throws: <none>
    * Since:  0.01
    Sample Usage:
    $username = $context->user();

initconfig()

    * Signature: $initconfig = $context->initconfig();
    * Param:  void
    * Return: $initconfig    {}
    * Throws: <none>
    * Since:  0.01
    Sample Usage:
    $initconfig = $context->initconfig();

The initconfig() method returns a hashreference to all of the variable/value pairs used in the initialization of the Context.

config()

    * Signature: $config = $context->config();
    * Param:  void
    * Return: $config    P5EEx::Blue::Config
    * Throws: <none>
    * Since:  0.01
    Sample Usage:
    $config = $context->config();

The config() method returns the user's config data structure.

session()

The session() method returns the session

    * Signature: $session = $context->session();
    * Param:  void
    * Return: $session    P5EEx::Blue::Session
    * Throws: <none>
    * Since:  0.01
    Sample Usage:
    $session = $context->session();

user_agent()

The user_agent() method returns a UserAgent objects which is primarily useful to see what capabilities the user agent (browser) supports.

    * Signature: $user_agent = $context->user_agent();
    * Param:  void
    * Return: $user_agent    P5EEx::Blue::UserAgent
    * Throws: <none>
    * Since:  0.01
    Sample Usage:
    $user_agent = $context->user_agent();

domain()

The domain() method is called to get the list of valid values in a data domain and the labels that should be used to represent these values to a user.

    * Signature: ($values, $labels) = $self->domain($domain_name)
    * Param:     $domain_name      string
    * Return:    $values           []
    * Return:    $labels           {}
    * Throws:    P5EEx::Blue::Exception
    * Since:     0.01
    Sample Usage:
    ($values, $labels) = $self->domain("gender");
    foreach (@$values) {
        print "$_ => $labels->{$_}\n";
    }


Public Methods: Debugging

dbg()

The dbg() method is used to check whether a given line of debug output should be generated. It returns true or false (1 or 0).

If all three parameters are specified, this function returns true only when the global debug level ($P5EEX::Blue::Context::DEBUG) is at least equal to $level and when the debug scope is set to debug this class and method.

    * Signature: $flag = $context->dbg($class,$method,$level);
    * Param:     $class       class   [in]
    * Param:     $method      string  [in]
    * Param:     $level       integer [in]
    * Return:    void
    * Throws:    P5EEx::Blue::Exception::Context
    * Since:     0.01
    Sample Usage:
    $context->dbgprint("this is debug output")
        if ($P5EEx::Blue::DEBUG && $context->dbg(3));
    $context->dbgprint("this is debug output")
        if ($context->dbg(3));

The first usage is functionally identical to the second, but the check of the global debug level explicitly reduces the runtime overhead to eliminate any method calls when debugging is not turned on.

dbgprint()

The dbgprint() method is used to produce debug output. The output goes to an output stream which is appropriate for the runtime context in which it is called.

    * Signature: $flag = $context->dbgprint(@args);
    * Param:     @args        string  [in]
    * Return:    void
    * Throws:    P5EEx::Blue::Exception::Context
    * Since:     0.01
    Sample Usage:
    $context->dbgprint("this is debug output")
        if ($P5EEx::Blue::DEBUG && $context->dbg(3));

dbglevel()

The dbglevel() method is used to set the debug level. Setting the dbglevel to 0 turns off debugging output and is suitable for production use. Setting the dbglevel to 1 or higher turns on increasingly verbose debug output.

    * Signature: $context->dbglevel($dbglevel);
    * Signature: $dbglevel = $context->dbglevel();
    * Param:     $dbglevel   integer
    * Return:    $dbglevel   integer
    * Throws:    P5EEx::Blue::Exception::Context
    * Since:     0.01
    Sample Usage:
    $context->dbglevel(1);             # turn it on
    $context->dbglevel(0);             # turn it off
    $dbglevel = $context->dbglevel();  # get the debug level

dbgscope()

The dbgscope() method is used to get the hash which determines which debug statements are to be printed out when the debug level is set to a positive number. It returns a hash reference. If class names or ``class.method'' names are defined in the hash, it will cause the debug statements from those classes or methods to be printed.

    * Signature: $dbgscope = $context->dbgscope();
    * Param:     void
    * Return:    $dbgscope   {}
    * Throws:    P5EEx::Blue::Exception::Context
    * Since:     0.01
    Sample Usage:
    $dbgscope = $context->dbgscope();
    $dbgscope->{"P5EEx::Blue::Context::CGI"} = 1;
    $dbgscope->{"P5EEx::Blue::Context::CGI.process_request"} = 1;

dump()

    * Signature: $perl = $context->dump();
    * Param:     void
    * Return:    $perl      text
    * Throws:    P5EEx::Blue::Exception
    * Since:     0.01
    Sample Usage:
    print $self->dump(), "\n";


Protected Methods

These methods are considered protected because no class is ever supposed to call them. They may however be called by the context-specific drivers.

dispatch_events()

The dispatch_events() method is called by the bootstrap environmental code in order to get the Context object rolling. It causes the program to block (wait on I/O), loop, or poll, in order to find events from the environment and dispatch them to the appropriate places within the P5EE framework.

It is considered ``protected'' because no classes should be calling it.

    * Signature: $context->dispatch_events()
    * Param:     void
    * Return:    void
    * Throws:    P5EEx::Blue::Exception
    * Since:     0.01
    Sample Usage:
    $context->dispatch_events();

shutdown()

The shutdown() method is called when the Context is preparing to exit. This allows for connections to databases, etc. to be closed gracefully.

    * Signature: $self->shutdown()
    * Param:     void
    * Return:    void
    * Throws:    P5EEx::Blue::Exception
    * Since:     0.01
    Sample Usage:
    $self->shutdown();