Boulder

 view release on metacpan or  search on metacpan

Stone.pm  view on Meta::CPAN

 # insert a tag/value pair
 $stone->insert(Martha => { First_name => 'Martha', Last_name => 'Steward'} );

 # find the first Address
 $stone->search('Address'); 

 # change an existing subtree
 $martha = $stone->Martha;
 $martha->replace(Last_name => 'Stewart');  # replace a value

 # iterate over the tree with a cursor
 $cursor = $stone->cursor;
 while (my ($key,$value) = $cursor->each) {
   print "$value: Go Bluejays!\n" if $key eq 'State' and $value eq 'Katonah';
 }

 # various format conversions
 print $stone->asTable;
 print $stone->asString;
 print $stone->asHTML;
 print $stone->asXML('Person');

=head1 DESCRIPTION

Stone.pm  view on Meta::CPAN

	person[0].name[0]=Fred
	person[0].pets[0]=Fido
	person[0].pets[1]=Rex
	person[0].pets[2]=Lassie
	person[0].age[0]=30
	person[1].name[0]=Harry
	person[1].pets[0]=Rover
	person[1].pets[1]=Spot
	person[1].age[0]=23

=head2 $cursor = $stone->cursor()

Retrieves an iterator over the object.  You can call this several
times in order to return independent iterators. The following brief
example is described in more detail in L<Stone::Cursor>.

 my $curs = $stone->cursor;
 while (my($tag,$value) = $curs->next_pair) {
   print "$tag => $value\n";
 }
 # yields:
   Sally[0].Address[0].Zip[0] => 10578
   Sally[0].Address[0].City[0] => Katonah
   Sally[0].Address[0].Street[0] => Hickory Street
   Sally[0].Address[0].State[0] => NY
   Sally[0].Last_name[0] => James
   Sally[0].Age[0] => 30

Stone.pm  view on Meta::CPAN

# Equivalent to $stone->{'tag'}
sub at {
    my $self = shift;
    return $self->{$_[0]};
}
				# 
# Delete the indicated key entirely.
sub delete {
    my($self,$key) = @_;
    delete $self->{$key};
    $self->_fix_cursors;
}

# Return all the tags in the stone.
sub tags {
  my $self = shift;
  return grep (!/^\./,keys %{$self});
}

# Return attributes as a hash reference
# (only used by asXML)

Stone.pm  view on Meta::CPAN

  if (defined $tag) {
    return $self->{'.att'} = $tag if ref $tag eq 'HASH';
    return $self->{'.att'}{$tag} = $value if defined $value;
    return $self->{'.att'}{$tag};
  } 
  return $self->{'.att'} ||= {};
}


# Fetch an Iterator on the Stone.
sub cursor {
    my $self = shift;
    return new Stone::Cursor($self);
}

# Convert a stone into a straight hash
sub to_hash {
  my ($self) = shift;
  my ($key,%result);
  foreach $key (keys %$self) {
    next if substr($key,0,1) eq '.';

Stone.pm  view on Meta::CPAN

  my ($tag,$value) = @_;
  $value =~ s/&/&amp;/g;
  $value =~ s/>/&gt;/g;
  $value =~ s/</&lt;/g;
  ($tag,$value);
}

# Dump the entire data structure, for debugging purposes
sub dump {
    my($self) = shift;
    my $i = $self->cursor;
    my ($key,$value);
    while (($key,$value)=$i->each) {
	print "$key=$value\n";
    }
    # this has to be done explicitly here or it won't happen.
    $i->DESTROY;		
}

# return the name of the Stone
sub name { 

Stone.pm  view on Meta::CPAN

	
	if ($ref eq 'HASH') {	# Insert a record, potentially recursively
	    $self->insert_hash($key,%{$_});
	    next;
	}

	warn "Attempting to insert a $ref into a Stone. Be alert.\n";
	push(@{$self->{$key}},$_);

    }
    $self->_fix_cursors;
}

# Put the values into the key, replacing
# whatever was there before.
sub replace_list {
    my($self,$key,@values) = @_;
    $self->{$key}=[];		# clear it out
    $self->insert_list($key,@values); # append the values
}

Stone.pm  view on Meta::CPAN

    my($self,$key) = @_;
    return $self->{$key}->[0];
}

sub get_last {
    my($self,$key) = @_;
    return $self->{$key}->[$#{$self->{$key}}];
}

# This is a private subroutine used for registering
# and unregistering cursors
sub _register_cursor {
    my($self,$cursor,$register) = @_;
    if ($register) {
	$self->{'.cursors'}->{$cursor}=$cursor;
    } else {
	delete $self->{'.cursors'}->{$cursor};
	delete $self->{'.cursors'} unless %{$self->{'.cursors'}};
    }
}

# This is a private subroutine used to alert cursors that
# our contents have changed.
sub _fix_cursors {
    my($self) = @_;
    return unless $self->{'.cursors'};
    my($cursor); 
    foreach $cursor (values %{$self->{'.cursors'}}) {
	$cursor->reset;
    }
}

# This is a private subroutine.  It indexes
# all the way into the structure.
#sub _index {
#    my($self,@indices) = @_;
#    my $stone = $self;
#    my($key,$index,@h);
#    while (($key,$index) = splice(@indices,0,2)) {

Stone.pm  view on Meta::CPAN

#	    $stone= ($index eq "\#") ? $stone->get_last($key):
#		     $stone->get($key,$index);
#	    last unless ref($stone)=~/Stone/;
#	}
#    }
#    return $stone;
#}

sub DESTROY {
    my $self = shift;
    undef %{$self->{'.cursor'}};  # not really necessary ?
}


1;

Stone/Cursor.pm  view on Meta::CPAN

=head1 NAME

Stone::Cursor - Traverse tags and values of a Stone

=head1 SYNOPSIS

 use Boulder::Store;
$store = Boulder::Store->new('./soccer_teams');

 my $stone = $store->get(28);
 $cursor = $stone->cursor;
 while (my ($key,$value) = $cursor->each) {
   print "$value: Go Bluejays!\n" if $key eq 'State' and $value eq 'Katonah';
 }

=head1 DESCRIPTION

Boulder::Cursor is a utility class that allows you to create one or
more iterators across a L<Stone> object.  This is used for traversing
large Stone objects in order to identify or modify portions of the
record.

=head2 CLASS METHODS

=item Boulder::Cursor->new($stone)

Return a new Boulder::Cursor over the specified L<Stone> object.  This
will return an error if the object is not a L<Stone> or a
descendent. This method is usually not called directly, but rather
indirectly via the L<Stone> cursor() method:

  my $cursor = $stone->cursor;

=head2 OBJECT METHODS

=item $cursor->each() 

Iterate over the attached B<Stone>.  Each iteration will return a
two-valued list consisting of a tag path and a value.  The tag path is
of a form that can be used with B<Stone::index()> (in fact, a cursor
is used internally to implement the B<Stone::dump()> method.  When the
end of the B<Stone> is reached, C<each()> will return an empty list,
after which it will start over again from the beginning.  If you
attempt to insert or delete from the stone while iterating over it,
all attached cursors will reset to the beginnning.

For example:

	$cursor = $s->cursor;
	while (($key,$value) = $cursor->each) {
           print "$value: BOW WOW!\n" if $key=~/pet/;		
	}

=item $cursor->reset()

This resets the cursor back to the beginning of the associated
B<Stone>.

=head1 AUTHOR

Lincoln D. Stein <lstein@cshl.org>.

=head1 COPYRIGHT

Copyright 1997-1999, Cold Spring Harbor Laboratory, Cold Spring Harbor
NY.  This module can be used and distributed on the same terms as Perl

Stone/Cursor.pm  view on Meta::CPAN


# New expects a Stone object as its single
# parameter.
sub new {
    my($package,$stone) = @_;
    die "Boulder::Cursor: expect a Stone object parameter"
	unless ref($stone);

    my $self = bless {'stone'=>$stone},$package;
    $self->reset;
    $stone->_register_cursor($self,'true');
    return $self;
}

# This procedure does a breadth-first search
# over the entire structure.  It returns an array that looks like this
# (key1[index1].key2[index2].key3[index3],value)
sub each {
  my $self = shift;
  my $short_keys = shift;

Stone/Cursor.pm  view on Meta::CPAN

  while ($top && !$found) {
    $found++ if ($key,$value) = $top->next;
    if (!$found) {		# this iterator is done
      pop @{$stack};
      $top = $stack->[$#{$stack}];
      next;
    }
    if ( ref $value && !exists $value->{'.name'} ) { # found another record to begin iterating on
      if (%{$value}) {
	undef $found;
	$top = $value->cursor;
	push @{$stack},$top;
	next;
      } else {
	undef $value;
      }
    }
  }
  unless ($found) {
    $self->reset;
    return ();

Stone/Cursor.pm  view on Meta::CPAN

    my $self = shift;
    $self->{'arrayindex'} = 0;
    $self->{'hashindex'} = 0;
    $self->{'keys'}=[$self->{'stone'}->tags];
    $self->{'stack'}=[$self];
}

sub DESTROY {
    my $self = shift;
    if (ref $self->{'stone'}) {
	$self->{'stone'}->_register_cursor($self,undef);
    }
}

# Next will return the next index in its Stone object,
# indexing first through the members of the array, and then through
# the individual keys.  When iteration is finished, it resets itself
# and returns an empty array.
sub next {
    my $self = shift;
    my($arrayi,$hashi,$stone,$keys) = ($self->{'arrayindex'},

docs/javaboulder.txt  view on Meta::CPAN

	[0-9]+  index leftward from first value
        -[0-9]+ index rightward from last value
	#       last item
	\?      random item (question mark)

*public Stone[] path(String index_string)

This is a better name for index(), but unfortunately not part of the
Perl Boulder API.  Maybe index() should be phased out.

*public Enumeration cursor()

Return an Enumeration over the Stone object.  Each call to
nextElement() takes a step in a breadth-first traversal of the Stone.
The elements of the Enumeration are Stones with three tags:

	tag name   interpretation
        --------   --------------
	"tag"      String representing the name of the current
                       element's tag
        "path"     String representing full path to current element

docs/javaboulder.txt  view on Meta::CPAN

Return True if this Stone should be passed up to higher layers.

===========================================================================

public interface Boulder.IO;

This interface defines everything that a generic Boulder IO class
should be able to do.  Both Boulder.Stream (serial input/output) and
Boulder.Store (record-oriented input/output) implement this interface.

Note that Boulder.IO has an intrinsic cursor behavior, in that it
returns Stones in some defined order.

* public abstract Stone read_record() throws IOException

Reads a new Stone from input and returns it.  If no further stones can 
be read returns NULL.  If an I/O error occurs returns IOException.
Returns EOFException if the caller makes additional calls to
read_record() after it has returned NULL.

* public abstract Stone read_record(String[] f) throws IOException



( run in 0.305 second using v1.01-cache-2.11-cpan-4d50c553e7e )