
conventions

main table is always lc(2nd class name).
that is, for My::Model, table is model, rel tables are model_somethingelse
or somethingelse_model

all referencing is declared in the main table, not _info table.

only name common to an object's table and table_info is 'id'.


an object contains or links to only one of another kind of object,
so use a simple list of the class name as key to a single class instance.

   # in init after constructor for "My::Class0" 
   # created using POOF::Data -->

   my $class3_link_id = $self->relates_1to1({ from => $self,
                                            
   $self->{linked_to} = { "My::Class1" => 
                            My::Class1::Shepherd::Staff->findOne({
                                                   field1 => $val1,
						   field2 => $val2   }),
                         "My::Class2" =>
			    My::Class2->new( $field1 => $val1,
			                     $field2 => $val2  ),

			 "My::Class3" => 
			    My::Class3->find1to1({ relation => $self }),

                       }

the first class anonymously uses the shepherd's staff, without the need
to summon a shepherd to find one sheep.  note that the shepherd's staff
must be defined in My::Class1::Shepherd::Staff as an object that simply
constructs itself as a POOF::Data::Shepherd at minimum for this to work.

class2's constructor may need these fields to do some kind of join.  

class3 link needs an id.



an object contains many of another kind of object,
referenced by field named by container object name . "_id".
Since many being managed, use a Data::Shepherd:

  $obj->{contains_many} = { "class1" => Data::Shepherd( herds => "class1" ),
                            "class2" => Data::Shepherd( herds => "class2" ) };

when a shepherd finds out it herds a particular class
(during constructor), it imports custom herd and search routines in
<that class>::Shepherd::Staff and <that class>::Shepherd::Sandals.

then $obj->{contains_many}->{class1} is the Shepherd, so

  $obj->{contains_many}->{class1}->GetAllByFields({
					$obj->class . "_id" => $obj->id })

  (i.e. 'whistle')

will populate $obj's shepherd for the contained object with
a herd of that object using a mass sql query for ids only.

  $obj->{contains_many}->{class1}->GetAllData([ ]);  # no fields specified

  (i.e. 'feed')

will do a mass SQL select of * (or specified fields) 
from Shepherd's herd class
where (same criteria as initial population query)



How the Shepherd implements the flock is internal.  The Shepherd
provides various routines like next, prev, super, sub, left, right based on
what structure is declared in the field structure of the object's table.

It might be a doubly-linked list or singly-linked list (as asked for),
if the object table has next_id and prev_id fields.  

It might be a
binary tree, if object table has left_id and right_id fields, and
would build in double-linking if it also has a super_id.  

With a super_id and a sub_id, it builds an n-ary tree, for example,
the Funk tree.  The main Funk object then has as many Shepherds
as there are root Funks, i.e. where super_id&&next_id&&prev_id=NULL.  
These Shepherds all maintain the trees underneath them.  But funk 
table also can contain a next_id and prev_id.  So, it loads prev
and next routines, and then an individual funk node can also have
a sequence of funks as a second dimension, i.e. a funk node is a
process that takes three funks.  I think it can just inherit 
subsequent libs that have prev/next or super/sub routines, layering
their functionality to become something new.  If a table has the
fields defined, load the routines; if an instance has fields not NULL,
allow the controls.  Like, in funk tree:  super_id, next_id, prev_id
are defined in table.  Root funks don't have any.  Category funks
have only super_id.  Process funk stem has super_id and next_id, 
but no prev_id.  Funks subsequent to a process funk stem have 
prev_id, but no next_id.  

My::SomeObj::Sandals contains any custom routines Shepherd needs 
to get data for a class.  My::SomeObj::Staff contains any custom
routines Shepherd needs to move an instance of My::SomeObj around
(for example, comparison routines against herds of My::AnotherObj.)
So, when developing a POOF flock (class), write in Sandals and 
Staff for the Shepherd, like $shep1->intersectOnCommonName( 
compare => $shep2 ) ... shep1 will compare $self->{herd} to 
$shep2->herd on a common attribute and return a new herd under
a new shepherd, but properly general routines like 'intersect' 
should make it to general Data::Shepherd.  

User's funk lib in user's choice namespace creates itself as a 
POOF::Funk and then contains one routine, "doit" or something,
plus menu printing routines that call POOF::App->something,
which is overridden by POOF::App::XML or POOF::App::HTML 
or POOF::App::Template as preferred.  

So My::Funk::ChargeCC_3->printresults assembles results and calls 
My::App->print with the output objects.  

There is a Funk in Funk tree with name ChargeCC_1 and the next_id
set to ChargeCC_2.  That means, if user selects ChargeCC_1,
action gets set to ChargeCC_2, which has prev_id set to ChargeCC_1.
That means ChargeCC_2 is a funk that processes form input.  
It also checks user auth against funk group ACL.  



If POOF::App::HTML, this assembles an output hash of the elements
expected by this funk (add these expected vals as columns in
funk_info which contain coderefs for anonymous subroutines that
take in objects or object herds as parameters and add the right 
value structure to the output hash, for example, takes an array 
and adds right structure of vars to set <select> <options> when
interpreted by HTML::Template.  Extracts the right values from
the input objects according to coderefs under columns in d.b.,
so they are called through standard object data_info routine.

If POOF::App::XML, calls object XML output methods for the
values it wants in the order it wants, formats output for other
formats of aggregate values like <ledger_total>, then outputs
with the appropriate XSLT parser for the App.  (Or it gets a 
custom XSLT parser for this funk?)

Similarly, you could have POOF::App::Term and POOF::App::NCurses.

Also, it needs POOF::Auth::WWW at least, and term interfaces would
want to develop POOF::Auth::Term.


This makes methods easy, where, say, a herd of Users has to be allotted
units of fixed supply, i.e. a herd of Goods({ type => 'typewriter' })
needs to be divvied up among a herd of Users({ department =>
'accounting' }), and comparisons or contests of herds have to be run
against each other.

# create a Shepherd to herd the Typewriters:
$goods_shep = new Shepherd( herds => "My::Goods" );

# Shepherd selects ids of all Goods in db where type = "typewriter"
# and foreach id creates an object that it adds to its herd.
$goods_shep->whistle( type => 'typewriter' );
$goods_shep->feed( weight, cost, supply );

$user_shep = new Shepherd( herds => "My::Users" );
$user_shep->whistle( department => 'accounting' );

$user_shep->distributeGoods( $goods_shep );

distributeGoods is imported by the Sheperd from My::User::Staff.
It calls $self->feed( rank, salary, productivity ) and then
distributes the herd of goods brought in by $goods_shep according
to some logic based on those values from database, and possibly
others called internally from My::User::Staff, like total_sales,
which would create a Ledger object and get a total of Sales.
These definitions are up to the programmer.  Because User is
also a POOF object, i.e. My::User creates itself as a POOF::User,
also some of these routines may make it into POOF::User::Staff
instead.

Any Shepherd of Funk knows that Funks herd together in
an n-ary tree with linked-list stems at nodes, because 
funk table structure defines super_id, next_id and prev_id 
but not sub_id.  sub_id isn't used for anything right now.

A Shepherd told to herd Funks brings in n-ary routines 
(super_id but not sub_id), and then brings in linked list
routines (next_id and prev_id).  Because it has both those
sets, Shepherd imports a routine to traverse them, which
always traverses this structure in a particular way.
From $shep->procreate({ root => $rootfunk }), Shep has no 
herd and so creates one with $rootfunk as the root or
ancestor.  If this funk has next_id but not prev_id, it
is a process stem.  For Shep, root node is head of tree,
and each node could also be the head of a linked list.

INCIDENTALLY, herd is a hash indexed by instance id (or array?).
Later, this could take the form of a custom header structure.

# for n-ary trees:
sub breed {
   my ($self,$stem) = @_;
   my $process = $stem;

   if ($self->{db}->table->fields->{super_id}) {
      # know it is a tree of some kind
   } elsif ($self->{db}->table->fields->{ {
      # it is a list if next_id and prev_id
   }

   if ($self->{db}->table->fields->{next_id}) {
   while ($next = $self->getOne({ prev_id => $process->id }) ) {
      $next->{prev} = $process;
      $process->{next} = $next;
      $process = $next;
   }
   foreach ($self->whistle({ super_id => $stem->id }) ) {
      $stem->{sub} = $_;
      $self->breed($_);
   }
}


