Configuration

This document provides an introduction into the configuration of the Cerny.js library. The configuration allows simple adaptation of some aspects of the behavior of Cerny.js without altering the source code. This way we can, for example, adjust the log level, specify the active interceptors or manage our dependencies so we can avoid manually importing scripts in the HTML page.

Creating a configuration file

The library is shipped with a default configuration file, which we can use as a template for our own configuration. It is called cerny.conf.js and resides in the same directory as cerny.js. Let's copy this file into our application directory and include it into our page before the cerny.js script. Before the configuration file, we set up the PopupWindow console, which will receive all the output from the Cerny.js library.

<script type="text/javascript" src="vendor/cerny.js/console/console.js" ></script> <script type="text/javascript" src="vendor/cerny.js/console/PopupWindow.js" ></script> <script type="text/javascript" src="ourapp/cerny.conf.js" ></script> <script type="text/javascript" src="vendor/cerny.js/cerny.js" ></script>

The structure of the configuration file

The configuration file is composed of three parts. It defines the object CERNY.Configuration, and the functions CERNY.configure and CERNY.print.

CERNY.Configuration = { Logger: { "indentStr": " ", "CERNY": "OFF", "CERNY.require": "FATAL", "CERNY.load": "ERROR", "NONE": "TRACE" }, // The catalog is used to resolve dependencies, which are stated in // a script by the means of CERNY.require. Catalog: { "cerny.js.path":"{configure-manually}", "CERNY.js.Array":"{cerny.js.path}/js/Array.js", "CERNY.js.Date":"{cerny.js.path}/js/Date.js", "CERNY.js.Number":"{cerny.js.path}/js/Number.js", "CERNY.js.String":"{cerny.js.path}/js/String.js", "CERNY.js.doc.Generator":"{cerny.js.path}/js/doc/Generator.js", "CERNY.js.doc.Schema":"{cerny.js.path}/js/doc/Schema.js", "CERNY.json.HtmlPrettyPrinter":"{cerny.js.path}/json/HtmlPrettyPrinter.js", "CERNY.json.Printer":"{cerny.js.path}/json/Printer.js", "CERNY.json.TextPrettyPrinter":"{cerny.js.path}/json/TextPrettyPrinter.js", "CERNY.schema":"{cerny.js.path}/schema/schema.js", "CERNY.text.DateFormat":"{cerny.js.path}/text/DateFormat.js", "CERNY.text.NumberFormat":"{cerny.js.path}/text/NumberFormat.js", "CERNY.util":"{cerny.js.path}/util/util.js", }, Interception: { active: [] } }; CERNY.configure = function() { var active = CERNY.Configuration.Interception.active; active.push(CERNY.Interceptors.LogIndenter); // active.push(CERNY.Interceptors.Profiler); active.push(CERNY.Interceptors.Tracer); // active.push(CERNY.Interceptors.TypeChecker); // active.push(CERNY.Interceptors.ContractChecker); }; // We are printing to the PopupWindow console CERNY.print = function(message) { // A generic console that works in all browsers CERNY.console.PopupWindow.print(message); // Firebug // console.log(message); // JsUnit with xbDebug // debug(message); // Rhino shell // print(message); };

Since some configuration parameters (e.g. Logger) require to be effective immediately, the configuration has to be loaded before the cerny.js script. Other concepts (e.g. Interception) need to reference functions and objects which are only available after some part of Cerny.js has been loaded. This is where the configure function becomes necessary. It is called somewhere in the middle of cerny.js, a line which we refer to as the configuration cut. Interception is only available after this cut.

Output in the Cerny.js library is directed to a function called CERNY.print. The definition of this function is dependent on the runtime environment and project preferences. In the above example, several options are given. Ultimately, it is up to the library user to decide, what should happen to the message that is passed into CERNY.print. But it is important to realize that this is the primary channel of communication from the library to the programmer.

Dependency management

Cerny.js uses a catalog to map expressions onto the location of its defining script. The catalog is defined in cerny.conf.js at CERNY.Configuration.Catalog. Since Cerny.js 2, it is possible to separate the catalog into several files. To use a catalog file, it must be included in CERNY.Configuration.Catalog in the property include:

CERNY.Configuration = { ... Catalog: { "include": ["catalog.json"] } ... };

A catalog must be a well-formed JSON document. The catalog of our web application, which also uses YUI, could look like this:

{"include": ["{cerny.js.path}/catalog.json"], "cerny.js.path": "/ourapp/vendor/cerny.js/js", // Declaring dependencies of the YUI library "yui.path": "/ourapp/vendor/yui/build", "YAHOO": "{yui.path}/yahoo/yahoo.js", "YAHOO.util.Dom": "YAHOO,{yui.path}/dom/dom.js", "YAHOO.util.Event": "YAHOO,{yui.path}/event/event.js", "YAHOO.widget.Calendar": "YAHOO,YAHOO.util.Event,YAHOO.util.Dom,{yui.path}/calendar/calendar.js", ... }
Declaring dependencies

In the catalog above we see that Cerny.js allows us to declare dependencies of third party libraries. In our own script we state dependencies in the beginning with a call to the function CERNY.require. Its first parameter is the name of the requiring expression, which is defined in the current script. Thereafter any number of required expressions can be passed as strings:

CERNY.require("OURAPP.somePackage", // the requiring expression "CERNY.js.Array", "YAHOO.widget.Calendar"); CERNY.namespace("somePackage", OURAPP); // Code starts here

If a dependency cannot be resolved via the catalog, an exception is thrown and more details are logged to the category CERNY.require. This indicates that the catalog is configured incorrectly. Since Cerny.js 1.3, the implementation of Cerny.load uses XMLHttpRequest to retrieve scripts. This should work for all modern browsers. It can be adapted for other runtime environments.

Reference of CERNY.Configuration

Logger
Holds a mapping of logger category to log level. Specific categories take precedence over general ones. If "CERNY" is set to "OFF", one can make an exception for "CERNY.schema" by setting it to "TRACE". The sequence of the entries does not matter.
indentStr
Allows the user of the library to specify a string used for indentation in logging. This feature only becomes available in cooperation with the LogIndenter interceptor. If this option is missing from the Configuration, two spaces will be used. When logging to HTML, it might be necessary to set the indentStr to "&nbsp;&nbsp;". Another option would be to use the preserve whitespace feature of CSS.
ROOT
This category is used as the top level for all other categories. Absence of this category from the configuration is interpreted as setting it to "OFF".
NONE
This special category is used when interception is installed on objects which do not hold a Logger in the member logger. It is recommended to keep this category to "TRACE" to avoid losing log output and to install a logger with a meaningful category for objects that are intercepted.
Catalog
The catalog is consulted, if the CERNY.require statement refers to an expression that is not yet defined in the current JavaScript context. The catalog might provide a reference (URL) to a file holding the definition of the missing expression. Subsequently an attempt to load this file is made by CERNY.load. This mechanism frees the programmer of manually importing required scripts in a page (see Dependency management).
Interception
active
Holds an array of the active interceptors. It can only be filled in the function CERNY.configure, because the interceptors are not defined when reading the configuration file and thus cannot be referred to.

API Documentation for version