Provided by: libur-perl_0.440-1_all bug

NAME

       UR::Object - transactional, queryable, process-independent entities

SYNOPSIS

       Create a new object in the current context, and return it:

         $elmo = Acme::Puppet->create(
           name => 'Elmo',
           father => $ernie,
           mother => $bigbird,
           jobs => [$dance, $sing],
           favorite_color => 'red',
         );

       Plain accessors work in the typial fashion:

         $color = $elmo->favorite_color();

       Changes occur in a transaction in the current context:

         $elmo->favorite_color('blue');

       Non-scalar (has_many) properties have a variety of accessors:

         @jobs = $elmo->jobs();
         $jobs = $elmo->job_arrayref();
         $set  = $elmo->job_set();
         $iter = $elmo->job_iterator();
         $job  = $elmo->add_job($snore);
         $success = $elmo->remove_job($sing);

       Query the current context to find objects:

         $existing_obj  = Acme::Puppet->get(name => 'Elmo');
         # same reference as $existing_obj

         @existing_objs = Acme::Puppet->get(
           favorite_color => ['red','yellow'],
         );
         # this will not get elmo because his favorite color is now blue

         @existing_objs = Acme::Puppet->get(job => $snore);
         # this will return $elmo along with other puppets that snore,
         # though we haven't saved the change yet..

       Save our changes:

         UR::Context->current->commit;

       Too many puppets...:

         $elmo->delete;

         $elmo->play; # this will throw an exception now

         $elmo = Acme::Puppet->get(name => 'Elmo'); # this returns nothing now

       Just kidding:

         UR::Context->current->rollback; # not a database rollback, an in-memory undo

       All is well:

         $elmo = Acme::Puppet->get(name => 'Elmo'); # back again!

DESCRIPTION

       UR::Objects are transactional, queryable, representations of entities, built to maintain
       separation between the physical reference in a program, and the logical entity the
       reference represents, using a well-defined interface.

       UR uses that separation to automatically handle I/O.  It provides a query API, and manages
       the difference between the state of entities in the application, and their state in
       external persistance systems.  It aims to do so transparently, keeping I/O logic
       orthogonally to "business logic", and hopefully making code around I/O unnecessary to
       write at all for most programs.

       Rather than explicitly constructing and serializing/deserializing objects, the application
       layer just requests objects from the current "context", according to their
       characteristics.  The context manages database connections, object state changes,
       references, relationships, in-memory transactions, queries and caching in tunable ways.

       Accessors dynamically fabricate references lazily, as needed through the same query API,
       so objects work as the developer would traditionally expect in most cases.  The goal of
       UR::Object is that your application doesn't have to do data management.  Just ask for what
       you want, use it, and let it go.

       UR::Objects support full reflection and meta-programming.  Its meta-object layer is fully
       self-bootstrapping (most classes of which UR is composed are themselves UR::Objects), so
       the class data can introspect itself, such that even classes can be created within
       transactions and discarded.

INHERITANCE

         UR::ModuleBase    Basic error, warning, and status messages for modules in UR.
           UR::Object      This class - general OO transactional OO features

WRITING CLASSES

       See UR::Manual::Tutorial for a narrative explanation of how to write clases.

       For a complete reference see UR::Manual::WritingClasses.

       For the meta-object API see UR::Object::Type.

       A simple example, declaring the class used above:

         class Acme::Puppet {
             id_by => 'name',
             has_optional => [
                 father => { is => 'Acme::Puppet' },
                 mother => { is => 'Acme::Puppet' },
                 jobs   => { is => 'Acme::Job', is_many => 1 },
             ]
         };

       You can also declare the same API, but specifying additional internal details to make
       database mapping occur the way you'd like:

         class Acme::Puppet {
             id_by => 'name',
             has_optional => [
                 father => { is => 'Acme::Puppet', id_by => 'father_id' },
                 mother => { is => 'Acme::Puppet', id_by => 'mother_id' },
             },
             has_many_optional => [
                 job_assignments => { is => 'Acme::PuppetJob', im_its => 'puppet' },
                 jobs            => { is => 'Acme::Job', via => 'job_assignments', to => 'job'  },
             ]
         };

CONSTRUCTING OBJECTS

       New objects are returned by create() and get(), which delegate to the current context for
       all object construction.

       The create() method will always create something new or will return undef if the identity
       is already known to be in use.

       The get() method lets the context internally decide whether to return a cached reference
       for the specified logical entities or to construct new objects by loading data from the
       outside.

METHODS

       The examples below use $obj where an actual object reference is required, and SomeClass
       where the class name can be used.  In some cases the example in the synopsisis is
       continued for deeper illustration.

   Base API
       get
             $obj = SomeClass->get($id);
             $obj = SomeClass->get(property1 => value1, ...);
             @obj = SomeClass->get(property1 => value1, ...);
             @obj = SomeClass->get('property1 operator1' => value1, ...);

           Query the current context for objects.

           It turns the passed-in parameters into a UR::BoolExpr and returns all objects of the
           given class which match.  The current context determines whether the request can be
           fulfilled without external queries.  Data is loaded from underlying database(s) lazliy
           as needed to fulfuill the request.

           In the simplest case of requesting an object by id which is cached, the call to get()
           is an immediate hash lookup, and is very fast.

           See UR::Manual::Queries, or look at UR::Object::Set, UR::BoolExpr, and UR::Context for
           details.

           If called in scalar context and more than one object matches the given parameters,
           get() will raise an exception through "die".

       create
             $obj = SomeClass->create(
               property1 => $value1,
               properties2 => \@values2,
             );

           Create a new entity in the current context, and return a reference to it.

           The only required property to create an object is the "id", and that is only required
           for objects which do not autogenerate their own ids.  This requirement may be
           overridden in subclasses to be more restrictive.

           If entities of this type persist in an underlying context, the entity will not appear
           there until commit.  (i.e. no insert is done until just before a real database commit)
           The object in question does not need to pass its own constraints when initially
           created, but must be fully valid before the transaction which created it commits.

       delete
             $obj->delete

           Deletes an object in the current context.

           The $obj reference will be garbage collected at the discretion of the Perl interpreter
           as soon as possible.  Any attempt to use the reference after delete() is called will
           result in an exception.

           If the represented entity was loaded from the parent context (i.e. persistent database
           objects), it will not be deleted from that context (the database) until commit is
           called.  The commit call will do both the delete and the commit, presuming the
           complete save works across all involved data sources.

           Should the transaction roll-back, the deleted object will be re-created in the current
           context, and a fresh reference will later be returnable by get().  See the
           documentation on UR::Context for details on how deleted objects are rememberd and
           removed later from the database, and how deleted objects are re-constructed on STM
           rollback.

       copy
             $obj->copy(%overrides)

           Copies the existing $obj by copying the values of all direct properties, except for ID
           properties, to a newly created object of the same type.  A list of params and values
           may be provided as overrides to the existing values or to specify an ID.

       class
            $class_name = $obj->class;
            $class_name = SomeClass->class;

           Returns the name of the class of the object in question.  See __meta__ below for the
           class meta-object.

       id
            $id = $obj->id;

           The unique identifier of the object within its class.

           For database-tracked entities this is the primary key value, or a composite blob
           containing the primary key values for multi-column primary keys.

           For regular objects private to the process, the default id embeds the hostname,
           process ID, and a timestamp to uniquely identify the UR::Context::Process object which
           is its final home.

           When inheritance is involved beneath UR::Object, the 'id' may identify the object
           within the super-class as well.  It is also possible for an object to have a different
           id upon sub-classification.

   Accessors
       Every relationship declared in the class definition results in at least one accesor being
       generated for the class in question.

       Identity properties are read-only, while non-identity properties are read-write unless
       is_mutable is explicitly set to false.

       Assigning an invalid value is allowed temporarily, but the current transaction will be in
       an invalid state until corrected, and will not be commitable.

       The return value of an the accessor when it mutates the object is the value of the
       property after the mutation has occurred.

       Single-value property accessors:

       By default, properties are expected to return a single value.

       NAME
           Regular accessors have the same name as the property, as declared, and also work as
           mutators as is commonly expected:

             $value = $obj->property_name;
             $obj->property_name($new_value);

           When the property is declared with id_by instead of recording the refereince, it
           records the id of the object automatically, such that both will return different
           values after either changes.

       Muli-value property accessors:

       When a property is declared with the "is_many" flag, a variety of accessors are made
       available on the object.  See "UR::Manual::WritingClasses" for more details on the ways to
       declare relationships between objects when writing classes.

       Using the example from the synopsis:

       NAMEs (the property name pluralized)
           A "has_many" relationship is declared using the plural form of the relationship name.
           An accessor returning the list of property values is generated for the class.  It is
           usable with or without additional filters:

             @jobs = $elmo->jobs();
             @fun_jobs = $elmo->jobs(is_fun => 1);

           The singular name is used for the remainder of the accessors...

       NAME (the property name in singular form)
           Returns one item from the group, which must be specified in parameters.  If more than
           one item is matched, an exception is thrown via die():

            $job = $elmo->job(name => 'Sing');

            $job = $elmo->job(is_fun => 1);
            # die: too many things are fun for Elmo

       NAME_list
           The default accessor is available as *_list.  Usable with or without additional
           filters:

             @jobs = $elmo->job_list();
             @fun_jobs = $elmo_>job_list(is_fun => 1);

       NAME_set
           Return a UR::Object::Set value representing the values with *_set:

             $set  = $elmo->job_set();
             $set  = $elmo->job_set(is_hard => 1);

       NAME_iterator
           Create a new iterator for the set of property values with *_iterator:

             $iter = $elmo->job_iterator();
             $iter = $elmo->job_iterator(is_fun => 1, -order_by => ['name]);
             while($obj = $iter->next()) { ... }

       add_NAME
           Add an item to the set of values with add_*:

             $added  = $elmo->add_job($snore);

           A variation of the above will construt the item and add it at once.  This second form
           of add_* automatically would identify that the line items also reference the order,
           and establish the correct converse relationship automatically.

             @lines = $order->lines;
             # 2 lines, for instance

             $line = $order->add_line(
                product => $p,
                quantity => $q,
             );
             print $line->num;
             # 3, if the line item has a multi-column primary key with auto_increment on the 2nd column called num

       remove_NAME
           Items can be removed from the assigned group in a way symetrical with how they are
           added:

             $removed = $elmo->remove_job($sing);

   Extended API
       These methods are available on any class defined by UR.  They are convenience methods
       around UR::Context, UR::Object::Set, UR::BoolExpr, UR::Object::View, UR::Observer and
       Mock::Object.

       create_iterator
             $iter = SomeClass->create_iterator(
               property1 => $explicit_value,
               property2 => \@my_in_clause,
               'property3 like' => 'some_pattern_with_%_as_wildcard',
               'property4 between' => [$low,$high],
             );

             while (my $obj = $iter->next) {
               ...
             }

           Takes the same sort of parameters as get(), but returns a UR::Object::Iterator for the
           matching objects.

           The next() method will return one object from the resulting set each time it is
           called, and undef when the results have been exhausted.

           "UR::Object::Iterator" instances are normal object references in the current process,
           not context-oriented UR::Objects.  They vanish upon dereference, and cannot be
           retrieved by querying the context.

           When using an iterator, the system attempts to return objects matching the params at
           the time the iterator is created, even if those objects do not match the params at the
           time they are returned from next().  Consider this case:

             # many objects in the DB match this
             my $iter = SomeClass->create_iterator(job => 'cleaner');

             my $an_obj = SomeClass->get(job => 'cleaner', id => 1);
             $an_obj->job('messer-upper');    # This no longer matches the iterator's params

             my @iter_objs;
             while (my $o = $iter->next) {
                 push @iter_objs, $o;
             }

           At the end, @iter_objs will contain several objects, including the object with id 1,
           even though its job is no longer 'cleaner'.  However, if an object matching the
           iterator's params is deleted between the time the iterator is created and the time
           next() would return that object, then next() will throw an exception.

       define_set
            $set = SomeClass->define_set(
               property1 => $explicit_value,
               property2 => \@my_in_clause,
               'property3 like' => 'some_pattern_with_%_as_wildcard',
               'property4 between' => [$low,$high],
            );

            @subsets = $set->group_by('property3','property4');

            @some_members = $subsets[0]->members;

           Takes the same sort of parameters as get(), but returns a set object.

           Sets are lazy, and only query underlying databases as much as necessary.  At any point
           in time the members() method returns all matches to the specified parameters.

           See UR::Object::Set for details.

       define_boolexpr
            $bx = SomeClass->define_boolexpr(
               property1 => $explicit_value,
               property2 => \@my_in_clause,
               'property3 like' => 'some_pattern_with_%_as_wildcard',
               'property4 between' => [$low,$high],
            );

            $bx->evaluate($obj1); # true or false?

           Takes the same sort of parameters as get(), but returns a UR::BoolExpr object.

           The boolean expression can be used to evaluate other objects to see if they match the
           given condition.  The "id" of the object embeds the complete "where clause", and as a
           semi-human-readable blob, such is reconstitutable from it.

           See UR::BoolExpr for details on how to use this to do advanced work on defining sets,
           comparing objects, creating query templates, adding object constraints, etc.

       add_observer
            $o = $obj1->add_observer(
               aspect => 'someproperty'
               callback => sub { print "change!\n" },
            );

            $obj1->property1('new value');

            # observer callback fires....

            $o->delete;

           Adds an observer to an object, monitoring one or more of its properties for changes.

           The specified callback is fired upon property changes which match the observation
           request.

           See UR::Observer for details.

       create_mock
            $mock = SomeClass->create_mock(
               property1 => $value,
               method1 => $return_value,
            );

           Creates a mock object using using the class meta-data for "SomeClass" via
           Mock::Object.

           Useful for test cases.

   Meta API
       The folowing methods allow the application to interrogate UR for information about the
       object in question.

       __meta__
             $class_obj = $obj->__meta__();

           Returns the class metadata object for the given object's class.  Class objects are
           from the class UR::Object::Type, and hold information about the class' properties,
           data source, relationships to other classes, etc.

       __extend_namespace__
             package Foo::Bar;

             class Foo::Bar { has => ['stuff','things'] };

             sub __extend_namespace__ {
                my $class = shift;
                my $ext = shift;
                return class {$class . '::' . $ext} { has => ['more'] };
             }

           Dynamically generate new classes under a given namespace.  This is called
           automatically by UR::ModuleLoader when an unidentified class name is used.

           If Foo::Bar::Baz is not a UR class, and this occurs:

             Foo::Bar::Baz->some_method()

           This is called:

             Foo::Bar->__extend_namespace__("Baz")

           If it returns a new class meta, the code will proceed on as though the class had
           always existed.

           If Foo::Bar does not exist, the above will be called recursively:

             Foo->__extend_namespace__("Bar")

           If Foo::Bar, whether loaded or generated, cannot extend itself for "Baz", the loader
           will go up the tree before giving up.  This means a top-level module could dynamically
           define classes for any given class name used under it:

             Foo->__extend_namespace__("Bar::Baz")

       __errors__
             @tags = $obj->__errors__()

           Return a list of UR::Object::Tag values describing the issues which would prevent a
           commit in the current transaction.

           The base implementation check the validity of an object by applying any constraints
           layed out in the class such as making sure any non-optional properties contain values,
           numeric properties contain numeric data, and properties with enumerated values only
           contain valid values.

           Sub-classes can override this method to add additional validity checking.

       __display_name__
            $text = $obj->__display_name__;
            # the class and id of $obj, by default

            $text = $line_item->__display_name__($order);

           Stringifies an object.  Some classes may choose to actually overload the
           stringification operator with this method.  Even if they do not, this method will
           still attempt to identify this object in text form.  The default returns the class
           name and id value of the object within a string.

           It can be overridden to do a more nuanced job.  The class might also choose to
           overload the stringification operator itself with this method, but even if it doesn
           not the system will presume this method can be called directly on an object for
           reasonable stringificaiton.

       __context__
            $c = $self->__context__;

           Return the UR::Context for the object reference in question.

           In UR, a "context" handles connextions between objects, instead of relying on having
           objects directly reference each other.  This allows an object to have a relationship
           with a large number of other logical entities, without having a "physical" reference
           present within the process in question.

           All attempts to resolve non-primitive attribute access go through the context.

   Extension API
       These methods are primarily of interest for debugging, for test cases, and internal UR
       development.

       They are likely to change before the 1.0 release.

       __signal_change__
           Called by all mutators to tell the current context about a state change.

       __changes__
             @tags = $obj->__changes__()

             @tags = $obj->__changes__('prop1', 'prop2', ...)

           Return a list of changes present on the object _directly_.  This is really only useful
           internally because the boundary of the object is internal/subjective.  Callers may
           also request only changes to particular properties.

           Changes to objects' properties are tracked by the system.  If an object has been
           changed since it was defined or loaded from its external data source, then changed()
           will return a list of UR::Object::Tag objects describing which properties have been
           changed.

           Work is in-progress on an API to request the portion of the changes in effect in the
           current transaction which would impact the return value of a given list of properties.
           This would be directly usable by a view/observer.

       __define__
           This is used internally to "virtually load" things.  Simply assert they already
           existed externally, and act as though they were just loaded...  It is used for classes
           defined in the source code (which is the default) by the "class {}" magic instead of
           in some database, as we'd do for regular objects.

       __strengthen__
             $obj->__strengthen__();

           Mark this object as unloadable by the object cache pruner.

           UR objects are normally tracked by the current Context for the life of the
           application, but the programmer can specify a limit to cache size, in which case old,
           unchanged objects are periodically pruned from the cache.  If strengthen() is called
           on an object, it will effectively be locked in the cache, and will not be considered
           for pruning.

           See UR::Context for more information about the pruning mechanism.

       is_strengthened
           Check if an object has been stengthened, "__stengthen__".

       __weaken__
             $obj->__weaken__();

           Give a hint to the object cache pruner that this instance is not going to be used in
           the application in the future, and should be removed with preference when pruning the
           cache.

       is_weakened
           Check if an object has been weakened, "__weaken__".

       DESTROY
           Perl calls this method on any object before garbage collecting it.  It should never by
           called by your application explicitly.

           The DESTROY handler is overridden in UR::Object.  If you override it in a subclass, be
           sure to call $self->SUPER::DESTROY() before exiting your override, or errors will
           occur.

ERRORS, WARNINGS and STATUS MESSAGES

       When an error occurs which is "exceptional" the API will throw an exception via die().

       In some cases, when the possibility of failure is "not-exceptional", the method will
       simply return false.  In scalar context this will be undef.  In list context an empty
       list.

       When there is ambiguity as to whether this is an error or not (get() for instance, might
       simply match zero items, ...or fail to understand your parameters), an exception is used.

       error_message
           The standard way to convey the error which has occurred is to set ->error_message() on
           the object.  This will propagate to the class, and through its inheritance.  This is
           much like DBI's errstr method, which affects the handle on which it was called, its
           source handle, and the DBI package itself.

       warning_message
           Calls to warning_message also record themselves on the object in question, and its
           class(es).

           They also emit a standard Perl warn(), which will invoke $SIG{__WARN__};

       status_message
           Calls to status_message are also recorded on the object in question.  They can be
           monitored through hooks, as can the other messages.

       See UR::ModuleBase for more information.

SEE ALSO

       UR, UR::Object::Type, UR::Context

       UR::Maual::Tutorial, UR::Manual::WritingClasses, UR::Manual::Queries,
       UR::Manual::Transactions

       UR::ObjectDeprecated contains additional methods which are deprecated in the API.