The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Rosetta::Model - Abstract syntax tree for the Rosetta D language

VERSION

This document describes Rosetta::Model version 0.724.1.

It also describes the same-number versions of Rosetta::Model::Document ("Document") and Rosetta::Model::Node ("Node").

Note that the "Rosetta::Model" package serves only as the name-sake representative for this whole file, which can be referenced as a unit by documentation or 'use' statements or Perl archive indexes. Aside from 'use' statements, you should never refer directly to "Rosetta::Model" in your code; instead refer to other above-named packages in this file.

SYNOPSIS

This documentation is pending.

DESCRIPTION

This documentation is pending.

INTERFACE

The interface of Rosetta::Model is entirely object-oriented; you use it by creating objects from its member classes, usually invoking new() on the appropriate class name, and then invoking methods on those objects. All of their attributes are private, so you must use accessor methods. Rosetta::Model does not declare any subroutines or export such.

The usual way that Rosetta::Model indicates a failure is to throw an exception; most often this is due to invalid input. If an invoked routine simply returns, you can assume that it has succeeded, even if the return value is undefined.

Rosetta::Model's input validation is performed over 2 main phases, which are referred to as "immediate" and "deferred". The immediate validations are performed at the moment the user tries to set the input, and input that fails immediate evaluation will not be set at all. The scope of immediate validation is kept to the minimum possible, and is essentially just concerned with the well-formedness of the input, such as that mandatory constructor arguments are provided and that they are of the correct container type (eg, hash vs array). The deferred validations are performed on demand at some time after the input has been set, and could potentially never be performed at all. They validate everything except well-formedness, such as that Rosetta::Model Nodes are arranged correctly depending on their types, that their attributes have reasonable values, and that attributes or Nodes are not missing. The deferred validations, which can be arbitrarily complex, make up the bulk of the Rosetta::Model code, and these could potentially be extended by third party add-ons.

The Rosetta::Model::Document Class

A Document object is a simple container which stores data to be used or displayed by your program. It is analagous to a simplified version of the "Document" interface defined in the XML DOM spec; it exists as a container in which Node objects live. The Document class is pure and deterministic, such that all of its class and object methods will each return the same result and/or make the same change to an object when the permutation of its arguments and any invocant object's attributes is identical; they do not interact with the outside environment at all.

A Document object has 2 main attributes:

@!all_nodes - All Nodes

Array of Rosetta::Model::Node - This stores a collection of Node objects, which are all of the Nodes that live in this Document.

@!root_nodes - Root Nodes

Array of Rosetta::Model::Node - This stores an ordered list of all this Document's Node objects that do not have parent Nodes of their own; it is a sub-set of All Nodes.

This is the main Document constructor method:

new( :@root_nodes? )

This method creates and returns a new Rosetta::Model::Document object. If the optional named parameter @root_nodes is set, then each element in it is used to initialize a new Node object (plus an optional hierarchy of new child Nodes of that new Node) that gets stored in the Root Nodes attribute (that attribute defaults to empty if the parameter's corresponding argument is undefined). The new Document object's All Nodes attribute starts out empty, but gains one element for each Node in the Node hierarchies created from a defined @root_nodes.

Some sample usage:

    my Rosetta::Model::Document $document .= new();

    my Rosetta::Model::Document $document2 .= new(
        root_nodes => [
            {
                'node_type'  => 'data_sub_type',
                'attributes' => { 'predef_base_type' => 'BOOLEAN' },
            },
        ],
    );

A Document object has these methods:

export_as_hash()

This method returns a deep copy of all of this Document's member Nodes as a tree of primitive Perl data structures (hash refs, array refs, scalars), which is suitable as a generic data interchange format between Rosetta::Model and other Perl code such as persistence solutions. Moreover, these data structures are in exactly the right input format for Document.new(), by which you can create an identical Document (with member Nodes) to the one you first invoked export_as_hash() on.

Specifically, export_as_hash() returns a Perl hash whose key list ('root_nodes') corresponds exactly to the named parameters of Document.new(); you can produce a direct clone like this:

    my $cloned_doc = Rosetta::Model::Document.new(
        |%($original_doc.export_as_hash()) );

Or, to demonstrate the use of a persistence solution:

    # When saving.
    my $hash_to_save = $original_doc.export_as_hash();
    MyPersist.put( $hash_to_save );

    # When restoring.
    my $hash_was_saved = MyPersist.get();
    my $cloned_doc = Rosetta::Model::Document.new( |%($hash_was_saved) );

The Rosetta::Model::Node Class

A Node object is a simple container which stores data to be used or displayed by your program. It is analagous to a simplified version of the "Node" interface defined in the XML DOM spec; it has a type (what the XML spec calls 'name') and attributes, and is arranged in a hierarchy with other Nodes (it does not support any analogy of CDATA sections, though). The Node class is pure and deterministic, such that all of its class and object methods will each return the same result and/or make the same change to an object when the permutation of its arguments and any invocant object's attributes is identical; they do not interact with the outside environment at all.

A Node object has 5 main attributes:

$!document - Document

Rosetta::Model::Document - This stores a reference to the Document that this Node and all of its relative Nodes live in.

$!parent_node - Parent Node

Rosetta::Model::Node - This stores a reference to this Node's parent Node, if it has one. Nodes that do not have this attribute set are considered "root Nodes" and are listed in their Document's Root Nodes property; in a manner of speaking, the Document itself is the parent of such Nodes.

$!node_type - Node Type

Str - This string identifies what kind of Node this is, and by extension what kinds of attributes or relative Nodes it can have, as well as where and how the Node can be used.

%!attributes - Attributes

Hash(Str) of Any - This contains zero or more attribute names and values that help to define this Node.

@!child_nodes - Child Nodes

Array of Rosetta::Model::Node - This stores an ordered list of all this Node's child Nodes, if it has any.

This is the main Node constructor method:

new( :$document!, :$parent_node?, :$node_type!, :%attributes?, :@child_nodes? )

This method creates and returns a new Rosetta::Model::Node object, that lives in the Document object given in the named parameter $document, and whose Node Type attribute is set from the named parameter $node_type (a string); the optional named parameter %attributes sets the "Attributes" attribute if provided (it defaults to empty if the parameter's corresponding argument is not provided). If the optional named parameter $parent_node (a Node) is set, then the new Node's "Parent Node" attribute is set to it, and the new Node is also stored in $parent_node's Child Nodes attribute; if $parent_node is not set, then the new Node is instead stored in its Document's "Root Nodes" attribute. If the optional named parameter @child_nodes is set, then each element in it is used to initialize a new Node object (plus an optional hierarchy of new child Nodes of that new Node) that gets stored in the Child Nodes attribute (that attribute defaults to empty if the corresponding argument is undefined).

Some sample usage:

    # Declare a unsigned 32-bit integer data type.
    my Rosetta::Model::Node $dt_uint32 .= new(
        node_type  => 'data_sub_type',
        attributes => {
            'predef_base_type' => 'NUMERIC',
            'num_precision'    => 2**32,
            'num_scale'        => 1,
            'num_min_value'    => 0,
        },
    );

    # Declare an enumerated ('F','M') character value data type.
    my Rosetta::Model::Node $dt_sex .= new(
        node_type   => 'data_sub_type',
        attributes  => {
            'predef_base_type' => 'CHAR_STR',
            'char_max_length'  => 1,
            'char_repertoire'  => 'UNICODE',
        },
        child_nodes => [
            {
                'node_type'  => 'data_sub_type_value',
                'attributes' => { 'value' => 'F' },
            },
            {
                'node_type'  => 'data_sub_type_value',
                'attributes' => { 'value' => 'M' },
            },
        ],
    );

A Node object has these methods:

export_as_hash()

This method returns a deep copy of this Node plus all of its descendent Nodes (if any) as a tree of primitive Perl data structures (hash refs, array refs, scalars), which is suitable as a generic data interchange format between Rosetta::Model and other Perl code such as persistence solutions. Moreover, these data structures are in exactly the right input format for Node.new(), by which you can create an identical Node (with child Nodes) to the one you first invoked export_as_hash() on.

Specifically, export_as_hash() returns a Perl hash whose key list ('node_type', 'attributes', 'child_nodes') corresponds exactly to the named parameters of Node.new(); you need to supply its $document and optional $parent_node though; you can produce a direct clone like this:

    my $cloned_node = Rosetta::Model::Document.new(
        document => $document, |%($original_node.export_as_hash()) );

Or, to demonstrate the use of a persistence solution:

    # When saving.
    my $hash_to_save = $original_node.export_as_hash();
    MyPersist.put( $hash_to_save );

    # When restoring.
    my $hash_was_saved = MyPersist.get();
    my $cloned_node = Rosetta::Model::Document.new(
        document => $document, |%($hash_was_saved) );

DIAGNOSTICS

This documentation is pending.

CONFIGURATION AND ENVIRONMENT

This documentation is pending.

DEPENDENCIES

This file requires any version of Perl 6.x.y that is at least 6.0.0.

It also requires these Perl 6 classes that are on CPAN: Locale::KeyedText-(1.72.0...) (for error messages).

INCOMPATIBILITIES

None reported.

SEE ALSO

Go to Rosetta for the majority of distribution-internal references, and Rosetta::SeeAlso for the majority of distribution-external references.

BUGS AND LIMITATIONS

This documentation is pending.

AUTHOR

Darren R. Duncan (perl@DarrenDuncan.net)

LICENCE AND COPYRIGHT

This file is part of the Rosetta DBMS framework.

Rosetta is Copyright (c) 2002-2006, Darren R. Duncan.

See the LICENCE AND COPYRIGHT of Rosetta for details.

ACKNOWLEDGEMENTS

The ACKNOWLEDGEMENTS in Rosetta apply to this file too.