AcePerl

 view release on metacpan or  search on metacpan

Ace.pm  view on Meta::CPAN

use constant STATUS_ERROR   => -1;
use constant ACE_PARSE      => 3;

use constant DEFAULT_PORT   => 200005;  # rpc server
use constant DEFAULT_SOCKET => 2005;    # socket server

require Ace::Iterator;
require Ace::Object;
eval qq{use Ace::Freesubs};  # XS file, may not be available

# Map database names to objects (to fix file-caching issue)
my %NAME2DB;

# internal cache of objects
my %MEMORY_CACHE;

my %DEFAULT_CACHE_PARAMETERS = (
				default_expires_in  => '1 day',
				auto_purge_interval => '12 hours',
				);

Ace.pm  view on Meta::CPAN

*list      = \&fetch;
*Ace::ERR  = *Error;

# now completely deprecated and gone
# *find_many = \&fetch_many;
# *models    = \&classes;

sub connect {
  my $class = shift;
  my ($host,$port,$user,$pass,$path,$program,
      $objclass,$timeout,$query_timeout,$database,
      $server_type,$url,$u,$p,$cache,$other);

  # one-argument single "URL" form
  if (@_ == 1) {
    return $class->connect(-url=>shift);
  }

  # multi-argument (traditional) form
  ($host,$port,$user,$pass,
   $path,$objclass,$timeout,$query_timeout,$url,$cache,$other) = 
     rearrange(['HOST','PORT','USER','PASS',
		'PATH',['CLASS','CLASSMAPPER'],'TIMEOUT',
		'QUERY_TIMEOUT','URL','CACHE'],@_);

  ($host,$port,$u,$pass,$p,$server_type) = $class->process_url($url) 
    or croak "Usage:  Ace->connect(-host=>\$host,-port=>\$port [,-path=>\$path]\n"
      if defined $url;

  if ($path) { # local database
    $server_type = 'Ace::Local';
  } else { # either RPC or socket server
    $host      ||= 'localhost';
    $user      ||= $u || '';
    $path      ||= $p || '';
    $port        ||= $server_type eq 'Ace::SocketServer' ? DEFAULT_SOCKET : DEFAULT_PORT;
    $query_timeout = 120 unless defined $query_timeout;
    $server_type ||= 'Ace::SocketServer' if $port <  100000;
    $server_type ||= 'Ace::RPC'          if $port >= 100000;
  }

  # we've normalized parameters, so do the actual connect
  eval "require $server_type" || croak "Module $server_type not loaded: $@";
  if ($path) {
    $database = $server_type->connect(-path=>$path,%$other);
  } else {
    $database = $server_type->connect($host,$port,$query_timeout,$user,$pass,%$other);
  }

  unless ($database) {
    $Ace::Error ||= "Couldn't open database";
    return;
  }

  my $contents = {
		  'database'=> $database,
		  'host'   => $host,
		  'port'   => $port,
		  'path'   => $path,
		  'class'  => $objclass || 'Ace::Object',
		  'timeout' => $query_timeout,
		  'user'    => $user,
		  'pass'    => $pass,
		  'other'  => $other,
		  'date_style' => 'java',
		  'auto_save' => 0,

Ace.pm  view on Meta::CPAN

  my $self = bless $contents,ref($class)||$class;

  $self->_create_cache($cache) if $cache;
  $self->name2db("$self",$self);
  return $self;
}

sub reopen {
  my $self = shift;
  return 1 if $self->ping;
  my $class = ref($self->{database});
  my $database;
  if ($self->{path}) {
    $database = $class->connect(-path=>$self->{path},%{$self->other});
  } else {
    $database = $class->connect($self->{host},$self->{port}, $self->{timeout},
				$self->{user},$self->{pass},%{$self->{other}});
  }
  unless ($database) {
    $Ace::Error = "Couldn't open database";
    return;
  }
  $self->{database} = $database;
  1;
}

sub class {
  my $self = shift;
  my $d = $self->{class};
  $self->{class} = shift if @_;
  $d;
}

Ace.pm  view on Meta::CPAN

    local $_ = $url;
    if (m!^rpcace://([^:]+):(\d+)$!) {  # rpcace://localhost:200005
      ($host,$port) = ($1,$2);
      $server_type = 'Ace::RPC';
    } elsif (m!^sace://([\w:]+)\@([^:]+):(\d+)$!) { # sace://user@localhost:2005
      ($user,$host,$port) = ($1,$2,$3);
      $server_type = 'Ace::SocketServer';
    } elsif (m!^sace://([^:]+):(\d+)$!) { # sace://localhost:2005
      ($host,$port) = ($1,$2);
      $server_type = 'Ace::SocketServer';
    } elsif (m!^tace:(/.+)$!) {           # tace:/path/to/database
      $path = $1;
      $server_type = 'Ace::Local';
    } elsif (m!^(/.+)$!) {                # /path/to/database
      $path = $1;
      $server_type = 'Ace::Local';
    } else {
      return;
    }
  }

  if ($user =~ /:/) {
    ($user,$pass) = split /:/,$user;
  }

  return ($host,$port,$user,$pass,$path,$server_type);  

}

# Return the low-level Ace::AceDB object
sub db {
  return $_[0]->{'database'};
}

# Fetch a model from the database.
# Since there are limited numbers of models, we cache
# the results internally.
sub model {
  my $self = shift;
  require Ace::Model;
  my $model       = shift;
  my $break_cycle = shift;  # for breaking cycles when following #includes
  my $key = join(':',$self,'MODEL',$model);
  $self->{'models'}{$model} ||= eval{$self->cache->get($key)};
  unless ($self->{models}{$model}) {

Ace.pm  view on Meta::CPAN

  my $key = join ':',$obj->class,$obj->name;
  my $cache = $self->cache or return;

  carp "deleting $key obj=",overload::StrVal($obj),"\n" if Ace->debug;
  $cache->remove($key,$obj);
}

#### END: CACHE AND CARRY CODE ####


# Fetch one or a group of objects from the database
sub fetch {
  my $self = shift;
  my ($class,$pattern,$count,$offset,$query,$filled,$total,$filltag) =  
    rearrange(['CLASS',['NAME','PATTERN'],'COUNT','OFFSET','QUERY',
	       ['FILL','FILLED'],'TOTAL','FILLTAG'],@_);

  if (defined $class
      && defined $pattern
      && $pattern !~ /[\?\*]/
#      && !wantarray

Ace.pm  view on Meta::CPAN



#########################################################
# These functions are for low-level (non OO) access only.
# This is for low-level access only.
sub show {
    my ($self,$class,$pattern,$tag) = @_;
    $Ace::Error = '';
    return unless $self->count($class,$pattern);

    # if we get here, then we've got some data to return.
    my @result;
    my $ts = $self->{'timestamps'} ? '-T' : '';
    $self->{database}->query("show -j $ts $tag");
    my $result = $self->read_object;
    unless ($result =~ /(\d+) object dumped/m) {
	$Ace::Error = 'Unexpected close during show';
	return;
    }
    return grep (!m!^//!,split("\n\n",$result));
}

sub read_object {
    my $self = shift;
    return unless $self->{database};
    my $result;
    while ($self->{database}->status == STATUS_PENDING()) {
      my $data = $self->{database}->read();
#      $data =~ s/\0//g;  # get rid of nulls in the buffer
      $result .= $data if defined $data;
    }
    return $result;
}

# do a query, and return the result immediately
sub raw_query {
  my ($self,$query,$no_alert,$parse) = @_;
  $self->_alert_iterators unless $no_alert;
  $self->{database}->query($query, $parse ? ACE_PARSE : () );
  return $self->read_object;
}

# return the last error
sub error {
  my $class = shift;
  $Ace::Error = shift() if defined($_[0]);
  $Ace::Error=~s/\0//g;  # get rid of nulls
  return $Ace::Error;
}

# close the database
sub close {
  my $self = shift;
  $self->raw_query('save') if $self->auto_save;
  foreach (keys %{$self->{iterators}}) {
    $self->_unregister_iterator($_);
  }
  delete $self->{database};
}

sub DESTROY { 
  my $self = shift;
  return if caller() =~ /^Cache\:\:/;
  warn "$self->DESTROY at ", join ' ',caller() if Ace->debug;
  $self->close;
}


Ace.pm  view on Meta::CPAN

        push(@return_array,$value);
    }
    push (@return_array,\%param) if %param;
    return @return_array;
}

# do a query, but don't return the result
sub _query {
  my ($self,@query) = @_;
  $self->_alert_iterators;
  $self->{'database'}->query("@query");
}

# return a portion of the active list
sub _list {
  my $self = shift;
  my ($count,$offset) = @_;
  my (@result);
  my $query = 'list -j';
  $query .= " -b $offset" if defined $offset;
  $query .= " -c $count"  if defined $count;

Ace.pm  view on Meta::CPAN

# return a portion of the active list
sub _fetch {
  my $self = shift;
  my ($count,$start,$tag) = @_;
  my (@result);
  $tag = '' unless defined $tag;
  my $query = "show -j $tag";
  $query .= ' -T' if $self->{timestamps};
  $query .= " -b $start"  if defined $start;
  $query .= " -c $count"  if defined $count;
  $self->{database}->query($query);
  while (my @objects = $self->_fetch_chunk) {
    push (@result,@objects);
  }
  # copy tag into a portion of the tree
  if ($tag) {
    for my $tree (@result) {
      my $obj = $self->class_for($tree->class,$tree->name)->new($tree->class,$tree->name,$self,1);
      $obj->_attach_subtree($tag=>$tree);
      $tree = $obj;
    }

Ace.pm  view on Meta::CPAN

      $_ = $obj;
    } else {
      $self->memory_cache_store($_);
    }
  }
  return wantarray ? @result : $result[0];
}

sub _fetch_chunk {
  my $self = shift;
  return unless $self->{database}->status == STATUS_PENDING();
  my $result = $self->{database}->read();
  $result =~ s/\0//g;  # get rid of &$#&@!! nulls
  my @chunks = split("\n\n",$result);
  my @result;
  foreach (@chunks) {
    next if m!^//!;
    next unless /\S/;  # occasional empty lines
    my ($class,$id) = Ace->split($_); # /^\?([^?]+)\?([^?]+)\?/m;
    push(@result,$self->class_for($class,$id)->newFromText($_,$self));
  }
  return @result;

Ace.pm  view on Meta::CPAN


__END__

=head1 NAME

Ace - Object-Oriented Access to ACEDB Databases

=head1 SYNOPSIS

    use Ace;
    # open a remote database connection
    $db = Ace->connect(-host => 'beta.crbm.cnrs-mop.fr',
                       -port => 20000100);

    # open a local database connection
    $local = Ace->connect(-path=>'~acedb/my_ace');

    # simple queries
    $sequence  = $db->fetch(Sequence => 'D12345');
    $count     = $db->count(Sequence => 'D*');
    @sequences = $db->fetch(Sequence => 'D*');
    $i         = $db->fetch_many(Sequence=>'*');  # fetch a cursor
    while ($obj = $i->next) {
       print $obj->asTable;
    }

Ace.pm  view on Meta::CPAN

    find Annotation Ready_for_submission ; follow gene ; 
    follow derived_sequence ; >DNA
    END
    @ready_dnas= $db->fetch(-query=>$query);

    $ready = $db->fetch_many(-query=>$query);
    while ($obj = $ready->next) {
        # do something with obj
    }

    # database cut and paste
    $sequence = $db->fetch(Sequence => 'D12345');
    $local_db->put($sequence);
    @sequences = $db->fetch(Sequence => 'D*');
    $local_db->put(@sequences);

    # Get errors
    print Ace->error;
    print $db->error;

=head1 DESCRIPTION

AcePerl provides an interface to the ACEDB object-oriented database.
Both read and write access is provided, and ACE objects are returned
as similarly-structured Perl objects.  Multiple databases can be
opened simultaneously.

You will interact with several Perl classes: I<Ace>, I<Ace::Object>,
I<Ace::Iterator>, I<Ace::Model>.  I<Ace> is the database accessor, and
can be used to open both remote Ace databases (running aceserver or
gifaceserver), and local ones.

I<Ace::Object> is the superclass for all objects returned from the
database.  I<Ace> and I<Ace::Object> are linked: if you retrieve an
Ace::Object from a particular database, it will store a reference to
the database and use it to fetch any subobjects contained within it.
You may make changes to the I<Ace::Object> and have those changes
written into the database.  You may also create I<Ace::Object>s from
scratch and store them in the database.

I<Ace::Iterator> is a utility class that acts as a database cursor for
long-running ACEDB queries.  I<Ace::Model> provides object-oriented
access to ACEDB's schema.

Internally, I<Ace> uses the I<Ace::Local> class for access to local
databases and I<Ace::AceDB> for access to remote databases.
Ordinarily you will not need to interact directly with either of these
classes.

=head1 CREATING NEW DATABASE CONNECTIONS

=head2 connect() -- multiple argument form

    # remote database
    $db = Ace->connect(-host  =>  'beta.crbm.cnrs-mop.fr',
                       -port  =>  20000100);

    # local (non-server) database
    $db = Ace->connect(-path  =>  '/usr/local/acedb);

Use Ace::connect() to establish a connection to a networked or local
AceDB database.  To establish a connection to an AceDB server, use the
B<-host> and/or B<-port> arguments.  For a local server, use the
B<-port> argument.  The database must be up and running on the
indicated host and port prior to connecting to an AceDB server.  The
full syntax is as follows:

    $db = Ace->connect(-host  =>  $host,
                       -port  =>  $port,
		       -path  =>  $database_path,
		       -program     => $local_connection_program
                       -classmapper =>  $object_class,
		       -timeout     => $timeout,
		       -query_timeout => $query_timeout
		       -cache        => {cache parameters},
		      );

The connect() method uses a named argument calling style, and
recognizes the following arguments:

Ace.pm  view on Meta::CPAN

By default, the cache is not size limited (the "max_size" property is
set to $NO_MAX_SIZE).  To adjust the size you may consider calling the
Ace object's cache() method to retrieve the physical cache and then
calling the cache object's limit_size($max_size) method from time to
time.  See L<Cache::SizeAwareFileCache> for more details.

=item B<-program>

By default AcePerl will use its internal compiled code calls to
establish a connection to Ace servers, and will launch a I<tace>
subprocess to communicate with local Ace databases.  The B<-program>
argument allows you to customize this behavior by forcing AcePerl to
use a local program to communicate with the database.  This argument
should point to an executable on your system.  You may use either a
complete path or a bare command name, in which case the PATH
environment variable will be consulted.  For example, you could force
AcePerl to use the I<aceclient> program to connect to the remote host
by connecting this way:

  $db = Ace->connect(-host => 'beta.crbm.cnrs-mop.fr',
                     -port => 20000100,
                     -program=>'aceclient');

=item B<-classmapper>

The optional B<-classmapper> argument (alias B<-class>) points to the
class you would like to return from database queries.  It is provided
for your use if you subclass Ace::Object.  For example, if you have
created a subclass of Ace::Object called Ace::Object::Graphics, you
can have the database return this subclass by default by connecting
this way:

  $db = Ace->connect(-host => 'beta.crbm.cnrs-mop.fr',
                     -port => 20000100,
	             -class=>'Ace::Object::Graphics');

The value of B<-class> can be a hash reference consisting of AceDB
class names as keys and Perl class names as values.  If a class name
does not exist in the hash, a key named _DEFAULT_ will be looked for.
If that does not exist, then Ace will default to Ace::Object.

The value of B<-class> can also be an object or a classname that
implements a class_for() method.  This method will receive three
arguments containing the AceDB class name, object ID and database
handle.  It should return a string indicating the perl class to
create.

=item B<-timeout>

If no response from the server is received within $timeout seconds,
the call will return an undefined value.  Internally timeout sets an
alarm and temporarily intercepts the ALRM signal.  You should be aware
of this if you use ALRM for your own purposes.

Ace.pm  view on Meta::CPAN

    -program       tace
    -class         Ace::Object
    -timeout       25
    -query_timeout 120

If you prefer to use a more Smalltalk-like message-passing syntax, you
can open a connection this way too:

  $db = connect Ace -host=>'beta.crbm.cnrs-mop.fr',-port=>20000100;

The return value is an Ace handle to use to access the database, or
undef if the connection fails.  If the connection fails, an error
message can be retrieved by calling Ace->error.

You may check the status of a connection at any time with ping().  It
will return a true value if the database is still connected.  Note
that Ace will timeout clients that have been inactive for any length
of time.  Long-running clients should attempt to reestablish their 
connection if ping() returns false.

    $db->ping() || die "not connected";

You may perform low-level calls using the Ace client C API by calling
db().  This fetches an Ace::AceDB object.  See THE LOW LEVEL C API for
details on using this object.
 

Ace.pm  view on Meta::CPAN

If not provided, the port defaults to 2005.

=item rpcace://hostname:port

Connect to an RPC server at the indicated hostname and RPC service number.  Example:

  rpcace://stein.cshl.org:400000

If not provided, the port defaults to 200005

=item tace:/path/to/database

Open up the local database at F</path/to/database> using tace.  Example:

  tace:/~acedb/elegans

=item /path/to/database

Same as the previous.

=back

=head2 close() Method

You can explicitly close a database by calling its close() method:

   $db->close();

This is not ordinarily necessary because the database will be
automatically close when it -- and all objects retrieved from it -- go
out of scope.

=head2 reopen() Method

The ACeDB socket server can time out.  The reopen() method will ping
the server and if it is not answering will reopen the connection.  If
the database is live (or could be resurrected), this method returns
true.

=head1 RETRIEVING ACEDB OBJECTS

Once you have established a connection and have an Ace databaes
handle, several methods can be used to query the ACE database to
retrieve objects.  You can then explore the objects, retrieve specific
fields from them, or update them using the I<Ace::Object> methods.
Please see L<Ace::Object>.

=head2 fetch() method

    $count   = $db->fetch($class,$name_pattern);
    $object  = $db->fetch($class,$name);
    @objects = $db->fetch($class,$name_pattern,[$count,$offset]);
    @objects = $db->fetch(-name=>$name_pattern,
                          -class=>$class
			  -count=>$count,
			  -offset=>$offset,
                          -fill=>$fill,
			  -filltag=>$tag,
	                  -total=>\$total);
    @objects = $db->fetch(-query=>$query);

Ace::fetch() retrieves objects from the database based on their class
and name.  You may retrieve a single object by requesting its name, or
a group of objects by fetching a name I<pattern>.  A pattern contains
one or more wildcard characters, where "*" stands for zero or more
characters, and "?" stands for any single character.

This method behaves differently depending on whether it is called in a
scalar or a list context, and whether it is asked to search for a name
pattern or a simple name.

When called with a class and a simple name, it returns the object
referenced by that time, or undef, if no such object exists.  In an
array context, it will return an empty list.

When called with a class and a name pattern in a list context, fetch()
returns the list of objects that match the name.  When called with a
pattern in a scalar context, fetch() returns the I<number> of objects
that match without actually retrieving them from the database.  Thus,
it is similar to count().

In the examples below, the first line of code will fetch the Sequence
object whose database ID is I<D12345>.  The second line will retrieve
all objects matching the pattern I<D1234*>.  The third line will
return the count of objects that match the same pattern.

   $object =  $db->fetch(Sequence => 'D12345');
   @objects = $db->fetch(Sequence => 'D1234*');
   $cnt =     $db->fetch(Sequence =>'D1234*');

A variety of communications and database errors may occur while
processing the request.  When this happens, undef or an empty list
will be returned, and a string describing the error can be retrieved
by calling Ace->error.

When retrieving database objects, it is possible to retrieve a
"filled" or an "unfilled" object.  A filled object contains the entire
contents of the object, including all tags and subtags.  In the case
of certain Sequence objects, this may be a significant amount of data.
Unfilled objects consist just of the object name.  They are filled in
from the database a little bit at a time as tags are requested.  By
default, fetch() returns the unfilled object.  This is usually a
performance win, but if you know in advance that you will be needing
the full contents of the retrieved object (for example, to display
them in a tree browser) it can be more efficient to fetch them in
filled mode. You do this by calling fetch() with the argument of
B<-fill> set to a true value.

The B<-filltag> argument, if provided, asks the database to fill in
the subtree anchored at the indicated tag.  This will improve
performance for frequently-accessed subtrees.  For example:

   @objects = $db->fetch(-name    => 'D123*',
                         -class   => 'Sequence',
                         -filltag => 'Visible');

This will fetch all Sequences named D123* and fill in their Visible
trees in a single operation.

Ace.pm  view on Meta::CPAN

consume a lot of memory, even if B<-fill> is false.  Consider using
B<fetch_many()> instead (see below).  Also see the get() method, which
is equivalent to the simple two-argument form of fetch().

=item get() method

   $object = $db->get($class,$name [,$fill]);

The get() method will return one and only one AceDB object
identified by its class and name.  The optional $fill argument can be
used to control how much data is retrieved from the database. If $fill
is absent or undefined, then the method will return a lightweight
"stub" object that is filled with information as requested in a lazy
fashion. If $fill is the number "1" then the retrieved object contains
all the relevant information contained within the database.  Any other
true value of $fill will be treated as a tag name: the returned object
will be prefilled with the subtree to the right of that tag.

Examples:

   # return lightweight stub for Author object "Sulston JE."
   $author = $db->get(Author=>'Sulston JE');

   # return heavyweight object
   $author = $db->get(Author=>'Sulston JE',1);

Ace.pm  view on Meta::CPAN

The get() method is equivalent to this form of the fetch()
method:

   $object = $db->fetch($class=>$name);

=head2 aql() method

    $count   = $db->aql($aql_query);
    @objects = $db->aql($aql_query);

Ace::aql() will perform an AQL query on the database.  In a scalar
context it returns the number of rows returned.  In an array context
it returns a list of rows.  Each row is an anonymous array containing
the columns returned by the query as an Ace::Object.

If an AQL error is encountered, will return undef or an empty list and
set Ace->error to the error message.

Note that this routine is not optimized -- there is no iterator
defined.  All results are returned synchronously, leading to large
memory consumption for certain queries.

=head2 put() method

   $cnt = $db->put($obj1,$obj2,$obj3);

This method will put the list of objects into the database,
overwriting like-named objects if they are already there.  This can
be used to copy an object from one database to another, provided that
the models are compatible.

The method returns the count of objects successfully written into the
database.  In case of an error, processing will stop at the last
object successfully written and an error message will be placed in
Ace->error();

=head2 parse() method

  $object = $db->parse('data to parse');

This will parse the Ace tags contained within the "data to parse"
string, convert it into an object in the databse, and return the
resulting Ace::Object.  In case of a parse error, the undefined value
will be returned and a (hopefully informative) description of the
error will be returned by Ace->error().

For example:

  $author = $db->parse(<<END);
  Author : "Glimitz JR"
  Full_name "Jonathan R. Glimitz"
  Mail	"128 Boylston Street"

Ace.pm  view on Meta::CPAN

  END

This method can also be used to parse several objects, but only the
last object successfully parsed will be returned.

=head2 parse_longtext() method

  $object = $db->parse($title,$text);

This will parse the long text (which may contain carriage returns and
other funny characters) and place it into the database with the given
title.  In case of a parse error, the undefined value will be returned
and a (hopefully informative) description of the error will be
returned by Ace->error(); otherwise, a LongText object will be returned.

For example:

  $author = $db->parse_longtext('A Novel Inhibitory Domain',<<END);
  We have discovered a novel inhibitory domain that inhibits
  many classes of proteases, including metallothioproteins.
  This inhibitory domain appears in three different gene families studied
  to date...
  END

=head2 parse_file() method

  @objects = $db->parse_file('/path/to/file');
  @objects = $db->parse_file('/path/to/file',1);

This will call parse() to parse each of the objects found in the
indicated .ace file, returning the list of objects successfully loaded
into the database.

By default, parsing will stop at the first object that causes a parse
error.  If you wish to forge on after an error, pass a true value as
the second argument to this method.

Any parse error messages are accumulated in Ace->error().

=head2 new() method

  $object = $db->new($class => $name);

This method creates a new object in the database of type $class and
name $name.  If successful, it returns the newly-created object.
Otherwise it returns undef and sets $db->error().

$name may contain sprintf()-style patterns.  If one of the patterns is
%d (or a variant), Acedb uses a class-specific unique numbering to return
a unique name.  For example:

  $paper = $db->new(Paper => 'wgb%06d');

The object is created in the database atomically.  There is no chance to rollback as there is
in Ace::Object's object editing methods.

See also the Ace::Object->add() and replace() methods.

=head2 list() method

    @objects = $db->list(class,pattern,[count,offset]);
    @objects = $db->list(-class=>$class,
                         -name=>$name_pattern,
                         -count=>$count,
                         -offset=>$offset);

This is a deprecated method.  Use fetch() instead.

=head2 count() method

    $count = $db->count($class,$pattern);
    $count = $db->count(-query=>$query);

This function queries the database for a list of objects matching the
specified class and pattern, and returns the object count.  For large
sets of objects this is much more time and memory effective than
fetching the entire list.

The class and name pattern are the same as the list() method above.

You may also provide a B<-query> argument to instead specify an
arbitrary ACE query such as "find Author COUNT Paper > 80".  See
find() below.

Ace.pm  view on Meta::CPAN

    $obj = $db->fetch_many($class,$pattern);

    $obj = $db->fetch_many(-class=>$class,
                           -name =>$pattern,
                           -fill =>$filled,
                           -chunksize=>$chunksize);

    $obj = $db->fetch_many(-query=>$query);

If you expect to retrieve many objects, you can fetch an iterator
across the data set.  This is friendly both in terms of network
bandwidth and memory consumption.  It is simple to use:

    $i = $db->fetch_many(Sequence,'*');  # all sequences!!!!
    while ($obj = $i->next) {
       print $obj->asTable;
    }

The iterator will return undef when it has finished iterating, and
cannot be used again.  You can have multiple iterators open at once
and they will operate independently of each other.

Like B<fetch()>, B<fetch_many()> takes an optional B<-fill> (or
B<-filled>) argument which retrieves the entire object rather than
just its name.  This is efficient on a network with high latency if 
you expect to be touching many parts of the object (rather than
just retrieving the value of a few tags).

B<fetch_many()> retrieves objects from the database in groups of a
certain maximum size, 40 by default.  This can be tuned using the
optional B<-chunksize> argument.  Chunksize is only a hint to the
database.  It may return fewer objects per transaction, particularly
if the objects are large.

You may provide raw Ace query string with the B<-query> argument.  If
present the B<-name> and B<-class> arguments will be ignored.

=head2 find_many() method

This is an alias for fetch_many().  It is now deprecated.

=head2 keyset() method

Ace.pm  view on Meta::CPAN

    $count   = $db->grep($grep_string);
    @objects = $db->grep(-pattern => $grep_string,
                         -offset=> $offset,
                         -count => $count,
                         -fill  => $fill,
                         -filltag => $filltag,
			 -total => \$total,
                         -long  => 1,
			);

This performs a "grep" on the database, returning all object names or
text that contain the indicated grep pattern.  In a scalar context
this call will return the number of matching objects.  In an array
context, the list of matching objects are retrieved.  There is also a
named-parameter form of the call, which allows you to specify the
number of objects to retrieve, the offset from the beginning of the
list to retrieve from, whether the retrieved objects should be filled
initially.  You can use B<-total> to discover the total number of
objects that match, while only retrieving a portion of the list.

By default, grep uses a fast search that only examines class names and

Ace.pm  view on Meta::CPAN


This will return an I<Ace::Model> object corresponding to the
indicated class.

=head2 new() method

   $obj = $db->new($class,$name);
   $obj = $db->new(-class=>$class,
                   -name=>$name);

Create a new object in the database with the indicated class and name
and return a pointer to it.  Will return undef if the object already
exists in the database.  The object isn't actually written into the database
until you call Ace::Object::commit().

=head2 raw_query() method

    $r = $db->raw_query('Model');

Send a command to the database and return its unprocessed output.
This method is necessary to gain access to features that are not yet
implemented in this module, such as model browsing and complex
queries.

=head2 classes() method

   @classes = $db->classes();
   @all_classes = $db->classes(1);

This method returns a list of all the object classes known to the
server.  In a list context it returns an array of class names.  In a
scalar context, it the number of classes defined in the database.

Ordinarily I<classes()> will return only those classes that are
exposed to the user interface for browsing, the so-called "visible"
classes.  Pass a true argument to the call to retrieve non-visible
classes as well.

=head2 class_count() method

   %classes = $db->class_count()

Ace.pm  view on Meta::CPAN


Returns various bits of status information from the server.  In an
array context, returns a hash of hashes.  In a scalar context, returns a
reference to a hash of hashes.  Keys and subkeys are as follows

   code
           program     name of acedb binary
           version     version of acedb binary
           build       build date of acedb binary in format Jan 25 2003 16:21:24

   database
           title       name of the database
           version     version of the database
           dbformat    database format version number
           directory   directory in which the database is stored
           session     session number
           user        user under which server is running
           write       whether the server has write access
           address     global address - not known if this is useful

   resources
           classes     number of classes defined
           keys        number of keys defined
           memory      amount of memory used by acedb objects (bytes)

For example, to get the program version:

   my $version = $db->status->{code}{version};

=head2 title() method

    my $title = $db->title

Returns the version of the current database, equivalent
to $db->status->{database}{title};

=head2 version() method

    my $version = $db->version;

Returns the version of the current database, equivalent 
to $db->status->{database}{version};

=head2 date_style() method

  $style = $db->date_style();
  $style = $db->date_style('ace');
  $style = $db->date_style('java');

For historical reasons, AceDB can display dates using either of two
different formats.  The first format, which I call "ace" style, puts
the year first, as in "1997-10-01".  The second format, which I call

Ace.pm  view on Meta::CPAN

B<date_style()> can be used to set or retrieve the current style.
Called with no arguments, it returns the current style, which will be
one of "ace" or "java."  Called with an argument, it will set the
style to one or the other.

=head2 timestamps() method

  $timestamps_on = $db->timestamps();
  $db->timestamps(1);

Whenever a data object is updated, AceDB records the time and date of
the update, and the user ID it was running under.  Ordinarily, the
retrieval of timestamp information is suppressed to conserve memory
and bandwidth.  To turn on timestamps, call the B<timestamps()> method 
with a true value.  You can retrieve the current value of the setting
by calling the method with no arguments.

Note that activating timestamps disables some of the speed
optimizations in AcePerl.  Thus they should only be activated if you
really need the information.

=head2 auto_save()

Sets or queries the I<auto_save> variable.  If true, the "save"
command will be issued automatically before the connection to the
database is severed.  The default is true.

Examples:

   $db->auto_save(1);
   $flag = $db->auto_save;

=head2 error() method

    Ace->error;

This returns the last error message.  Like UNIX errno, this variable
is not reset between calls, so its contents are only valid after a
method call has returned a result value indicating a failure.

For your convenience, you can call error() in any of several ways:

    print Ace->error();
    print $db->error();  # $db is an Ace database handle
    print $obj->error(); # $object is an Ace::Object

There's also a global named $Ace::Error that you are free to use.

=head2 datetime() and date()

  $datetime = Ace->datetime($time);
  $today    = Ace->datetime();
  $date     = Ace->date($time);
  $today    = Ace->date([$time]);

Ace.pm  view on Meta::CPAN


=head2 debug()

  $debug_level = Ace->debug([$new_level])

This class method gets or sets the debug level.  Higher integers
increase verbosity.  0 or undef turns off debug messages.

=head2 name2db()

 $db = Ace->name2db($name [,$database])

This class method associates a database URL with an Ace database
object. This is used internally by the Ace::Object class in order to
discover what database they "belong" to.

=head2 cache()

Get or set the Cache::SizeAwareFileCache object, if one has been
created.

=head2 memory_cache_fetch()

  $obj = $db->memory_cache_fetch($class,$name)

Ace.pm  view on Meta::CPAN

 ACE_OUTOFCONTEXT
 ACE_SYNTAXERROR
 ACE_UNRECOGNIZED

Please see the ace client library documentation for a full description
of these error codes and their significance.

=item encore()

This method may return true after you have performed one or more
read() operations, and indicates that there is more data to read.  You
will not ordinarily have to call this method.

=back

=head1 BUGS

1. The ACE model should be consulted prior to updating the database.

2. There is no automatic recovery from connection errors.

3. Debugging has only one level of verbosity, despite the best
of intentions.

4. Performance is poor when fetching big objects, because of 
many object references that must be created.  This could be
improved.

Ace.pm  view on Meta::CPAN


# -------------------- AUTOLOADED SUBS ------------------

sub debug {
  my $package = shift;
  my $d = $DEBUG_LEVEL;
  $DEBUG_LEVEL = shift if @_;
  $d;
}

# Return true if the database is still connected.  This is oddly convoluted
# because there are numerous things that can go wrong, including:
#   1. server has gone away
#   2. server has timed out our connection! (grrrrr)
#   3. communications channel contains unread garbage and is in an inconsistent state
sub ping {
  my $self = shift;
  local($SIG{PIPE})='IGNORE';  # so we don't get a fatal exception during the check
  my $result = $self->raw_query('');
  return unless $result;  # server has gone away
  return if $result=~/broken connection|client time out/;  # server has timed us out  
  return unless $self->{database}->status() == STATUS_WAITING(); #communications oddness
  return 1;
}

# Get or set the display style for dates
sub date_style {
  my $self = shift;
  $self->{'date_style'} = $_[0] if defined $_[0];
  return $self->{'date_style'};
}

# Get or set whether we retrieve timestamps
sub timestamps {
  my $self = shift;
  $self->{'timestamps'} = $_[0] if defined $_[0];
  return $self->{'timestamps'};
}

# Add one or more objects to the database
sub put {
  my $self = shift;
  my @objects = @_;
  my $count = 0;
  $Ace::Error = '';
  foreach my $object (@objects) {
    croak "Can't put a non-Ace object into an Ace database"
      unless $object->isa('Ace::Object');
    croak "Can't put a non-object into a database"
      unless $object->isObject;
    $object = $object->fetch unless $object->isRoot;  # make sure we're putting root object
    my $data = $object->asAce;
    $data =~ s/\n/; /mg;
    my $result = $self->raw_query("parse = $data");
    $Ace::Error = $result if $result =~ /sorry|parse error/mi;
    return $count if $Ace::Error;
    $count++;  # bump if succesful
  }
  return $count;
}

# Parse a single object and return the result as an object
sub parse {
  my $self = shift;
  my $ace_data = shift;
  my @lines = split("\n",$ace_data);
  foreach (@lines) { s/;/\\;/;  } # protect semicolons  
  my $query = join("; ",@lines);
  my $result = $self->raw_query("parse = $query");
  $Ace::Error = $result=~/sorry|parse error/mi ? $result : '';
  my @results = $self->_list(1,0);
  return $results[0];
}

# Parse a single object as longtext and return the result
# as an object

Ace.pm  view on Meta::CPAN

      $errors .= $Ace::Error;  # keep track of errors
      last unless $keepgoing;
    }
    push(@objects,$obj);
  }
  close ACE;
  $Ace::Error = $errors;
  return @objects;
}

# Create a new Ace::Object in the indicated database
# (doesn't actually write into database until you do a commit)
sub new {
  my $self = shift;
  my ($class,$name) = rearrange([qw/CLASS NAME/],@_);
  return if $self->fetch($class,$name);
  my $obj = $self->class_for($class,$name)->new($class,$name,$self);
  return $obj;
}

# Return the layout, which contains classes that should be displayed
sub layout {

Ace.pm  view on Meta::CPAN

# Return a hash of all the classes and the number of objects in each
sub class_count {
  my $self = shift;
  return $self->raw_query('classes') =~ /^\s+(\S+) (\d+)/gm;
}

# Return a hash of miscellaneous status information from the server
# (to be expanded later)
sub status {
  my $self = shift;
  my $data = $self->raw_query('status');
  study $data;

  my %status;

  # -Code section
  my ($program)    = $data=~/Program:\s+(.+)/m;
  my ($aceversion) = $data=~/Version:\s+(.+)/m;
  my ($build)      = $data=~/Build:\s+(.+)/m;
  $status{code}    = { program=>$program,
		       version=>$aceversion,
		       build  =>$build};

  # -Database section
  my ($title)      = $data=~/Title:\s+(.+)/m;
  my ($name)       = $data=~/Name:\s+(.+)/m;
  my ($release)    = $data=~/Release:\s+(.+)/m;
  my ($directory)  = $data=~/Directory:\s+(.+)/m;
  my ($session)    = $data=~/Session:\s+(\d+)/m;
  my ($user)       = $data=~/User:\s+(.+)/m;
  my ($write)      = $data=~/Write Access:\s+(.+)/m;
  my ($address)    = $data=~/Global Address:\s+(\d+)/m;
  $status{database} = {
		       title     => $title,
		       version   => $name,
		       dbformat  => $release,
		       directory => $directory,
		       session   => $session,
		       user      => $user,
		       write     => $write,
		       address   => $address,
		       };

  # other info - not all
  my ($classes)   = $data=~/classes:\s+(\d+)/;
  my ($keys)      = $data=~/keys:\s+(\d+)/;
  my ($memory)    = $data=~/blocks:\s+\d+,\s+allocated \(kb\):\s+(\d+)/;
  $status{resources} = {
		      classes => $classes,
		      keys    => $keys,
		      memory  => $memory * 1024,
		      };
  return wantarray ? %status : \%status;
}

sub title {
  my $self = shift;
  my $status= $self->status;
  $status->{database}{title};
}

sub version {
  my $self = shift;
  my $status= $self->status;
  $status->{database}{version};
}

sub auto_save {
  my $self = shift;
  if ($self->db && $self->db->can('auto_save')) {
    $self->db->auto_save;
  } else {
    $self->{'auto_save'} = $_[0] if defined $_[0];
    return $self->{'auto_save'};
  }

Ace.pm  view on Meta::CPAN

  @h;
}

sub pick {
    my ($self,$class,$item) = @_;
    $Ace::Error = '';
    # assumption of uniqueness of name is violated by some classes!
    #    return () unless $self->count($class,$item) == 1;
    return unless $self->count($class,$item) >= 1;

    # if we get here, then we've got some data to return.
    # yes, we're repeating code slightly...
    my @result;
    my $ts = $self->{'timestamps'} ? '-T' : '';
    my $result = $self->raw_query("show -j $ts");
    unless ($result =~ /(\d+) object dumped/m) {
	$Ace::Error = 'Unexpected close during pick';
	return;
    }

    @result = grep (!m!^\s*//!,split("\n\n",$result));

Ace.pm  view on Meta::CPAN

  my $self = shift;
  my $iterator = shift;
  return unless $self->{iterators}{$iterator};
  $self->{iterator_stack} ||= [];
  return 1 if grep { $_ eq $iterator } @{$self->{iterator_stack}};
  $self->raw_query("spush",'no_alert');
  unshift @{$self->{iterator_stack}},$iterator;
  1;  # result code -- CHANGE THIS LATER
}

# horrid method that keeps the database's view of
# iterators in synch with our view
sub _restore_iterator {
  my $self = shift;
  my $iterator = shift;

  # no such iterator known, return false
  return unless $self->{iterators}{$iterator};

  # make other iterators save themselves
  $self->_alert_iterators;

Ace.pm  view on Meta::CPAN

  return unless $i < @$list;

  # Sse spop if the list size is 1.  Otherwise use spick, which is
  # only supported in hacked versions of the server.
  my $result = $i == 0 ? $self->raw_query("spop",'no_alert') 
                       : $self->raw_query("spick $i",'no_alert');
  
  if ($result =~ /Keyword spick does not match/) {
    # _restore_iterator will now only work for a single iterator (non-reentrantly)
    $self->{no_spick}++;
    $self->raw_query('spop','no_alert') foreach @$list;  # empty database stack
    $self->{iterator_stack} = [];             # and local copy
    return;
  }

  unless (($result =~ /The stack now holds (\d+) keyset/ && ($1 == (@$list-1) ))
	  or 
	  ($result =~ /stack is (now )?empty/ && @$list == 1)
	 ) {
    $Ace::Error = 'Unexpected result from spick: $result';
    return;

Ace/Browser/AceSubs.pm  view on Meta::CPAN

    my $bookmark = cookie(
			  -name=>"HOME_${db}",
			  -value=>$referer,
			  -path=>'/');
    push(@COOKIES,$bookmark);
  }

  if ($searches{$quovadis}) {
    Delete('Go');
    my $search_name = "SEARCH_${db}_${quovadis}";
    my $search_data = cookie(-name  => $search_name,
			     -value => query_string(),
			     -path=>'/',
			    );
    my $last_search = cookie(-name=>"ACEDB_$db",
			     -value=>$quovadis,
			     -path=>'/');
    push(@COOKIES,$search_data,$last_search);
  }

  print @COOKIES ? header(-cookie=>\@COOKIES,@_) : header(@_);

  @COOKIES = ();
  $HEADER++;
}

=item AceInit()

This subroutine initializes the AcePerl connection to the configured
database.  If the database cannot be opened, it generates an error
message and exits.  This subroutine is not exported by default, but is 
called by PrintTop() and Header() internally.

=cut

# Subroutines used by all scripts.
# Will generate an HTTP 'document not found' error if you try to get an 
# undefined database name.  Check the return code from this function and
# return immediately if not true (actually, not needed because we exit).
sub AceInit   {
  $HEADER   = 0;
  $TOP      = 0;
  @COOKIES  = ();

  # keeps track of what sections should be open
  %OPEN = param('open') ? map {$_ => 1} split(' ',param('open')) : () ;

  return 1 if Configuration();

  # if we get here, it is a big NOT FOUND error
  print header(-status=>'404 Not Found',-type=>'text/html');
  $HEADER++;
  print start_html(-title => 'Database Not Found',
		   -style => Ace::Browser::SiteDefs->getConfig(DEFAULT_DATABASE)->Style,
		  ),
        h1('Database not found'),
        p('The requested database',i(get_symbolic()),'is not recognized',
	  'by this server.');
  print p('Please return to the',a({-href=>referer()},'referring page.')) if referer();
  print end_html;
  Apache::exit(0) if defined &Apache::exit;  # bug out of here!
  exit(0);
}

=item AceMissing([$class,$name])

This subroutine will print out an error message indicating that an

Ace/Browser/AceSubs.pm  view on Meta::CPAN

and name of the object are not provided as arguments, they are taken
from CGI's param() function.

=cut

sub AceMissing {
    my ($class,$name) = @_;
    $class ||= param('class');
    $name  ||= param('name');
    PrintTop(undef,undef,$name);
    print strong('There is no further information about this object in the database.');
    PrintBottom();
    Apache->exit(0) if defined &Apache::exit;
    exit(0);
}

=item AceMultipleChoices($symbol,$report,$objects)

This function is called when a search has recovered multiple objects
and the user must make a choice among them.  The user is presented
with an ordered list of the objects, and asked to click on one of

Ace/Browser/AceSubs.pm  view on Meta::CPAN

exit the script. If the class and name of the object are not provided
as arguments, they are taken from CGI's param() function.

=cut

sub AceNotFound {
  my $class = shift || param('class');
  my $name  = shift || param('name');
  PrintTop(undef,undef,"$class: $name not found");
  print p(font({-color => 'red'},
	       strong("The $class named \"$name\" is not found in the database.")));
  PrintBottom();
  Apache->exit(0) if defined &Apache::exit;
  exit(0);
}

=item ($uri,$physical_path) = AcePicRoot($directory)

This function returns the physical and URL paths of a temporary
directory in which the pic script can write pictures.  Not exported by
default.  Returns a two-element list containing the URL and physical

Ace/Browser/AceSubs.pm  view on Meta::CPAN

}

=item $configuration = Configuration()

The Configuration() function returns the Ace::Browser::SiteDefs object
for the current session.  From this object you can retrieve
information from the configuration file.

=cut

# get the configuration object for this database
sub Configuration {
  my $s = get_symbolic()||return;
  return Ace::Browser::SiteDefs->getConfig($s);
}

=item $name = DB_Name()

This function returns the symbolic name of the current database, for
example "default".

=cut

*DB_Name = \&get_symbolic;

=item DoRedirect($object)

This subroutine immediately redirects to the default display for the
Ace::Object indicated by $object and exits the script.  It must be

Ace/Browser/AceSubs.pm  view on Meta::CPAN

  my $obj_name =  escape(param('name'));
  my $obj_class = escape(param('class')) || ucfirst url(-relative=>1);
  my $referer   = escape(self_url());
  my $name      = get_symbolic();

  # set up the feedback link
  my $feedback_link = Configuration()->Feedback_recipients &&
      $obj_name &&
	  (url(-relative=>1) ne 'feedback') ?
    a({-href=>ResolveUrl("misc/feedback/$name","name=$obj_name;class=$obj_class;referer=$referer")},
      "Click here to send data or comments to the maintainers")
      : '';

  # set up the privacy statement link
  my $privacy_link = ( Configuration()->Print_privacy_statement &&
		       url(-relative=>1) ne PRIVACY()) 
    ?
      a({ -href=>ResolveUrl(PRIVACY."/$name") },'Privacy Statement')
	: '';

  my ($home,$label) = @{Configuration()->Home};

Ace/Browser/AceSubs.pm  view on Meta::CPAN

    </TD>
</TR>
</TABLE>
END
}

=item $object = GetAceObject()

This function is called by display scripts to return the
Ace::Object.that the user wishes to view.  It automatically opens or
refreshes the database, and performs the request using the values of the
"name" and "class" CGI variables.

If a single object is found, the function returns it as the function
result.  If no objects are found, it returns undef.  If more than one
object is found, the function invokes AceMultipleChoices() and exits
the script.

=cut

# open database, return object requested by CGI parameters
sub GetAceObject {
  my $db = OpenDatabase() ||  AceError("Couldn't open database."); # exits
  my $name  = param('name') or return;
  my $class = param('class') or return;
  my @objs = $db->fetch($class => $name);
  if (@objs > 1) {
    AceMultipleChoices($name,'',\@objs);
    Apache->exit(0) if defined &Apache::exit;
    exit(0);
  }
  return $objs[0];
}

Ace/Browser/AceSubs.pm  view on Meta::CPAN

  my $object     = shift;
  my $link_text  = shift;
  my $target     = shift;
  my $url = Object2URL($object,@_) or return ($link_text || "$object");
  my @targ = $target ? (-target=>$target) : ();
  return a({-href=>Object2URL($object,@_),-name=>"$object",@targ},($link_text || "$object"));
}

=item $db = OpenDatabase()

This function opens the Acedb database designated by the configuration
file.  In modperl environments, this function caches database handles
and reuses them, pinging and reopening them in the case of timeouts.

This function is not exported by default.

=cut

use Carp 'cluck';

################ open a database #################
sub OpenDatabase {
  my $name = shift || get_symbolic();
  AceInit();
  $name =~ s!/$!!;
  my $db = $DB{$name};
  return $db if $db && $db->ping;

  my ($host,$port,$user,$password,
      $cache_root,$cache_size,$cache_expires,$auto_purge_interval)
    = getDatabasePorts($name);

Ace/Browser/AceSubs.pm  view on Meta::CPAN

hash before calling start_html().  See the pic script for an example
of how this is done this.

This function is not exported by default.

=cut

=item $url = ResolveUrl($url,$param)

Given a URL and a set of parameters, this function does the necessary
magic to add the symbolic database name to the end of the URL (if
needed) and then tack the parameters onto the end.

A typical call is:

  $url = ResolveUrl('/cgi-bin/ace/generic/tree','name=fred;class=Author');

This function is not exported by default.

=cut

Ace/Browser/AceSubs.pm  view on Meta::CPAN

}

=item $url = Url($display,$params)

Given a symbolic display name, such as "tree" and a set of parameters, 
this function looks up its URL and then calls ResolveUrl() to create a 
single Url.

When hard-coding relative URLs into AceBrowser scripts, it is
important to pass them through Url().  The reason for this is that
AceBrowser may need to attach the database name to the URL in order to
identify it.

Example:

  my $url = Url('../sequence_dump',"name=$name;long_dump=yes");
  print a({-href=>$url},'Dump this sequence');

=cut

sub Url {

Ace/Browser/AceSubs.pm  view on Meta::CPAN

<td>';
}

sub Close_table{
print '</tr>
</td>
</table>';
}


# return host and port for symbolic database name
sub getDatabasePorts {
  my $name = shift;
  my $config = Ace::Browser::SiteDefs->getConfig($name);
  return ($config->Host,$config->Port,
	  $config->Username,$config->Password,
	  $config->Cacheroot,$config->Cachesize,$config->Cacheexpires,$config->Cachepurge,
	 ) if $config;

  # If we get here, then try getservbynam()
  # I think this is a bit of legacy code.

Ace/Browser/SiteDefs.pm  view on Meta::CPAN

The config object methods are a canonicalized form of the
configuration file variables, in which the first character of the
method is uppercase, and subsequent characters are lower case.  For
example, if the configuration variable was $ROOT, the method will be
$config_object->Root.

=head2 Working with Configuration Objects

To fetch a configuration object, use the Ace::Browser::AceSubs
Configuration() function.  This will return a configuration object for 
the current database:

  $config_object = Configuration();

Thereafter, it's just a matter of making the proper method calls.

   If the Configuration file is a....    The method call returns a...
   ----------------------------------    ----------------------------

   Scalar variable                       Scalar
   Array variable                        Array reference

Ace/Browser/SiteDefs.pm  view on Meta::CPAN

# get location of configuration file
use Ace::Browser::LocalSiteDefs '$SITE_DEFS';

my %CONFIG;
my %CACHETIME;
my %CACHED;

sub getConfig {
  my $package = shift;
  my $name    = shift;
  croak "Usage: getConfig(\$database_name)" unless defined $name;
  $package = ref $package if ref $package;
  my $file    = "${name}.pm";

  # make search relative to SiteDefs.pm file
  my $path = $package->get_config || $package->resolveConf($file);

  return unless -r $path;
  return $CONFIG{$name} if exists $CONFIG{$name} and $CACHETIME{$name} >= (stat($path))[9];
  return unless $CONFIG{$name} = $package->_load($path);
  $CONFIG{$name}->{'name'} ||= $name;  # remember name

Ace/Browser/SiteDefs.pm  view on Meta::CPAN


  $file =~ m!([/a-zA-Z0-9._-]+)!;
  my $safe = $1;

  (my $ns = $safe) =~ s/\W/_/g;
  my $namespace = __PACKAGE__ . '::Config::' . $ns;
  unless (eval "package $namespace; require '$safe';") {
    die "compile error while parsing config file '$safe': $@\n";
  }
  # build the object up from the values compiled into the $namespace area
  my %data;

  # get the scalars
  local *symbol;
  foreach (keys %{"${namespace}::"}) {
    *symbol = ${"${namespace}::"}{$_};
    $data{ucfirst(lc $_)} = $symbol if defined($symbol);
    $data{ucfirst(lc $_)} = \%symbol if defined(%symbol);
    $data{ucfirst(lc $_)} = \@symbol if defined(@symbol);
    $data{ucfirst(lc $_)} = \&symbol if defined(&symbol);
    undef *symbol unless defined &symbol;  # conserve  some memory
  }

  # special case: get the search scripts as both an array and as a hash
  if (my @searches = @{"$namespace\:\:SEARCHES"}) {
    $data{Searches} = [ @searches[map {2*$_} (0..@searches/2-1)] ];
    %{$data{Search_titles}} = @searches;
  }

  # return this thing as a blessed object
  return bless \%data,$package;
}

sub resolvePath {
  my $self = shift;
  my $file = shift;
  my $root = $self->Root || '/cgi-bin';
  return "$root/$file";
}

sub resolveConf {

Ace/Browser/TreeSubs.pm  view on Meta::CPAN

# colors
use constant OPENCOLOR      => '#FF0000'; # color when a tree is expanded
use constant CLOSEDCOLOR    => '#909090'; # color when a tree is collapsed

# auto-expand subtrees when the number of subobjects is
# less than or equal to this number
use constant MAXEXPAND => 4;


# A hack to allow access to external images.
# We use the name of the database as a URL to an external image.
# The URL will look like this:
#     /ace_images/external/database_name/foo.gif
# You must arrange for the URL to return the correct image, either with
# a CGI script, a symbolic link, or a redirection directive.
sub AceImageHackURL {
  my $image_name = shift;
  # correct some bad image file names in the database
  $image_name .= '.jpeg' unless $image_name =~ /\.(gif|jpg|jpeg|png|tiff|ps)$/;
  my $picture_path = Configuration->Pictures->[0];
  return join('/',$picture_path,Configuration->Name,'external',escape("$image_name"));
}


1;

Ace/Graphics/Panel.pm  view on Meta::CPAN


  $panel->add_track(segments => [[$abc_5,$abc_3],
				 [$xxx_5,$xxx_3],
				 [$yyy_5,$yyy_3]],
		    -connect_groups => 1);

=item $gd = $panel->gd

The gd() method lays out the image and returns a GD::Image object
containing it.  You may then call the GD::Image object's png() or
jpeg() methods to get the image data.

=item $png = $panel->png

The png() method returns the image as a PNG-format drawing, without
the intermediate step of returning a GD::Image object.

=item $boxes = $panel->boxes

=item @boxes = $panel->boxes

Ace/Iterator.pm  view on Meta::CPAN


    $i  = $db->fetch_many(Sequence=>'*');  # fetch a cursor
    while ($obj = $i->next) {
       print $obj->asTable;
    }


=head1 DESCRIPTION

The Ace::Iterator class implements a persistent query on an Ace
database.  You can create multiple simultaneous queries and retrieve
objects from each one independently of the others.  This is useful
when a query is expected to return more objects than can easily fit
into memory.  The iterator is essentially a database "cursor."

=head2 new() Method

  $iterator = Ace::Iterator->new(-db        => $db,
                                 -query     => $query,
                                 -filled    => $filled,
                                 -chunksize => $chunksize);

An Ace::Iterator is returned by the Ace accessor's object's
fetch_many() method. You usually will not have cause to call the new()
method directly.  If you do so, the parameters are as follows:

=over 4

=item -db

The Ace database accessor object to use.

=item -query

A query, written in Ace query language, to pass to the database.  This
query should return a list of objects.

=item -filled

If true, then retrieve complete objects from the database, rather than
empty object stubs.  Retrieving filled objects uses more memory and
network bandwidth than retrieving unfilled objects, but it's
recommended if you know in advance that you will be accessing most or
all of the objects' fields, for example, for the purposes of
displaying the objects.

=item -chunksize

The iterator will fetch objects from the database in chunks controlled
by this argument.  The default is 40.  You may want to tune the
chunksize to optimize the retrieval for your application.

=back

=head2 next() method

  $object = $iterator->next;

This method retrieves the next object from the query, performing
whatever database accesses it needs.  After the last object has been
fetched, the next() will return undef.  Usually you will call next()
inside a loop like this:

  while (my $object = $iterator->next) {
     # do something with $object
  }

Because of the way that object caching works, next() will be most
efficient if you are only looping over one iterator at a time.
Although parallel access will work correctly, it will be less

Ace/Local.pm  view on Meta::CPAN

  my($pid) = open2($rdr,$wtr,"$program $args");
  unless ($pid) {
    $Ace::Error = <$rdr>;
    return undef;
  }

  # Figure out the prompt by reading until we get zero length,
  # then take whatever's at the end.
  unless ($nosync) {
    local($/) = "> ";
    my $data = <$rdr>;
    ($prompt) = $data=~/^(.+> )/m;
    unless ($prompt) {
      $Ace::Error = "$program didn't open correctly";
      return undef;
    }
  }

  return bless {
		'read'   => $rdr,
		'write'  => $wtr,
		'prompt' => $prompt,

Ace/Local.pm  view on Meta::CPAN

    warn "\tquery($msg)";
  }

  return undef if $self->{'status'} == STATUS_ERROR;
  do $self->read() until $self->{'status'} != STATUS_PENDING;
  my $wtr = $self->{'write'};
  print $wtr "$query\n";
  $self->{'status'} = STATUS_PENDING;
}

sub low_read {  # hack to accomodate "uninitialized database" warning from tace
  my $self = shift;
  my $rdr = $self->{'read'};
  return undef unless $self->{'status'} == STATUS_PENDING;
  my $rin = '';
  my $data = '';
  vec($rin,fileno($rdr),1)=1;
  unless (select($rin,undef,undef,1)) {
    $self->{'status'} = STATUS_WAITING;
    return undef;
  }
  sysread($rdr,$data,READSIZE);
  return $data;
}

sub read {
  my $self = shift;
  return undef unless $self->{'status'} == STATUS_PENDING;
  my $rdr  = $self->{'read'};
  my $len  = defined $self->{'buffer'} ? length($self->{'buffer'}) : 0;
  my $plen = length($self->{'prompt'});
  my ($result, $bytes, $pos, $searchfrom);

  while (1) {

    # Read the data directly onto the end of the buffer

    $bytes = sysread($rdr, $self->{'buffer'},
		     READSIZE, $len);

    unless ($bytes > 0) {
      $self->{'status'} = STATUS_ERROR;
      return;
    }

    # check for prompt

    # The following checks were implemented using regexps and $' and
    # friends.  I have changed this to use {r}index and substr (a)
    # because they're much faster than regexps and (b) because using
    # $' and $` causes all regexps in a program to execute
    # very slowly due to excessive and unnecessary pre/post-match
    # copying -- tim.cutts@incyte.com 08 Sep 1999

    # Note, don't need to search the whole buffer for the prompt;
    # just need to search the new data and the prompt length from
    # any previous data.

    $searchfrom = ($len <= $plen) ? 0 : ($len - $plen);

    if (($pos = index($self->{'buffer'},
		      $self->{'prompt'},
		      $searchfrom)) > 0) {
      $self->{'status'} = STATUS_WAITING;
      $result = substr($self->{'buffer'}, 0, $pos);
      $self->{'buffer'} = '';
      return $result;

Ace/Local.pm  view on Meta::CPAN

  return $path unless $homedir;

  $path =~ s!^~[^/]*!$homedir!;
  return $path;
}

__END__

=head1 NAME

Ace::Local - use giface, tace or gifaceclient to open a local connection to an Ace database

=head1 SYNOPSIS

  use Ace::Local
  my $ace = Ace::Local->connect(-path=>'/usr/local/acedb/elegans');
  $ace->query('find author Se*');
  die "Query unsuccessful" unless $ace->status;
  $ace->query('show');
  while ($ace->encore) {
    print $ace->read;
  }

=head1 DESCRIPTION

This class is provided for low-level access to local (non-networked)
Ace databases via the I<giface> program.  You will generally not need
to access it directly.  Use Ace.pm instead.

For the sake of completeness, the method can also use the I<aceclient>
program for its access.  However the Ace::AceDB class is more efficient
for this purpose.

=head1 METHODS

=head2 connect()

  $accessor = Ace::Local->connect(-path=>$path_to_database);

Connect to the database at the indicated path using I<giface> and
return a connection object (an "accessor").  I<Giface> must be on the
current search path.  Multiple accessors may be open simultaneously.

Arguments include:

=over 4

=item B<-path>

Path to the database (location of the "wspec/" directory).

=item B<-program>

Used to indicate the location of the desired I<giface> or
I<gifaceclient> executable.  You may also use I<tace> or I<aceclient>,
but in that case the asGIF() functionality will nog work.  Can be used
to override the search path.

=item B<-host>

Ace/Local.pm  view on Meta::CPAN

entire result.  Canonical example:

  $accessor->query("find Sequence D*");
  die "Got an error ",$accessor->error() if $accessor->status == STATUS_ERROR;
  while ($accessor->status == STATUS_PENDING) {
     $result .= $accessor->read;
  }

=head2 low_read()

Read whatever data's available, or undef if none.  This is only used
by the ace.pl replacement for giface/tace.

=head2 status()

Return the status code from the last operation.  Status codes are
exported by default when you B<use> Ace.pm.  The status codes you may
see are:

  STATUS_WAITING    The server is waiting for a query.
  STATUS_PENDING    A query has been sent and Ace is waiting for

Ace/Local.pm  view on Meta::CPAN

  STATUS_ERROR      A communications or syntax error has occurred

=head2 error()

May return a more detailed error code supplied by Ace.  Error checking
is not fully implemented.

=head2 encore()

This method will return true after you have performed one or more
read() operations, and indicates that there is more data to read.
B<encore()> is functionally equivalent to:

   $encore = $accessor->status == STATUS_PENDING;

In fact, this is how it's implemented.

=head2 auto_save()

Sets or queries the I<auto_save> variable.  If true, the "save"
command will be issued automatically before the connection to the
database is severed.  The default is true.

Examples:

   $accessor->auto_save(1);
   $flag = $accessor->auto_save;

=head1 SEE ALSO

L<Ace>, L<Ace::Object>, L<Ace::Iterator>, L<Ace::Model>

Ace/Model.pm  view on Meta::CPAN


$VERSION = '1.51';

my $TAG     = '\b\w+\b';
my $KEYWORD  = q[^(XREF|UNIQUE|ANY|FREE|REPEAT|Int|Text|Float|DateType)$];
my $METAWORD = q[^(XREF|UNIQUE|ANY|FREE|REPEAT|Int|Text|Float|DateType)$];

# construct a new Ace::Model
sub new {
  my $class = shift;
  my ($data,$db,$break_cycle)  = @_;
  $break_cycle ||= {};

  $data=~s!\s+//.*$!!gm;  # remove all comments
  $data=~s!\0!!g;
  my ($name) = $data =~ /\A[\?\#](\w+)/;
  my $self = bless { 
		    name      => $name,
		    raw       => $data,
		    submodels => [],
	       },$class;

  if (!$break_cycle->{$name} && $db && (my @hashes = grep {$_ ne $name} $data =~ /\#(\S+)/g)) {
    $break_cycle->{$name}++;
    my %seen;
    my @submodels = map {$db->model($_,$break_cycle)} grep {!$seen{$_}++} @hashes;
    $self->{submodels} = \@submodels;
  }

  return $self;
}

sub name {

Ace/Model.pm  view on Meta::CPAN

  $name = $model->name;
  @tags = $model->tags;
  print "Paper is a valid tag" if $model->valid_tag('Paper');

=head1 DESCRIPTION

This class is provided for access to AceDB class models.  It provides
the model in human-readable form, and does some limited but useful
parsing on your behalf.  

Ace::Model objects are obtained either by calling an Ace database
handle's model() method to retrieve the model of a named class, or by
calling an Ace::Object's model() method to retrieve the object's
particular model.

=head1 METHODS

=head2 new()

  $model = Ace::Model->new($model_data);

This is a constructor intended only for use by Ace and Ace::Object
classes.  It constructs a new Ace::Model object from the raw string
data in models.wrm.

=head2 name()

  $name = $model->name;

This returns the class name for the model.

=head2 tags()

   @tags = $model->tags;

Ace/Model.pm  view on Meta::CPAN


   $boolean  = $model->valid_tag($tag);

This returns true if the given tag is part of the model.

=head2 path()
   
   @path = $model->path($tag)

Returns the path to the indicated tag, returning a list of intermediate tags.
For example, in the C elegans ?Locus model, the path for 'Compelementation_data"
will return the list ('Type','Gene').

=head2 asString()

   print $model->asString;

asString() returns the human-readable representation of the model with
comments stripped out.  Internally this method is called to
automatically convert the model into a string when appropriate.  You
need only to start performing string operations on the model object in

Ace/Object.pm  view on Meta::CPAN

	: $self->{'class'};
}

################### name and class together #################
sub id {
  my $self = shift;
  return "$self->{class}:$self->{name}";
}

############## return true if two objects are equivalent ##################
# to be equivalent, they must have identical names, classes and databases #
# We handle comparisons between objects and numbers ourselves, and let    #
# Perl handle comparisons between objects and strings                     #
sub eq {
    my ($a,$b,$rev) = @_;
    unless (UNIVERSAL::isa($b,'Ace::Object')) {
	$a = $a->name + 0; # convert to numeric
	return $a == $b;  # do a numeric comparison
    }
    return 1 if ($a->name eq $b->name) 
      && ($a->class eq $b->class)

Ace/Object.pm  view on Meta::CPAN

sub ne { 
    return !&eq;
}


############ returns true if this is a top-level object #######
sub isRoot {
  return exists shift()->{'.root'};
}

################### handle to ace database #################
sub db {
  my $self = shift;
  if (@_) {
    my $db = shift;
    $self->{db} = "$db";  # store string representation, not object
  }
  Ace->name2db($self->{db});
}

### Return a portion of the tree at the indicated tag path     ###

Ace/Object.pm  view on Meta::CPAN

  $self->{'.dirty'} = shift if @_ && $self->isRoot;
  $self->{'.dirty'};
}

#### return true if tree is populated, without populating it #####
sub filled {
  my $self = shift;
  return exists($self->{'.right'}) || exists($self->{'.raw'});
}

#### return true if you can follow the object in the database (i.e. a class ###
sub isPickable {
    return shift->isObject;
}

#### Return a string representation of the object subject to Ace escaping rules ###
sub escape {
  my $self = shift;
  my $name = $self->name;
  my $needs_escaping = $name=~/[^\w.-]/ || $self->isClass;
  return $name unless $needs_escaping;

Ace/Object.pm  view on Meta::CPAN

  $self->_parse;
  return $self->{'.down'} unless defined $pos;
  my $node = $self;
  while ($pos--) {
    defined($node = $node->down) || return;
  }
  $node;
}

#############################################
#  fetch current node from the database     #
sub fetch {
    my ($self,$tag) = @_;
    return $self->search($tag) if defined $tag;
    my $thing_to_pick = ($self->isTag and defined($self->right)) ? $self->right : $self;
    return $thing_to_pick unless $thing_to_pick->isObject;
    my $obj = $self->db->get($thing_to_pick->class,$thing_to_pick->name) if $self->db;
    return $obj;
}

#############################################
# follow a tag into the database, returning a
# list of followed objects.
sub follow {
    my $self = shift;
    my ($tag,$filled) =  rearrange(['TAG','FILLED'],@_);

    return unless $self->db;
    return $self->fetch() unless $tag;
    my $class = $self->class;
    my $name = Ace->freeprotect($self->name);
    my @options;
    if ($filled) {
      @options = $filled =~ /^[a-zA-Z]/ ? ('filltag' => $filled) : ('filled'=>1);
    }
    return $self->db->fetch(-query=>"find $class $name ; follow $tag",@options);
}

# returns true if the object has a Model, i.e, can be followed into
# the database.
sub isObject {
    my $self = shift;
    return _isObject($self->class);
    1;
}

# returns true if the object is a tag.
sub isTag {
    my $self = shift;
    return 1 if $self->class eq 'tag';

Ace/Object.pm  view on Meta::CPAN

}

### Returns the object's model (as an Ace::Model object)
sub model {
  my $self = shift;
  return unless $self->db && $self->isObject;
  return $self->db->model($self->class);
}

### Return the class in which to bless all objects retrieved from
# database. Might want to override in other classes
sub factory {
  return __PACKAGE__;
}

#####################################################################
#####################################################################
############### mostly private functions from here down #############
#####################################################################
#####################################################################
# simple clone

Ace/Object.pm  view on Meta::CPAN

    # Turn into a toplevel object
    $newobj{'.root'}++;
    return bless \%newobj,$pack;
}

sub _fill {
    my $self = shift;
    return if $self->filled;
    return unless $self->db && $self->isObject;

    my $data = $self->db->pick($self->class,$self->name);
    return unless $data;

    # temporary object, don't cache it.
    my $new = $self->newFromText($data,$self->db);
    %{$self}=%{$new};

    $new->{'.nocache'}++; # this line prevents the thing from being cached

    $self->_dirty(1);
}

sub _parse {
  my $self = shift;
  return unless my $raw = $self->{'.raw'};

Ace/Object.pm  view on Meta::CPAN

    my $o = $self->right;
    while ($o) {
	return ($o->right($pos),$p,$self) if (lc($o) eq lc($tag));
	$p = $o;
	$o = $o->down;
    }
    return;
}


# Used to munge special data types.  Right now dates are the
# only examples.
sub _ace_format {
  my $self = shift;
  my ($class,$name) = @_;
  return undef unless defined $class && defined $name;
  return $class eq 'date' ? $self->_to_ace_date($name) : $name;
}

# It's an object unless it is one of these things
sub _isObject {

Ace/Object.pm  view on Meta::CPAN

1;

__END__

=head1 NAME

Ace::Object - Manipulate  Ace Data Objects

=head1 SYNOPSIS

    # open database connection and get an object
    use Ace;
    $db = Ace->connect(-host => 'beta.crbm.cnrs-mop.fr',
                       -port => 20000100);
    $sequence  = $db->fetch(Sequence => 'D12345');
    
    # Inspect the object
    $r    = $sequence->at('Visible.Overlap_Right');
    @row  = $sequence->row;
    @col  = $sequence->col;
    @tags = $sequence->tags;
    
    # Explore object substructure
    @more_tags = $sequence->at('Visible')->tags;
    @col       = $sequence->at("Visible.$more_tags[1]")->col;

    # Follow a pointer into database
    $r     = $sequence->at('Visible.Overlap_Right')->fetch;
    $next  = $r->at('Visible.Overlap_left')->fetch;

    # Classy way to do the same thing
    $r     = $sequence->Overlap_right;
    $next  = $sequence->Overlap_left;

    # Pretty-print object
    print $sequence->asString;
    print $sequence->asTabs;

Ace/Object.pm  view on Meta::CPAN


    # Rollback changes
    $sequence->rollback()

    # Get errors
    print $sequence->error;

=head1 DESCRIPTION

I<Ace::Object> is the base class for objects returned from ACEDB
databases. Currently there is only one type of I<Ace::Object>, but
this may change in the future to support more interesting
object-specific behaviors.

Using the I<Ace::Object> interface, you can explore the internal
structure of an I<Ace::Object>, retrieve its content, and convert it
into various types of text representation.  You can also fetch a
representation of any object as a GIF image.

If you have write access to the databases, add new data to an object,
replace existing data, or kill it entirely.  You can also create a new
object de novo and write it into the database.

For information on connecting to ACEDB databases and querying them,
see L<Ace>.

=head1 ACEDB::OBJECT METHODS

The structure of an Ace::Object is very similar to that of an Acedb
object.  It is a tree structure like this one (an Author object):

 Thierry-Mieg J->Full_name ->Jean Thierry-Mieg
                  |
                 Laboratory->FF

Ace/Object.pm  view on Meta::CPAN

such as the multiple papers written by the Author.

Each node in the tree has a type and a name.  Types include integers,
strings, text, floating point numbers, as well as specialized
biological types, such as "dna" and "peptide."  Another fundamental
type is "tag," which is a text identifier used to label portions of
the tree.  Examples of tags include "Paper" and "Laboratory" in the
example above.

In addition to these built-in types, there are constructed types known
as classes.  These types are specified by the data model.  In the
above example, "Thierry-Mieg J" is an object of the "Author" class,
and "Genome Project Database" is an object of the "Paper" class.  An
interesting feature of objects is that you can follow them into the
database, retrieving further information.  For example, after
retrieving the "Genome Project Database" Paper from the Author object,
you could fetch more information about it, either by following B<its>
right pointer, or by using one of the specialized navigation routines
described below.

=head2 new() method

    $object = new Ace::Object($class,$name,$database);
    $object = new Ace::Object(-class=>$class,
                              -name=>$name,
                              -db=>database);

You can create a new Ace::Object from scratch by calling the new()
routine with the object's class, its identifier and a handle to the
database to create it in.  The object won't actually be created in the
database until you add() one or more tags to it and commit() it (see
below).  If you do not provide a database handle, the object will be
created in memory only.

Arguments can be passed positionally, or as named parameters, as shown
above.

This routine is usually used internally.  See also add_row(),
add_tree(), delete() and replace() for ways to manipulate this object.

=head2 name() method

Ace/Object.pm  view on Meta::CPAN

    $object = $db->fetch(Author,"Thierry-Mieg J");
    print "$object did not write 'Pride and Prejudice.'\n";

=head2 class() method

    $class = $object->class();

Return the class of the object.  The return value may be one of
"float," "int," "date," "tag," "txt," "dna," "peptide," and "scalar."
(The last is used internally by Perl to represent objects created
programatically prior to committing them to the database.)  The class
may also be a user-constructed type such as Sequence, Clone or
Author.  These user-constructed types usually have an initial capital
letter.

=head2 db() method

     $db = $object->db();

Return the database that the object is associated with.

=head2 isClass() method

     $bool = $object->isClass();

Returns true if the object is a class (can be fetched from the
database).

=head2 isTag() method

     $bool = $object->isTag();

Returns true if the object is a tag.

=head2 tags() method

     @tags = $object->tags();

Ace/Object.pm  view on Meta::CPAN

If $object contains the "Thierry-Mieg J" Author object, then the first
series of accesses shown above retrieves the string "Jean
Thierry-Mieg" and the second retrieves "34033 Montpellier."  If the
right or bottom pointers are NULL, these methods will return undef.

In addition to being somewhat awkard, you will probably never need to
use these methods.  A simpler way to retrieve the same information
would be to use the at() method described in the next section.  

The right() and down() methods always walk through the tree of the
current object.  They do not follow object pointers into the database.
Use B<fetch()> (or the deprecated B<pick()> or B<follow()> methods)
instead.

=head2 at() method

    $subtree    = $object->at($tag_path);
    @values     = $object->at($tag_path);

at() is a simple way to fetch the portion of the tree that you are
interested in.  It takes a single argument, a simple tag or a path.  A

Ace/Object.pm  view on Meta::CPAN

index at all.  An index of [1] navigates one step to the right, [2]
moves two steps to the right, and so on.  Using the Thierry-Mieg
object as an example again, here are the results of various indexes:

    $object = $db->fetch(Author,"Thierry-Mieg J");
    $a = $object->at('Address[0]')   --> "Address"
    $a = $object->at('Address[1]')   --> "Mail"
    $a = $object->at('Address[2]')   --> "CRBM duCNRS"

In an array context, the last index in the path does something very
interesting.  It returns the entire column of data K steps to the
right of the path, where K is the index.  This is used to implement
so-called "tag[2]" syntax, and is very useful in some circumstances.
For example, here is a fragment of code to return the Thierry-Mieg
object's full address without having to refer to each of the
intervening "Mail", "E_Mail" and "Phone" tags explicitly.

   @address = $object->at('Address[2]');
   --> ('CRBM duCNRS','BP 5051','34033 Montpellier','FRANCE',
        'mieg@kaa.cnrs-mop.fr,'33-67-613324','33-67-521559')

Similarly, "tag[3]" will return the column of data three hops to the
right of the tag.  "tag[1]" is identical to "tag" (with no index), and
will return the column of data to the immediate right.  There is no
special behavior associated with using "tag[0]" in an array context;
it will always return the subtree rooted at the indicated tag.

Internal indices such as "Homol[2].BLASTN", do not have special
behavior in an array context.  They are always treated as if they were
called in a scalar context.

Also see B<col()> and B<get()>.

=head2 get() method

Ace/Object.pm  view on Meta::CPAN


=head2 Autogenerated Access Methods

     $scalar = $object->Name_of_tag;
     $scalar = $object->Name_of_tag($position);
     @array  = $object->Name_of_tag;
     @array  = $object->Name_of_tag($position);
     @array  = $object->Name_of_tag($subtag=>$position);
     @array  = $object->Name_of_tag(-fill=>$tag);

The module attempts to autogenerate data access methods as needed.
For example, if you refer to a method named "Fax" (which doesn't
correspond to any of the built-in methods), then the code will call
the B<get()> method to find a tag named "Fax" and return its
contents.

Unlike get(), this method will B<always step into objects>.  This
means that:

   $map = $clone->Map;

Ace/Object.pm  view on Meta::CPAN


  @papers = $author->Paper;
  foreach (@papers) { 
    my $paper = $_->fetch;
    print  $paper->asString;
  }

You can provide an optional positional index to rapidly navigate
through the tree or to obtain tag[2] behavior.  In the following
examples, the first two return the object's Fax number, and the third
returns all data two hops to the right of Address.

     $object   = $db->fetch(Author => 'Thierry-Mieg J');
     ($fax_no) = $object->Fax;
     $fax_no   = $object->Fax(1);
     @address  = $object->Address(2);

You may also position at a subtag, using this syntax:

     $representative = $object->Laboratory('Representative');

Ace/Object.pm  view on Meta::CPAN

versions, calling an autogenerated method in a scalar context returned
the subtree rooted at the tag.  In the current version, an implicit
right() and dereference is performed.


=head2 fetch() method

    $new_object = $object->fetch;
    $new_object = $object->fetch($tag);

Follow object into the database, returning a new object.  This is
the best way to follow object references.  For example:

    $laboratory = $object->at('Laboratory')->fetch;
    print $laboratory->asString;

Because the previous example is a frequent idiom, the optional $tag
argument allows you to combine the two operations into a single one:

    $laboratory = $object->fetch('Laboratory');

=head2 follow() method

    @papers        = $object->follow('Paper');
    @filled_papers = $object->follow(-tag=>'Paper',-filled=>1);
    @filled_papers = $object->follow(-tag=>'Paper',-filled=>'Author');

The follow() method will follow a tag into the database, dereferencing
the column to its right and returning the objects resulting from this
operation.  Beware!  If you follow a tag that points to an object,
such as the Author "Paper" tag, you will get a list of all the Paper
objects.  If you follow a tag that points to a scalar, such as
"Full_name", you will get an empty string.  In a scalar context, this
method will return the number of objects that would have been
followed.

The full named-argument form of this call accepts the arguments
B<-tag> (mandatory) and B<-filled> (optional).  The former points to
the tag to follow.  The latter accepts a boolean argument or the name
of a subtag.  A numeric true argument will return completely "filled"
objects, increasing network and memory usage, but possibly boosting
performance if you have a high database access latency.
Alternatively, you may provide the name of a tag to follow, in which
case just the named portion of the subtree in the followed objects
will be filled (v.g.)

For backward compatability, if follow() is called without any
arguments, it will act like fetch().

=head2 pick() method

Deprecated method.  This has the same semantics as fetch(), which

Ace/Object.pm  view on Meta::CPAN

Use whatever syntax is most comfortable for you.

In a scalar context, B<col()> returns the number of items in the
column.

=head2 row() method

     @row=$object->row();
     @row=$object->row($position);

B<row()> will return the row of data to the right of the object.  The
first member of the list will be the object itself.  In the case of
the "Thierry-Mieg J" object, the example below will return the list
('Address','Mail','CRBM duCNRS').

     @row = $object->Address->row();

You can provide an optional position to move rightward one or more
places before retrieving the row.  This code fragment will return
('Mail','CRBM duCNRS'):

Ace/Object.pm  view on Meta::CPAN


The option B<-coords> argument allows you to provide the top and
bottom of the display for MAP objects only.  These coordinates are in
the map's native coordinate system (cM, bp).  By default, AceDB will
show most (but not necessarily all) of the map according to xace's
display rules.  If you call this method with the B<-getcoords>
argument and a true value, it will return a two-element array
containing the coordinates of the top and bottom of the map.

asGIF() returns a two-element array.  The first element is the GIF
data.  The second element is an array reference that indicates special 
areas of the image called "boxes."  Boxes are rectangular areas that
surround buttons, and certain displayed objects.  Using the contents
of the boxes array, you can turn the GIF image into a client-side
image map.  Unfortunately, not everything that is clickable is
represented as a box.  You still have to pass clicks on unknown image
areas back to the server for processing.

Each box in the array is a hash reference containing the following
keys:

    'coordinates'  => [$left,$top,$right,$bottom]
    'class'        => object class or "BUTTON"
    'name'         => object name, if any
    'comment'      => a text comment of some sort

I<coordinates> points to an array of points indicating the top-left and 
bottom-right corners of the rectangle.  I<class> indicates the class
of the object this rectangle surrounds.  It may be a database object,
or the special word "BUTTON" for one of the display action buttons.
I<name> indicates the name of the object or the button.  I<comment> is 
some piece of information about the object in question.  You can
display it in the status bar of the browser or in a popup window if
your browser provides that facility.

=head2 asDNA() and asPeptide() methods

    $dna = $object->asDNA();
    $peptide = $object->asPeptide();

Ace/Object.pm  view on Meta::CPAN

will return strings corresponding to the DNA or peptide sequence in
FASTA format.

=head2 add_row() method

    $result_code = $object->add_row($tag=>$value);    
    $result_code = $object->add_row($tag=>[list,of,values]);    
    $result_code = $object->add(-path=>$tag,
				-value=>$value);

add_row() updates the tree by adding data to the indicated tag path.  The
example given below adds the value "555-1212" to a new Address entry
named "Pager".  You may call add_row() a second time to add a new value
under this tag, creating multi-valued entries.

 $object->add_row('Address.Pager'=>'555-1212');

You may provide a list of values to add an entire row of data.  For
example:

 $sequence->add_row('Assembly_tags'=>['Finished Left',38949,38952,'AC3']);

Actually, the array reference is not entirely necessary, and if you
prefer you can use this more concise notation:

 $sequence->add_row('Assembly_tags','Finished Left',38949,38952,'AC3');

No check is done against the database model for the correct data type
or tag path.  The update isn't actually performed until you call
commit(), at which time a result code indicates whether the database
update was successful.

You may create objects that reference other objects this way:

    $lab = new Ace::Object('Laboratory','LM',$db);
    $lab->add_row('Full_name','The Laboratory of Medicine');
    $lab->add_row('City','Cincinatti');
    $lab->add_row('Country','USA');

    $author = new Ace::Object('Author','Smith J',$db);

Ace/Object.pm  view on Meta::CPAN


See also the Ace->new() method.

=head2 add_tree()

  $result_code = $object->add_tree($tag=>$ace_object);
  $result_code = $object->add_tree(-tag=>$tag,-tree=>$ace_object);

The add_tree() method will insert an entire Ace subtree into the object
to the right of the indicated tag.  This can be used to build up
complex Ace objects, or to copy portions of objects from one database
to another.  The first argument is a tag path, and the second is the
tree that you wish to insert.  As with add_row() the database will
only be updated when you call commit().

When inserting a subtree, you must be careful to remember that
everything to the *right* of the node that you are pointing at will be
inserted; not the node itself.  For example, given this Sequence
object:

  Sequence AC3
    DB_info     Database    EMBL
    Assembly_tags   Finished Left   1   4   AC3
                    Clone left end      1   4   AC3
                    Clone right end     5512    5515    K07C5
                                        38949   38952   AC3
                    Finished Right      38949   38952   AC3

If we use at('Assembly_tags') to fetch the subtree rooted on the
"Assembly_tags" tag, it is the tree to the right of this tag,
beginning with "Finished Left", that will be inserted.

Here is an example of copying the "Assembly_tags" subtree
from one database object to another:

 $remote = Ace->connect(-port=>200005)  || die "can't connect";
 $ac3 = $remote->fetch(Sequence=>'AC3') || die "can't get AC7";
 my $assembly = $ac3->at('Assembly_tags');

 $local = Ace->connect(-path=>'~acedb') || die "can't connect";
 $AC3copy = Ace::Object->new(Sequence=>'AC3copy',$local);
 $AC3copy->add_tree('Assembly_tags'=>$tags);
 $AC3copy->commit || warn $AC3copy->error;

Ace/Object.pm  view on Meta::CPAN


    $result_code = $object->delete($tag_path,$value);
    $result_code = $object->delete(-path=>$tag_path,
                                   -value=>$value);

Delete the indicated tag and value from the object.  This example
deletes the address line "FRANCE" from the Author's mailing address:

    $object->delete('Address.Mail','FRANCE');

No actual database deletion occurs until you call commit().  The
delete() result code indicates whether the deletion was successful.
Currently it is always true, since the database model is not checked.
    
=head2 replace() method

    $result_code = $object->replace($tag_path,$oldvalue,$newvalue);
    $result_code = $object->replace(-path=>$tag_path,
				    -old=>$oldvalue,
				    -new=>$newvalue);

Replaces the indicated tag and value with the new value.  This example
changes the address line "FRANCE" to "LANGUEDOC" in the Author's
mailing address:

    $object->delete('Address.Mail','FRANCE','LANGUEDOC');

No actual database changes occur until you call commit().  The
delete() result code indicates whether the replace was successful.
Currently is true if the old value was identified.

=head2 commit() method

     $result_code = $object->commit;

Commits all add(), replace() and delete() operations to the database.
It can also be used to write a completely new object into the
database.  The result code indicates whether the object was
successfully written.  If an error occurred, further details can be
found in the Ace->error() error string.

=head2 rollback() method

    $object->rollback;

Discard all adds, deletions and replacements, returning the object to
the state it was in prior to the last commit().

rollback() works by deleting the object from Perl memory and fetching
the object anew from AceDB.  If someone has changed the object in the
database while you were working with it, you will see this version,
ot the one you originally fetched.

If you are creating an entirely new object, you I<must> add at least
one tag in order to enter the object into the database.

=head2 kill() method

    $result_code = $object->kill;

This will remove the object from the database immediately and
completely.  It does not wait for a commit(), and does not respond to
a rollback().  If successful, you will be left with an empty object
that contains just the class and object names.  Use with care!

In the case of failure, which commonly happens when the database is
not open for writing, this method will return undef.  A description of
the problem can be found by calling the error() method.

=head2 date_style() method

   $object->date_style('ace');

This is a convenience method that can be used to set the date format
for all objects returned by the database.  It is exactly equivalent to

   $object->db->date_style('ace');

Note that the text representation of the date will change for all
objects returned from this database, not just the current one.

=head2 isRoot() method

    print "Top level object" if $object->isRoot;

This method will return true if the object is a "top level" object,
that is the root of an object tree rather than a subtree.

=head2 model() method

Ace/Object.pm  view on Meta::CPAN

This method will return the object's model as an Ace::Model object, or
undef if the object does not have a model. See L<Ace::Model> for
details.

=head2 timestamp() method

   $stamp = $object->timestamp;

The B<timestamp()> method will retrieve the modification time and date
from the object.  This works both with top level objects and with
subtrees.  Timestamp handling must be turned on in the database, or
B<timestamp()> will return undef.

The returned timestamp is actually a UserSession object which can be
printed and explored like any other object.  However, there is
currently no useful information in UserSession other than its name.

=head2 comment() method

   $comment = $object->comment;

Ace/Object.pm  view on Meta::CPAN

    for (my $i=0;$i<@fields;$i++) {
      $max[$i] = length($fields[$i]) if
	!defined($max[$i]) or $max[$i] < length($fields[$i]);
    }
  }
  foreach (@max) { $_ = $MAXWIDTH if $_ > $MAXWIDTH; } # crunch long lines
  my $format1 = join(' ',map { "^"."<"x $max[$_] } (0..$#max)) . "\n";
  my $format2 =   ' ' . join('  ',map { "^"."<"x ($max[$_]-1) } (0..$#max)) . "~~\n";
  $^A = '';
  foreach (@lines) {
    my @data = split("\t");
    push(@data,('')x(@max-@data));
    formline ($format1,@data);
    formline ($format2,@data);
  }
  return ($result = $^A,$^A='')[0];
}

# run a series of GIF commands and return the Gif and the semi-parsed
# "boxes" structure.  Commands is typically a series of mouseclicks
# ($gif,$boxes) = $aceObject->asGif(-clicks=>[[$x1,$y1],[$x2,$y2]...],
#                                   -dimensions=>[$x,$y]);
sub asGif {
  my $self = shift;

Ace/Object.pm  view on Meta::CPAN

  if ($view || $c || $self->class =~ /Map/i) {
      @commands = "gif map \"@{[$self->name]}\" $view $c";
  } else {
      @commands = "gif display $display $view @{[$self->class]} \"@{[$self->name]}\"";
  }
  push(@commands,"Dimensions @$dimensions") if ref($dimensions);
  push(@commands,map { "mouseclick @{$_}" } @$clicks) if ref($clicks);

  if ($getcoords) { # just want the coordinates
    my ($start,$stop);
    my $data = $self->db->raw_query(join(' ; ',@commands));    
    return unless $data =~ /\"[^\"]+\" ([\d.-]+) ([\d.-]+)/;
    ($start,$stop) = ($1,$2);
    return ($start,$stop);
  }

  push(@commands,"gifdump -");

  # do the query
  my $data = $self->db->raw_query(join(' ; ',@commands));

  # A $' has been removed here to improve speed -- tim.cutts@incyte.com 2 Sep 1999

  # did this query succeed?
  my ($bytes, $trim);
  return unless ($bytes, $trim) = $data=~m!^// (\d+) bytes\n\0*(.+)!sm;

  my $gif = substr($trim,0,$bytes);

  # now process the boxes
  my @b;
  my @boxes = split("\n",substr($trim,$bytes));
  foreach (@boxes) {
    last if m!^//!;
    chomp;
    my ($left,$top,$right,$bottom,$class,$name,$comments) = 

Ace/Object.pm  view on Meta::CPAN

    my $current = $self->right;
    my @tags;
    while (defined($current)) {
	push(@tags,$current);
	$current = $current->down;
    }
    return @tags;
}

################# kill an object ################
# Removes the object from the database immediately.
sub kill {
  my $self = shift;
  return unless my $db = $self->db;
  return 1 unless $db->count($self->class,$self->name);
  my $result = $db->raw_query("kill");
  if (defined($result) and $result=~/write access/im) {  # this keeps changing
    $Ace::Error = "Write access denied";
    return;
  }
  # uncache cached values and clear the object out

Ace/Object.pm  view on Meta::CPAN

    $p->{'.right'} = $values[0];
  }

  push(@{$self->{'.update'}},join(' ',map { Ace->freeprotect($_) } (@tags,@values)));
  delete $self->{'.PATHS'}; # uncache cached values
  $self->_dirty(1);
  1;
}

# Use this method to add an entire subobject to the right of the tag.
# The tree may come from another database.
sub add_tree {
  my $self = shift;
  my($tag,$value,@rest) = rearrange([['TAG','PATH'],['VALUE','TREE']],@_);
  croak "Value must be an Ace::Object" unless ref($value) && $value->isa('Ace::Object');

  unless ($tag =~ /\./) {
    my $model = $self->model;
    my @intermediate_tags = $model->path($tag);
    $tag = join '.',@intermediate_tags,$tag;
  }

Ace/Object.pm  view on Meta::CPAN

  my $self = shift;
  my($tag,$oldvalue,$newvalue,@rest) = rearrange([['TAG','PATH'],
						  ['OLDVALUE','OLD'],
						  ['NEWVALUE','NEW']],@_);
    $self->delete($tag,$oldvalue);
    $self->add($tag,$newvalue,@rest);
    delete $self->{'.PATHS'}; # uncache cached values
    1;
}

# commit changes from local copy to database copy
sub commit {
  my $self = shift;
  return unless my $db = $self->db;
  
  my ($retval,@cmd);
  my $name = $self->{'name'};
  return unless defined $name;
  
  $name =~ s/([^a-zA-Z0-9_-])/\\$1/g;
  return 1 unless exists $self->{'.update'} && $self->{'.update'};

Ace/Object.pm  view on Meta::CPAN

  # and synchronize our in-memory copy with the db
  delete $self->{'.right'};
  delete $self->{'.PATHS'};
  return 1;
}

# undo changes
sub rollback {
    my $self = shift;
    undef $self->{'.update'};
    # this will force object to be reloaded from database
    # next time it is needed.
    delete $self->{'.right'};
    delete $self->{'.PATHS'};
    1;
}

sub debug {
    my $self = shift;
    Ace->debug(@_);
}

### Get or set the date style (actually calls through to the database object) ###
sub date_style {
  my $self = shift;
  return unless $self->db;
  return $self->db->date_style(@_);
}

sub _asHTML {
  my($self,$out,$position,$level,$morph_code) = @_;
  do {
    $$out .= "<TR ALIGN=LEFT VALIGN=TOP>" unless $position;

Ace/Object.pm  view on Meta::CPAN

  } while defined $self;
  return --$level;
}


# This function is overly long because it is optimized to prevent parsing
# parts of the tree that haven't previously been parsed.
sub _asTable {
    my($self,$out,$position,$level) = @_;
    do {
      if ($self->{'.raw'}) {  # we still have raw data, so we can optimize
	my ($a,$start,$end) = @{$self}{ qw(.col .start_row .end_row) };
	my @to_append = map { join("\t",@{$_}[$a..$#{$_}]) } @{$self->{'.raw'}}[$start..$end];
	my $new_row;
	foreach (@to_append) {
	  # hack alert
	  s/(\?.*?[^\\]\?.*?[^\\]\?)\S*/$self->_ace_format(Ace->split($1))/eg;
	  if ($new_row++) {
	    $$out .= "\n";
	    $$out .= "\t" x ($level-1) 
	  }

Ace/Object.pm  view on Meta::CPAN

    $string = "<B>$self</B>";
  } elsif ($self->isComment) {
    $string = "<I>$self</I>";
  }  else {
    $string = qq{<FONT COLOR="blue">$self</FONT>} ;
  }
  return ($string,$prune);
}

# Insert a new tag or value.
# Local only. Will not affect the database.
# Returns the inserted tag, or the preexisting
# tag, if already there.
sub _insert {
    my ($self,$tag) = @_;
    my $p = $self->{'.right'};
    return $self->{'.right'} = $self->new('tag',$tag)
	unless $p;
    while ($p) {
	return $p if "$p" eq $tag;
	last unless $p->{'.down'};

Ace/Sequence.pm  view on Meta::CPAN

	       'REFSEQ',
	       ['DATABASE','DB'],
	      ],@_);

  # Object must have a parent sequence and/or a reference
  # sequence.  In some cases, the parent sequence will be the
  # object itself.  The reference sequence is used to set up
  # the frame of reference for the coordinate system.

  # fetch the sequence object if we don't have it already
  croak "Please provide either a Sequence object or a database and name"
    unless ref($seq) || ($seq && $db);

  # convert start into offset
  $offset = $start - 1 if defined($start) and !defined($offset);

  # convert stop/end into length
  $length = ($end > $start) ? $end - $offset : $end - $offset - 2
    if defined($end) && !defined($length);

  # if just a string is passed, try to fetch a Sequence object
  my $obj = ref($seq) ? $seq : $db->fetch('Sequence'=>$seq);
  unless ($obj) {
    Ace->error("No Sequence named $obj found in database");
    return;
  }

  # get parent coordinates and length of this sequence
  # the parent is an Ace Sequence object in the "+" strand
  my ($parent,$p_offset,$p_length,$strand) = find_parent($obj);
  return unless $parent;

  # handle negative strands
  my $r_strand = $strand;

Ace/Sequence.pm  view on Meta::CPAN

	croak "Reference sequence has no common ancestor with sequence"
	  unless $self->parent eq $refseq->parent;
	my ($a,$b,$c) = @{$refseq->{refseq}};
	#	$b += $refseq->offset;
	$b += $refseq->offset;
	$arrayref = [$refseq,$b,$refseq->strand];
	last BLOCK;
      }


      # look up reference sequence in database if we aren't given
      # database object already
      $refseq = $self->db->fetch('Sequence' => $refseq)
	unless $refseq->isa('Ace::Object');
      croak "Invalid reference sequence" unless $refseq;

      # find position of ref sequence in parent strand
      my ($r_parent,$r_offset,$r_length,$r_strand) = find_parent($refseq);
      croak "Reference sequence has no common ancestor with sequence" 
	unless $r_parent eq $self->{parent};

      # set to array reference containing this information

Ace/Sequence.pm  view on Meta::CPAN

sub type    { 'Sequence' }
sub subtype { }

sub debug {
  my $self = shift;
  my $d = $self->{_debug};
  $self->{_debug} = shift if @_;
  $d;
}

# return the database this sequence is associated with
sub db {
  return Ace->name2db($_[0]->{db} ||= $_[0]->source->db);
}

sub start {
  my ($self,$abs) = @_;
  $abs = $self->absolute unless defined $abs;
  return $self->{p_offset} + $self->{offset} + 1 if $abs;

  if ($self->refseq) {

Ace/Sequence.pm  view on Meta::CPAN

  }
  my @features = map {Ace::Sequence::Feature->new($parent,$r,$r_offset,$r_strand,$abs,$_)}
                 grep !m@^(?:\#|//)@ && $filter->($_),split("\n",$gff);
}


# low level GFF call, no changing absolute to relative coordinates
sub _gff {
  my $self = shift;
  my ($opt,$db) = @_;
  my $data = $self->_query("seqfeatures -version 2 $opt",$db);
  $data =~ s/\0+\Z//;
  return $data; #blasted nulls!
}

# shortcut for running a gif query
sub _query {
  my $self = shift;
  my $command = shift;
  my $db      = shift || $self->db;

  my $parent = $self->parent;
  my $start = $self->start(1);

Ace/Sequence.pm  view on Meta::CPAN

}

1;

=head1 NAME

Ace::Sequence - Examine ACeDB Sequence Objects

=head1 SYNOPSIS

    # open database connection and get an Ace::Object sequence
    use Ace::Sequence;

    $db  = Ace->connect(-host => 'stein.cshl.org',-port => 200005);
    $obj = $db->fetch(Predicted_gene => 'ZK154.3');

    # Wrap it in an Ace::Sequence object 
    $seq = Ace::Sequence->new($obj);

    # Find all the exons
    @exons = $seq->features('exon');

Ace/Sequence.pm  view on Meta::CPAN


I<Ace::Sequence>, and its allied classes L<Ace::Sequence::Feature> and
L<Ace::Sequence::FeatureList>, provide a convenient interface to the
ACeDB Sequence classes and the GFF sequence feature file format.

Using this class, you can define a region of the genome by using a
landmark (sequenced clone, link, superlink, predicted gene), an offset
from that landmark, and a distance.  Offsets and distances can be
positive or negative.  This will return an I<Ace::Sequence> object.
Once a region is defined, you may retrieve its DNA sequence, or query
the database for any features that may be contained within this
region.  Features can be returned as objects (using the
I<Ace::Sequence::Feature> class), as GFF text-only dumps, or in the
form of the GFF class defined by the Sanger Centre's GFF.pm module.

This class builds on top of L<Ace> and L<Ace::Object>.  Please see
their manual pages before consulting this one.

=head1 Creating New Ace::Sequence Objects, the new() Method

 $seq = Ace::Sequence->new($object);

Ace/Sequence.pm  view on Meta::CPAN

                           -length  => $length,
			   -refseq  => $reference_sequence);

 $seq = Ace::Sequence->new(-name    => $name,
			   -db      => $db,
                           -offset  => $offset,
                           -length  => $length,
			   -refseq  => $reference_sequence);

In order to create an I<Ace::Sequence> you will need an active I<Ace>
database accessor.  Sequence regions are defined using a "source"
sequence, an offset, and a length.  Optionally, you may also provide a
"reference sequence" to establish the coordinate system for all
inquiries.  Sequences may be generated from existing I<Ace::Object>
sequence objects, from other I<Ace::Sequence> and
I<Ace::Sequence::Feature> objects, or from a sequence name and a
database handle.

The class method named new() is the interface to these facilities.  In
its simplest, one-argument form, you provide new() with a
previously-created I<Ace::Object> that points to Sequence or
sequence-like object (the meaning of "sequence-like" is explained in
more detail below.)  The new() method will return an I<Ace::Sequence>
object extending from the beginning of the object through to its
natural end.

In the named-parameter form of new(), the following arguments are

Ace/Sequence.pm  view on Meta::CPAN

You can provide either an I<Ace::Object> or just a sequence name for
this argument.  The source and reference sequences must share a common
ancestor, but do not have to be directly related.  An attempt to use a
disjunct reference sequence, such as one on a different chromosome,
will fail.

=item -name

As an alternative to using an I<Ace::Object> with the B<-source>
argument, you may specify a source sequence using B<-name> and B<-db>.
The I<Ace::Sequence> module will use the provided database accessor to
fetch a Sequence object with the specified name. new() will return
undef is no Sequence by this name is known.

=item -db

This argument is required if the source sequence is specified by name
rather than by object reference.

=back

Ace/Sequence.pm  view on Meta::CPAN

sequence corresponds to the smallest ACeDB sequence object that
completely encloses the selected sequence segment.  The "parent"
sequence is the smallest ACeDB sequence object that contains the
"source".  The parent is used to derive the length and orientation of
source sequences that are not directly associated with DNA objects.

In many cases, the source sequence will be identical to the sequence
initially passed to the new() method.  However, there are exceptions
to this rule.  One common exception occurs when the offset and/or
length cross the boundaries of the passed-in sequence.  In this case,
the ACeDB database is searched for the smallest sequence that contains 
both endpoints of the I<Ace::Sequence> object.

The other common exception occurs in Ace 4.8, where there is support
for "sequence-like" objects that contain the C<SMap> ("Sequence Map")
tag.  The C<SMap> tag provides genomic location information for
arbitrary object -- not just those descended from the Sequence class.
This allows ACeDB to perform genome map operations on objects that are
not directly related to sequences, such as genetic loci that have been
interpolated onto the physical map.  When an C<SMap>-containing object
is passed to the I<Ace::Sequence> new() method, the module will again

Ace/Sequence.pm  view on Meta::CPAN


Return the immediate ancestor of this I<Ace::Sequence> (i.e., the
sequence that contains this one).  The return value is a new
I<Ace::Sequence> or undef, if no parent sequence exists.

=head2 get_children()

  @children = $seq->get_children();

Returns all subsequences that exist as independent objects in the
ACeDB database.  What exactly is returned is dependent on the data
model.  In older ACeDB databases, the only subsequences are those
under the catchall Subsequence tag.  In newer ACeDB databases, the
objects returned correspond to objects to the right of the S_Child
subtag using a tag[2] syntax, and may include Predicted_genes,
Sequences, Links, or other objects.  The return value is a list of
I<Ace::Sequence> objects.

=head2 features()

  @features = $seq->features;
  @features = $seq->features('exon','intron','Predicted_gene');
  @features = $seq->features('exon:GeneFinder','Predicted_gene:hand.*');

Ace/Sequence.pm  view on Meta::CPAN

merged together by the features() call.  If true (the default), then
the left and right end of clones will be merged into "clone" features,
introns, exons and CDS entries will be merged into
Ace::Sequence::Transcript objects, and similarity entries will be
merged into Ace::Sequence::GappedAlignment objects.

=head2 db()

  $db = $seq->db;

Returns the L<Ace> database accessor associated with this sequence.

=head1 SEE ALSO

L<Ace>, L<Ace::Object>, L<Ace::Sequence::Feature>,
L<Ace::Sequence::FeatureList>, L<GFF>

=head1 AUTHOR

Lincoln Stein <lstein@cshl.org> with extensive help from Jean
Thierry-Mieg <mieg@kaa.crbm.cnrs-mop.fr>

Ace/Sequence/Feature.pm  view on Meta::CPAN

sub method    { shift->_field('method',@_) }  # ... I prefer "method"
sub subtype   { shift->_field('method',@_) }  # ... or even "subtype"
sub type      { shift->_field('type',@_)   }  # ... I prefer "type"
sub score     { shift->_field('score',@_)  }  # float indicating some sort of score
sub frame     { shift->_field('frame',@_)  }  # one of 1, 2, 3 or undef
sub info      {                  # returns Ace::Object(s) with info about the feature
  my $self = shift;
  unless ($self->{group}) {
    my $info = $self->{info}{group} || 'Method "'.$self->method.'"';
    $info =~ s/(\"[^\"]*);([^\"]*\")/$1$;$2/g;
    my @data = split(/\s*;\s*/,$info);
    foreach (@data) { s/$;/;/g }
    $self->{group} = [map {$self->toAce($_)} @data];
  }
  return wantarray ? @{$self->{group}} : $self->{group}->[0];
}

# bioperl compatibility
sub primary_tag { shift->type(@_)    }
sub source_tag  { shift->subtype(@_) }

sub db { # database identifier (from Ace::Sequence::Multi)
  my $self = shift;
  my $db = $self->_field('db',@_);
  return $db || $self->SUPER::db;
}

sub group  { $_[0]->info; }
sub target { $_[0]->info; }

sub asString {
  my $self = shift;

Ace/Sequence/Feature.pm  view on Meta::CPAN

    my ($tag,@values) = $thing=~/(\"[^\"]+?\"|\S+)/g;
    foreach (@values) { # strip the damn quotes
      s/^\"(.*)\"$/$1/;  # get rid of leading and trailing quotes
    }
    return $self->tag2ace($tag,@values);
}

# synthesize an artificial Ace object based on the tag
sub tag2ace {
    my $self = shift;
    my ($tag,@data) = @_;

    # Special cases, hardcoded in Ace GFF code...
    my $db = $self->db;;
    my $class = $db->class;

    # for Notes we just return a text, no database associated
    return $class->new(Text=>$data[0]) if $tag eq 'Note';

    # for homols, we create the indicated Protein or Sequence object
    # then generate a bogus Homology object (for future compatability??)
    if ($tag eq 'Target') {
	my ($objname,$start,$end) = @data;
	my ($classe,$name) = $objname =~ /^(\w+):(.+)/;
	return Ace::Sequence::Homol->new_homol($classe,$name,$db,$start,$end);
    }

    # General case:
    my $obj = $class->new($tag=>$data[0],$self->db);

    return $obj if defined $obj;

    # Last resort, return a Text
    return $class->new(Text=>$data[0]);
}

sub sub_SeqFeature {
  return wantarray ? () : 0;
}

1;

=head1 NAME

Ace::Sequence::Feature - Examine Sequence Feature Tables

=head1 SYNOPSIS

    # open database connection and get an Ace::Object sequence
    use Ace::Sequence;

    # get a megabase from the middle of chromosome I
    $seq = Ace::Sequence->new(-name   => 'CHROMOSOME_I,
                              -db     => $db,
			      -offset => 3_000_000,
			      -length => 1_000_000);

    # get all the homologies (a list of Ace::Sequence::Feature objs)
    @homol = $seq->features('Similarity');

Ace/Sequence/Feature.pm  view on Meta::CPAN

  
  note                   A Text object containing the note.
  
  similarity             An Ace::Sequence::Homology object containing
                         the target and its start/stop positions.

  intron                 An Ace::Object containing the gene from 
  exon                   which the feature is derived.
  misc_feature

  other                  A Text object containing the group data.

=item asString()

  $label = $feature->asString;

Returns a human-readable identifier describing the nature of the
feature.  The format is:

 $type:$name/$start-$end

Ace/Sequence/GappedAlignment.pm  view on Meta::CPAN

1;

__END__

=head1 NAME

Ace::Sequence::GappedAlignment - Gapped alignment object

=head1 SYNOPSIS

    # open database connection and get an Ace::Sequence object
    use Ace::Sequence;

    # get a megabase from the middle of chromosome I
    $seq = Ace::Sequence->new(-name   => 'CHROMOSOME_I,
                              -db     => $db,
			      -offset => 3_000_000,
			      -length => 1_000_000);

    # get all the gapped alignments
    @alignments = $seq->alignments('EST_GENOME');

Ace/Sequence/Gene.pm  view on Meta::CPAN

1;

__END__

=head1 NAME

Ace::Sequence::Gene - Simple "Gene" Object

=head1 SYNOPSIS

    # open database connection and get an Ace::Object sequence
    use Ace::Sequence;

    # get a megabase from the middle of chromosome I
    $seq = Ace::Sequence->new(-name   => 'CHROMOSOME_I,
                              -db     => $db,
			      -offset => 3_000_000,
			      -length => 1_000_000);

    # get all the genes
    @genes = $seq->genes;

Ace/Sequence/Multi.pm  view on Meta::CPAN

  my $opt = $self->_feature_filter($features);

  for my $db ($self->secondary) {
    my $supplement = $self->_gff($opt,$db);
    $self->transformGFF(\$supplement) unless $abs;

    my $string = $db->asString;

    foreach (grep !$seen{$_}++,split("\n",$supplement)) {  #ignore duplicates
      next if m!^(//|\#)!;  # ignore comments
      push(@lines, join "\t",$_,$string);   # add database as an eighth field
    }
  }

  return join("\n",@lines,'');
}

# turn a GFF file and a filter into a list of Ace::Sequence::Feature objects
sub _make_features {
  my $self = shift;
  my ($gff,$filter) = @_;

Ace/Sequence/Multi.pm  view on Meta::CPAN

__END__

=head1 NAME

Ace::Sequence::Multi - Combine Feature Tables from Multiple Databases

=head1 SYNOPSIS

    use Ace::Sequence::Multi;

    # open reference database
    $ref = Ace->connect(-host=>'stein.cshl.org',-port=>200009);

    # open some secondary databases
    $db1 = Ace->connect(-host=>'stein.cshl.org',-port=>200010);
    $db2 = Ace->connect(-path=>'/usr/local/acedb/mydata');

    # Make an Ace::Sequence::Multi object
    $seq = Ace::Sequence::Multi->new(-name   => 'CHROMOSOME_I,
                                     -db     => $ref,
			             -offset => 3_000_000,
			             -length => 1_000_000);

    # add the secondary databases
    $seq->add_secondary($db1,$db2);

    # get all the homologies (a list of Ace::Sequence::Feature objs)
    @homol = $seq->features('Similarity');

    # Get information about the first one -- goes to the correct db
    $feature = $homol[0];
    $type    = $feature->type;
    $subtype = $feature->subtype;
    $start   = $feature->start;

Ace/Sequence/Multi.pm  view on Meta::CPAN


    # Follow the target
    $target  = $feature->info;

    # print the target's start and end positions
    print $target->start,'-',$target->end, "\n";

=head1 DESCRIPTION

I<Ace::Sequence::Multi> transparently combines information stored
about a sequence in a reference database with features tables from any 
number of annotation databases.  The resulting object can be used just 
like an Ace::Sequence object, except that the features remember their
database of origin and go back to that database for information.

This class will only work properly if the reference database and all
annotation databases share the same cosmid map.

=head1  OBJECT CREATION

You will use the new() method to create new Ace::Sequence::Multi
objects.  The arguments are identical to the those in the
Ace::Sequence parent class, with the addition of an option
B<-secondary> argument, which points to one or more secondary databases 
from which to fetch annotation information.

=over 4

=item -source

The sequence source.  This must be an I<Ace::Object> of the "Sequence" 
class, or be a sequence-like object containing the SMap tag (see
below).

Ace/Sequence/Multi.pm  view on Meta::CPAN

You can provide either an I<Ace::Object> or just a sequence name for
this argument.  The source and reference sequences must share a common
ancestor, but do not have to be directly related.  An attempt to use a
disjunct reference sequence, such as one on a different chromosome,
will fail.

=item -name

As an alternative to using an I<Ace::Object> with the B<-source>
argument, you may specify a source sequence using B<-name> and B<-db>.
The I<Ace::Sequence> module will use the provided database accessor to
fetch a Sequence object with the specified name. new() will return
undef is no Sequence by this name is known.

=item -db

This argument is required if the source sequence is specified by name
rather than by object reference.  It must be a previously opened
handle to the reference database.

=item -secondary

This argument points to one or more previously-opened annotation
databases.  You may use a scalar if there is only one annotation
database.  Otherwise, use an array reference.  You may add and delete
annotation databases after the object is created by using the
add_secondary() and delete_secondary() methods.

=back

If new() is successful, it will create an I<Ace::Sequence::Multi>
object and return it.  Otherwise it will return undef and return a
descriptive message in Ace->error().  Certain programming errors, such
as a failure to provide required arguments, cause a fatal error.


=head1 OBJECT METHODS

Most methods are inherited from I<Ace::Sequence>.  The following
additional methods are supported:

=over 4

=item secondary()

  @databases = $seq->secondary;

Return a list of the secondary databases currently in use, or an empty 
list if none.

=item add_secondary()

  $seq->add_secondary($db1,$db2,...)

Add one or more secondary databases to the list of annotation
databases.  Duplicate databases will be silently ignored.

=item delete_secondary()

  $seq->delete_secondary($db1,$db2,...)

Delete one or more secondary databases from the list of annotation
databases.  Databases not already in use will be silently ignored.

=back

=head1 SEE ALSO

L<Ace>, L<Ace::Object>, L<Ace::Sequence>,L<Ace::Sequence::Homol>,
L<Ace::Sequence::FeatureList>, L<Ace::Sequence::Feature>, L<GFF>

=head1 AUTHOR

Ace/Sequence/Transcript.pm  view on Meta::CPAN

1;

__END__

=head1 NAME

Ace::Sequence::Transcript - Simple "Gene" Object

=head1 SYNOPSIS

    # open database connection and get an Ace::Object sequence
    use Ace::Sequence;

    # get a megabase from the middle of chromosome I
    $seq = Ace::Sequence->new(-name   => 'CHROMOSOME_I,
                              -db     => $db,
			      -offset => 3_000_000,
			      -length => 1_000_000);

    # get all the transcripts
    @genes = $seq->transcripts;

Ace/SocketServer.pm  view on Meta::CPAN

    $self->{encoring} = 1;
  } else {
    $self->{status}   = STATUS_ERROR;
    return _error($body);
  }
  return $body;
}

sub write {
  my $self = shift;
  my $data = shift;
  unless ($self->_send_msg($data,1)) {
    $self->{status} = STATUS_ERROR;
    return _error("Write to socket server failed: $!");
  }
  $self->{status} = STATUS_PENDING;
  $self->{encoring} = 0;
  return 1;
}

sub _error {
  $Ace::Error = shift;

ChangeLog  view on Meta::CPAN

	to return fewer than the correct number of objects (approximately 0.2% loss).
1.54	2/10/99
	1. Fixed spin-loop (polling) bug in Ace::Local.  Should no longer
	consume 99% of CPU time while waiting for tace to answer a long query.
	2. Fixed bug in get() and at() in which tags got duplicated because
	of capitalization variations.
1.53	1/23/99
	1. Bug fix in Ace::find function.  Was causing a crash.
1.52	1/21/99
	1. Fixed bad bug in the kill method which caused objects
	to be removed from the database seemingly randomly.
	2. Optimized tag searching to improve performance when
	navigating objects.
	3. Better error message reporting when objects do not contain
	a desired tag.
1.51	12/14/98
	1. Comparison between objects now is more sensible:
	"eq" performs a string comparison on object names
	"==" performs an object comparison.  Two objects are
	identical iff their names, classes and databases are identical
	2. Fixed bugs involving names containing "*" and "?" characters.
	3. Added the -long option to grep.
	4. Added the -display option to asGIF()
	5. The follow() method now follows a tag into the database.
1.50    10/28.98
	1. THE SEMANTICS OF AUTOGENERATED FUNCTIONS HAS CHANGED.  THEY NOW
	ALWAYS DEREFERENCE THE TAG AND FETCH AN OBJECT FROM THE DATABASE.
	2. Added the Ace::put() function to the Ace object, allowing you to move
	objects from one database to another.
	3. Added Ace::Object::add_row() and add_tree() functions, making it easier to build
	up objects from scratch, or to mix and match objects from different databases.
        4. Added Ace::parse() and parse_file() methods, for creating objects from .ace files.
	5. Removed nulls from error strings.
    
1.47-49	Internal releases
    
1.46	1. Fixed nasty bug in which newlines appeared as "n" in text
        fields.
    
1.45.   1. Fixed problems with autogeneration
	2. Added the format() routine 3. Added the model() methods and

ChangeLog  view on Meta::CPAN


	3. search() now takes an optional numeric argument indicating how
 	far to the right in the tree to go before retrieving the column.
	Specifically, search($tag,2) implements tag[2] semantics.

	4. automatically-generated methods (such as Homol) now take an optional
	numeric argument that is passed to search.  $obj->Homol(2) implements
	tag[2] semantics.

	5. fetch() now takes an optional tag argument which will be followed
	prior to fetching from the database.  $obj->fetch('Laboratory') will
	return the Laboratory object.

	6. tace can be used to access local databases, by passing a -path
 	argument to the Ace::connect() method.

	7. dates are displayed in Java style (3 March 1998 hh:mm:ss) by 
	default.  This can be altered with a call to Ace::date_style().

	8. Default port has changed to 23456

1.34    5/20/98 Fixed bug in Ace.xs caused by 1.33 change!  Only some objects
	were retrieved by fetch().

GFF/Filehandle.pm  view on Meta::CPAN

# this is a dumb trick to work around GFF.pm's current inability to
# take data from memory.  It makes the in-memory data look like a filehandle.
package GFF::Filehandle;

sub TIEHANDLE {
    my ($package,$datalines) = @_;
    return bless $datalines,$package;
}

sub READLINE {
    my $self = shift;
    return shift @$self;
}

1;

MANIFEST  view on Meta::CPAN

examples/upstream2.pl
install.PLS
make_docs.PLS
t/basic.t
t/object.t
t/sequence.t
t/update.t
typemap
util/install.PLS
util/ace.PLS
META.yml                                 Module meta-data (added by MakeMaker)

Makefile.PL  view on Meta::CPAN

use Config;
use ExtUtils::MakeMaker qw(prompt WriteMakefile);
use File::Path;
require 5.8.0;

my $choice;
while (!$choice) {
  $reply = prompt(
		  "\nWhat do you want to build?\n\n" .
		  "  1) Interface to Ace socket server and local databases (pure Perl)\n" .
		  "  2) The above plus XS optimizations (requires C compiler)\n" .
		  "  3) The above plus RPC server interface (requires C compiler)\n\n" .
		  "Enter your choice: ", "1");
  if ($reply =~ /(\d+)/) {
    $choice = $1;
    die "invalid choice: $choice!" if $choice < 1  ||  $choice > 3;
  }
}
$choice ||= 1; # safe default

Makefile.PL  view on Meta::CPAN


=head1 SYNOPSIS

 use Ace::Browser::LocalSiteDefs qw($SITE_DEFS $HTML_PATH $CGI_PATH);

=head1 DESCRIPTION

This file, which is created at install time, defines three exportable
variables:

 $SITE_DEFS   Location of the directory that hold's AceBrowser's database-specific
              configuration files, e.g. /usr/local/apache/conf/ace/

 $HTML_PATH   Location of AceBrowser's HTML files and images, e.g. ~www/htdocs/ace/

 $CGI_PATH    Location of AceBrowser's CGI scripts, e.g. ~www/cgi-bin/ace/

=head1 SEE ALSO

L<Ace>

README  view on Meta::CPAN

This is version 1.86 of AcePerl, a Perl interface for the ACEDB
object-oriented database.  Designed specifically for use in genome
sequencing projects, ACEDB provides powerful modeling and management
services for biological and laboratory data.  For others, it is a good
open source introduction to the world of object-oriented databases

See the ChangeLog for important notices, including recent user
interfaces changes.  Please see DISCLAIMER.txt for disclaimers of
warranty.

INSTALLATION:

In addition to this package, you will need Perl 5.00503 or higher
(5.6.0 or higher recommended), and the Digest::MD5 module.  Both are
available on CPAN (http://www.cpan.org).

If you are using AcePerl to communicate with WormBase, a public server
is running on host aceserver.cshl.org, port 2005.  You can open a
connection to this server like this:

   $db = Ace->connect('sace://aceserver.cshl.org:2005');

Otherwise, if you wish to communicate with your own ACEDB database,
you must use ACEDB version 4.8a or higher, available from this
location:

	ftp://ncbi.nlm.nih.gov/repository/acedb/
	
To take full advantage of the sequence annotation features in the
Ace::Sequence and Ace::Sequence::Feature classes, you will need
version 4.9r or higher.

If you wish to use AcePerl in a client-server fashion, you must get

README  view on Meta::CPAN


2. cd AcePerl-X.XX

3. perl Makefile.PL

   This script will ask you whether you wish to build: (1) the minimal package
   with support only for newer (socket) versions of the Ace server, (3) the maximum
   package, which supports both older (RPC) and newer (socket) versions of the 
   Ace server, or (2) a version that supports the socket server and has some C 
   language optimizations.  Choice (3) is recommended.  All versions will support
   local Acedb databases.

   The script will also ask you whether you wish to install support for the 
   AceBrowser Web server extensions.  Only answer yes if you are installing
   on a machine that already runs a web server and you wish to have AceBrowser
   installed.  If you answer in the affirmative, then you will be asked a number
   of directory configuration questions.  See README.ACEBROWSER for more details
   on installation.

   At this point, Makefile.PL will create the make files necessary to build
   AcePerl.  Among other things, the Makefile.PL script will attempt

README  view on Meta::CPAN

   that it works correctly for the next person who tries it.

4. make

   This will build the ACEDB client library, libaceperl.a, in the ace
   subdirectory.  It will then link in the Perl client subs.

5. make test (optional)

   You may "make test" to test the system.  It will attempt to open a
   connection to a database at beta.crbm.cnrs-mop.fr:20000100.  You may
   change these defaults by setting the environment variables ACEDB_HOST
   and ACEDB_PORT, or by defining them on the command line, as in:

    make test ACEDB_HOST=localhost ACEDB_PORT=200005

   However, since some of the tests are dependent on specific values in
   the database, this may cause some tests to fail.  Do not be alarmed if
   a handful of tests fail.  Do be alarmed if all of the tests fail.

  6. make install

  This will install AcePerl into your perl5 library directory.

  You may need to be root (superuser) in order to "make install".  This
  is because Perl will want to install the newly-built files into its
  library tree, /usr/local/lib/perl5/site_perl (or something similar),
  and this tree is usually not writable by mere mortals.  Do not

README  view on Meta::CPAN

want to define PERL5LIB to be the location of the machine-specific 
build directory.  For example:

  setenv PERL5LIB $HOME/ace/bin.LINUX_4_OPT

Or you could reinstall AcePerl in the main Perl library tree just by
entering the wperl/ subdirectory, and rerunning "perl Makefile.PL"
without defining INSTALLSITELIB.

See ACEDB.HOWTO in the docs/ subdirectory for instructions on
obtaining and setting up the ACeDB database.  You'll find other hints
here too.

USING ACEPERL

A. Read the copious documentation
   
   perldoc Ace

B. Review the examples

A few useful examples can be found in the "examples" subdirectory.
Among these is a script called "ace.pl", which implements a text
interface to any local or remote ace database.  If you have the Perl
Term::readline module installed, it gives you command-line editing,
completion, and history.

The script "dump_cdna.pl" shows you how to dump out all spliced cDNAs
from wormbase.org.  Other dump scripts show similar tricks.  You can
use these as templates for doing other biologically interesting
tricks.

There is also family of CGI scripts that run on top of AcePerl to give
a WebAce-like interface to Ace (it is not as feature-full as WebAce,

README.ACEBROWSER  view on Meta::CPAN

AceBrowser Version 3.1
September 20, 2001

The AcePerl distribution now includes a collection of CGI scripts that
run on top of AcePerl to provide a simple browsable interface to ACEDB
databases.  Some of the code has been tuned for the C. elegans
database, but most of it is fully generic.

Demos are running at http://stein.cshl.org/elegans/.

REQUIREMENTS:

1. AcePerl 1.76 or higher (available at http://stein.cshl.org/AcePerl/)
2. Perl 5.6.0 or higher
3. CGI.pm 2.77 or higher (available at http://stein.cshl.org/WWW/software/CGI)
4. A Web server
5. sgifaceserver 4.8c or higher.  For best results, use the version of

README.ACEBROWSER  view on Meta::CPAN

install AceBrowser.  Answer "yes."  

3. You will be asked for the installation locations for several groups
of files.  The answers depend on the configuration of your web server
The install script will attempt to create any directories that do not
already exist.

  a. Site-specific configuration file directory

	Acebrowser needs access to one or more configuration files.
	Each file describes a data source and how information from
	the data source is to be rendered.  All configuration files
	are stored in a directory at the location indicated here.

	The default is /usr/local/apache/conf/ace/.

  b. Acebrowser CGI script directory

        The core of Acebrowser is a set of CGI scripts.  This is the
	directory that will contain them.  Choose a directory that will
	be recognized by the web server as containing CGI script.  If
	you are using Apache/mod_perl, select a directory under the 

README.ACEBROWSER  view on Meta::CPAN

Depending on the permissions of your web server directories, you may
have to be root in order to create some of these directories.

4. Run "make", "make test" and "make install" as described in the main
README.  If this is successful, run "make install-browser".  This will
copy the acebrowser files into the directories chosen in step (3).
Depending on the permissions of your web server directories, you may
have to be root in order to complete this step.

5. If you installed the CGI scripts in their default location, you
should now be able to search the C. elegans database by fetching the
following URL:

	http://your.host/cgi-bin/ace/searches/text

You can then follow the links to browse the database.  A slightly more 
sophisticated search allows you to search a subset of object classes:

        http://your.host/cgi-bin/ace/searches/basic

or the entire list of object classes:

        http://your.host/cgi-bin/ace/searches/browser

There is also a default Acebrowser "home page" installed at the URL:

	http://your.host/ace/index.html

You may have to adjust these URLs for the locations of the directories
chosen in step (3).

CONFIGURATION

Acebrowser is configured to allow access to multiple ACEDB databases.
You can customize each database extensively by changing the appearance
of pages, adding new search capabilities, and adding new displays for
particular Ace object classes.

Each database has a symbolic name, and each symbolic name corresponds
to a configuration file located in the site-specific configuration
directory.  There are three databases defined in a new Acebrowser
installation: 

  simple   An acedb database running on port 2005 of the 
	   local host

  moviedb  An example database of movies running on port 200008 
	   of stein.cshl.org

  default  An oldish snapshot of the C. elegans database running
	   on port 2005 of stein.cshl.org

To select among the data sources, append the symbolic name to the end
of the URL of the desired CGI script.  For example, to do a text
search on the "moviedb" database, fetch this URL:

  http://your.site/cgi-bin/ace/searches/text/moviedb

If no symbolic name is specified, the default database is assumed.
  http://your.site/cgi-bin/ace/searches/text 

is equivalent to

  http://your.site/cgi-bin/ace/searches/text/default

As described in EXTENDING ACEBROWSER, another way to select among
databases is to place the CGI script itself in a directory with the
same name as the database.  For example, if you have written a
specialized CGI script called screenplay that is designed to work with 
the "moviedb" database, you could place it in a subdirectory named
moviedb, and refer to it this way:

  http://your.site/cgi-bin/ace/moviedb/screenplay

The symbolic name can actually appear anywhere in the path, so this
would work as well:

  http://your.site/cgi-bin/ace/moviedb/custom/screenplay

THE CONFIGURATION FILES

The configuration files are located in the directory selected for
acebrowser configuration.  Their names are formed by appending ".pm"
to the symbolic name of the database.  For example, the configuration
file "simple.pm" corresponds to the database "simple".

Each of the configuration files is actually an executable Perl script.
As such it can use any Perl constructions you wish, including variable
interpolation.  The purpose of the configuration file is to set a
series of configuration variables, which by convention are all
uppercase.  For example, here is an excerpt from the default.pm
configuration file:

 $HOST = 'stein.cshl.org';
 $PORT = 2005;
 $USERNAME = '';
 $PASSWORD = '';

In addition to scalar variables, the configuration file is used to set 
arrays, hashes and specially-named functions.

If you are only interested in accessing a single database, it is
easiest to modify the default.pm configuration file.  To serve
multiple databases, just make a copy of default.pm and edit the copy.

If, for some reason, Acebrowser cannot find its configuration files,
it will generate an internal server error.  The location of the
configuration files directory is stored in the module
Ace::Browser::LocalSiteDefs, typically somewhere inside the
"site_perl" subdirectory of the Perl library directory (use "perl -V"
to see where that is).  You can find out where Acebrowser expects to
find its configuration files by running the following command:

  perl -MAce::Browser::LocalSiteDefs \

README.ACEBROWSER  view on Meta::CPAN


This is where Acebrowser expects to find its icons. This subdirectory
holds icons and other small static images.  Note how the
previously-defined $DOCROOT variable is used.  You will probably not
need to change this.

 $IMAGES = "$DOCROOT/images";

This is where Acebrowser expects to find its "images" subdirectory.
This directory contains images generated dynamically by the ACEDB
database.  It *must* be writable by the web server user, usually
"nobody".  When the AcePerl install script creates this directory, it
makes it world-writable by default.  You may prefer to make it owned
by the "nobody" user and/or group.

 $HOST = 'stein.cshl.org';

This is the name of the host where the desired acedb server can be
found.

 $PORT = 2005;

This is the network port on which the desired acedb server is
listening.  Network ports in the range 1024-65535 are assumed to
correspond to the newer socket-based sgifaceserver.  Ports in the
range 65536-4,294,967,296 are assumed to correspond to the older
RPC-based gifaceserver.

 $USERNAME = '';
 $PASSWORD = '';

For password-protected ACEDB databases, these variables contain the
username and password.

 $STYLESHEET = "$DOCROOT/stylesheets/aceperl.css";

This is the cascading stylesheet used to set the background color,
font, table colors, and so forth.  You probably don't need to change
this, but you might want to modify the stylesheet itself.

 @PICTURES = ($IMAGES => "$HTML_PATH/images");

README.ACEBROWSER  view on Meta::CPAN


 $ROOT = '/movies';


EXTENDING ACEBROWSER

Acedb is fundamentally object based.  In addition to having a name,
each object has a class, such as "Sequence".  Acebrowser takes
advantage of this object structure by allowing you to assign one or
more displays to a class.  Each display is a CGI script that fetches
the desired object from the database, formats it, and displays it as
HTML or an image.

Whenever Acebrowser is called upon to display an object, it consults
the configuration file to determine what displays are registered for
the object, and then presents a row of display names across the top of
the window.  In Acebrowser jargon, this line of displays is called the
"type selector."  The user can change the display to use by selecting
the corresponding link.

Three generic displays, which will work with all databases, come with
Acebrowser:

  tree  an HTML representation of the Acedb object which
	presents the object in the form of a collapsible outline.

  xml   an XML representation of the Acedb object

  pic   a clickable GIF image, as returned from gifaceserver.


RPC/RPC.h  view on Meta::CPAN

#ifndef ACEPERL_H
#define ACEPERL_H

#define STATUS_WAITING 0
#define STATUS_PENDING 1
#define STATUS_ERROR  -1
#define ACE_PARSE      3

typedef struct AceDB {
  ace_handle*    database;
  unsigned char* answer;
  int            length;
  int            encoring;
  int            status;
  int            errcode;
} AceDB;

#endif

RPC/RPC.xs  view on Meta::CPAN

	if (RETVAL == NULL) XSRETURN_UNDEF;
	RETVAL->encoring = FALSE;
	RETVAL->status = STATUS_WAITING;
	RETVAL->answer = NULL;
	RETVAL->errcode = 0;
	ace = openServer(host,rpc_port,timeOut);
	if (ace == NULL) {
		safefree(RETVAL);
		XSRETURN_UNDEF;
	} else {
		RETVAL->database = ace;
	}
OUTPUT:
	RETVAL

void
DESTROY(self)
	AceDB* self
CODE:
	if (self->answer != NULL)
	   free((void*) self->answer);
	if (self->database != NULL)
	   closeServer(self->database);
	safefree((char*)self);

ace_handle*
handle(self)
	AceDB* self
CODE:
	RETVAL = self->database;
OUTPUT:
	RETVAL

int
encore(self)
	AceDB* self
CODE:
	RETVAL = self->encoring;
OUTPUT:
	RETVAL

RPC/RPC.xs  view on Meta::CPAN

	char*  request
	int    type
PREINIT:
	unsigned char* answer = NULL;
	int retval,length,isWrite=0,isEncore=0;
CODE:
        if (type == ACE_PARSE)
           isWrite = 1;
        else if (type > 0)
           isEncore = 1;
	retval = askServerBinary(self->database,request,
	                         &answer,&length,&isEncore,CHUNKSIZE);
	if (self->answer) {
	   free((void*) self->answer);
	   self->answer = NULL;
	}
	self->errcode = retval;
        self->status = STATUS_WAITING;
	if ((retval > 0) || (answer == NULL) ) {
	   self->status = STATUS_ERROR;
	   RETVAL = 0;

RPC/RPC.xs  view on Meta::CPAN

read(self)
	AceDB* self
PREINIT:
	unsigned char* answer = NULL;
	int retval,length,encore=0;
CODE:
	if (self->status != STATUS_PENDING)
	   XSRETURN_UNDEF;

	if (self->answer == NULL && self->encoring) {
	  retval = askServerBinary(self->database,"encore",&answer,
                                    &length,&encore,CHUNKSIZE);
	  self->errcode = retval;
	  self->encoring = encore;
	  if ((retval > 0) || (answer == NULL) ) {
	    self->status = STATUS_ERROR;
	    XSRETURN_UNDEF;
	  }
	  self->answer = answer;
	  self->length = length;
	}

acebrowser/cgi-bin/generic/acetable  view on Meta::CPAN


use Ace 1.38;
use CGI 2.42 qw/:standard :html3 escape/;
use CGI::Carp qw/fatalsToBrowser/;
use Ace::Browser::AceSubs;

AceInit();
$NAME  = param('name');
#$PARMS = param('parms');

# fetch database handle
$DB = OpenDatabase() || AceError("Couldn't open database.");

AceHeader();
AceError(<<END) unless $NAME ;
Call this script with URL parameters of
<VAR>name</VAR> and <VAR>parms,</VAR> where
"name" is the name of a table definition in acedb
END

display_table($NAME," ");
exit 0;

acebrowser/cgi-bin/generic/acetable  view on Meta::CPAN

  my ($n,$c) = (escape($name),escape($parms));


  print
    start_html(-Title=>"$name: $parms",
	       -Style=>STYLE,
	       -Class=>'tree',
	       -Bgcolor=>BGCOLOR_TREE),
    h1("$name: $parms"),
    &show_table($obj),
    #$obj->asHTML() || strong('No more text information about this object in the database'),
    FOOTER,
    end_html;
}


sub show_table {
  my $obj = shift;
  my $dna = "$obj";
  #$dna=~s/(\w{50})/$1/g;
  return (pre($dna),0);

acebrowser/cgi-bin/generic/model  view on Meta::CPAN

}

print_tree($model);
PrintBottom();

exit 0;

sub print_tree {
  my $obj = shift;
  print $obj->asHTML(\&to_href) 
    || strong('No more text information about this object in the database'),"\n";
}

# this is cut-and-paste out of etree, but with simplifications
sub to_href {
  my $obj = shift;

  unless ($obj->isObject or $obj->isTag) {
    $obj =~s/\\n/<BR>/g;
    return ($obj,0);
  }

acebrowser/cgi-bin/generic/pic  view on Meta::CPAN


  my $b2   = $map_stop + $half;
  $b2      = $max if $b2 > $max;
  my $b1   = $b2 - ($map_stop - $map_start);

  my $m1   = $map_start + $half/2;
  my $m2   = $map_stop  - $half/2;


  print start_table({-border=>1});
  print TR(td({-align=>'CENTER',-class=>'datatitle',-colspan=>2},'Map Control'));
  print start_TR();
  print td(
	   table({-border=>0},
		 TR(td('&nbsp;'),
		    td(
		       $map_start > $min ?
		       a({-href=>"$self?name=$name;class=$class;map_start=$a1;map_stop=$a2"},
			 img({-src=>UP_ICON,-align=>'MIDDLE',-border=>0}),' Up')
		       :
		       font({-color=>'#A0A0A0'},img({-src=>UP_ICON,-align=>'MIDDLE',-border=>0}),' Up')

acebrowser/cgi-bin/generic/tree  view on Meta::CPAN

#!/usr/bin/perl

# generic tree display
# should work with any data model

use strict;
use vars qw/$DB $URL $NAME $CLASS/;

use Ace 1.51;
use CGI 2.42 qw/:standard :html3 escape/;
use CGI::Carp qw/fatalsToBrowser/;
use Ace::Browser::AceSubs qw(:DEFAULT Url);
use Ace::Browser::TreeSubs;

acebrowser/cgi-bin/generic/tree  view on Meta::CPAN

  my $obj = shift;
  my $name  = $obj->name;
  my $class = $obj->class;
  my ($n,$c) = (escape($name),escape($class));
  my $myimage = ($class =~ /^Picture/ ? $obj->Pick_me_to_call->right->right : 'No_Image') ;
  if ($class eq 'LongText'){
    print $obj->asHTML(sub { pre(shift) });
  }
  else{
    print  $obj->asHTML(\&to_href) || strong('No more text information
     about this object in the database'), "\n";
  }
}

sub to_href {
  my $obj = shift;

  unless ($obj->isObject or $obj->isTag) {
    if ($obj=~/\S{50}/){         # if you have >50 chars without a space
      $obj=~s/(\S{50})/$1\n/g; # add some
      $obj = "<pre>$obj</pre>";# and assume preformatted (e.g. seq)

acebrowser/cgi-bin/generic/xml  view on Meta::CPAN

#!/usr/bin/perl

# generic xml display
# should work with any data model

use strict;
use vars qw($DB);

use Ace 1.65;
use CGI 2.42 qw/:standard :html3 escape/;
use CGI::Carp qw/fatalsToBrowser/;
use Ace::Browser::AceSubs;


acebrowser/cgi-bin/misc/feedback  view on Meta::CPAN

#!/usr/bin/perl
# -*- Mode: perl -*-
# file: feedback
# Provide feedback to data curator(s)

use strict;

use CGI 2.42 qw(:standard);
use Ace::Browser::AceSubs qw(:DEFAULT Header DB_Name);
use vars '@FEEDBACK_RECIPIENTS';

# This page called with the parameters:
#      recipients- numeric index(es) for recipients of message
#      name    - name of object to update

acebrowser/cgi-bin/misc/feedback  view on Meta::CPAN

	h1($title);
}

sub print_instructions {
  my @defaults;
  for (my $i=0; $i<@FEEDBACK_RECIPIENTS; $i++) {
    push @defaults,$i if $FEEDBACK_RECIPIENTS[$i][2];
  }
  print
    p({-class=>'small'},
      "Use this form to send new data or corrections to",
      "the maintainers of this database.  An e-mail message",
      "will be sent to the individuals selected from the list",
      "below."),
	blockquote({-class=>'small'},
		   checkbox_group(-name    => 'recipients',
				  -Values  => [(0..$#FEEDBACK_RECIPIENTS)],
				  -Labels  => { map {
				    $_=>"$FEEDBACK_RECIPIENTS[$_]->[0] ($FEEDBACK_RECIPIENTS[$_]->[1])"
				  } (0..$#FEEDBACK_RECIPIENTS) },
				  -defaults=>\@defaults,
				  -linebreak=>1));

acebrowser/cgi-bin/misc/feedback  view on Meta::CPAN

	AceError($error);
	return;
    }
    return 1;
}

sub print_confirmation {
    print 
	p("Thank you for taking the time to submit this information.",
	  "Please use the buttons below to submit more reports or to",
	  "return to the database.",
	  ),
	start_form,
	submit(-name=>'restart',-label=>'Submit Another Report'),
	hidden('referer'),
	submit(-name=>'return',-label=>'Return to Database'),
	end_form;
}



( run in 0.551 second using v1.01-cache-2.11-cpan-0d8aa00de5b )