Config::Model(3pm)

NAME
Config::Model - Framework to create configuration validation tools and editors

SYNOPSIS
 # create new Model object
 my $model = Config::Model->new() ;

 # create config model
 $model ->create_config_class
  (
   name => "SomeRootClass",
   element => [ ...  ]
  ) ;

 # create instance
 my $instance = $model->instance (root_class_name => 'SomeRootClass',
                                  instance_name => 'test1');

 # get configuration tree root
 my $cfg_root = $instance -> config_root ;

 # You can also use load on demand
 my $model = Config::Model->new() ;

 # this call will look for a AnotherClass.pl that will contain
 # the model
 my $inst2 = $model->instance (root_class_name => 'AnotherClass',
                              instance_name => 'test2');

 # then get configuration tree root
 my $cfg_root = $inst2 -> config_root ;

DESCRIPTION
Using Config::Model, a typical configuration validation tool will be made of 3 parts :

1.  A reader and writer that will parse the configuration file and transform in a tree representation within Config::Model. The values contained in this configuration tree can be written back in the configuraiton file(s).

2.  A validation engine which is in charge of validating the content and structure of configuration stored in the configuration tree. This validation engine will follow the structure and constraint declared in a configuration model. This model is a kind of schema for the configuration tree.

3.  A user interface to modify the content of the configuration tree. A modification will be validated instantly by the validation engine.

Storage backend, configuration reader and writer
See Config::Model::AutoRead for details

Validation engine
"Config::Model" provides a way to get a validation engine from a set of rules. This set of rules is called the configuration model.

User interface
The user interface will use some parts of the API to set and get configuration values. More importantly, a generic user interface will need to explore the configuration model to be able to generate at run-time relevant configuration screens.

Simple text interface if provided in this module. Curses and Tk interfaces are provided by Config::Model::CursesUI and Config::Model::TkUI.

Constructor
Simply call new without parameters:

 my $model = Config::Model -> new ;

This will create an empty shell for your model.

Configuration Model
To validate a configuration tree, we must create a configuration model that will set all the properties of the validation engine you want to create.

The configuration model is expressed in a declarative form (i.e. a Perl data structure which is always easier to maintain than a lot of code)

Each configuration class contains a set of:

•   node element that will refer to another configuration class

•   value element that will contains actual configuration data

•   List or hash of node or value elements

By declaring a set of configuration classes and refering them in node element, you will shape the structure of your configuration tree.

The structure of the configuration data must be based on a tree structure. This structure has several advantages:

•   Unique path to get to a node or a leaf.

•   Simpler exploration and query

•   Simple hierarchy. Deletion of configuration items is simpler to grasp: when you cut a branch, all the leaves attaches to that branch go down.

But using a tree has also some drawbacks:

•   A complex configuration cannot be mapped on a simple tree. Some more relation between nodes and leaves must be added.

•   Some configuration part are actually graph instead of a tree (for instance, any configuration that will map a service to a resource). The graph relation must be decomposed in a tree with special reference relation. See "Value Reference" in Config::Model::Value

Note: a configuration tree is a tree of objects. The model is declared with classes. The classes themselves have relations that closely match the relation of the object of the configuration tree. But the class need not to be declared in a tree structure (always better to reuse classes). But they must be declared as a DAG (directed acyclic graph).

Each configuration class declaration specifies:

•   The "name" of the class (mandatory)

•   A "class_description" used in user interfaces (optional)

•   Optional include specification to avoid duplicate declaration of elements.

•   The class elements

Each element will specify:

8   Most importantly, the type of the element (mostly "leaf", or "node")

*   The properties of each element (boundaries, check, integer or string, enum like type ...)

*   The default values of parameters (if any)

*   Whether the parameter is mandatory

*   Targeted audience (beginner, advance, master), i.e. the level of expertise required to tinker a parameter (to hide expert parameters from newbie eyes)

*   On-line help (for each parameter or value of parameter)

See Config::Model::Node for details on how to declare a configuration class.

Example:

 $ cat lib/Config/Model/models/Xorg.pl
 [
   {
     name => 'Xorg',
     class_description => 'Top level Xorg configuration.',
     include => [ 'Xorg::ConfigDir'],
     element => [
                 Files => {
                           type => 'node',
                           description => 'File pathnames',
                           config_class_name => 'Xorg::Files'
                          },
                 # snip
                ]
   },
   {
     name => 'Xorg::DRI',
     element => [
                 Mode => {
                          type => 'leaf',
                          value_type => 'uniline',
                          description => 'DRI mode, usually set to 0666'
                         }
                ]
   }
 ];

Configuration instance
A configuration instance if the staring point of a configuration tree. When creating a model instance, you must specify the root class name, I.e. the configuration class that is used by the root node of the tree.

 my $model = Config::Model->new() ;
 $model ->create_config_class
  (
   name => "SomeRootClass",
   element => [ ...  ]
  ) ;

 # instance name is 'default'
 my $inst = $model->instance (root_class_name => 'SomeRootClass');

You can create several separated instances from a model using "name" option:

 # instance name is 'default'
 my $inst = $model->instance (root_class_name => 'SomeRootClass',
                              name            => 'test1');

Usually, model files will be loaded automatically depending on "root_class_name". But you can choose to specify the file containing the model with "model_file" parameter. This is mostly useful for tests.

Configuration class
A configuration class is made of series of elements which are detailed in Config::Model::Node.

Whatever its type (node, leaf,... ), each element of a node has several other properties:

experience
    By using the "experience" parameter, you can change the experience level of each element. Possible experience levels are "master", "advanced" and "beginner" (default).

level
    Level is "important", "normal" or "hidden".

    The level is used to set how configuration data is presented to the user in browsing mode. "Important" elements will be shown to the user no matter what. "hidden" elements will be explained with the warp notion.

status
    Status is "obsolete", "deprecated" or "standard" (default).

    Using a deprecated element will issue a warning. Using an obsolete element will raise an exception.

description
    Description of the element. This description will be used when generating user interfaces.

summary
    Summary of the element. This description will be used when generating user interfaces and may be used in comments when writing the configuration file.

class_description
    Description of the configuration class. This description will be used when generating user interfaces.

generated_by
    Mention with a descriptive string if this class was generated by a program. This parameter is currently reserved for Config::Model::Itself model editor.

include
    Include element description from another class.

      include => 'AnotherClass' ,

    or

      include => [qw/ClassOne ClassTwo/]

    In a configuration class, the order of the element is important. For instance if "foo" is warped by "bar", you must declare "bar" element before "foo".

    When including another class, you may wish to insert the included elements after a specific element of your including class:

      # say AnotherClass contains element xyz
      include => 'AnotherClass' ,
      include_after => "foo" ,
      element => [ bar => ... , foo => ... , baz => ... ]

    Now the element of your class will be:

      ( bar , foo , xyz , baz )

Example:

  my $model = Config::Model -> new ;

  $model->create_config_class
  (
   config_class_name => 'SomeRootClass',
   experience        => [ [ qw/tree_macro warp/ ] => 'advanced'] ,
   description       => [ X => 'X-ray' ],
   level             => [ 'tree_macro' => 'important' ] ,
   class_description => "SomeRootClass description",
   element           => [ ... ]
  ) ;

Again, see Config::Model::Node for more details on configuration class declaration.

For convenience, "experience", "level" and "description" parameters can also be declared within the element declaration:

  $model->create_config_class
  (
   config_class_name => 'SomeRootClass',
   class_description => "SomeRootClass description",
   'element'
   => [
        tree_macro => { level => 'important',
                        experience => 'advanced',
                      },
        warp       => { experience => 'advanced', } ,
        X          => { description => 'X-ray', } ,
      ]
  ) ;

Load pre-declared model
You can also load pre-declared model.

  load( <model_name> )
This method will open the model directory and execute a ".pl" file containing the model declaration,

This perl file must return an array ref to declare models. E.g.:

 [
  [
   name => 'Class_1',
   element => [ ... ]
  ],
  [
   name => 'Class_2',
   element => [ ... ]
  ]
 ];

do not put "1;" at the end or "load" will not work

If a model name contain a "::" (e.g "Foo::Bar"), "load" will look for a file named "Foo/Bar.pl".

Returns a list containining the names of the loaded classes. For instance, if "Foo/Bar.pl" contains a model for "Foo::Bar" and "Foo::Bar2", "load" will return "( 'Foo::Bar' , 'Foo::Bar2' )".

Model query

  get_model( config_class_name )
Return a hash containing the model declaration.

  get_element_model( config_class_name , element)
Return a hash containing the model declaration for the specified class and element.

  get_element_name( class => Foo, for => advanced )
Get all names of the elements of class "Foo" that are accessible for experience level "advanced".

Level can be "master" (default), "advanced" or "beginner".

  list_class_element
Returns a string listing all the class and elements. Useful for debugging your configuration model.

Error handling
Errors are handled with an exception mechanism (See Exception::Class).

When a strongly typed Value object gets an authorized value, it raises an exception. If this exception is not catched, the programs exits.

See Config::Model::Exception for details on the various exception classes provided with "Config::Model".

Log and Traces
Currently a rather lame trace mechanism is provided:

•   Set $::debug to 1 to get debug messages on STDOUT.

•   Set $::verbose to 1 to get verbose messages on STDOUT.

Depending on available time, a better log/error system may be implemented.

AUTHOR
Dominique Dumont, (ddumont at cpan dot org)

LICENSE
    Copyright (c) 2005-2010 Dominique Dumont.

    This file is part of Config-Model.

    Config-Model is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser Public License as
    published by the Free Software Foundation; either version 2.1 of
    the License, or (at your option) any later version.

    Config-Model 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
    Lesser Public License for more details.

    You should have received a copy of the GNU Lesser Public License
    along with Config-Model; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
    02110-1301 USA

SEE ALSO
Config::Model::Instance,

http://sourceforge.net/apps/mediawiki/config-model/index.php?title=Creating_a_model

  Model elements
The arrow shows the inheritance of the classes

•   Config::Model::Node <- Config::Model::AutoRead <- Config::Model::AnyThing

•   Config::Model::HashId <- Config::Model::AnyId <- Config::Model::WarpedThing <- Config::Model::AnyThing

•   Config::Model::ListId <- Config::Model::AnyId <- Config::Model::WarpedThing <- Config::Model::AnyThing

•   Config::Model::Value <- Config::Model::WarpedThing <- Config::Model::AnyThing

•   Config::Model::CheckList <- Config::Model::WarpedThing <- Config::Model::AnyThing

•   Config::Model::WarpedNode <- Config::Model::WarpedThing <- Config::Model::AnyThing

  command line
config-edit

  Read and write backends

•   Config::Model::Backend::IniFile <- Config::Model::Backend::Any

•   Config::Model::Backend::ShellVar <- Config::Model::Backend::Any

•   Config::Model::Backend::Yaml <- Config::Model::Backend::Any

  Model utilities

•   Config::Model::Annotation

•   Config::Model::Describe

•   Config::Model::Dumper

•   Config::Model::DumpAsData

•   Config::Model::Loader

•   Config::Model::ObjTreeScanner

•   Config::Model::Report

•   Config::Model::Searcher

•   Config::Model::TermUI

•   Config::Model::WizardHelper

•   Config::Model::AutoRead

•   Config::Model::ValueComputer