The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Repository::Simple::Engine - Abstract base class for storage engines

DESCRIPTION

This documentation is meant for developers wishing to implement a content repository engine. If you just want to know how to use the repository API, Repository::Simple is where you'll want to go.

A developer may extend this class to provide a new storage engine. Each engine is simply an implementation of the bridge API specified here and requires only a single package.

To implement a content repository engine, create a subclass of Repository::Simple::Engine that implements all the methods described in this documentation.

  package Repository::Simple::Engine::MyCustom;

  use strict;
  use warnings;

  use base qw( Repository::Simple::Engine );

  sub new { ... }
  sub node_type_named { ... }
  sub property_type_named { ... }
  sub path_exists { ... }
  sub node_type_of { ... }
  sub property_type_of { ... }
  sub nodes_in { ... }
  sub properties_in { ... }
  sub get_scalar { ... }
  sub set_scalar { ... }
  sub get_handle { ... }
  sub set_handle { ... }
  sub namespaces { ... }
  sub has_permission { ... }

METHODS

Every storage engine must implement the following methods:

$engine = Repository::Simple::Engine->new(@args)

This method constructs an instance of the engine. The arguments can be anything you want. The attach() method of Repository::Simple will pass the arguments directly to the new method upon creation. I.e.,

  my $repository = Repository::Simple->attach(
      MyEngine => qw( a b c )
  );

would effectively call:

  Repository::Simple::Engine::MyEngine->new('a', 'b', 'c');

This interface doesn't define anything specific regarding these arguments.

This method must return an instance of the storage engine upon which all the other methods may be called.

A basic default implementation is provided that simply treats all arguments given as a hash and blesses that hash into the class. Therefore, you can use the built-in implementation like this:

  sub new {
      my ($class, $some_arg) = @_;
      
      # Do some manipulations on $some_arg...

      my $self = $class->SUPER::new( some_arg => $some_arg );

      # Do some manipulations on $self
      
      return $self;
  }
$exists = $engine->path_exists($path)

Returns information regarding whether a given path refers to a node, a property, or nothing. The method must return one of the following values:

$NOT_EXISTS

There is no node or property at the given path, $path.

$NODE_EXISTS

There is a node at the given path, $path.

$PROPERTY_EXISTS

There is a property at the given path, $path.

These can be imported from the Repository::Simple::Engine package:

  use Repository::Simple::Engine qw( 
      $NOT_EXISTS $NODE_EXISTS $PROPERTY_EXISTS 
  );

  # OR
  use Repository::Simple::Engine qw( :exists_constants );

This method must be implemented by subclasses. No implementation is provided.

$node_type = $engine->node_type_named($name)

Given a node type name, this method returns an instance of Repository::Simple::Type::Node for the matching node type or undef if no node type by the given name exists.

This method must be implemented by subclasses. No implementation is provided.

$property_type = $engine->property_type_named($name)

Given a property type name, this method returns an instance of Repository::Simple::Type::Property for the matching property type or undef if no property type by the given name exists.

This method must be implemented by subclasses. No implementation is provided.

@names = $engine->nodes_in($path)

Given a path, this method should return all the child nodes of that path or an empty list if the node found has no children. If the given path itself does not exist, the method must die.

The nodes should be returned as names relative to the given path.

This method must be implemented by subclasses. No implementation is provided.

@names = $engine->properties_in($path)

Given a path, this method should return all the child properties of the node at the given path or an empty list if the node found has no children. If the given path itself does not exist or does not refer to a node, the method must die.

Properties must be returned as names relative to the given path.

This method must be implemented by subclasses. No implementation is provided.

$node_type = $engine->node_type_of($path)

Given a path, this method should return the Repository::Simple::Type::Node object for the node at that path. If there is no node at that path, then the method must die.

This method must be implemented by subclasses. No implementation is provided.

$property_type = $engine->property_type_of($path)

Return the property type of the given class via a Repository::Simple::Type::Property instance. If there is no property at that path, then the method must die.

This method must be implemented by subclasses. No implementation is provided.

$scalar = $engine->get_scalar($path)

Return the value of the property at the given path as a scalar value.

This method must be implemented by subclasses. No implementation is provided.

$engine->set_scalar($path, $value)

Set the value stored the property at $path to the scalar value $scalar.

This method is optional. If your engine does not support writes, then it does not need to define this method.

See save_property() for information on how these changes are actually committed.

$handle = $engine->get_handle($path, $mode)

Return the value of the property at the given path as an IO handle, with the given mode, $mode. The $mode must be one of:

  • "<"

  • ">"

  • ">>"

  • "+<"

  • "+>"

  • "+>>"

These have the same meaning as the Perl open() built-in (i.e., read, write, append, read-write, write-read, append-read).

This method must be implemented by subclasses. No implementation is provided.

An implementation must support reading properties by handle for all properties, but is not required to implement write or append handles. If writes or appends are not available, the method must throw an exception when an unsupported file handle type is requested.

The user is required not to call close on any file handle returned via this method, but might do so anyway. The result of such behavior is undefined. It is suggested that the engine should make sure any returned file handles are closed when the appropriate save handle is called.

Whether or not writes/appends are supported does not affect whether or not set_handle() is supported.

See save_property() for information on how these changes are actually committed.

$engine->set_handle($path, $handle)

This method allows the user to set a value using a custom file handle. This file handle must be a read-handle ready to read immediately using the readline or read. This specification recommends the use of File::Temp or IO::Scalar for creating these file handles.

This operation is optional and does not need to be implemented if the engine does not handle write operations. Whether this method is implemented does not affect whether or not get_handle() supports writes/appends.

See save_property() for information on how these changes are actually committed.

$namespaces = $engine->namespaces

This method returns a reference to a hash of all the namespaces the storage engine currently supports. The keys are the prefixes and the values are URLs.

$test = $engine->has_permission($path, $action)

Tests to see if the current engine session has permission to perform the given action, $action, on path, $path. This method should return a true value if permissions would allow the action to proceed. Return false if the action would fail. The repository will attempt to guarantee that this method will not be called when it is not applicable.

The $action is one of the constants described under check_permission() in the documentation for Repository::Simple.

$engine->save_property($path)

This method is responsible for committing changes made by set_scalar(), get_handle() (using a write or append file handle), and set_handle(). If any of these methods are implemented, this method must also be implemented.

Changes made by one of the mutator methods must be set on the property given path, $path, by the time save_property() returns. However, the changes may be committed sooner.

The implementation of this method is optional, but required if any of set_scalar(), writes/appends via get_handle(), or set_handle() are implemented.

SEE ALSO

Repository::Simple

AUTHOR

Andrew Sterling Hanenkamp, <hanenkamp@cpan.org>

LICENSE AND COPYRIGHT

Copyright 2006 Andrew Sterling Hanenkamp <hanenkamp@cpan.org>. All Rights Reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.

This program 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.