The Perl and Raku Conference 2025: Greenville, South Carolina - June 27-29 Learn more

use 5.008;
use strict;
use vars qw($VERSION);
BEGIN {
$VERSION='2.28'; # version template
}
use Carp;
my $default_factory;
sub DOES {
my ($self,$role)=@_;
if ($role eq __PACKAGE__) {
# we don't implement Treex::PML::Factory interface, but anything derived from use is assumed to do so
return ref($role) eq __PACKAGE__ ? 0 : 1;
} else {
return $self->DOES($role);
}
}
sub new {
my $class = shift;
return bless {@_}, $class;
}
sub make_default {
my $obj = shift;
my $class = ref($obj) || $obj;
die __PACKAGE__." is not a proper factory and cannot be made default!\n"
if $class eq __PACKAGE__;
my $prev = Treex::PML::Factory->get_default_factory;
unless ((ref($prev)||'') eq $class) {
Treex::PML::Factory->set_default_factory(ref($obj) ? $obj : $class->new(@_));
}
return $prev;
}
sub set_default_factory {
my ($self,$factory)=@_;
die __PACKAGE__."->set_default_factory: argument must implement ".__PACKAGE__."!"
unless UNIVERSAL::DOES::does($factory,__PACKAGE__);
$default_factory = $factory;
}
sub get_default_factory {
return $default_factory;
}
BEGIN {
no strict 'refs';
for my $method (qw(
createPMLSchema createPMLInstance
createDocument createDocumentFromFile
createFSFormat
createNode createTypedNode createList createSeq
createAlt createContainer createStructure
)) {
*$method = sub { shift; $default_factory->$method(@_) }
}
}
1;
__END__
=head1 NAME
Treex::PML::Factory - a base class for Treex::PML object factories
=head1 SYNOPSIS
use Treex::PML;
use MyTreex::PML::Factory;
MyTreex::PML::Factory->make_default();
# These class methods invoke similarly named methods on the default
# factory; the default factory method's are responsible for
# creating and returning the corresponding objects.
Treex::PML::Factory->createPMLSchema(...)
Treex::PML::Factory->createPMLInstance(...)
Treex::PML::Factory->createDocument(..)
Treex::PML::Factory->createDocumentFromFile(..)
Treex::PML::Factory->createFSFormat(..)
Treex::PML::Factory->createNode(..)
Treex::PML::Factory->createTypedNode($decl,...);
Treex::PML::Factory->createList(...)
Treex::PML::Factory->createSeq(...)
Treex::PML::Factory->createAlt(...)
Treex::PML::Factory->createContainer(...)
Treex::PML::Factory->createStructure(...)
=head1 DESCRIPTION
This class maintains a default factory for creating Treex::PML objects and
delegates C<create...()> methods called as class methods to the
default factory.
Note that this class does not implement a factory,
L<Treex::PML::StandardFactory> does that.
This class provides means for creating various types of Treex::PML-like
objects without having to name particular classes. The user can plug
in their own default factory in order to replace the default Treex::PML
class hierarchy with their own one. The classes in the user hierarchy
typically derive from the corresponding classes in the Treex::PML
hierarchy; if not, they must at least implement the same interfaces
and use the same types of references for the underlying objects (or
overloading to them, so that also low-level code using HASH or ARRAY
dereferencing on objects still works).
User can define factory by implementing all the C<create*> methods as
object methods. The factory must be derived from the 'Treex::PML::Factory'
class or, alternatively, provide a constructor 'new' and implement the
DOES method which then returns true if 'Treex::PML::Factory' is passed to
it as an argument.
=head2 CLASS METHODS
=over 5
=item $class->make_default()
If inherited by a customized factory class, makes the invocant class
the default factory. Every factory class should either inherit this
method or reimplement it using a call to
C<< Treex::PML::Factory->set_default_factory >>.
=item $class->new(name=>value, ...)
If inherited by a customized factory class, creates a new instance of
that class. The default constructor will create a blessed hash
reference using the constructor arguments to populate the hash with
name=>value pairs.
=item Treex::PML::Factory->get_default_factory()
Returns the default factory (usually a singleton Treex::PML::Factory object).
=item Treex::PML::Factory->set_default_factory($default_factory)
Change the default factory to a given object (the object must implment
the Treex::PML::Factory interface).
=back
=head2 METHODS FOR CREATING OBJECTS
The following functions B<must be implemented by custom factory classes
as object methods>, but should be called as class methods of the
'Treex::PML::Factory' class. The class methods of
'Treex::PML::Factory' delegate the call to the default factory.
=over 5
=item Treex::PML::Factory->createPMLSchema({ option => value, ... })
Parses an XML representation of a PML Schema from a string,
filehandle, local file, or URL, processing the modular instructions as
described in
and returns the corresponding object implementing the interface or
L<Treex::PML::Schema>. One of the following options must be given:
=over 5
=item C<string>
a XML string to parse
=item C<filename>
a file name or URL
=item C<fh>
a file-handle (IO::File, IO::Pipe, etc.) open for reading
=back
The following options are optional:
=over 5
=item C<base_url>
base URL for referred schemas (usefull when parsing from a file-handle or a string)
=item C<use_resources>
if this option is used with a true value, the parser will attempt to
locate referred schemas also in L<Treex::PML> resource paths.
=item C<revision>, C<minimal_revision>, C<maximal_revision>
put constraints on the revision number of the schema.
=item C<validate>
if this option is used with a true value, the parser will validate the
schema on the fly using a RelaxNG grammar given using the
C<relaxng_schema> parameter; if C<relaxng_schema> is not given, the
file 'pml_schema_inline.rng' searched for in L<Treex::PML> resource paths
is assumed.
=item C<relaxng_schema>
a particular RelaxNG grammar to validate against. The value may be an
URL or filename for the grammar in the RelaxNG XML format, or a
XML::LibXML::RelaxNG object representation. The compact format is not
supported.
=back
=item Treex::PML::Factory->createPMLInstance({ option=>value, ...})
Without arguments (the option HashRef) creates a empty object implementing
the L<Treex::PML::Instance> interface.
If called with the option HashRef, a new object implementing the
L<Treex::PML::Instance> interface is created and its content is read
from a given XML input in the PML format. The input can be a file,
filehandle, string, or a DOM tree. The arguments are described in the
documentation of the the C<load()> method of L<Treex::PML::Instance>.
=item Treex::PML::Factory->createDocument({ option => value, ... })
Creates a new empty object implementing the L<Treex::PML::Document>
interface. The options are used to initialize the object's attributes
and include: C<name>, C<format>, C<trees>, C<backend>, C<FS>, C<hint>,
C<patterns>, C<tail>, C<save_status>. See the documentation of
the C<create()> method of L<Treex::PML::Document> for details.
=item Treex::PML::Factory->createDocumentFromFile($filename, { option => value, ... })
Creates a new object implementing the L<Treex::PML::Document> interface and
reads its content from a given file. The arguments are described in
the documentation of the the C<load()> method of
L<Treex::PML::Document>.
=item Treex::PML::Factory->createFSFormat($definition)
Return a new object implementing the L<Treex::PML::FSFormat> interface.
The argument can be a HashRef containing the FS format definition in
parsed from, or an ARRAY reference (whose elements are individual
lines of the FS format definition) or a GLOB reference with an input
stream from which the FS format definition is to be read.
=item Treex::PML::Factory->createNode($hashRef?,$reuse?)
Return a new node object implementing the L<Treex::PML::Node> interface,
using given HashRef reference as the source of initial set of attributes;
if the C<$reuse> argument is true, the HashRef may be actually
blessed into the new class (if supported by the implementation).
=item Treex::PML::Factory->createTypedNode($pml_type_decl,...);
or
=item Treex::PML::Factory->createTypedNode($type_name,$pml_schema,...);
Return a new node object implementing the L<Treex::PML::Node>
interface, associated with the given PML type (passed either as a
L<Treex::PML::Schema::Decl> object or as the type name followed by a PML
schema object).
=item Treex::PML::Factory->createList($arrayRef?,$reuse?)
Return a new list (object implementing the L<Treex::PML::List> interface),
populated with the values passed in the (optional) ArrayRef.
If the C<$reuse> argument is true, the given ArrayRef may actually be
reblessed into the target class (if supported by the implementation).
=item Treex::PML::Factory->createAlt($arrayRef?,$reuse?)
Return a new alternative (object implementing the L<Treex::PML::Alt> interface),
populated with the values passed in the (optional) ArrayRef.
If the C<$reuse> argument is true, the given ArrayRef may actually be
reblessed into the target class (if supported by the implementation).
=item Treex::PML::Factory->createSeq($arrayRef?, $content_pattern?,$reuse?)
Return a new sequence (object implementing the L<Treex::PML::Seq>
interface). The object gets populated by elements from a given
ArrayRef (if given). Each element of the ArrayRef should be a
L<Treex::PML::Seq::Element> object. The second optional argument is a
regular expression constraint which can be stored in the object and
used later for validating its content (see validate() method of
L<Treex::PML::Seq>). If the C<$reuse> argument is true, the ArrayRef
can be used directly as the container for the content of the sequence
(if supported by the implementation); otherwise it is copied.
=item Treex::PML::Factory->createContainer($value?, $hashRef?, $reuse?)
Create a new container (object implementing the L<Treex::PML::Container>
interface). The the initial value for the container's value with $value
and its attributes with the name-value pairs from the given
HashRef. If $reuse is true, the HashRef passed may actually be reblessed into the target class (if supported
by the implementation).
=item Treex::PML::Factory->createStructure($hashRef?, $reuse?)
Create a new structure (object implementing the L<Treex::PML::Struct>
interface). The structure is initialized with the name-value pairs
from the given HashRef (optional). If $reuse is true, the HashRef may
actually be reblessed into the target class (if supported by the
implementation).
=item DOES($interface)
Check whether the class implements a given interface (role). Note, the
class Treex::PML::Factory itself does not implement the
Treex::PML::Factory interface, but assumes that anything derived from
it does!
=back
=head2 EXPORT
None by default.
=head1 SEE ALSO
L<Treex::PML>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2010 by Petr Pajas, 2010-2024 Jan Stepanek
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.2 or,
at your option, any later version of Perl 5 you may have available.
=head1 BUGS
None reported... yet.
=cut