package AMF::Parser;

##  AMF::Parser -- perl module to parse AMF data files
##  
##  Copyright (c) 2004-5 Ivan Kurmanov. All rights reserved.
##
##  This code is free software; you can redistribute it and/or modify it
##  under the same terms as Perl itself.


=head1 NAME

AMF::Parser -- perl module to parse AMF data files

=head1 SYNOPSIS

  use AMF::Parser;

  if ( AMF::Parser::open_file( $file ) ) {
     while ( my $rec = AMF::Parser::get_next_record() ) {
       print "Record (", $rec ->type, "):\n"; 
       print "Title:\t", $rec ->get_value( 'title' );
       ...
     }
  }

or simply

  amf_open_file $file;  
  # or, for instance
  amf_parse_string $string;
  my $rec = amf_get_next_record;

and then

  my $id  = $rec ->id;
  my $ref = $rec ->ref;
  my $ty  = $rec ->type;
 
  if ( $ty eq 'person' ) {
     my $name = $rec ->get_value( 'name' );
     ...
  } 


=head1 DESCRIPTION

AMF Parser parses AMF data.  AMF is Academic Metadata Format, an XML-based
language for academics-related data.  http://amf.openlib.org/

This version of the module implements AMF as described by
http://amf.openlib.org/doc/asakusa.html ; the latest AMF spec shall be at
http://amf.openlib.org/doc/amf.html

=head2 FUNCTIONS

=head3 C<open_file( FILE )>

Opens an AMF file FILE for parsing.  Conseqent calls to C<get_next_record()>
will give you the extracted data objects.  It doesn't read the whole file at
once, it only starts parsing it.  This means if the file turns out to be not
well-formed XML you will not know that.  You may simply get less records from
it than it contains.  If the file is very big, you can process it record by
record, no problem.

Returns true on success, false otherwise.

=head3 C<parse_string( STRING )>

Parses the STRING as AMF data.  Returns true if no fatal error happened while
parsing.  A fatal error is either XML well-formedness error or an internal
parser error.

=head3 get_next_record()

Returns the next record object (AMF::Record) from the currently parsed file or
string, if there is any.  Returns false otherwise (for instance, if end of
file reached).


=head3 get_next_noun()

Returns the next noun object (AMF::Noun or AMF::Record) from the currently
parsed file or string, if there is any.  Returns false otherwise (for
instance, if end of file reached).


=head2 Exporting C<amf_...>something

Module exports by default functions C<amf_open_file, amf_parse_string,
amf_get_next_record, amf_get_next_noun>, which are the aliases of C<open_file,
parse_string, get_next_record, get_next_noun> respectively.

So C<use AMF::Parser> and you are ready to rock.  If you don't want this, do: 

  use AMF::Parser ();

=head1 SEE ALSO

L<AMF::Record> module, L<amfch> utility

=head1 AUTHOR

Ivan Kurmanov, http://www.ahinea.com/en/ for ACIS project,
http://acis.openlib.org/ 

=cut


BEGIN {
$VERSION = do { my @r=(q$Revision: 1.14 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
#                       $Id: Parser.pm,v 1.14 2005/10/05 12:26:26 ivan Exp $
}


use Exporter;

@ISA = qw( Exporter );
@EXPORT = qw( amf_open_file 
              amf_parse_string 
              amf_get_next_record 
              amf_get_next_noun );


use AMF::Spec::Parsed;
use AMF::Parser::Basic;

use strict;
use warnings;

use vars qw( $parser );

$parser = AMF::Parser::Basic -> new( SPEC => $AMF::Spec );


sub amf_open_file ($) { open_file( @_ ); }

sub open_file {
  my $file = shift || die;
  return $parser -> start_file( $file );
}



sub amf_get_next_record () { get_next_record( @_ ); }

sub get_next_record {
  while ( 1 ) {
    my $n = $parser -> get_next_noun;
    if ( not $n ) { return $n; }
    if ( $n ->id ) {
      return $n;
    } 
  }
}


sub amf_get_next_noun () { get_next_noun( @_ ); }

sub get_next_noun {
  return $parser -> get_next_noun;
}


sub amf_parse_string ($) { parse_string( @_ ); }

sub parse_string {
  my $str = shift;
  return $parser -> parse_string( $str );
}


1;

