summaryrefslogtreecommitdiff
path: root/lib/Class/MakeMethods/Template
diff options
context:
space:
mode:
authorAndreas Brachold <vdr07@deltab.de>2007-08-13 18:41:27 +0000
committerAndreas Brachold <vdr07@deltab.de>2007-08-13 18:41:27 +0000
commitbcbf441e09fb502cf64924ff2530fa144bdf52c5 (patch)
treef377707a2dac078db8cd0c7d7abfe69ac1006d71 /lib/Class/MakeMethods/Template
downloadxxv-bcbf441e09fb502cf64924ff2530fa144bdf52c5.tar.gz
xxv-bcbf441e09fb502cf64924ff2530fa144bdf52c5.tar.bz2
* Move files to trunk
Diffstat (limited to 'lib/Class/MakeMethods/Template')
-rw-r--r--lib/Class/MakeMethods/Template/Array.pm102
-rw-r--r--lib/Class/MakeMethods/Template/Class.pm103
-rw-r--r--lib/Class/MakeMethods/Template/ClassInherit.pm144
-rw-r--r--lib/Class/MakeMethods/Template/ClassName.pm330
-rw-r--r--lib/Class/MakeMethods/Template/ClassVar.pm178
-rw-r--r--lib/Class/MakeMethods/Template/Flyweight.pm43
-rw-r--r--lib/Class/MakeMethods/Template/Generic.pm2349
-rw-r--r--lib/Class/MakeMethods/Template/Global.pm97
-rw-r--r--lib/Class/MakeMethods/Template/Hash.pm229
-rw-r--r--lib/Class/MakeMethods/Template/Inheritable.pm154
-rw-r--r--lib/Class/MakeMethods/Template/InsideOut.pm218
-rw-r--r--lib/Class/MakeMethods/Template/PackageVar.pm168
-rw-r--r--lib/Class/MakeMethods/Template/Ref.pm207
-rw-r--r--lib/Class/MakeMethods/Template/Scalar.pm80
-rw-r--r--lib/Class/MakeMethods/Template/Static.pm41
-rw-r--r--lib/Class/MakeMethods/Template/Struct.pm41
-rw-r--r--lib/Class/MakeMethods/Template/StructBuiltin.pm148
-rw-r--r--lib/Class/MakeMethods/Template/Universal.pm415
18 files changed, 5047 insertions, 0 deletions
diff --git a/lib/Class/MakeMethods/Template/Array.pm b/lib/Class/MakeMethods/Template/Array.pm
new file mode 100644
index 0000000..0d2ab2d
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/Array.pm
@@ -0,0 +1,102 @@
+package Class::MakeMethods::Template::Array;
+
+use Class::MakeMethods::Template::Generic '-isasubclass';
+
+$VERSION = 1.008;
+use strict;
+require 5.00;
+use Carp;
+
+=head1 NAME
+
+Class::MakeMethods::Template::Array - Methods for manipulating positional values in arrays
+
+=head1 SYNOPSIS
+
+
+=head1 DESCRIPTION
+
+=cut
+
+use vars qw( %ClassInfo );
+
+sub generic {
+ {
+ 'params' => {
+ 'array_index' => undef,
+ },
+ 'code_expr' => {
+ _VALUE_ => '_SELF_->[_STATIC_ATTR_{array_index}]',
+ '-import' => { 'Template::Generic:generic' => '*' },
+ _EMPTY_NEW_INSTANCE_ => 'bless [], _SELF_CLASS_',
+ _SET_VALUES_FROM_HASH_ => 'while ( scalar @_ ) { local $_ = shift(); $self->[ _BFP_FROM_NAME_{ $_ } ] = shift() }'
+ },
+ 'behavior' => {
+ '-init' => sub {
+ my $m_info = $_[0];
+
+ # If we're the first one,
+ if ( ! $ClassInfo{$m_info->{target_class}} ) {
+ # traverse inheritance hierarchy, looking for fields to inherit
+ my @results;
+ no strict 'refs';
+ my @sources = @{"$m_info->{target_class}\::ISA"};
+ while ( my $class = shift @sources ) {
+ next unless exists $ClassInfo{ $class };
+ push @sources, @{"$class\::ISA"};
+ if ( scalar @results ) {
+ Carp::croak "Too many inheritances of fields";
+ }
+ push @results, @{$ClassInfo{$class}};
+ }
+ $ClassInfo{$m_info->{target_class}} = \@sources;
+ }
+
+ my $class_info = $ClassInfo{$m_info->{target_class}};
+ if ( ! defined $m_info->{array_index} ) {
+ foreach ( 0..$#$class_info ) {
+ if ( $class_info->[$_] eq $m_info->{'name'} ) {
+ $m_info->{array_index} = $_; last }
+ }
+ if ( ! defined $m_info->{array_index} ) {
+ push @ $class_info, $m_info->{'name'};
+ $m_info->{array_index} = $#$class_info;
+ }
+ }
+
+ return;
+ },
+ },
+ }
+}
+
+########################################################################
+
+=head2 Standard Methods
+
+The following methods from Generic should be supported:
+
+ scalar
+ string
+ number
+ boolean
+ bits (?)
+ array
+ hash
+ tiedhash (?)
+ hash_of_arrays (?)
+ object
+ instance
+ array_of_objects (?)
+ code
+ code_or_scalar (?)
+
+See L<Class::MakeMethods::Template::Generic> for the interfaces and behaviors of these method types.
+
+The items marked with a ? above have not been tested sufficiently; please inform the author if they do not function as you would expect.
+
+=cut
+
+########################################################################
+
+1;
diff --git a/lib/Class/MakeMethods/Template/Class.pm b/lib/Class/MakeMethods/Template/Class.pm
new file mode 100644
index 0000000..c846709
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/Class.pm
@@ -0,0 +1,103 @@
+package Class::MakeMethods::Template::Class;
+
+use Class::MakeMethods::Template::Generic '-isasubclass';
+
+$VERSION = 1.008;
+use strict;
+require 5.0;
+use Carp;
+
+=head1 NAME
+
+Class::MakeMethods::Template::Class - Associate information with a package
+
+=head1 SYNOPSIS
+
+ package MyObject;
+ use Class::MakeMethods::Template::Class (
+ scalar => [ 'foo' ]
+ );
+
+ package main;
+
+ MyObject->foo('bar')
+ print MyObject->foo();
+
+=head1 DESCRIPTION
+
+These meta-methods provide access to class-specific values. They are similar to Static, except that each subclass has separate values.
+
+=cut
+
+sub generic {
+ {
+ '-import' => {
+ 'Template::Generic:generic' => '*'
+ },
+ 'modifier' => {
+ },
+ 'code_expr' => {
+ '_VALUE_' => '_ATTR_{data}->{_SELF_CLASS_}',
+ },
+ }
+}
+
+########################################################################
+
+=head2 Class:scalar
+
+Creates methods to handle a scalar variable in the declaring package.
+
+See the documentation on C<Generic:scalar> for interfaces and behaviors.
+
+=cut
+
+########################################################################
+
+=head2 Class:array
+
+Creates methods to handle a array variable in the declaring package.
+
+See the documentation on C<Generic:array> for interfaces and behaviors.
+
+=cut
+
+sub array {
+ {
+ '-import' => {
+ 'Template::Generic:array' => '*',
+ },
+ 'modifier' => {
+ '-all' => q{ _REF_VALUE_ or @{_ATTR_{data}->{_SELF_CLASS_}} = (); * },
+ },
+ 'code_expr' => {
+ '_VALUE_' => '\@{_ATTR_{data}->{_SELF_CLASS_}}',
+ },
+ }
+}
+
+########################################################################
+
+=head2 Class:hash
+
+Creates methods to handle a hash variable in the declaring package.
+
+See the documentation on C<Generic:hash> for interfaces and behaviors.
+
+=cut
+
+sub hash {
+ {
+ '-import' => {
+ 'Template::Generic:hash' => '*',
+ },
+ 'modifier' => {
+ '-all' => q{ _REF_VALUE_ or %{_ATTR_{data}->{_SELF_CLASS_}} = (); * },
+ },
+ 'code_expr' => {
+ '_VALUE_' => '\%{_ATTR_{data}->{_SELF_CLASS_}}',
+ },
+ }
+}
+
+1;
diff --git a/lib/Class/MakeMethods/Template/ClassInherit.pm b/lib/Class/MakeMethods/Template/ClassInherit.pm
new file mode 100644
index 0000000..9c61393
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/ClassInherit.pm
@@ -0,0 +1,144 @@
+=head1 NAME
+
+Class::MakeMethods::Template::ClassInherit - Overridable class data
+
+=head1 SYNOPSIS
+
+ package MyClass;
+
+ use Class::MakeMethods( 'Template::ClassInherit:scalar' => 'foo' );
+ # We now have an accessor method for an "inheritable" scalar value
+
+ package main;
+
+ MyClass->foo( 'Foozle' ); # Set a class-wide value
+ print MyClass->foo(); # Retrieve class-wide value
+ ...
+
+ package MySubClass;
+ @ISA = 'MyClass';
+
+ print MySubClass->foo(); # Intially same as superclass,
+ MySubClass->foo('Foobar'); # but overridable per subclass/
+
+=head1 DESCRIPTION
+
+The MakeMethods subclass provides accessor methods that search an inheritance tree to find a value. This allows you to set a shared or default value for a given class, and optionally override it in a subclass.
+
+=cut
+
+########################################################################
+
+package Class::MakeMethods::Template::ClassInherit;
+
+use Class::MakeMethods::Template::Generic '-isasubclass';
+
+$VERSION = 1.008;
+use strict;
+require 5.0;
+use Carp;
+
+sub generic {
+ {
+ '-import' => {
+ 'Template::Generic:generic' => '*'
+ },
+ 'modifier' => {
+ '-all' => [ q{
+ _INIT_VALUE_CLASS_
+ *
+ } ],
+ },
+ 'code_expr' => {
+ '_VALUE_CLASS_' => '$_value_class',
+ '_INIT_VALUE_CLASS_' => q{
+ my _VALUE_CLASS_;
+ for ( my @_INC_search = _SELF_CLASS_; scalar @_INC_search; ) {
+ _VALUE_CLASS_ = shift @_INC_search;
+ last if ( exists _ATTR_{data}->{_VALUE_CLASS_} );
+ no strict 'refs';
+ unshift @_INC_search, @{"_VALUE_CLASS_\::ISA"};
+ }
+ },
+ '_VALUE_' => '_ATTR_{data}->{_VALUE_CLASS_}',
+ '_GET_VALUE_' => q{ _ATTR_{data}->{_VALUE_CLASS_} },
+ '_SET_VALUE_{}' => q{ ( _VALUE_CLASS_ = _SELF_CLASS_ and _ATTR_{data}->{_VALUE_CLASS_} = * ) },
+ },
+ }
+}
+
+########################################################################
+
+=head2 Standard Methods
+
+The following methods from Generic should all be supported:
+
+ scalar
+ string
+ string_index (?)
+ number
+ boolean
+ bits (?)
+ array (*)
+ hash (*)
+ tiedhash (?)
+ hash_of_arrays (?)
+ object (?)
+ instance (?)
+ array_of_objects (?)
+ code (?)
+ code_or_scalar (?)
+
+See L<Class::MakeMethods::Template::Generic> for the interfaces and behaviors of these method types.
+
+The items marked with a * above are specifically defined in this package, whereas the others are formed automatically by the interaction of this package's generic settings with the code templates provided by the Generic superclass.
+
+The items marked with a ? above have not been tested sufficiently; please inform the author if they do not function as you would expect.
+
+=cut
+
+sub array {
+ {
+ '-import' => {
+ 'Template::Generic:array' => '*',
+ },
+ 'modifier' => {
+ '-all' => [ q{ _VALUE_ ||= []; * } ],
+ },
+ 'code_expr' => {
+ '_VALUE_' => '\@{_ATTR_{data}->{_SELF_CLASS_}}',
+ },
+ }
+}
+
+sub hash {
+ {
+ '-import' => {
+ 'Template::Generic:hash' => '*',
+ },
+ 'modifier' => {
+ '-all' => [ q{ _VALUE_ ||= {}; * } ],
+ },
+ 'code_expr' => {
+ '_VALUE_' => '\%{_ATTR_{data}->{_SELF_CLASS_}}',
+ },
+ }
+}
+
+########################################################################
+
+=head1 SEE ALSO
+
+See L<Class::MakeMethods> for general information about this distribution.
+
+See L<Class::MakeMethods::Template> for more about this family of subclasses.
+
+See L<Class::MakeMethods::Template::Generic> for information about the various accessor interfaces subclassed herein.
+
+If you just need scalar accessors, see L<Class::Data::Inheritable> for a very elegant and efficient implementation.
+
+=cut
+
+########################################################################
+
+1;
diff --git a/lib/Class/MakeMethods/Template/ClassName.pm b/lib/Class/MakeMethods/Template/ClassName.pm
new file mode 100644
index 0000000..c37433f
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/ClassName.pm
@@ -0,0 +1,330 @@
+package Class::MakeMethods::Template::ClassName;
+
+use Class::MakeMethods::Template '-isasubclass';
+$VERSION = 1.008;
+
+sub _diagnostic { &Class::MakeMethods::_diagnostic }
+
+########################################################################
+###### CLASS NAME MANIPULATIONS
+########################################################################
+
+=head1 NAME
+
+Class::MakeMethods::Template::ClassName - Access object's class
+
+=head1 SYNOPSIS
+
+ package MyObject;
+ use Class::MakeMethods::Template::ClassName (
+ subclass_name => [ 'type' ]
+ );
+ ...
+ package main;
+ my $object = MyObject->new;
+
+ $object->type('Foo')
+ # reblesses object to MyObject::Foo subclass
+
+ print $object->type();
+ # prints "Foo".
+
+=head1 DESCRIPTION
+
+These method types access or change information about the class an object is associated with.
+
+=head2 class_name
+
+Called without arguments, returns the class name.
+
+If called with an argument, reblesses object into that class.
+If the class doesn't already exist, it will be created.
+
+=head2 subclass_name
+
+Called without arguments, returns the subclass name.
+
+If called with an argument, reblesses object into that subclass.
+If the subclass doesn't already exist, it will be created.
+
+The subclass name is written as follows:
+
+=over 4
+
+=item *
+
+if it's the original, defining class: empty
+
+=item *
+
+if its a a package within the namespace of the original: the distingushing name within that namespace, without leading C<::>
+
+=item *
+
+if it's a package elsewhere: the full name with leading C<::>
+
+=back
+
+=cut
+
+# $subclass = _pack_subclass( $base, $pckg );
+sub _pack_subclass {
+ my $base = shift;
+ my $pckg = shift;
+
+ ( $pckg eq $base ) ? '' :
+ ( $pckg =~ s/^\Q$base\E\:\:// ) ? $pckg :
+ "::$pckg";
+}
+
+# $pckg = _unpack_subclass( $base, $subclass );
+sub _unpack_subclass {
+ my $base = shift;
+ my $subclass = shift;
+
+ ! $subclass ? $base :
+ ( $subclass =~ s/^::// ) ? $subclass :
+ "$base\::$subclass";
+}
+
+# $pckg = _require_class( $package );
+sub _require_class {
+ my $package = shift;
+
+ no strict 'refs';
+ unless ( @{$package . '::ISA'} ) {
+ (my $file = $package . '.pm' ) =~ s|::|/|go;
+ local $SIG{__DIE__} = sub { die @_ };
+ # warn "Auto-requiring package $package \n";
+ eval { require $file };
+ if ( $@ ) { _diagnostic('mm_package_fail', $package, $@) }
+ }
+
+ return $package;
+}
+
+# $pckg = _provide_class( $base, $package );
+sub _provide_class {
+ my $base = shift;
+ my $package = shift;
+
+ # If the subclass hasn't been created yet, do so.
+ no strict 'refs';
+ unless ( scalar @{$package . '::ISA'} ) {
+ # warn "Auto-vivifying $base subclass $package\n";
+ @{$package . '::ISA'} = ( $base );
+ }
+
+ return $package;
+}
+
+sub class_name {
+ {
+ 'interface' => {
+ default => 'autocreate',
+ autocreate => { '*'=>'autocreate' },
+ require => { '*'=>'require' },
+ },
+ 'behavior' => {
+ 'autocreate' => q{
+ if ( ! scalar @_ ) {
+ _CLASS_GET_
+ } else {
+ _CLASS_PROVIDE_
+ }
+ },
+ 'require' => q{
+ if ( ! scalar @_ ) {
+ _CLASS_GET_
+ } else {
+ _CLASS_REQUIRE_
+ }
+ },
+ },
+ 'code_expr' => {
+ _CLASS_GET_ => q{
+ my $class = ref $self || $self;
+ },
+ _CLASS_REQUIRE_ => q{
+ my $class = Class::MakeMethods::Template::ClassName::_require_class( shift() );
+ _BLESS_AND_RETURN_
+ },
+ _CLASS_PROVIDE_ => q{
+ my $class = Class::MakeMethods::Template::ClassName::_provide_class(
+ $m_info->{'target_class'}, shift() );
+ _BLESS_AND_RETURN_
+ },
+ _BLESS_AND_RETURN_ => q{
+ bless $self, $class if ( ref $self );
+ return $class;
+ },
+ },
+ }
+}
+
+sub subclass_name {
+ {
+ '-import' => {
+ 'Template::ClassName:class_name' => '*',
+ },
+ 'code_expr' => {
+ _CLASS_GET_ => q{
+ my $class = ref $self || $self;
+ Class::MakeMethods::Template::ClassName::_pack_subclass( $m_info->{'target_class'}, $class )
+ },
+ _CLASS_REQUIRE_ => q{
+ my $subclass = Class::MakeMethods::Template::ClassName::_unpack_subclass(
+ $m_info->{'target_class'}, shift() );
+ my $class = Class::MakeMethods::Template::ClassName::_require_class($subclass);
+ _BLESS_AND_RETURN_
+ },
+ _CLASS_PROVIDE_ => q{
+ my $subclass = Class::MakeMethods::Template::ClassName::_unpack_subclass(
+ $m_info->{'target_class'}, shift() );
+ my $class = Class::MakeMethods::Template::ClassName::_provide_class(
+ $m_info->{'target_class'}, $subclass );
+ _BLESS_AND_RETURN_
+ },
+ },
+ }
+}
+
+
+########################################################################
+### CLASS_REGISTRY
+
+=head2 static_hash_classname
+
+Provides a shared hash mapping keys to class names.
+
+ class_registry => [ qw/ foo / ]
+
+Takes a single string or a reference to an array of strings as its argument.
+For each string, creates a new anonymous hash and associated accessor methods
+that will map scalar values to classes in the calling package's subclass
+hiearchy.
+
+The accessor methods provide an interface to the hash as illustrated below.
+Note that several of these functions operate quite differently depending on the
+number of arguments passed, or the context in which they are called.
+
+=over 4
+
+=item @indexes = $class_or_ref->x;
+
+Returns the scalar values that are indexes associated with this class, or the class of this object.
+
+=item $class = $class_or_ref->x( $index );
+
+Returns the class name associated with the provided index value.
+
+=item @classes = $class_or_ref->x( @indexes );
+
+Returns the associated classes for each index in order.
+
+=item @all_indexes = $class_or_ref->x_keys;
+
+Returns a list of the indexes defined for this registry.
+
+=item @all_classes = $class_or_ref->x_values;
+
+Returns a list of the classes associated with this registry.
+
+=item @all_classes = $class_or_ref->unique_x_values;
+
+Returns a list of the classes associated with this registry, with no more than one occurance of any value.
+
+=item %mapping = $class_or_ref->x_hash;
+
+Return the key-value pairs used to store this attribute
+
+=item $mapping_ref = $class_or_ref->x_hash;
+
+Returns a reference to the hash used for the mapping.
+
+=item $class_or_ref->add_x( @indexes );
+
+Adds an entry in the hash for each of the provided indexes, mapping it to this class, or the class of this object.
+
+=item $class_or_ref->clear_x;
+
+Removes those entries from the hash whose values are this class, or the class of this object.
+
+=item $class_or_ref->clear_xs( @indexes );
+
+Remove all entries from the hash.
+
+=back
+
+=cut
+
+sub static_hash_classname {
+ {
+ '-import' => {
+ 'Template::Static:hash' => '*',
+ },
+ 'params' => { 'instance' => {} },
+ 'interface' => {
+ default => {
+ '*'=>'get_classname',
+ 'add_*'=>'add_classname',
+ 'clear_*'=>'drop_classname',
+ '*_keys'=>'keys',
+ '*_hash'=>'get',
+ '*_values'=>'values',
+ 'clear_*s'=>'clear',
+ 'unique_*_values'=>'unique_values',
+ },
+ },
+ 'behavior' => {
+ 'get_classname' => sub { my $m_info = $_[0]; sub {
+ my $self = shift;
+ my $class = ( ref($self) || $self );
+
+ defined $m_info->{'instance'} or $m_info->{'instance'} = {};
+ my $hash = $m_info->{'instance'};
+
+ if ( ! scalar @_ ) {
+ my @keys = grep { $hash->{$_} eq $class } keys %$hash;
+ return wantarray ? @keys : $keys[0];
+ } elsif (scalar @_ == 1) {
+ return $hash->{ shift() };
+ } else {
+ return @{$hash}{ @_ };
+ }
+ }},
+ 'add_classname' => sub { my $m_info = $_[0]; sub {
+ my $self = shift;
+ my $class = ( ref($self) || $self );
+
+ defined $m_info->{'instance'} or $m_info->{'instance'} = {};
+ my $hash = $m_info->{'instance'};
+
+ foreach ( @_ ) { $hash->{$_} = $class }
+ }},
+ 'drop_classname' => sub { my $m_info = $_[0]; sub {
+ my $self = shift;
+ my $class = ( ref($self) || $self );
+
+ defined $m_info->{'instance'} or $m_info->{'instance'} = {};
+ my $hash = $m_info->{'instance'};
+
+ foreach ( grep { $hash->{$_} eq $class } keys %$hash ){
+ delete $hash{$_}
+ }
+ }},
+ },
+ }
+}
+
+########################################################################
+
+=head1 SEE ALSO
+
+See L<Class::MakeMethods> for general information about this distribution.
+
+See L<Class::MakeMethods::Template> for information about this family of subclasses.
+
+=cut
+
+1;
diff --git a/lib/Class/MakeMethods/Template/ClassVar.pm b/lib/Class/MakeMethods/Template/ClassVar.pm
new file mode 100644
index 0000000..a5a2478
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/ClassVar.pm
@@ -0,0 +1,178 @@
+package Class::MakeMethods::Template::ClassVar;
+
+use Class::MakeMethods::Template::Generic '-isasubclass';
+
+$VERSION = 1.008;
+use strict;
+require 5.0;
+use Carp;
+
+=head1 NAME
+
+Class::MakeMethods::Template::ClassVar - Static methods with subclass variation
+
+=head1 SYNOPSIS
+
+ package MyObject;
+ use Class::MakeMethods::Template::ClassVar (
+ scalar => [ 'foo' ]
+ );
+
+ package main;
+
+ MyObject->foo('bar')
+ print MyObject->foo();
+
+ $MyObject::foo = 'bazillion';
+ print MyObject->foo();
+
+=head1 DESCRIPTION
+
+These meta-methods provide access to package (class global) variables,
+with the package determined at run-time.
+
+This is basically the same as the PackageVar meta-methods, except
+that PackageVar methods find the named variable in the package that
+defines the method, while ClassVar methods use the package the object
+is blessed into. As a result, subclasses will each store a distinct
+value for a ClassVar method, but will share the same value for a
+PackageVar or Static method.
+
+B<Common Parameters>: The following parameters are defined for ClassVar meta-methods.
+
+=over 4
+
+=item variable
+
+The name of the variable to store the value in. Defaults to the same name as the method.
+
+=back
+
+=cut
+
+sub generic {
+ {
+ '-import' => {
+ 'Template::Generic:generic' => '*'
+ },
+ 'params' => {
+ 'variable' => '*'
+ },
+ 'modifier' => {
+ '-all' => [ q{ no strict; * } ],
+ },
+ 'code_expr' => {
+ '_VALUE_' => '${_SELF_CLASS_."::"._ATTR_{variable}}',
+ },
+ }
+}
+
+########################################################################
+
+=head2 Standard Methods
+
+The following methods from Generic should all be supported:
+
+ scalar
+ string
+ string_index (?)
+ number
+ boolean
+ bits (?)
+ array (*)
+ hash (*)
+ tiedhash (?)
+ hash_of_arrays (?)
+ object (?)
+ instance (?)
+ array_of_objects (?)
+ code (?)
+ code_or_scalar (?)
+
+See L<Class::MakeMethods::Template::Generic> for the interfaces and behaviors of these method types.
+
+The items marked with a * above are specifically defined in this package, whereas the others are formed automatically by the interaction of this package's generic settings with the code templates provided by the Generic superclass.
+
+The items marked with a ? above have not been tested sufficiently; please inform the author if they do not function as you would expect.
+
+=cut
+
+########################################################################
+
+sub array {
+ {
+ '-import' => {
+ 'Template::Generic:array' => '*',
+ },
+ 'modifier' => {
+ '-all' => q{ no strict; _ENSURE_REF_VALUE_; * },
+ },
+ 'code_expr' => {
+ '_ENSURE_REF_VALUE_' => q{
+ _REF_VALUE_ or @{_SELF_CLASS_."::"._ATTR_{variable}} = ();
+ },
+ '_VALUE_' => '(\@{_SELF_CLASS_."::"._ATTR_{variable}})',
+ },
+ }
+}
+
+########################################################################
+
+sub hash {
+ {
+ '-import' => {
+ 'Template::Generic:hash' => '*',
+ },
+ 'modifier' => {
+ '-all' => q{ no strict; _ENSURE_REF_VALUE_; * },
+ },
+ 'code_expr' => {
+ '_ENSURE_REF_VALUE_' => q{
+ _REF_VALUE_ or %{_SELF_CLASS_."::"._ATTR_{variable}} = ();
+ },
+ '_VALUE_' => '(\%{_SELF_CLASS_."::"._ATTR_{variable}})',
+ },
+ }
+}
+
+########################################################################
+
+=head2 vars
+
+This rewrite rule converts package variable names into ClassVar methods of the equivalent data type.
+
+Here's an example declaration:
+
+ package MyClass;
+
+ use Class::MakeMethods::Template::ClassVar (
+ vars => '$VERSION @ISA'
+ );
+
+MyClass now has methods that get and set the contents of its $MyClass::VERSION and @MyClass::ISA package variables:
+
+ MyClass->VERSION( 2.4 );
+ MyClass->push_ISA( 'Exporter' );
+
+Subclasses can use these methods to adjust their own variables:
+
+ package MySubclass;
+ MySubclass->MyClass::push_ISA( 'MyClass' );
+ MySubclass->VERSION( 1.0 );
+
+=cut
+
+sub vars {
+ my $mm_class = shift;
+ my @rewrite = map [ "Template::ClassVar:$_" ], qw( scalar array hash );
+ my %rewrite = ( '$' => 0, '@' => 1, '%' => 2 );
+ while (@_) {
+ my $name = shift;
+ my $data = shift;
+ $data =~ s/\A(.)//;
+ push @{ $rewrite[ $rewrite{ $1 } ] }, { 'name'=>$name, 'variable'=>$data };
+ }
+ return @rewrite;
+}
+
+1;
diff --git a/lib/Class/MakeMethods/Template/Flyweight.pm b/lib/Class/MakeMethods/Template/Flyweight.pm
new file mode 100644
index 0000000..33f44ed
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/Flyweight.pm
@@ -0,0 +1,43 @@
+package Class::MakeMethods::Template::Flyweight;
+
+use Class::MakeMethods::Template::InsideOut '-isasubclass';
+
+$VERSION = 1.008;
+
+sub new { { '-import' => { 'Template::Scalar:new' => '*' } } }
+
+1;
+
+__END__
+
+=head1 NAME
+
+Class::MakeMethods::Template::Flyweight - Deprecated name for InsideOut
+
+=head1 SYNOPSIS
+
+ package MyObject;
+ use Class::MakeMethods::Template::InsideOut (
+ new => [ 'new' ]
+ scalar => [ 'foo', 'bar' ]
+ );
+
+ package main;
+
+ my $obj = MyObject->new( foo => "Foozle", bar => "Bozzle" );
+ print $obj->foo(); # Prints Foozle
+ $obj->bar("Bamboozle"); # Sets $obj->{bar}
+
+=head1 DESCRIPTION
+
+Earlier versions of this package included a package named Class::MakeMethods::Template::Flyweight.
+
+However, in hindsight, this name was poorly chosen, as it suggests that the Flyweight object design pattern is being used, when the functionality is more akin to what's sometimes known as "inside-out objects."
+
+This functionality is now provided by Class::MakeMethods::Template::InsideOut, of which this is an almost-empty subclass retained to provide backwards compatibility.
+
+=head1 SEE ALSO
+
+L<Class::MakeMethods::Template::InsideOut>.
+
+=cut \ No newline at end of file
diff --git a/lib/Class/MakeMethods/Template/Generic.pm b/lib/Class/MakeMethods/Template/Generic.pm
new file mode 100644
index 0000000..368f21f
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/Generic.pm
@@ -0,0 +1,2349 @@
+=head1 NAME
+
+Class::MakeMethods::Template::Generic - Templates for common meta-method types
+
+=head1 SYNOPSIS
+
+ package MyObject;
+ use Class::MakeMethods (
+ 'Template::Hash:new' => [ 'new' ],
+ 'Template::Hash:scalar' => [ 'foo' ]
+ 'Template::Static:scalar' => [ 'bar' ]
+ );
+
+ package main;
+
+ my $obj = MyObject->new( foo => "Foozle", bar => "Bozzle" );
+ print $obj->foo();
+ $obj->bar("Bamboozle");
+
+=head1 DESCRIPTION
+
+This package provides a variety of abstract interfaces for constructors
+and accessor methods, which form a common foundation for meta-methods
+provided by the Hash, Scalar, Flyweight, Static, PackageVar, and
+ClassVar implementations.
+
+Generally speaking, the Generic meta-methods define calling interfaces
+and behaviors which are bound to differently scoped data by each
+of those subclasses.
+
+=cut
+
+########################################################################
+
+package Class::MakeMethods::Template::Generic;
+
+use Class::MakeMethods::Template '-isasubclass';
+
+$VERSION = 1.008;
+use strict;
+use Carp;
+
+# use AutoLoader 'AUTOLOAD';
+
+########################################################################
+
+sub generic {
+ {
+ 'params' => {
+ },
+ 'modifier' => {
+ '-import' => { 'Template::Universal:generic' => '*' },
+ },
+ 'code_expr' => {
+ '-import' => { 'Template::Universal:generic' => '*' },
+ '_VALUE_' => undef,
+ '_REF_VALUE_' => q{ _VALUE_ },
+ '_GET_VALUE_' => q{ _VALUE_ },
+ '_SET_VALUE_{}' => q{ ( _VALUE_ = * ) },
+ '_PROTECTED_SET_VALUE_{}' => q{ (_ACCESS_PROTECTED_ and _SET_VALUE_{*}) },
+ '_PRIVATE_SET_VALUE_{}' => q{ ( _ACCESS_PRIVATE_ and _SET_VALUE_{*} ) },
+ },
+ }
+}
+
+# 1;
+
+# __END__
+
+########################################################################
+
+=head2 new Constructor
+
+There are several types of hash-based object constructors to choose from.
+
+Each of these methods creates and returns a reference to a new
+blessed instance. They differ in how their (optional) arguments
+are interpreted to set initial values, and in how they operate when
+called as class or instance methods.
+
+B<Interfaces>: The following interfaces are supported.
+
+=over 4
+
+=item -with_values,
+
+Provides the with_values behavior.
+
+=item -with_init
+
+Provides the with_init behavior.
+
+=item -with_methods
+
+Provides the with_methods behavior.
+
+=item -new_and_init
+
+Provides the with_init behavior for I<*>, and the general purpose method_init behavior as an init method.
+
+=item -copy_with_values
+
+Provides the copy behavior.
+
+=back
+
+B<Behaviors>: The following types of constructor methods are available.
+
+=over 4
+
+=item with_values
+
+Creates and blesses a new instance.
+
+If arguments are passed they are included in the instance, otherwise it will be empty.
+
+Returns the new instance.
+
+May be called as a class or instance method.
+
+=item with_methods
+
+Creates, blesses, and returns a new instance.
+
+The arguments are treated as a hash of method-name/argument-value
+pairs, with each such pair causing a call C<$self-E<gt>name($value)>.
+
+=item with_init
+
+Creates and blesses a new instance, then calls a method named C<init>,
+passing along any arguments that were initially given.
+
+Returns the new instance.
+
+The I<init>() method should be defined in the class declaring these methods.
+
+May be called as a class or instance method.
+
+=item and_then_init
+
+Creates a new instance using method-name/argument-value pairs, like C<with_methods>, but then calls a method named C<init> before returning the new object. The C<init> method does not receive any arguments.
+
+The I<init>() method should be defined in the class declaring these methods.
+
+=item instance_with_methods
+
+If called as a class method, creates, blesses, and returns a new
+instance. If called as an object method, operates on and returns
+the existing instance.
+
+Accepts name-value pair arguments, or a reference to hash of such
+pairs, and calls the named method for each with the supplied value
+as a single argument. (See the Universal method_init behavior for
+more discussion of this pattern.)
+
+=item copy_with values
+
+Produce a copy of an instance. Can not be called as a class method.
+
+The copy is a *shallow* copy; any references will be shared by the
+instance upon which the method is called and the returned newborn.
+
+If a list of key-value pairs is passed as arguments to the method,
+they are added to the copy, overwriting any values with the same
+key that may have been copied from the original.
+
+=item copy_with_methods
+
+Produce a copy of an instance. Can not be called as a class method.
+
+The copy is a *shallow* copy; any references will be shared by the
+instance upon which the method is called and the returned newborn.
+
+Accepts name-value pair arguments, or a reference to hash of such
+pairs, and calls the named method on the copy for each with the
+supplied value as a single argument before the copy is returned.
+
+=item copy_instance_with_values
+
+If called as a class method, creates, blesses, and returns a new
+instance. If called as an object method, produces and returns a
+copy of an instance.
+
+The copy is a *shallow* copy; any references will be shared by the
+instance upon which the method is called and the returned newborn.
+
+If a list of key-value pairs is passed as arguments to the method,
+they are added to the copy, overwriting any values with the same
+key that may have been copied from the original.
+
+=item copy_instance_with_methods
+
+If called as a class method, creates, blesses, and returns a new
+instance. If called as an object method, produces and returns a
+copy of an instance.
+
+The copy is a *shallow* copy; any references will be shared by the
+instance upon which the method is called and the returned newborn.
+
+Accepts name-value pair arguments, or a reference to hash of such
+pairs, and calls the named method on the copy for each with the supplied value as
+a single argument before the copy is returned.
+
+=back
+
+B<Parameters>: The following parameters are supported:
+
+=over 4
+
+=item init_method
+
+The name of the method to call after creating a new instance. Defaults to 'init'.
+
+=back
+
+=cut
+
+sub new {
+ {
+ '-import' => {
+ # 'Template::Generic:generic' => '*',
+ },
+ 'interface' => {
+ default => 'with_methods',
+ with_values => 'with_values',
+ with_methods => 'with_methods',
+ with_init => 'with_init',
+ and_then_init => 'and_then_init',
+ new_and_init => { '*'=>'new_with_init', 'init'=>'method_init'},
+ instance_with_methods => 'instance_with_methods',
+ copy => 'copy_with_values',
+ copy_with_values => 'copy_with_values',
+ copy_with_methods => 'copy_with_methods',
+ copy_instance_with_values => 'copy_instance_with_values',
+ copy_instance_with_methods => 'copy_instance_with_methods',
+ },
+ 'behavior' => {
+ 'with_methods' => q{
+ $self = _EMPTY_NEW_INSTANCE_;
+ _CALL_METHODS_FROM_HASH_
+ return $self;
+ },
+ 'with_values' => q{
+ $self = _EMPTY_NEW_INSTANCE_;
+ _SET_VALUES_FROM_HASH_
+ return $self;
+ },
+ 'with_init' => q{
+ $self = _EMPTY_NEW_INSTANCE_;
+ my $init_method = $m_info->{'init_method'} || 'init';
+ $self->$init_method( @_ );
+ return $self;
+ },
+ 'and_then_init' => q{
+ $self = _EMPTY_NEW_INSTANCE_;
+ _CALL_METHODS_FROM_HASH_
+ my $init_method = $m_info->{'init_method'} || 'init';
+ $self->$init_method();
+ return $self;
+ },
+ 'instance_with_methods' => q{
+ $self = ref ($self) ? $self : _EMPTY_NEW_INSTANCE_;
+ _CALL_METHODS_FROM_HASH_
+ return $self;
+ },
+ 'copy_with_values' => q{
+ @_ = ( %$self, @_ );
+ $self = _EMPTY_NEW_INSTANCE_;
+ _SET_VALUES_FROM_HASH_
+ return $self;
+ },
+ 'copy_with_methods' => q{
+ @_ = ( %$self, @_ );
+ $self = _EMPTY_NEW_INSTANCE_;
+ _CALL_METHODS_FROM_HASH_
+ return $self;
+ },
+ 'copy_instance_with_values' => q{
+ $self = bless { ( ref $self ? %$self : () ) }, _SELF_CLASS_;
+ _SET_VALUES_FROM_HASH_
+ return $self;
+ },
+ 'copy_instance_with_methods' => q{
+ $self = bless { ref $self ? %$self : () }, _SELF_CLASS_;
+ _CALL_METHODS_FROM_HASH_
+ return $self;
+ },
+ },
+ }
+}
+
+########################################################################
+
+=head2 scalar Accessor
+
+A generic scalar-value accessor meta-method which serves as an
+abstraction for basic "get_set" methods and numerous related
+interfaces
+
+ use Class::MakeMethods -MakerClass => "...",
+ scalar => [ 'foo', 'bar' ];
+ ...
+ $self->foo( 'my new foo value' );
+ print $self->foo();
+
+(Note that while you can use the scalar methods to store references to
+various data structures, there are other meta-methods defined below that
+may be more useful for managing references to arrays, hashes, and objects.)
+
+B<Interfaces>: The following calling interfaces are available.
+
+=over 4
+
+=item get_set (default)
+
+Provides get_set method for I<*>.
+
+Example: Create method foo, which sets the value of 'foo' for this
+instance if an argument is passed in, and then returns the value
+whether or not it's been changed:
+
+ use Class::MakeMethods -MakerClass => "...",
+ scalar => [ 'foo' ];
+
+=item get_protected_set
+
+Provides an get_set accessor for I<*> that croaks if a new value
+is passed in from a package that is not a subclass of the declaring
+one.
+
+=item get_private_set
+
+Provides an get_set accessor for I<*> that croaks if a new value
+is passed in from a package other than the declaring one.
+
+=item read_only
+
+Provides an accessor for I<*> that does not modify its value. (Its
+initial value would have to be set by some other means.)
+
+=item eiffel
+
+Provides get behavior as I<*>, and set behavior as set_I<*>.
+
+Example: Create methods bar which returns the value of 'bar' for
+this instance (takes no arguments), and set_bar, which sets the
+value of 'bar' (no return):
+
+ use Class::MakeMethods -MakerClass => "...",
+ scalar => [ --eiffel => 'bar' ];
+
+=item java
+
+Provides get behavior as getI<*>, and set behavior as setI<*>.
+
+Example: Create methods getBaz which returns the value of 'Baz'
+for this instance (takes no arguments), and setBaz, which sets the
+value for this instance (no return):
+
+ use Class::MakeMethods -MakerClass => "...",
+ scalar => [ --java => 'Baz' ];
+
+
+=item init_and_get
+
+Creates methods which cache their results in a hash key.
+
+Provides the get_init behavior for I<*>, and an delete behavior for clear_I<*>.
+Specifies default value for init_method parameter of init_I<*>.
+
+
+=item with_clear
+
+Provides get_set behavior for I<*>, and a clear_I<*> method.
+
+=back
+
+
+B<Behaviors>: The following types of accessor methods are available.
+
+=over 4
+
+=item get_set
+
+If no argument is provided, returns the value of the current instance. The value defaults to undef.
+
+If an argument is provided, it is stored as the value of the current
+instance (even if the argument is undef), and that value is returned.
+
+Also available as get_protected_set and get_private_set, which are
+available for public read-only access, but have access control
+limitations.
+
+=item get
+
+Returns the value from the current instance.
+
+=item set
+
+Sets the value for the current instance. If called with no arguments,
+the value is set to undef. Does not return a value.
+
+=item clear
+
+Sets value to undef.
+
+=item get_set_chain
+
+Like get_set, but if called with an argument, returns the object it was called on. This allows a series of mutators to be called as follows:
+
+ package MyObject;
+ use Class::MakeMethods (
+ 'Template::Hash:scalar --get_set_chain' => 'foo bar baz'
+ );
+ ...
+
+ my $obj = MyObject->new->foo('Foozle');
+ $obj->bar("none")->baz("Brazil");
+ print $obj->foo, $obj->bar, $obj->baz;
+
+=item get_set_prev
+
+Like get_set, but if called with an argument, returns the previous value before it was changed to the new one.
+
+=item get_init
+
+If the value is currently undefined, calls the init_method. Returns the value.
+
+=back
+
+B<Parameters>: The following parameters are supported:
+
+=over 4
+
+=item init_method
+
+The name of a method to be called to initialize this meta-method.
+
+Only used by the get_init behavior.
+
+=back
+
+=cut
+
+sub scalar {
+ {
+ '-import' => { 'Template::Generic:generic' => '*' },
+ 'interface' => {
+ default => 'get_set',
+ get_set => { '*'=>'get_set' },
+ noclear => { '*'=>'get_set' },
+ with_clear => { '*'=>'get_set', 'clear_*'=>'clear' },
+
+ read_only => { '*'=>'get' },
+ get_private_set => 'get_private_set',
+ get_protected_set => 'get_protected_set',
+
+ eiffel => { '*'=>'get', 'set_*'=>'set_return' },
+ java => { 'get*'=>'get', 'set*'=>'set_return' },
+
+ init_and_get => { '*'=>'get_init', -params=>{ init_method=>'init_*' } },
+
+ },
+ 'behavior' => {
+ 'get' => q{ _GET_VALUE_ },
+ 'set' => q{ _SET_VALUE_{ shift() } },
+ 'set_return' => q{ _BEHAVIOR_{set}; return },
+ 'clear' => q{ _SET_VALUE_{ undef } },
+ 'defined' => q{ defined _VALUE_ },
+
+ 'get_set' => q {
+ if ( scalar @_ ) {
+ _BEHAVIOR_{set}
+ } else {
+ _BEHAVIOR_{get}
+ }
+ },
+ 'get_set_chain' => q {
+ if ( scalar @_ ) {
+ _BEHAVIOR_{set};
+ return _SELF_
+ } else {
+ _BEHAVIOR_{get}
+ }
+ },
+ 'get_set_prev' => q {
+ my $value = _BEHAVIOR_{get};
+ if ( scalar @_ ) {
+ _BEHAVIOR_{set};
+ }
+ return $value;
+ },
+
+ 'get_private_set' => q{
+ if ( scalar @_ ) {
+ _PRIVATE_SET_VALUE_{ shift() }
+ } else {
+ _BEHAVIOR_{get}
+ }
+ },
+ 'get_protected_set' => q{
+ if ( scalar @_ ) {
+ _PROTECTED_SET_VALUE_{ shift() }
+ } else {
+ _BEHAVIOR_{get}
+ }
+ },
+ 'get_init' => q{
+ if ( ! defined _VALUE_ ) {
+ my $init_method = _ATTR_REQUIRED_{'init_method'};
+ _SET_VALUE_{ _SELF_->$init_method( @_ ) };
+ } else {
+ _BEHAVIOR_{get}
+ }
+ },
+
+ },
+ 'params' => {
+ new_method => 'new'
+ },
+ }
+}
+
+########################################################################
+
+=head2 string Accessor
+
+A generic scalar-value accessor meta-method which serves as an
+abstraction for basic "get_set" methods and numerous related
+interfaces
+
+ use Class::MakeMethods -MakerClass => "...",
+ string => [ 'foo', 'bar' ];
+ ...
+ $self->foo( 'my new foo value' );
+ print $self->foo();
+
+This meta-method extends the scalar meta-method, and supports the same interfaces and parameters.
+
+However, it generally treats values as strings, and can not be used to store references.
+
+B<Interfaces>: In addition to those provided by C<scalar>, the following calling interfaces are available.
+
+=over 4
+
+=item -get_concat
+
+Provides the get_concat behavior for I<*>, and a clear_I<*> method.
+
+Example:
+
+ use Class::MakeMethods
+ get_concat => { name => 'words', join => ", " };
+
+ $obj->words('foo');
+ $obj->words('bar');
+ $obj->words() eq 'foo, bar';
+
+=back
+
+B<Behaviors>: In addition to those provided by C<scalar>, the following types of accessor methods are available.
+
+=over 4
+
+=item concat
+
+Concatenates the argument value with the existing value.
+
+=item get_concat
+
+Like get_set except sets do not clear out the original value, but instead
+concatenate the new value to the existing one.
+
+=back
+
+B<Parameters>: In addition to those provided by C<scalar>, the following parameters are supported.
+
+=over 4
+
+=item join
+
+If the join parameter is defined, each time the get_concat behavior
+is invoked, it will glue its argument onto any existing value with
+the join string as the separator. The join field is applied I<between>
+values, not prior to the first or after the last. Defaults to undefined
+
+=back
+
+=cut
+
+sub string {
+ {
+ '-import' => { 'Template::Generic:scalar' => '*' },
+ 'interface' => {
+ get_concat => { '*'=>'get_concat', 'clear_*'=>'clear',
+ -params=>{ 'join' => '' }, },
+ },
+ 'params' => {
+ 'return_value_undefined' => '',
+ },
+ 'behavior' => {
+ 'get' => q{
+ if ( defined( my $value = _GET_VALUE_) ) {
+ _GET_VALUE_;
+ } else {
+ _STATIC_ATTR_{return_value_undefined};
+ }
+ },
+ 'set' => q{
+ my $new_value = shift();
+ _SET_VALUE_{ "$new_value" };
+ },
+ 'concat' => q{
+ my $new_value = shift();
+ if ( defined( my $value = _GET_VALUE_) ) {
+ _SET_VALUE_{join( _STATIC_ATTR_{join}, $value, $new_value)};
+ } else {
+ _SET_VALUE_{ "$new_value" };
+ }
+ },
+ 'get_concat' => q{
+ if ( scalar @_ ) {
+ _BEHAVIOR_{concat}
+ } else {
+ _BEHAVIOR_{get}
+ }
+ },
+ },
+ }
+}
+
+########################################################################
+
+=head2 string_index
+
+ string_index => [ qw / foo bar baz / ]
+
+Creates string accessor methods, like string above, but also
+maintains a static hash index in which each object is stored under
+the value of the field when the slot is set.
+
+This is a unique index, so only one object can have a given key.
+If an object has a slot set to a value which another object is
+already set to the object currently set to that value has that slot
+set to undef and the new object will be put into the hash under
+that value.
+
+Objects with undefined values are not stored in the index.
+
+Note that to free items from memory, you must clear these values!
+
+B<Methods>:
+
+=over 4
+
+=item *
+
+The method find_x is defined which if called with any arguments
+returns a list of the objects stored under those values in the
+hash. Called with no arguments, it returns a reference to the hash.
+
+=back
+
+B<Profiles>:
+
+=over 4
+
+=item *
+
+find_or_new
+
+ 'string_index -find_or_new' => [ qw / foo bar baz / ]
+
+Just like string_index except the find_x method is defined to call the new
+method to create an object if there is no object already stored under
+any of the keys you give as arguments.
+
+=back
+
+=cut
+
+sub string_index {
+ ( {
+ '-import' => { 'Template::Generic:generic' => '*' },
+ 'params' => {
+ 'new_method' => 'new',
+ },
+ 'interface' => {
+ default => { '*'=>'get_set', 'clear_*'=>'clear', 'find_*'=>'find' },
+ find_or_new=>{'*'=>'get_set', 'clear_*'=>'clear', 'find_*'=>'find_or_new'}
+ },
+ 'code_expr' => {
+ _REMOVE_FROM_INDEX_ => q{
+ if (defined ( my $old_v = _GET_VALUE_ ) ) {
+ delete _ATTR_{'index'}{ $old_v };
+ }
+ },
+ _ADD_TO_INDEX_ => q{
+ if (defined ( my $new_value = _GET_VALUE_ ) ) {
+ if ( my $old_item = _ATTR_{'index'}{$new_value} ) {
+ # There's already an object stored under that value so we
+ # need to unset it's value.
+ # And maybe issue a warning? Or croak?
+ my $m_name = _ATTR_{'name'};
+ $old_item->$m_name( undef );
+ }
+
+ # Put ourself in the index under that value
+ _ATTR_{'index'}{$new_value} = _SELF_;
+ }
+ },
+ _INDEX_HASH_ => '_ATTR_{index}',
+ },
+ 'behavior' => {
+ '-init' => [ sub {
+ my $m_info = $_[0];
+ defined $m_info->{'index'} or $m_info->{'index'} = {};
+ return;
+ } ],
+ 'get' => q{
+ return _GET_VALUE_;
+ },
+ 'set' => q{
+ my $new_value = shift;
+
+ _REMOVE_FROM_INDEX_
+
+ # Set our value to new
+ _SET_VALUE_{ $new_value };
+
+ _ADD_TO_INDEX_
+ },
+ 'get_set' => q{
+ if ( scalar @_ ) {
+ _BEHAVIOR_{set}
+ } else {
+ _BEHAVIOR_{get}
+ }
+ },
+ 'clear' => q{
+ _REMOVE_FROM_INDEX_
+ _SET_VALUE_{ undef };
+ },
+ 'find' => q{
+ if ( scalar @_ ) {
+ return @{ _ATTR_{'index'} }{ @_ };
+ } else {
+ return _INDEX_HASH_
+ }
+ },
+ 'find_or_new' => q{
+ if ( scalar @_ ) {
+ my $class = _SELF_CLASS_;
+ my $new_method = _ATTR_REQUIRED_{'new_method'};
+ my $m_name = _ATTR_{'name'};
+ foreach (@_) {
+ next if defined _ATTR_{'index'}{$_};
+ # create new instance and set its value; it'll add itself to index
+ $class->$new_method()->$m_name($_);
+ }
+ return @{ _ATTR_{'index'} }{ @_ };
+ } else {
+ return _INDEX_HASH_
+ }
+ },
+ },
+ } )
+}
+
+########################################################################
+
+=head2 number Accessor
+
+A generic scalar-value accessor meta-method which serves as an
+abstraction for basic "get_set" methods and numerous related
+interfaces
+
+ use Class::MakeMethods -MakerClass => "...",
+ string => [ 'foo', 'bar' ];
+ ...
+ $self->foo( 23 );
+ print $self->foo();
+
+This meta-method extends the scalar meta-method, and supports the same interfaces and parameters.
+
+However, it generally treats values as numbers, and can not be used to store strings or references.
+
+B<Interfaces>: In addition to those provided by C<scalar>, the following calling interfaces are available.
+
+=over 4
+
+=item -counter
+
+Provides the numeric get_set behavior for I<*>, and numeric I<*>_incr and I<*>_reset methods.
+
+=back
+
+B<Behaviors>: In addition to those provided by C<scalar>, the following types of accessor methods are available.
+
+=over 4
+
+=item get_set
+
+The get_set behavior is similar to the default scalar behavior except that empty values are treated as zero.
+
+=item increment
+
+If no argument is provided, increments the I<hash_key> value by 1.
+If an argument is provided, the value is incremented by that amount.
+Returns the increased value.
+
+=item clear
+
+Sets the value to zero.
+
+=back
+
+=cut
+
+sub number {
+ {
+ '-import' => { 'Template::Generic:scalar' => '*' },
+ 'interface' => {
+ counter => { '*'=>'get_set', '*_incr'=>'incr', '*_reset'=>'clear' },
+ },
+ 'params' => {
+ 'return_value_undefined' => 0,
+ },
+ 'behavior' => {
+ 'get_set' => q{
+ if ( scalar @_ ) {
+ local $_ = shift;
+ if ( defined $_ ) {
+ croak "Can't set _STATIC_ATTR_{name} to non-numeric value '$_'"
+ if ( /[^\+\-\,\d\.e]/ );
+ s/\,//g;
+ }
+ _SET_VALUE_{ $_ }
+ }
+ defined( _GET_VALUE_ ) ? _GET_VALUE_
+ : _STATIC_ATTR_{return_value_undefined}
+ },
+ 'incr' => q{
+ _VALUE_ ||= 0;
+ _VALUE_ += ( scalar @_ ? shift : 1 )
+ },
+ 'decr' => q{
+ _VALUE_ ||= 0;
+ _VALUE_ -= ( scalar @_ ? shift : 1 )
+ },
+ },
+ }
+}
+
+########################################################################
+
+=head2 boolean Accessor
+
+A generic scalar-value accessor meta-method which serves as an abstraction for basic "get_set" methods and numerous related interfaces
+
+ use Class::MakeMethods -MakerClass => "...",
+ string => [ 'foo', 'bar' ];
+ ...
+ $self->foo( 1 );
+ print $self->foo();
+ $self->clear_foo;
+
+This meta-method extends the scalar meta-method, and supports the
+same interfaces and parameters. However, it generally treats values
+as true-or-false flags, and can not be used to store strings,
+numbers, or references.
+
+B<Interfaces>:
+
+=over 4
+
+=item flag_set_clear (default)
+
+Provides the get_set behavior for I<*>, and set_I<*> and clear_I<*> methods to set the value to true or false.
+
+=back
+
+B<Behaviors>: In addition to those provided by C<scalar>, the following types of accessor methods are available.
+
+=over 4
+
+=item get_set
+
+The get_set behavior is similar to the get_set scalar behavior
+except that empty or false values are treated as zero, and true
+values are treated as zero.
+
+=item set_true
+
+Sets the value to one.
+
+=item set_false
+
+Sets the value to zero.
+=back
+
+=cut
+
+sub boolean {
+ {
+ '-import' => { 'Template::Generic:scalar' => '*' },
+ 'interface' => {
+ default => {'*'=>'get_set', 'clear_*'=>'set_false',
+ 'set_*'=>'set_true'},
+ flag_set_clear => {'*'=>'get_set', 'clear_*'=>'set_false',
+ 'set_*'=>'set_true'},
+ },
+ 'behavior' => {
+ 'get' => q{ _GET_VALUE_ || 0 },
+ 'set' => q{
+ if ( shift ) {
+ _BEHAVIOR_{set_true}
+ } else {
+ _BEHAVIOR_{set_false}
+ }
+ },
+ 'set_true' => q{ _SET_VALUE_{ 1 } },
+ 'set_false' => q{ _SET_VALUE_{ 0 } },
+ 'set_value' => q{
+ _SET_VALUE_{ scalar @_ ? shift : 1 }
+ },
+ },
+ }
+}
+
+########################################################################
+
+=head2 bits Accessor
+
+A generic accessor for bit-field values.
+
+The difference between 'Template::Generic:bits' and
+'Template::Generic:boolean' is that all flags created with this
+meta-method are stored in a single vector for space efficiency.
+
+B<Interfaces>: The following calling interfaces are available.
+
+=over 4
+
+=item default
+
+Provides get_set behavior for I<*>, a set_I<*> method which sets
+the value to true and a clear_I<*> method which sets the value to
+false.
+
+Also defines methods named bits, bit_fields, and bit_dump with the
+behaviors below. These methods are shared across all of the boolean
+meta-methods defined by a single class.
+
+=item class_methods
+
+.
+
+=back
+
+B<Basic Behaviors>: The following types of bit-level accessor methods are available.
+
+=over 4
+
+=item get_set
+
+Returns the value of the named flag. If called with an argument, it first
+sets the named flag to the truth-value of the argument.
+
+=item set_true
+
+Sets the value to true.
+
+=item set_false
+
+Sets the value to false.
+
+=back
+
+B<Group Methods>: The following types of methods manipulate the overall vector value.
+
+=over 4
+
+=item bits
+
+Returns the vector containing all of the bit fields (remember however
+that a vector containing all 0 bits is still true).
+
+=item bit_dump
+
+Returns a hash of the flag-name/flag-value pairs.
+
+=item bits_size
+
+Returns the number of bits that can fit into the current vector.
+
+=item bits_complement
+
+Returns the twos-complement of the vector.
+
+=item bit_pos_get
+
+Takes a single argument and returns the value of the bit stored in that position.
+
+=item bit_pos_set
+
+Takes two arguments and sets the bit stored in the position of the first argument to the value of the second argument.
+
+=back
+
+B<Class Methods>: The following types of class methods are available.
+
+=over 4
+
+=item bit_names
+
+Returns a list of all the flags by name.
+
+=back
+
+=cut
+
+sub bits {
+ {
+ '-import' => {
+ # 'Template::Generic:generic' => '*',
+ },
+ 'interface' => {
+ default => {
+ '*'=>'get_set', 'set_*'=>'set_true', 'clear_*'=>'set_false',
+ 'bit_fields'=>'bit_names', 'bit_string'=>'bit_string',
+ 'bit_list'=>'bit_list', 'bit_hash'=>'bit_hash',
+ },
+ class_methods => {
+ 'bit_fields'=>'bit_names', 'bit_string'=>'bit_string',
+ 'bit_list'=>'bit_list', 'bit_hash'=>'bit_hash',
+ },
+ },
+ 'code_expr' => {
+ '_VEC_POS_VALUE_{}' => 'vec(_VALUE_, *, 1)',
+ _VEC_VALUE_ => '_VEC_POS_VALUE_{ _ATTR_{bfp} }',
+ _CLASS_INFO_ => '$Class::MakeMethods::Template::Hash::bits{_STATIC_ATTR_{target_class}}',
+ },
+ 'modifier' => {
+ '-all' => [ q{
+ defined _VALUE_ or _VALUE_ = "";
+ *
+ } ],
+ },
+ 'behavior' => {
+ '-init' => sub {
+ my $m_info = $_[0];
+
+ $m_info->{bfp} ||= do {
+ my $array = ( $Class::MakeMethods::Template::Hash::bits{$m_info->{target_class}} ||= [] );
+ my $idx;
+ foreach ( 0..$#$array ) {
+ if ( $array->[$_] eq $m_info->{'name'} ) { $idx = $_; last }
+ }
+ unless ( $idx ) {
+ push @$array, $m_info->{'name'};
+ $idx = $#$array;
+ }
+ $idx;
+ };
+
+ return;
+ },
+ 'bit_names' => q{
+ @{ _CLASS_INFO_ };
+ },
+ 'bit_string' => q{
+ if ( @_ ) {
+ _SET_VALUE_{ shift @_ };
+ } else {
+ _VALUE_;
+ }
+ },
+ 'bits_size' => q{
+ 8 * length( _VALUE_ );
+ },
+ 'bits_complement' => q{
+ ~ _VALUE_;
+ },
+ 'bit_hash' => q{
+ my @bits = @{ _CLASS_INFO_ };
+ if ( @_ ) {
+ my %bits = @_;
+ _SET_VALUE_{ pack 'b*', join '', map { $_ ? 1 : 0 } @bits{ @bits } };
+ return @_;
+ } else {
+ map { $bits[$_], vec(_VALUE_, $_, 1) } 0 .. $#bits
+ }
+ },
+ 'bit_list' => q{
+ if ( @_ ) {
+ _SET_VALUE_{ pack 'b*', join( '', map { $_ ? 1 : 0 } @_ ) };
+ return map { $_ ? 1 : 0 } @_;
+ } else {
+ split //, unpack "b*", _VALUE_;
+ }
+ },
+ 'bit_pos_get' => q{
+ vec(_VALUE_, $_[0], 1)
+ },
+ 'bit_pos_set' => q{
+ vec(_VALUE_, $_[0], 1) = ( $_[1] ? 1 : 0 )
+ },
+
+ 'get_set' => q{
+ if ( @_ ) {
+ _VEC_VALUE_ = ( $_[0] ? 1 : 0 );
+ } else {
+ _VEC_VALUE_;
+ }
+ },
+ 'get' => q{
+ _VEC_VALUE_;
+ },
+ 'set' => q{
+ _VEC_VALUE_ = ( $_[0] ? 1 : 0 );
+ },
+ 'set_true' => q{
+ _VEC_VALUE_ = 1;
+ },
+ 'set_false' => q{
+ _VEC_VALUE_ = 0;
+ },
+
+ },
+ }
+}
+
+
+########################################################################
+
+=head2 array Accessor
+
+Creates accessor methods for manipulating arrays of values.
+
+B<Interfaces>: The following calling interfaces are available.
+
+=over 4
+
+=item default
+
+Provides get_set behavior for I<*>, and I<verb>_I<*> methods for the non-get behaviors below.
+
+=item minimal
+
+Provides get_set behavior for I<*>, and I<*>_I<verb> methods for clear behavior.
+
+=item get_set_items
+
+Provides the get_set_items for I<*>.
+
+=item x_verb
+
+Provides get_push behavior for I<*>, and I<*>_I<verb> methods for the non-get behaviors below.
+
+=item get_set_ref
+
+Provides the get_set_ref for I<*>.
+
+=item get_set_ref_help
+
+Provides the get_set_ref for I<*>, and I<verb>_I<*> methods for the non-get behaviors below.
+
+=back
+
+B<Behaviors>: The following types of accessor methods are available.
+
+=over 4
+
+=item get_set_items
+
+Called with no arguments returns a reference to the array stored in the slot.
+
+Called with one simple scalar argument it treats the argument as an index
+and returns the value stored under that index.
+
+Called with more than one argument, treats them as a series of index/value
+pairs and adds them to the array.
+
+=item get_push
+
+If arguments are passed, these values are pushed on to the list; if a single array ref is passed, its values are used as the arguments.
+
+This method returns the list of values stored in the slot. In an array
+context it returns them as an array and in a scalar context as a
+reference to the array.
+
+=item get_set_ref
+
+If arguments are passed, these values are placed on the list, replacing the current contents; if a single array ref is passed, its values are used as the arguments.
+
+This method returns the list of values stored in the slot. In an array
+context it returns them as an array and in a scalar context as a
+reference to the array.
+
+=item get_set
+
+If arguments are passed, these values are placed on the list, replacing the current contents.
+
+This method returns the list of values stored in the slot. In an array
+context it returns them as an array and in a scalar context as a
+reference to the array.
+
+
+=item push
+
+Append items to tail.
+
+=item pop
+
+Remove an item from the tail.
+
+=item shift
+
+Remove an item from the front.
+
+=item unshift
+
+Prepend items to front.
+
+=item splice
+
+Remove or replace items.
+
+=item clear
+
+Remove all items.
+
+=item count
+
+Returns the number of item in the list.
+
+=back
+
+=cut
+
+sub array {
+ {
+ '-import' => { 'Template::Generic:generic' => '*' },
+ 'interface' => {
+ default => {
+ '*'=>'get_set',
+ map( ($_.'_*' => $_ ), qw( pop push unshift shift splice clear count )),
+ map( ('*_'.$_ => $_ ), qw( ref index ) ),
+ },
+ minimal => { '*'=>'get_set', '*_clear'=>'clear' },
+ get_set_items => { '*'=>'get_set_items' },
+ x_verb => {
+ '*'=>'get_set',
+ map( ('*_'.$_ => $_ ), qw(pop push unshift shift splice clear count ref index )),
+ },
+ get_set_ref => { '*'=>'get_set_ref' },
+ get_set_ref_help => { '*'=>'get_set_ref', '-base'=>'default' },
+ },
+ 'modifier' => {
+ '-all' => [ q{ _ENSURE_REF_VALUE_; * } ],
+ },
+ 'code_expr' => {
+ '_ENSURE_REF_VALUE_' => q{ _REF_VALUE_ ||= []; },
+ },
+ 'behavior' => {
+ 'get_set' => q{
+ @{_REF_VALUE_} = @_ if ( scalar @_ );
+ return wantarray ? @{_GET_VALUE_} : _REF_VALUE_;
+ },
+ 'get_set_ref' => q{
+ @{_REF_VALUE_} = ( ( scalar(@_) == 1 and ref($_[0]) eq 'ARRAY' ) ? @{$_[0]} : @_ ) if ( scalar @_ );
+ return wantarray ? @{_GET_VALUE_} : _REF_VALUE_;
+ },
+ 'get_push' => q{
+ push @{_REF_VALUE_}, map { ref $_ eq 'ARRAY' ? @$_ : ($_) } @_;
+ return wantarray ? @{_GET_VALUE_} : _REF_VALUE_;
+ },
+ 'ref' => q{ _REF_VALUE_ },
+ 'get' => q{ return wantarray ? @{_GET_VALUE_} : _REF_VALUE_ },
+ 'set' => q{ @{_REF_VALUE_} = @_ },
+ 'pop' => q{ pop @{_REF_VALUE_} },
+ 'push' => q{ push @{_REF_VALUE_}, @_ },
+ 'shift' => q{ shift @{_REF_VALUE_} },
+ 'unshift' => q{ unshift @{_REF_VALUE_}, @_ },
+ 'slice' => q{ _GET_VALUE_->[ @_ ] },
+ 'splice' => q{ splice @{_REF_VALUE_}, shift, shift, @_ },
+ 'count' => q{ scalar @{_GET_VALUE_} },
+ 'clear' => q{ @{ _REF_VALUE_ } = () },
+ 'index' => q{
+ my $list = _REF_VALUE_;
+ ( scalar(@_) == 1 ) ? $list->[shift]
+ : wantarray ? (map $list->[$_], @_) : [map $list->[$_], @_]
+ },
+ 'get_set_items' => q{
+ if ( scalar @_ == 0 ) {
+ return _REF_VALUE_;
+ } elsif ( scalar @_ == 1 ) {
+ return _GET_VALUE_->[ shift() ];
+ } else {
+ _BEHAVIOR_{set_items}
+ }
+ },
+ 'set_items' => q{
+ ! (@_ % 2) or croak "Odd number of items in assigment to _STATIC_ATTR_{name}";
+ while ( scalar @_ ) {
+ my ($index, $value) = splice @_, 0, 2;
+ _REF_VALUE_->[ $index ] = $value;
+ }
+ return _REF_VALUE_;
+ },
+ }
+ }
+}
+
+########################################################################
+
+=head2 hash Accessor
+
+Creates accessor methods for manipulating hashes of key-value pairs.
+
+B<Interfaces>: The following calling interfaces are available.
+
+=over 4
+
+=item default
+
+Provides get_set behavior for I<*>, and I<*>_I<verb> methods for most of the other behaviors below.
+
+=item get_set_items
+
+Provides the get_set_items for I<*>.
+
+=back
+
+B<Behaviors>: The following types of accessor methods are available.
+
+=over 4
+
+=item get_set_items
+
+Called with no arguments returns a reference to the hash stored.
+
+Called with one simple scalar argument it treats the argument as a key
+and returns the value stored under that key.
+
+Called with more than one argument, treats them as a series of key/value
+pairs and adds them to the hash.
+
+=item get_push
+
+Called with no arguments returns the hash stored, as a hash
+in a list context or as a reference in a scalar context.
+
+Called with one simple scalar argument it treats the argument as a key
+and returns the value stored under that key.
+
+Called with one array reference argument, the array elements
+are considered to be be keys of the hash. x returns the list of values
+stored under those keys (also known as a I<hash slice>.)
+
+Called with one hash reference argument, the keys and values of the
+hash are added to the hash.
+
+Called with more than one argument, treats them as a series of key/value
+pairs and adds them to the hash.
+
+=item get_set
+
+Like get_push, except if called with more then one argument, empties
+the current hash items before adding those arguments to the hash.
+
+=item push
+
+Called with one hash reference argument, the keys and values of the
+hash are added to the hash.
+
+Called with more than one argument, treats them as a series of key/value
+pairs and adds them to the hash.
+
+=item keys
+
+Returns a list of the keys of the hash.
+
+=item values
+
+Returns a list of the values in the hash.
+
+=item tally
+
+Takes a list of arguments and for each scalar in the list increments the
+value stored in the hash and returns a list of the current (after the
+increment) values.
+
+=item exists
+
+Takes a single key, returns whether that key exists in the hash.
+
+=item delete
+
+Takes a list, deletes each key from the hash, and returns the corresponding values.
+
+=item clear
+
+Resets hash to empty.
+
+=back
+
+=cut
+
+sub hash {
+ {
+ '-import' => { 'Template::Generic:generic' => '*' },
+ 'interface' => {
+ 'default' => {
+ '*'=>'get_set',
+ map {'*_'.$_ => $_} qw(push set keys values delete exists tally clear),
+ },
+ get_set_items => { '*'=>'get_set_items' },
+ },
+ 'modifier' => {
+ '-all' => [ q{ _ENSURE_REF_VALUE_; * } ],
+ },
+ 'code_expr' => {
+ '_ENSURE_REF_VALUE_' => q{ _REF_VALUE_ ||= {}; },
+ _HASH_GET_ => q{
+ ( wantarray ? %{_GET_VALUE_} : _REF_VALUE_ )
+ },
+ _HASH_GET_VALUE_ => q{
+ ( ref $_[0] eq 'ARRAY' ? @{ _GET_VALUE_ }{ @{ $_[0] } }
+ : _REF_VALUE_->{ $_[0] } )
+ },
+ _HASH_SET_ => q{
+ ! (@_ % 2) or croak "Odd number of items in assigment to _STATIC_ATTR_{name}";
+ %{_REF_VALUE_} = @_
+ },
+ _HASH_PUSH_ => q{
+ ! (@_ % 2)
+ or croak "Odd number of items in assigment to _STATIC_ATTR_{name}";
+ my $count;
+ while ( scalar @_ ) {
+ local $_ = shift;
+ _REF_VALUE_->{ $_ } = shift();
+ ++ $count;
+ }
+ $count;
+ },
+ },
+ 'behavior' => {
+ 'get_set' => q {
+ # If called with no arguments, return hash contents
+ return _HASH_GET_ if (scalar @_ == 0);
+
+ # If called with a hash ref, act as if contents of hash were passed
+ # local @_ = %{ $_[0] } if ( scalar @_ == 1 and ref $_[0] eq 'HASH' );
+ @_ = %{ $_[0] } if ( scalar @_ == 1 and ref $_[0] eq 'HASH' );
+
+ # If called with an index, get that value, or a slice for array refs
+ return _HASH_GET_VALUE_ if (scalar @_ == 1 );
+
+ # Push on new values and return complete set
+ _HASH_SET_;
+ return _HASH_GET_;
+ },
+
+ 'get_push' => q{
+ # If called with no arguments, return hash contents
+ return _HASH_GET_ if (scalar @_ == 0);
+
+ # If called with a hash ref, act as if contents of hash were passed
+ # local @_ = %{ $_[0] } if ( scalar @_ == 1 and ref $_[0] eq 'HASH' );
+ @_ = %{ $_[0] } if ( scalar @_ == 1 and ref $_[0] eq 'HASH' );
+
+ # If called with an index, get that value, or a slice for array refs
+ return _HASH_GET_VALUE_ if (scalar @_ == 1 );
+
+ # Push on new values and return complete set
+ _HASH_PUSH_;
+ return _HASH_GET_;
+ },
+ 'get_set_items' => q{
+ if ( scalar @_ == 0 ) {
+ return _REF_VALUE_;
+ } elsif ( scalar @_ == 1 ) {
+ return _REF_VALUE_->{ shift() };
+ } else {
+ while ( scalar @_ ) {
+ my ($index, $value) = splice @_, 0, 2;
+ _REF_VALUE_->{ $index } = $value;
+ }
+ return _REF_VALUE_;
+ }
+ },
+ 'get' => q{ _HASH_GET_ },
+ 'set' => q{ _HASH_SET_ },
+ 'push' => q{
+ # If called with a hash ref, act as if contents of hash were passed
+ # local @_ = %{ $_[0] } if ( scalar @_ == 1 and ref $_[0] eq 'HASH' );
+ @_ = %{ $_[0] } if ( scalar @_ == 1 and ref $_[0] eq 'HASH' );
+
+ _HASH_PUSH_
+ },
+
+ 'keys' => q{ keys %{_GET_VALUE_} },
+ 'values' => q{ values %{_GET_VALUE_} },
+ 'unique_values' => q{
+ values %{ { map { $_=>$_ } values %{_GET_VALUE_} } }
+ },
+ 'delete' => q{ scalar @_ <= 1 ? delete @{ _REF_VALUE_ }{ $_[0] }
+ : map { delete @{ _REF_VALUE_ }{ $_ } } (@_) },
+ 'exists' => q{
+ return 0 unless defined _GET_VALUE_;
+ foreach (@_) { return 0 unless exists ( _REF_VALUE_->{$_} ) }
+ return 1;
+ },
+ 'tally' => q{ map { ++ _REF_VALUE_->{$_} } @_ },
+ 'clear' => q{ %{ _REF_VALUE_ } = () },
+ 'ref' => q{ _REF_VALUE_ },
+ },
+ }
+}
+
+########################################################################
+
+=head2 tiedhash Accessor
+
+A variant of Generic:hash which initializes the hash by tieing it to a caller-specified package.
+
+See the documentation on C<Generic:hash> for interfaces and behaviors.
+
+B<Parameters>: The following parameters I<must> be provided:
+
+=over 4
+
+=item tie
+
+I<Required>. The name of the class to tie to.
+I<Make sure you have C<use>d the required class>.
+
+=item args
+
+I<Required>. Additional arguments for the tie, as an array ref.
+
+=back
+
+Example:
+
+ use Class::MakeMethods
+ tie_hash => [ hits => { tie => q/Tie::RefHash/, args => [] } ];
+
+ use Class::MakeMethods
+ tie_hash => [ [qw(hits errors)] => { tie => q/Tie::RefHash/, args => [] } ];
+
+ use Class::MakeMethods
+ tie_hash => [ { name => hits, tie => q/Tie::RefHash/, args => [] } ];
+
+=cut
+
+sub tiedhash {
+ {
+ '-import' => { 'Template::Generic:hash' => '*' },
+ 'modifier' => {
+ '-all' => [ q{
+ if ( ! defined _GET_VALUE_ ) {
+ %{ _REF_VALUE_ } = ();
+ tie %{ _REF_VALUE_ }, _ATTR_REQUIRED_{tie}, @{ _ATTR_{args} };
+ }
+ *
+ } ],
+ },
+ }
+}
+
+########################################################################
+
+=head2 hash_of_arrays Accessor
+
+Creates accessor methods for manipulating hashes of array-refs.
+
+B<Interfaces>: The following calling interfaces are available.
+
+=over 4
+
+=item default
+
+Provides get behavior for I<*>, and I<*>_I<verb> methods for the other behaviors below.
+
+=back
+
+B<Behaviors>: The following types of accessor methods are available.
+
+=over 4
+
+=item get
+
+Returns all the values for all the given keys, in order. If no keys are
+given, returns all the values (in an unspecified key order).
+
+The result is returned as an arrayref in scalar context. This arrayref
+is I<not> part of the data structure; messing with it will not affect
+the contents directly (even if a single key was provided as argument.)
+
+If any argument is provided which is an arrayref, then the members of
+that array are used as keys. Thus, the trivial empty-key case may be
+utilized with an argument of [].
+
+=item keys
+
+Returns the keys of the hash. As an arrayref in scalar context.
+
+=item exists
+
+Takes a list of keys, and returns whether all of the key exists in the hash
+(i.e., the C<and> of whether the individual keys exist).
+
+=item delete
+
+Takes a list, deletes each key from the hash.
+
+=item push
+
+Takes a key, and some values. Pushes the values onto the list denoted
+by the key. If the first argument is an arrayref, then each element of
+that arrayref is treated as a key and the elements pushed onto each
+appropriate list.
+
+=item pop
+
+Takes a list of keys, and pops each one. Returns the list of popped
+elements. undef is returned in the list for each key that is has an
+empty list.
+
+=item unshift
+
+Like push, only the from the other end of the lists.
+
+=item shift
+
+Like pop, only the from the other end of the lists.
+
+=item splice
+
+Takes a key, offset, length, and a values list. Splices the list named
+by the key. Anything from the offset argument (inclusive) may be
+omitted. See L<perlfunc/splice>.
+
+=item clear
+
+Takes a list of keys. Resets each named list to empty (but does not
+delete the keys.)
+
+=item count
+
+Takes a list of keys. Returns the sum of the number of elements for
+each named list.
+
+=item index
+
+Takes a key, and a list of indices. Returns a list of each item at the
+corresponding index in the list of the given key. Uses undef for
+indices beyond range.
+
+=item remove
+
+Takes a key, and a list of indices. Removes each corresponding item
+from the named list. The indices are effectively looked up at the point
+of call -- thus removing indices 3, 1 from list (a, b, c, d) will
+remove (d) and (b).
+
+=item sift
+
+Takes a key, and a set of named arguments, which may be a list or a hash
+ref. Removes list members based on a grep-like approach.
+
+=over 4
+
+=item filter
+
+The filter function used (as a coderef). Is passed two arguments, the
+value compared against, and the value in the list that is potential for
+grepping out. If returns true, the value is removed. Default is C<sub { $_[0] == $_[1] }>.
+
+=item keys
+
+The list keys to sift through (as an arrayref). Unknown keys are
+ignored. Default: all the known keys.
+
+=item values
+
+The values to sift out (as an arrayref). Default: C<[undef]>
+
+=back
+
+=back
+
+=cut
+
+sub hash_of_arrays {
+ {
+ '-import' => { 'Template::Generic:hash' => '*' },
+ 'interface' => {
+ default => {
+ '*'=>'get',
+ map( ('*_'.$_ => $_ ), qw(keys exists delete pop push shift unshift splice clear count index remove sift last set )),
+ },
+ },
+ 'behavior' => {
+ 'get' => q{
+ my @Result;
+
+ if ( ! scalar @_ ) {
+ @Result = map @$_, values %{_VALUE_};
+ } elsif ( scalar @_ == 1 and ref ($_[0]) eq 'ARRAY' ) {
+ @Result = map @$_, @{_VALUE_}{@{$_[0]}};
+ } else {
+ my @keys = map { ref ($_) eq 'ARRAY' ? @$_ : $_ }
+ grep exists _VALUE_{$_}, @_;
+ @Result = map @$_, @{_VALUE_}{@keys};
+ }
+
+ return wantarray ? @Result : \@Result;
+ },
+ 'pop' => q{
+ map { pop @{_VALUE_->{$_}} } @_
+ },
+ 'last' => q{
+ map { _VALUE_->{$_}->[-1] } @_
+ },
+ 'push' => q{
+ for ( ( ref ($_[0]) eq 'ARRAY' ? @{shift()} : shift() ) ) {
+ push @{_VALUE_->{$_}}, @_;
+ }
+ },
+ 'shift' => q{
+ map { shift @{_VALUE_->{$_}} } @_
+ },
+ 'unshift' => q{
+ for ( ( ref ($_[0]) eq 'ARRAY' ? @{shift()} : shift() ) ) {
+ unshift @{_VALUE_->{$_}}, @_;
+ }
+ },
+ 'splice' => q{
+ my $key = shift;
+ splice @{ _VALUE_->{$key} }, shift, shift, @_;
+ },
+ 'clear' => q{
+ foreach (@_) { _VALUE_->{$_} = []; }
+ },
+ 'count' => q{
+ my $Result = 0;
+ foreach (@_) {
+ # Avoid autovivifying additional entries.
+ $Result += exists _VALUE_->{$_} ? scalar @{_VALUE_->{$_}} : 0;
+ }
+ return $Result;
+ },
+ 'index' => q{
+ my $key_r = shift;
+
+ my @Result;
+ my $key;
+ foreach $key ( ( ref ($key_r) eq 'ARRAY' ? @$key_r : $key_r ) ) {
+ my $ary = _VALUE_->{$key};
+ for (@_) {
+ push @Result, ( @{$ary} > $_ ) ? $ary->[$_] : undef;
+ }
+ }
+ return wantarray ? @Result : \@Result;
+ },
+ 'set' => q{
+ my $key_r = shift;
+
+ croak "_ATTR_{name} expects a key and then index => value pairs.\n"
+ if @_ % 2;
+ while ( scalar @_ ) {
+ my $pos = shift;
+ _VALUE_->{$key_r}->[ $pos ] = shift();
+ }
+ return;
+ },
+ 'remove' => q{
+ my $key_r = shift;
+
+ my $key;
+ foreach $key ( ( ref ($key_r) eq 'ARRAY' ? @$key_r : $key_r ) ) {
+ my $ary = _VALUE_->{$key};
+ foreach ( sort {$b<=>$a} grep $_ < @$ary, @_ ) {
+ splice (@$ary, $_, 1);
+ }
+ }
+ return;
+ },
+ 'sift' => q{
+ my %args = ( scalar @_ == 1 and ref $_[0] eq 'HASH' ) ? %{$_[0]} : @_;
+ my $hash = _VALUE_;
+ my $filter_sr = $args{'filter'} || sub { $_[0] == $_[1] };
+ my $keys_ar = $args{'keys'} || [ keys %$hash ];
+ my $values_ar = $args{'values'} || [undef];
+
+ # This is harder than it looks; reverse means we want to grep out only
+ # if *none* of the values matches. I guess an evaled block, or closure
+ # or somesuch is called for.
+ # my $reverse = $args{'reverse'} || 0;
+
+ my ($key, $i, $value);
+ KEY: foreach $key (@$keys_ar) {
+ next KEY unless exists $hash->{$key};
+ INDEX: for ($i = $#{$hash->{$key}}; $i >= 0; $i--) {
+ foreach $value (@$values_ar) {
+ if ( $filter_sr->($value, $hash->{$key}[$i]) ) {
+ splice @{$hash->{$key}}, $i, 1;
+ next INDEX;
+ }
+ }
+ }
+ }
+ return;
+ },
+ },
+ }
+}
+
+########################################################################
+
+=head2 object Accessor
+
+Creates accessor methods for manipulating references to objects.
+
+In addition to creating a method to get and set the object reference,
+the meta-method can also define forwarded methods that automatically
+pass calls onto the object stored in that slot; see the description of the 'delegate' parameter below.
+
+B<Interfaces>: The following calling interfaces are available.
+
+=over 4
+
+=item default
+
+Provides get_set behavior for I<*>, clear behavior for 'delete_*',
+and forwarding methods for any values in the method's 'delegate'
+or 'soft_delegate' parameters.
+
+=item get_and_set
+
+Provides named get method, set_I<x> and clear_I<x> methods.
+
+=item get_init_and_set
+
+Provides named get_init method, set_I<x> and clear_I<x> methods.
+
+=back
+
+B<Behaviors>: The following types of accessor methods are available.
+
+=over 4
+
+=item get_set
+
+The get_set method, if called with a reference to an object of the
+given class as the first argument, stores it.
+
+If called with any other arguments, creates and stores a new object, passing the arguemnts to the new() method for the object.
+
+If called without arguments, returns the current value, which may be undefined if one has not been stored yet.
+
+=item get_set_init
+
+The get_set_init method, if called with a reference to an object of the
+given class as the first argument, stores it.
+
+If the slot is not filled yet it creates an object by calling the given
+new method of the given class. Any arguments passed to the get_set_init
+method are passed on to new.
+
+In all cases the object now stored is returned.
+
+=item get_init
+
+If the instance is empty, creates and stores a new one. Returns the instance.
+
+=item get
+
+Returns the current value, which may be undefined if one has not been stored yet.
+
+=item set
+
+If called with a reference to an object of the given class as the first argument, stores it.
+
+If called with any other arguments, creates and stores a new object, passing the arguments to the new() method.
+
+If called without arguments, creates and stores a new object, without any arguments to the new() method.
+
+=item clear
+
+Removes the reference value.
+
+=item I<forwarding>
+
+If a 'delegate' or 'soft_delegate' parameter is provided, methods
+with those names are created that are forwarded directly to the
+object in the slot, as described below.
+
+=back
+
+B<Parameters>: The following parameters are supported:
+
+=over 4
+
+=item class
+
+I<Required>. The type of object that will be stored.
+
+=item new_method
+
+The name of the method to call on the above class to create a new instance. Defaults to 'new'.
+
+=item delegate
+
+The methods to forward to the object. Can contain a method name,
+a string of space-spearated method names, or an array of method
+names. This type of method will croak if it is called when the
+target object is not defined.
+
+=item soft_delegate
+
+The methods to forward to the object, if it is present. Can contain
+a method name, a string of space-spearated method names, or an
+array of method names. This type of method will return nothing if
+it is called when the target object is not defined.
+
+=back
+
+=cut
+
+sub object {
+ {
+ '-import' => {
+ # 'Template::Generic:generic' => '*',
+ },
+ 'interface' => {
+ default => { '*'=>'get_set', 'clear_*'=>'clear' },
+ get_set_init => { '*'=>'get_set_init', 'clear_*'=>'clear' },
+ get_and_set => {'*'=>'get', 'set_*'=>'set', 'clear_*'=>'clear' },
+ get_init_and_set => { '*'=>'get_init','set_*'=>'set','clear_*'=>'clear' },
+ init_and_get => { '*'=>'init_and_get', -params=>{ init_method=>'init_*' } },
+ },
+ 'params' => {
+ new_method => 'new'
+ },
+ 'code_expr' => {
+ '_CALL_NEW_AND_STORE_' => q{
+ my $new_method = _ATTR_REQUIRED_{new_method};
+ my $class = _ATTR_REQUIRED_{'class'};
+ _SET_VALUE_{ $class->$new_method(@_) };
+ },
+ },
+ 'behavior' => {
+ '-import' => {
+ 'Template::Generic:scalar' => [ qw( get clear ) ],
+ },
+ 'get_set' => q{
+ if ( scalar @_ ) {
+ if (ref $_[0] and UNIVERSAL::isa($_[0], _ATTR_REQUIRED_{'class'})) {
+ _SET_VALUE_{ shift };
+ } else {
+ _CALL_NEW_AND_STORE_
+ }
+ } else {
+ _VALUE_;
+ }
+ },
+ 'set' => q{
+ if ( ! defined $_[0] ) {
+ _SET_VALUE_{ undef };
+ } elsif (ref $_[0] and UNIVERSAL::isa($_[0], _ATTR_REQUIRED_{'class'})) {
+ _SET_VALUE_{ shift };
+ } else {
+ _CALL_NEW_AND_STORE_
+ }
+ },
+ 'get_init' => q{
+ if ( ! defined _VALUE_ ) {
+ _CALL_NEW_AND_STORE_
+ }
+ _VALUE_;
+ },
+ 'init_and_get' => q{
+ if ( ! defined _VALUE_ ) {
+ my $init_method = _ATTR_REQUIRED_{'init_method'};
+ _SET_VALUE_{ _SELF_->$init_method( @_ ) };
+ } else {
+ _BEHAVIOR_{get}
+ }
+ },
+ 'get_set_init' => q{
+ if (ref $_[0] and UNIVERSAL::isa($_[0], _ATTR_REQUIRED_{'class'})) {
+ _SET_VALUE_{ shift };
+ } elsif ( ! defined _VALUE_ ) {
+ _CALL_NEW_AND_STORE_
+ }
+ _VALUE_;
+ },
+ '-subs' => sub {
+ {
+ 'delegate' => sub { my($m_info, $name) = @_; sub {
+ my $m_name = $m_info->{'name'};
+ my $obj = (shift)->$m_name()
+ or Carp::croak("Can't forward $name because $m_name is empty");
+ $obj->$name(@_)
+ } },
+ 'soft_delegate' => sub { my($m_info, $name) = @_; sub {
+ my $m_name = $m_info->{'name'};
+ my $obj = (shift)->$m_name() or return;
+ $obj->$name(@_)
+ } },
+ }
+ },
+ },
+ }
+}
+
+########################################################################
+
+=head2 instance Accessor
+
+Creates methods to handle an instance of the calling class.
+
+PROFILES
+
+=over 4
+
+=item default
+
+Provides named get method, and I<verb>_I<x> set, new, and clear methods.
+
+=item -implicit_new
+
+Provides named get_init method, and I<verb>_I<x> set, and clear methods.
+
+=item -x_verb
+
+Provides named get method, and I<x>_I<verb> set, new, and clear methods.
+
+=back
+
+B<Behaviors>: The following types of accessor methods are available.
+
+=over 4
+
+=item get
+
+Returns the value of the instance parameter, which may be undefined if one has not been stored yet.
+
+=item get_init
+
+If the instance is empty, creates and stores a new one. Returns the instance.
+
+=item set
+
+Takes a single argument and sets the instance to that value.
+
+=item new
+
+Creates and stores a new instance.
+
+=item clear
+
+Sets the instance parameter to undef.
+
+=back
+
+B<Parameters>: The following parameters are supported:
+
+=over 4
+
+=item instance
+
+Holds the instance reference. Defaults to undef
+
+=item new_method
+
+The name of the method to call when creating a new instance. Defaults to 'new'.
+
+=back
+
+=cut
+
+sub instance {
+ {
+ '-import' => {
+ 'Template::Generic:object' => '*',
+ },
+ 'interface' => {
+ default => 'get_set',
+ },
+ 'code_expr' => {
+ '_CALL_NEW_AND_STORE_' => q{
+ my $new_method = _ATTR_REQUIRED_{new_method};
+ _SET_VALUE_{ (_SELF_)->$new_method(@_) };
+ },
+ },
+ }
+}
+
+########################################################################
+
+=head2 array_of_objects Accessor
+
+Creates accessor methods for manipulating references to arrays of object references.
+
+Operates like C<Generic:array>, but prior to adding any item to
+the array, it first checks to see if it is an instance of the
+designated class, and if not passes it as an argument to that
+class's new method and stores the result instead.
+
+Forwarded methods return a list of the results returned
+by C<map>ing the method over each object in the array.
+
+See the documentation on C<Generic:array> for interfaces and behaviors.
+
+B<Parameters>: The following parameters are supported:
+
+=over 4
+
+=item class
+
+I<Required>. The type of object that will be stored.
+
+=item delegate
+
+The methods to forward to the object. Can contain a method name, a string of space-spearated method names, or an array of method names.
+
+=item new_method
+
+The name of the method to call on the above class to create a new instance. Defaults to 'new'.
+
+=back
+
+=cut
+
+sub array_of_objects {
+ {
+ '-import' => {
+ 'Template::Generic:array' => '*',
+ },
+ 'params' => {
+ new_method => 'new',
+ },
+ 'modifier' => {
+ '-all get_set' => q{ _BLESS_ARGS_ * },
+ '-all get_push' => q{ _BLESS_ARGS_ * },
+ '-all set' => q{ _BLESS_ARGS_ * },
+ '-all push' => q{ _BLESS_ARGS_ * },
+ '-all unshift' => q{ _BLESS_ARGS_ * },
+ # The below two methods are kinda broken, because the new values
+ # don't get auto-blessed properly...
+ '-all splice' => q{ * },
+ '-all set_items' => q{ * },
+ },
+ 'code_expr' => {
+ '_BLESS_ARGS_' => q{
+ my $new_method = _ATTR_REQUIRED_{'new_method'};
+ @_ = map {
+ (ref $_ and UNIVERSAL::isa($_, _ATTR_REQUIRED_{class})) ? $_
+ : _ATTR_{'class'}->$new_method($_)
+ } @_;
+ },
+ },
+ 'behavior' => {
+ '-subs' => sub {
+ {
+ 'delegate' => sub { my($m_info, $name) = @_; sub {
+ my $m_name = $m_info->{'name'};
+ map { $_->$name(@_) } (shift)->$m_name()
+ } },
+ }
+ },
+ },
+ }
+}
+
+########################################################################
+
+=head2 code Accessor
+
+Creates accessor methods for manipulating references to subroutines.
+
+B<Interfaces>: The following calling interfaces are available.
+
+=over 4
+
+=item default
+
+Provides the call_set functionality.
+
+=item method
+
+Provides the call_method functionality.
+
+=back
+
+B<Behaviors>: The following types of accessor methods are available.
+
+=over 4
+
+=item call_set
+
+If called with one argument which is a CODE reference, it installs that
+code in the slot. Otherwise it runs the code stored in the slot with
+whatever arguments (including none) were passed in.
+
+=item call_method
+
+Just like B<call_set>, except the code is called like a method, with $self
+as its first argument. Basically, you are creating a method which can be
+different for each object.
+
+=back
+
+=cut
+
+sub code {
+ {
+ '-import' => {
+ # 'Template::Generic:generic' => '*',
+ },
+ 'interface' => {
+ default => 'call_set',
+ call_set => 'call_set',
+ method => 'call_method',
+ },
+ 'behavior' => {
+ '-import' => {
+ 'Template::Generic:scalar' => [ qw( get_set get set clear ) ],
+ },
+ 'call_set' => q{
+ if ( scalar @_ == 1 and ref($_[0]) eq 'CODE') {
+ _SET_VALUE_{ shift }; # Set the subroutine reference
+ } else {
+ &{ _VALUE_ }( @_ ); # Run the subroutine on the given arguments
+ }
+ },
+ 'call_method' => q{
+ if ( scalar @_ == 1 and ref($_[0]) eq 'CODE') {
+ _SET_VALUE_{ shift }; # Set the subroutine reference
+ } else {
+ &{ _VALUE_ }( _SELF_, @_ ); # Run the subroutine on self and args
+ }
+ },
+ },
+ }
+}
+
+
+########################################################################
+
+=head2 code_or_scalar Accessor
+
+Creates accessor methods for manipulating either strings or references to subroutines.
+
+You can store any scalar value; code refs are executed when you retrieve the value, while other scalars are returned as-is.
+
+B<Interfaces>: The following calling interfaces are available.
+
+=over 4
+
+=item default
+
+Provides the call_set functionality.
+
+=item method
+
+Provides the call_method functionality.
+
+=item eiffel
+
+Provides the named get_method, and a helper set_* method.
+
+=back
+
+B<Behaviors>: The following types of accessor methods are available.
+
+=over 4
+
+=item get_set_call
+
+If called with an argument, either a CODE reference or some other scalar, it installs that code in the slot. Otherwise, if the current value runs the code stored in the slot with
+whatever arguments (including none) were passed in.
+
+=item get_set_method
+
+Just like B<call_set>, except the code is called like a method, with $self
+as its first argument. Basically, you are creating a method which can be
+different for each object.
+
+=back
+
+=cut
+
+sub code_or_scalar {
+ {
+ '-import' => { 'Template::Generic:scalar' => '*' },
+ 'interface' => {
+ default => 'get_set_call',
+ get_set => 'get_set_call',
+ eiffel => { '*'=>'get_method', 'set_*'=>'set' },
+ method => 'get_set_method',
+ },
+ 'params' => {
+ },
+ 'behavior' => {
+ 'get_call' => q{
+ my $value = _GET_VALUE_;
+ ( ref($value) eq 'CODE' ) ? &$value( @_ ) : $value
+ },
+ 'get_method' => q{
+ my $value = _GET_VALUE_;
+ ( ref($value) eq 'CODE' ) ? &$value( _SELF_, @_ ) : $value
+ },
+ 'get_set_call' => q{
+ if ( scalar @_ == 1 ) {
+ _BEHAVIOR_{set}
+ } else {
+ _BEHAVIOR_{get_call}
+ }
+ },
+ 'get_set_method' => q{
+ if ( scalar @_ == 1 ) {
+ _BEHAVIOR_{set}
+ } else {
+ _BEHAVIOR_{get_call}
+ }
+ },
+ },
+ }
+}
+
+
+########################################################################
+
+=head1 SEE ALSO
+
+See L<Class::MakeMethods> for general information about this distribution.
+
+See L<Class::MakeMethods::Template> for information about this family of subclasses.
+
+=cut
+
+1;
diff --git a/lib/Class/MakeMethods/Template/Global.pm b/lib/Class/MakeMethods/Template/Global.pm
new file mode 100644
index 0000000..0e4c79e
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/Global.pm
@@ -0,0 +1,97 @@
+package Class::MakeMethods::Template::Global;
+
+use Class::MakeMethods::Template::Generic '-isasubclass';
+
+$VERSION = 1.008;
+use strict;
+require 5.0;
+
+=head1 NAME
+
+Class::MakeMethods::Template::Global - Method that are not instance-dependent
+
+=head1 SYNOPSIS
+
+ package MyObject;
+ use Class::MakeMethods::Template::Global (
+ scalar => [ 'foo' ]
+ );
+
+ package main;
+
+ MyObject->foo('bar')
+ print MyObject->foo();
+ ...
+ print $my_instance->foo(); # same thing
+
+=head1 DESCRIPTION
+
+These meta-methods access values that are shared across all instances
+of your object in your process. For example, a hash_scalar meta-method
+will be able to store a different value for each hash instance you
+call it on, but a static_scalar meta-method will return the same
+value for any instance it's called on, and setting it from any
+instance will change the value that all other instances see.
+
+B<Common Parameters>: The following parameters are defined for Static meta-methods.
+
+=over 4
+
+=item data
+
+The shared value.
+
+=back
+
+=cut
+
+sub generic {
+ {
+ '-import' => {
+ 'Template::Generic:generic' => '*'
+ },
+ 'code_expr' => {
+ _VALUE_ => '_ATTR_{data}',
+ },
+ 'params' => {
+ 'data' => undef,
+ }
+ }
+}
+
+########################################################################
+
+=head2 Standard Methods
+
+The following methods from Generic should be supported:
+
+ scalar
+ string
+ number
+ boolean
+ bits (?)
+ array
+ hash
+ tiedhash (?)
+ hash_of_arrays (?)
+ object
+ instance
+ array_of_objects (?)
+ code
+ code_or_scalar (?)
+
+See L<Class::MakeMethods::Template::Generic> for the interfaces and behaviors of these method types.
+
+The items marked with a ? above have not been tested sufficiently; please inform the author if they do not function as you would expect.
+
+=head1 SEE ALSO
+
+See L<Class::MakeMethods> for general information about this distribution.
+
+See L<Class::MakeMethods::Template> for more about this family of subclasses.
+
+See L<Class::MakeMethods::Template::Generic> for information about the various accessor interfaces subclassed herein.
+
+=cut
+
+1;
diff --git a/lib/Class/MakeMethods/Template/Hash.pm b/lib/Class/MakeMethods/Template/Hash.pm
new file mode 100644
index 0000000..9163178
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/Hash.pm
@@ -0,0 +1,229 @@
+package Class::MakeMethods::Template::Hash;
+
+use Class::MakeMethods::Template::Generic '-isasubclass';
+
+$VERSION = 1.008;
+use strict;
+require 5.0;
+
+sub generic {
+ {
+ 'params' => {
+ 'hash_key' => '*',
+ },
+ 'code_expr' => {
+ _VALUE_ => '_SELF_->{_STATIC_ATTR_{hash_key}}',
+ '-import' => { 'Template::Generic:generic' => '*' },
+ _EMPTY_NEW_INSTANCE_ => 'bless {}, _SELF_CLASS_',
+ _SET_VALUES_FROM_HASH_ => 'while ( scalar @_ ) { local $_ = shift(); $self->{ $_ } = shift() }'
+ },
+ 'behavior' => {
+ 'hash_delete' => q{ delete _VALUE_ },
+ 'hash_exists' => q{ exists _VALUE_ },
+ },
+ 'modifier' => {
+ # XXX the below doesn't work because modifiers can't have params,
+ # although interfaces can... Either add support for default params
+ # in modifiers, or else move this to another class.
+ # X Should there be a version which uses caller() instead of target_class?
+ 'class_keys' => { 'hash_key' => '"*{target_class}::*{name}"' },
+ }
+ }
+}
+
+########################################################################
+
+=head1 NAME
+
+Class::MakeMethods::Template::Hash - Method interfaces for hash-based objects
+
+=head1 SYNOPSIS
+
+ package MyObject;
+ use Class::MakeMethods::Template::Hash (
+ new => [ 'new' ],
+ scalar => [ 'foo', 'bar' ]
+ );
+
+ package main;
+
+ my $obj = MyObject->new( foo => "Foozle", bar => "Bozzle" );
+ print $obj->foo();
+ $obj->bar("Bamboozle");
+
+=head1 DESCRIPTION
+
+These meta-methods create and access values within blessed hash objects.
+
+B<Common Parameters>: The following parameters are defined for Hash meta-methods.
+
+=over 4
+
+=item hash_key
+
+The hash key to use when retrieving values from each hash instance. Defaults to '*', the name of the meta-method.
+
+Changing this allows you to change an accessor method name to something other than the name of the hash key used to retrieve its value.
+
+Note that this parameter is not portable to the other implementations, such as Global or InsideOut.
+
+You can take advantage of parameter expansion to define methods whose hash key is composed of the defining package's name and the individual method name, such as C<$self-E<gt>{I<MyObject>-I<foo>}>:
+
+ 'hash_key' => '*{target_class}-*{name}'
+
+=back
+
+B<Common Behaviors>
+
+=over 4
+
+=item Behavior: delete
+
+Deletes the named key and associated value from the current hash instance.
+
+=back
+
+=head2 Standard Methods
+
+The following methods from Generic are all supported:
+
+ new
+ scalar
+ string
+ string_index
+ number
+ boolean
+ bits (*)
+ array
+ hash
+ tiedhash
+ hash_of_arrays
+ object
+ instance
+ array_of_objects
+ code
+ code_or_scalar
+
+See L<Class::MakeMethods::Template::Generic> for the interfaces and behaviors of these method types.
+
+The items marked with a * above are specifically defined in this package, whereas the others are formed automatically by the interaction of this package's generic settings with the code templates provided by the Generic superclass.
+
+=cut
+
+# This is the only one that needs to be specifically defined.
+sub bits {
+ {
+ '-import' => { 'Template::Generic:bits' => '*' },
+ 'params' => {
+ 'hash_key' => '*{target_class}__*{template_name}',
+ },
+ }
+}
+
+########################################################################
+
+=head2 struct
+
+ struct => [ qw / foo bar baz / ];
+
+Creates methods for setting, checking and clearing values which
+are stored by position in an array. All the slots created with this
+meta-method are stored in a single array.
+
+The argument to struct should be a string or a reference to an
+array of strings. For each string meta-method x, it defines two
+methods: I<x> and I<clear_x>. x returns the value of the x-slot.
+If called with an argument, it first sets the x-slot to the argument.
+clear_x sets the slot to undef.
+
+Additionally, struct defines three class method: I<struct>, which returns
+a list of all of the struct values, I<struct_fields>, which returns
+a list of all the slots by name, and I<struct_dump>, which returns a hash of
+the slot-name/slot-value pairs.
+
+=cut
+
+sub struct {
+ ( {
+ 'interface' => {
+ default => {
+ '*'=>'get_set', 'clear_*'=>'clear',
+ 'struct_fields'=>'struct_fields',
+ 'struct'=>'struct', 'struct_dump'=>'struct_dump'
+ },
+ },
+ 'params' => {
+ 'hash_key' => '*{target_class}__*{template_name}',
+ },
+ 'behavior' => {
+ '-init' => sub {
+ my $m_info = $_[0];
+
+ $m_info->{class} ||= $m_info->{target_class};
+
+ my $class_info =
+ ($Class::MakeMethods::Template::Hash::struct{$m_info->{class}} ||= []);
+ if ( ! defined $m_info->{sfp} ) {
+ foreach ( 0..$#$class_info ) {
+ if ( $class_info->[$_] eq $m_info->{'name'} ) {
+ $m_info->{sfp} = $_;
+ last
+ }
+ }
+ if ( ! defined $m_info->{sfp} ) {
+ push @$class_info, $m_info->{'name'};
+ $m_info->{sfp} = $#$class_info;
+ }
+ }
+ return;
+ },
+
+ 'struct_fields' => sub { my $m_info = $_[0]; sub {
+ my $class_info =
+ ( $Class::MakeMethods::Template::Hash::struct{$m_info->{class}} ||= [] );
+ @$class_info;
+ }},
+ 'struct' => sub { my $m_info = $_[0]; sub {
+ my $self = shift;
+ $self->{$m_info->{hash_key}} ||= [];
+ if ( @_ ) { @{$self->{$m_info->{hash_key}}} = @_ }
+ @{$self->{$m_info->{hash_key}}};
+ }},
+ 'struct_dump' => sub { my $m_info = $_[0]; sub {
+ my $self = shift;
+ my $class_info =
+ ( $Class::MakeMethods::Template::Hash::struct{$m_info->{class}} ||= [] );
+ map { ($_, $self->$_()) } @$class_info;
+ }},
+
+ 'get_set' => sub { my $m_info = $_[0]; sub {
+ my $self = shift;
+ $self->{$m_info->{hash_key}} ||= [];
+
+ if ( @_ ) {
+ $self->{$m_info->{hash_key}}->[ $m_info->{sfp} ] = shift;
+ }
+ $self->{$m_info->{hash_key}}->[ $m_info->{sfp} ];
+ }},
+ 'clear' => sub { my $m_info = $_[0]; sub {
+ my $self = shift;
+ $self->{$m_info->{hash_key}} ||= [];
+ $self->{$m_info->{hash_key}}->[ $m_info->{sfp} ] = undef;
+ }},
+ },
+ } )
+}
+
+########################################################################
+
+=head1 SEE ALSO
+
+See L<Class::MakeMethods> for general information about this distribution.
+
+See L<Class::MakeMethods::Template> for more about this family of subclasses.
+
+See L<Class::MakeMethods::Template::Generic> for information about the various accessor interfaces subclassed herein.
+
+=cut
+
+1;
diff --git a/lib/Class/MakeMethods/Template/Inheritable.pm b/lib/Class/MakeMethods/Template/Inheritable.pm
new file mode 100644
index 0000000..ac6e7c0
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/Inheritable.pm
@@ -0,0 +1,154 @@
+=head1 NAME
+
+Class::MakeMethods::Template::Inheritable - Overridable data
+
+=head1 SYNOPSIS
+
+ package MyClass;
+
+ use Class::MakeMethods( 'Template::Inheritable:scalar' => 'foo' );
+ # We now have an accessor method for an "inheritable" scalar value
+
+ MyClass->foo( 'Foozle' ); # Set a class-wide value
+ print MyClass->foo(); # Retrieve class-wide value
+
+ my $obj = MyClass->new(...);
+ print $obj->foo(); # All instances "inherit" that value...
+
+ $obj->foo( 'Foible' ); # until you set a value for an instance.
+ print $obj->foo(); # This now finds object-specific value.
+ ...
+
+ package MySubClass;
+ @ISA = 'MyClass';
+
+ print MySubClass->foo(); # Intially same as superclass,
+ MySubClass->foo('Foobar'); # but overridable per subclass,
+ print $subclass_obj->foo(); # and shared by its instances
+ $subclass_obj->foo('Fosil');# until you override them...
+ ...
+
+=head1 DESCRIPTION
+
+The MakeMethods subclass provides accessor methods that search an inheritance tree to find a value. This allows you to set a shared or default value for a given class, and optionally override it in a subclass.
+
+=cut
+
+########################################################################
+
+package Class::MakeMethods::Template::Inheritable;
+
+use Class::MakeMethods::Template::Generic '-isasubclass';
+
+$VERSION = 1.008;
+use strict;
+require 5.0;
+use Carp;
+
+sub generic {
+ {
+ '-import' => {
+ 'Template::Generic:generic' => '*'
+ },
+ 'modifier' => {
+ '-all' => [ q{
+ _INIT_VALUE_CLASS_
+ *
+ } ],
+ },
+ 'code_expr' => {
+ '_VALUE_CLASS_' => '$_value_class',
+ '_INIT_VALUE_CLASS_' => q{
+ my _VALUE_CLASS_;
+ my @_INC_search = ( _SELF_, _SELF_CLASS_ );
+ while ( scalar @_INC_search ) {
+ _VALUE_CLASS_ = shift @_INC_search;
+ last if ( exists _ATTR_{data}->{_VALUE_CLASS_} );
+ no strict 'refs';
+ unshift @_INC_search, @{"_VALUE_CLASS_\::ISA"} if ! ref _VALUE_CLASS_;
+ }
+ },
+ '_VALUE_' => '_ATTR_{data}->{_VALUE_CLASS_}',
+ '_GET_VALUE_' => q{ _ATTR_{data}->{_VALUE_CLASS_} },
+ '_SET_VALUE_{}' => q{ do { my $data = *; defined($data) ? ( _VALUE_CLASS_ = _SELF_ and _ATTR_{data}->{_SELF_} = $data ) : ( delete _ATTR_{data}->{_SELF_} and undef ) } },
+ },
+ }
+}
+
+########################################################################
+
+=head2 Standard Methods
+
+The following methods from Generic should be supported:
+
+ scalar
+ string
+ string_index (?)
+ number
+ boolean (?)
+ bits (?)
+ array (?)
+ hash (?)
+ tiedhash (?)
+ hash_of_arrays (?)
+ object (?)
+ instance (?)
+ array_of_objects (?)
+ code (?)
+ code_or_scalar (?)
+
+See L<Class::MakeMethods::Template::Generic> for the interfaces and behaviors of these method types.
+
+The items marked with a * above are specifically defined in this package, whereas the others are formed automatically by the interaction of this package's generic settings with the code templates provided by the Generic superclass.
+
+The items marked with a ? above have not been tested sufficiently; please inform the author if they do not function as you would expect.
+
+=cut
+
+sub array {
+ {
+ '-import' => {
+ 'Template::Generic:array' => '*',
+ },
+ 'modifier' => {
+ '-all' => q{ _INIT_VALUE_CLASS_; _ENSURE_REF_VALUE_; * },
+ },
+ 'code_expr' => {
+ '_ENSURE_REF_VALUE_' => q{ _VALUE_ ||= []; },
+ '_REF_VALUE_' => '(\@{_ATTR_{data}->{_VALUE_CLASS_}})',
+ },
+ }
+}
+
+sub hash {
+ {
+ '-import' => {
+ 'Template::Generic:hash' => '*',
+ },
+ 'modifier' => {
+ '-all' => q{ _INIT_VALUE_CLASS_; _ENSURE_REF_VALUE_; * },
+ },
+ 'code_expr' => {
+ '_ENSURE_REF_VALUE_' => q{ _VALUE_ ||= {}; },
+ '_REF_VALUE_' => '(\%{_ATTR_{data}->{_VALUE_CLASS_}})',
+ },
+ }
+}
+
+########################################################################
+
+=head1 SEE ALSO
+
+See L<Class::MakeMethods> for general information about this distribution.
+
+See L<Class::MakeMethods::Template> for more about this family of subclasses.
+
+See L<Class::MakeMethods::Template::Generic> for information about the various accessor interfaces subclassed herein.
+
+If you just need scalar accessors, see L<Class::Data::Inheritable> for a very elegant and efficient implementation.
+
+=cut
+
+########################################################################
+
+1;
diff --git a/lib/Class/MakeMethods/Template/InsideOut.pm b/lib/Class/MakeMethods/Template/InsideOut.pm
new file mode 100644
index 0000000..964856c
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/InsideOut.pm
@@ -0,0 +1,218 @@
+package Class::MakeMethods::Template::InsideOut;
+
+use Class::MakeMethods::Template::Generic '-isasubclass';
+
+$VERSION = 1.008;
+use strict;
+require 5.0;
+
+my %ClassInfo;
+my %Data;
+
+sub generic {
+ {
+ '-import' => {
+ 'Template::Generic:generic' => '*'
+ },
+ 'code_expr' => {
+ '_VALUE_' => '_ATTR_{data}->{_SELF_}',
+ },
+ 'behavior' => {
+ -register => [ sub {
+ my $m_info = shift;
+ my $class_info = ( $ClassInfo{$m_info->{target_class}} ||= [] );
+ return (
+ 'DESTROY' => sub {
+ my $self = shift;
+ foreach ( @$class_info ) { delete $self->{data}->{$self} }
+ # $self->SUPER::DESTROY( @_ )
+ },
+ );
+ } ],
+ }
+ }
+}
+
+########################################################################
+
+=head1 NAME
+
+Class::MakeMethods::Template::InsideOut - External data
+
+=head1 SYNOPSIS
+
+ package MyObject;
+ use Class::MakeMethods::Template::InsideOut (
+ scalar => [ 'foo', 'bar' ]
+ );
+ sub new { ... }
+
+ package main;
+
+ my $obj = MyObject->new( foo => "Foozle", bar => "Bozzle" );
+ print $obj->foo(); # Prints Foozle
+ $obj->bar("Bamboozle"); # Sets $obj's bar value
+
+=head1 DESCRIPTION
+
+Supports the Generic object constructor and accessors meta-method
+types, but accepts any object as the underlying implementation type,
+with member data stored in external indices.
+
+Each method stores the values associated with various objects in
+an hash keyed by the object's stringified identity. Since that hash
+is accessible only from the generated closures, it is impossible
+for foreign code to manipulate those values except through the
+method interface.
+
+A DESTROY method is installed to remove data for expired objects
+from the various hashes. (If the DESTROY method is not called, your
+program will not release this data and memory will be wasted.)
+
+B<Common Parameters>: The following parameters are defined for
+InsideOut meta-methods.
+
+=over 4
+
+=item data
+
+An auto-vivified reference to a hash to be used to store the values
+for each object.
+
+=back
+
+Note that using InsideOut meta-methods causes the installation of
+a DESTROY method in the calling class, which deallocates data for
+each instance when it is discarded.
+
+NOTE: This needs some more work to properly handle inheritance.
+
+=head2 Standard Methods
+
+The following methods from Generic are all supported:
+
+ scalar
+ string
+ string_index *
+ number
+ boolean
+ bits
+ array
+ hash
+ tiedhash
+ hash_of_arrays
+ object
+ instance
+ array_of_objects
+ code
+ code_or_scalar
+
+See L<Class::MakeMethods::Template::Generic> for the interfaces and behaviors of these method types.
+
+The items marked with a * above are specifically defined in this package, whereas the others are formed automatically by the interaction of this package's generic settings with the code templates provided by the Generic superclass.
+
+=cut
+
+########################################################################
+
+=head2 boolean_index
+
+ boolean_index => [ qw / foo bar baz / ]
+
+Like InsideOut:boolean, boolean_index creates x, set_x, and clear_x
+methods. However, it also defines a class method find_x which returns
+a list of the objects which presently have the x-flag set to
+true.
+
+Note that to free items from memory, you must clear these bits!
+
+=cut
+
+sub boolean_index {
+ {
+ '-import' => {
+ 'Template::Generic:boolean' => '*',
+ },
+ 'interface' => {
+ default => {
+ '*'=>'get_set', 'set_*'=>'set_true', 'clear_*'=>'set_false',
+ 'find_*'=>'find_true',
+ },
+ },
+ 'behavior' => {
+ '-init' => [ sub {
+ my $m_info = $_[0];
+ defined $m_info->{data} or $m_info->{data} = {};
+ return;
+ } ],
+ 'set_true' => q{ _SET_VALUE_{ _SELF_ } },
+ 'set_false' => q{ delete _VALUE_; 0 },
+ 'find_true' => q{
+ values %{ _ATTR_{data} };
+ },
+ },
+ }
+}
+
+sub string_index {
+ {
+ '-import' => {
+ 'Template::Generic:string_index' => '*',
+ },
+ 'interface' => {
+ default => {
+ '*'=>'get_set', 'set_*'=>'set_true', 'clear_*'=>'set_false',
+ 'find_*'=>'find_true',
+ },
+ },
+ 'code_expr' => {
+ _INDEX_HASH_ => '_ATTR_{data}',
+ _GET_FROM_INDEX_ => q{
+ if (defined ( my $old_v = _GET_VALUE_ ) ) {
+ delete _ATTR_{'data'}{ $old_v };
+ }
+ },
+ _REMOVE_FROM_INDEX_ => q{
+ if (defined ( my $old_v = _GET_FROM_INDEX_ ) ) {
+ delete _ATTR_{'data'}{ $old_v };
+ }
+ },
+ _ADD_TO_INDEX_{} => q{
+ if (defined ( my $new_value = _GET_VALUE_ ) ) {
+ if ( my $old_item = _ATTR_{'data'}{$new_value} ) {
+ # There's already an object stored under that value so we
+ # need to unset it's value.
+ # And maybe issue a warning? Or croak?
+ my $m_name = _ATTR_{'name'};
+ $old_item->$m_name( undef );
+ }
+
+ # Put ourself in the index under that value
+ _ATTR_{'data'}{ * } = _SELF_;
+ }
+ },
+ },
+ 'behavior' => {
+ '-init' => [ sub {
+ my $m_info = $_[0];
+ defined $m_info->{data} or $m_info->{data} = {};
+ return;
+ } ],
+ 'get' => q{
+ return _GET_FROM_INDEX_;
+ },
+ 'set' => q{
+ my $new_value = shift;
+ _REMOVE_FROM_INDEX_
+ _ADD_TO_INDEX_{ $new_value }
+ },
+ 'clear' => q{
+ _REMOVE_FROM_INDEX_
+ },
+ },
+ }
+}
+
+########################################################################
+
+1;
diff --git a/lib/Class/MakeMethods/Template/PackageVar.pm b/lib/Class/MakeMethods/Template/PackageVar.pm
new file mode 100644
index 0000000..da0f7be
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/PackageVar.pm
@@ -0,0 +1,168 @@
+package Class::MakeMethods::Template::PackageVar;
+
+use Class::MakeMethods::Template::Generic '-isasubclass';
+
+$VERSION = 1.008;
+use strict;
+require 5.0;
+use Carp;
+
+=head1 NAME
+
+Class::MakeMethods::Template::PackageVar - Static methods with global variables
+
+=head1 SYNOPSIS
+
+ package MyObject;
+ use Class::MakeMethods::Template::PackageVar (
+ scalar => [ 'foo' ]
+ );
+
+ package main;
+
+ MyObject->foo('bar')
+ print MyObject->foo();
+
+ $MyObject::foo = 'bazillion';
+ print MyObject->foo();
+
+=head1 DESCRIPTION
+
+These meta-methods provide access to package (class global) variables.
+These are essentially the same as the Static meta-methods, except
+that they use a global variable in the declaring package to store
+their values.
+
+B<Common Parameters>: The following parameters are defined for PackageVar meta-methods.
+
+=over 4
+
+=item variable
+
+The name of the variable to store the value in. Defaults to the same name as the method.
+
+=back
+
+=cut
+
+sub generic {
+ {
+ '-import' => {
+ 'Template::Generic:generic' => '*'
+ },
+ 'params' => {
+ 'variable' => '*'
+ },
+ 'modifier' => {
+ '-all' => [ q{ no strict; * } ],
+ },
+ 'code_expr' => {
+ '_VALUE_' => '${_ATTR_{target_class}."::"._ATTR_{variable}}',
+ },
+ }
+}
+
+########################################################################
+
+=head2 Standard Methods
+
+The following methods from Generic should all be supported:
+
+ scalar
+ string
+ string_index (?)
+ number
+ boolean
+ bits (?)
+ array (*)
+ hash (*)
+ tiedhash (?)
+ hash_of_arrays (?)
+ object (?)
+ instance (?)
+ array_of_objects (?)
+ code (?)
+ code_or_scalar (?)
+
+See L<Class::MakeMethods::Template::Generic> for the interfaces and behaviors of these method types.
+
+The items marked with a * above are specifically defined in this package, whereas the others are formed automatically by the interaction of this package's generic settings with the code templates provided by the Generic superclass.
+
+The items marked with a ? above have not been tested sufficiently; please inform the author if they do not function as you would expect.
+
+=cut
+
+########################################################################
+
+sub array {
+ {
+ '-import' => {
+ 'Template::Generic:array' => '*',
+ },
+ 'modifier' => {
+ '-all' => q{ no strict; _ENSURE_REF_VALUE_; * },
+ },
+ 'code_expr' => {
+ '_ENSURE_REF_VALUE_' => q{
+ _REF_VALUE_ or @{_ATTR_{target_class}."::"._ATTR_{variable}} = ();
+ },
+ '_VALUE_' => '\@{_ATTR_{target_class}."::"._ATTR_{variable}}',
+ },
+ }
+}
+
+########################################################################
+
+sub hash {
+ {
+ '-import' => {
+ 'Template::Generic:hash' => '*',
+ },
+ 'modifier' => {
+ '-all' => q{ no strict; _ENSURE_REF_VALUE_; * },
+ },
+ 'code_expr' => {
+ '_ENSURE_REF_VALUE_' => q{
+ _REF_VALUE_ or %{_ATTR_{target_class}."::"._ATTR_{variable}} = ();
+ },
+ '_VALUE_' => '\%{_ATTR_{target_class}."::"._ATTR_{variable}}',
+ },
+ }
+}
+
+########################################################################
+
+=head2 PackageVar:vars
+
+This rewrite rule converts package variable names into PackageVar methods of the equivalent data type.
+
+Here's an example declaration:
+
+ package MyClass;
+
+ use Class::MakeMethods::Template::PackageVar (
+ vars => '$DEBUG %Index'
+ );
+
+MyClass now has methods that get and set the contents of its $MyClass::DEBUG and %MyClass::Index package variables:
+
+ MyClass->DEBUG( 1 );
+ MyClass->Index( 'foo' => 'bar' );
+
+=cut
+
+sub vars {
+ my $mm_class = shift;
+ my @rewrite = map [ "Template::PackageVar:$_" ], qw( scalar array hash );
+ my %rewrite = ( '$' => 0, '@' => 1, '%' => 2 );
+ while (@_) {
+ my $name = shift;
+ my $data = shift;
+ $data =~ s/\A(.)//;
+ push @{ $rewrite[ $rewrite{ $1 } ] }, { 'name'=>$name, 'variable'=>$data };
+ }
+ return @rewrite;
+}
+
+
+1;
diff --git a/lib/Class/MakeMethods/Template/Ref.pm b/lib/Class/MakeMethods/Template/Ref.pm
new file mode 100644
index 0000000..d97bafa
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/Ref.pm
@@ -0,0 +1,207 @@
+=head1 NAME
+
+Class::MakeMethods::Template::Ref - Universal copy and compare methods
+
+=head1 SYNOPSIS
+
+ package MyObject;
+ use Class::MakeMethods::Template::Ref (
+ 'Hash:new' => [ 'new' ],
+ clone => [ 'clone' ]
+ );
+
+ package main;
+
+ my $obj = MyObject->new( foo => ["Foozle", "Bozzle"] );
+ my $clone = $obj->clone();
+ print $obj->{'foo'}[1];
+
+=cut
+
+package Class::MakeMethods::Template::Ref;
+
+$VERSION = 1.008;
+use strict;
+require 5.00;
+use Carp;
+
+use Class::MakeMethods::Template '-isasubclass';
+use Class::MakeMethods::Utility::Ref qw( ref_clone ref_compare );
+
+######################################################################
+
+=head1 DESCRIPTION
+
+The following types of methods are provided via the Class::MakeMethods interface:
+
+=head2 clone
+
+Produce a deep copy of an instance of almost any underlying datatype.
+
+Parameters:
+
+init_method
+
+If defined, this method is called on the new object with any arguments passed in.
+
+=cut
+
+sub clone {
+ {
+ 'params' => { 'init_method' => '' },
+ 'interface' => {
+ default => 'clone',
+ clone => { '*'=>'clone', },
+ },
+ 'behavior' => {
+ 'clone' => sub { my $m_info = $_[0]; sub {
+ my $callee = shift;
+ ref $callee or croak "Can only copy instances, not a class.\n";
+
+ my $self = ref_clone( $callee );
+
+ my $init_method = $m_info->{'init_method'};
+ if ( $init_method ) {
+ $self->$init_method( @_ );
+ } elsif ( scalar @_ ) {
+ croak "No init_method";
+ }
+ return $self;
+ }},
+ },
+ }
+}
+
+######################################################################
+
+=head2 prototype
+
+Create new instances by making a deep copy of a static prototypical instance.
+
+Parameters:
+
+init_method
+
+If defined, this method is called on the new object with any arguments passed in.
+=cut
+
+sub prototype {
+ ( {
+ 'interface' => {
+ default => { '*'=>'set_or_new', },
+ },
+ 'behavior' => {
+ 'set_or_new' => sub { my $m_info = $_[0]; sub {
+ my $class = shift;
+
+ if ( scalar @_ == 1 and UNIVERSAL::isa( $_[0], $class ) ) {
+ # set
+ $m_info->{'instance'} = shift
+
+ } else {
+ # get
+ croak "Prototype is not defined" unless $m_info->{'instance'};
+ my $self = ref_clone($m_info->{'instance'});
+
+ my $init_method = $m_info->{'init_method'};
+ if ( $init_method ) {
+ $self->$init_method( @_ );
+ } elsif ( scalar @_ ) {
+ croak "No init_method";
+ }
+ return $self;
+ }
+ }},
+ 'set' => sub { my $m_info = $_[0]; sub {
+ my $class = shift;
+ $m_info->{'instance'} = shift
+ }},
+ 'new' => sub { my $m_info = $_[0]; sub {
+ my $class = shift;
+
+ croak "Prototype is not defined" unless $m_info->{'instance'};
+ my $self = ref_clone($m_info->{'instance'});
+
+ my $init_method = $m_info->{'init_method'};
+ if ( $init_method ) {
+ $self->$init_method( @_ );
+ } elsif ( scalar @_ ) {
+ croak "No init_method";
+ }
+ return $self;
+ }},
+ },
+ } )
+}
+
+######################################################################
+
+=head2 compare
+
+Compare one object to another.
+
+B<Templates>
+
+=over 4
+
+=item *
+
+default
+
+Three-way (sorting-style) comparison.
+
+=item *
+
+equals
+
+Are these two objects equivalent?
+
+=item *
+
+identity
+
+Are these two references to the exact same object?
+
+=back
+
+=cut
+
+sub compare {
+ {
+ 'params' => { 'init_method' => '' },
+ 'interface' => {
+ default => { '*'=>'compare', },
+ equals => { '*'=>'equals', },
+ identity => { '*'=>'identity', },
+ },
+ 'behavior' => {
+ 'compare' => sub { my $m_info = $_[0]; sub {
+ my $callee = shift;
+ ref_compare( $callee, shift );
+ }},
+ 'equals' => sub { my $m_info = $_[0]; sub {
+ my $callee = shift;
+ ref_compare( $callee, shift ) == 0;
+ }},
+ 'identity' => sub { my $m_info = $_[0]; sub {
+ $_[0] eq $_[1]
+ }},
+ },
+ }
+}
+
+######################################################################
+
+=head1 SEE ALSO
+
+See L<Class::MakeMethods> for general information about this distribution.
+
+See L<Class::MakeMethods::Template> for more about this family of subclasses.
+
+See L<Class::MakeMethods::Utility::Ref> for the clone and compare functions used above.
+
+=cut
+
+######################################################################
+
+1;
diff --git a/lib/Class/MakeMethods/Template/Scalar.pm b/lib/Class/MakeMethods/Template/Scalar.pm
new file mode 100644
index 0000000..705f007
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/Scalar.pm
@@ -0,0 +1,80 @@
+package Class::MakeMethods::Template::Scalar;
+
+use Class::MakeMethods::Template::Generic '-isasubclass';
+
+$VERSION = 1.008;
+use strict;
+require 5.00;
+use Carp;
+
+=head1 NAME
+
+Class::MakeMethods::Template::Scalar - Methods for blessed scalars
+
+=head1 SYNOPSIS
+
+ package MyObject;
+ use Class::MakeMethods::Template::ExternalData (
+ new => 'new',
+ scalar => 'foo',
+ );
+
+ package main;
+
+ my $obj = MyObject->new( foo => "Foozle" );
+ print $obj->foo(); # Prints Foozle
+ $obj->foo("Bamboozle"); # Sets $$obj
+ print $obj->foo(); # Prints Bamboozle
+
+=head1 DESCRIPTION
+
+Supports the Generic object constructor and accessors meta-method
+types, but uses scalar refs as the underlying implementation type,
+so only one accessor method can be used effectively.
+
+=cut
+
+sub generic {
+ {
+ '-import' => {
+ 'Template::Generic:generic' => '*'
+ },
+ 'code_expr' => {
+ _VALUE_ => '(${_SELF_})',
+ _EMPTY_NEW_INSTANCE_ => 'bless \( my $scalar = undef ), _SELF_CLASS_',
+ },
+ 'params' => {
+ }
+ }
+}
+
+########################################################################
+
+=head2 Standard Methods
+
+The following methods from Generic are all supported:
+
+ new
+ scalar
+ string
+ string_index
+ number
+ boolean
+ bits
+ array
+ hash
+ tiedhash
+ hash_of_arrays
+ object
+ instance
+ array_of_objects
+ code
+ code_or_scalar
+
+See L<Class::MakeMethods::Template::Generic> for the interfaces and behaviors of these method types.
+
+However, note that due to special nature of this package, all accessor methods reference the same scalar value, so setting a value with one method will overwrite the value retrieved by another.
+
+=cut
+
+1;
diff --git a/lib/Class/MakeMethods/Template/Static.pm b/lib/Class/MakeMethods/Template/Static.pm
new file mode 100644
index 0000000..4dfccca
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/Static.pm
@@ -0,0 +1,41 @@
+package Class::MakeMethods::Template::Static;
+
+use Class::MakeMethods::Template::Global '-isasubclass';
+
+$VERSION = 1.008;
+
+1;
+
+__END__
+
+=head1 NAME
+
+Class::MakeMethods::Template::Static - Deprecated name for Global
+
+=head1 SYNOPSIS
+
+ package MyObject;
+ use Class::MakeMethods::Template::Global (
+ scalar => [ 'foo' ]
+ );
+
+ package main;
+
+ MyObject->foo('bar')
+ print MyObject->foo();
+ ...
+ print $my_instance->foo(); # same thing
+
+=head1 DESCRIPTION
+
+Earlier versions of this package included a package named Class::MakeMethods::Template::Static.
+
+However, in hindsight, this name was poorly chosen, as it suggests a constant, unchanging value, whereas the actual functionality is akin to traditional "global" variables.
+
+This functionality is now provided by Class::MakeMethods::Template::Global, of which this is an empty subclass retained to provide backwards compatibility.
+
+=head1 SEE ALSO
+
+L<Class::MakeMethods::Template::Global>.
+
+=cut \ No newline at end of file
diff --git a/lib/Class/MakeMethods/Template/Struct.pm b/lib/Class/MakeMethods/Template/Struct.pm
new file mode 100644
index 0000000..7d9540b
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/Struct.pm
@@ -0,0 +1,41 @@
+package Class::MakeMethods::Template::Struct;
+
+use Class::MakeMethods::Template::Array '-isasubclass';
+
+$VERSION = 1.008;
+
+1;
+
+__END__
+
+=head1 NAME
+
+Class::MakeMethods::Template::Struct - Deprecated name for Array
+
+=head1 SYNOPSIS
+
+ package MyObject;
+ use Class::MakeMethods::Template::Array (
+ new => [ 'new' ]
+ scalar => [ 'foo', 'bar' ]
+ );
+
+ package main;
+
+ my $obj = MyObject->new( foo => "Foozle", bar => "Bozzle" );
+ print $obj->foo(); # Prints Foozle
+ $obj->bar("Bamboozle"); # Sets $obj->[1]
+
+=head1 DESCRIPTION
+
+Earlier versions of this package included a package named Class::MakeMethods::Template::Struct.
+
+However, in hindsight, this name was poorly chosen, as it suggests some connection to C-style structs, where the behavior implemented more simply parallels the functionality of Template::Hash and the other Generic subclasses.
+
+This functionality is now provided by Class::MakeMethods::Template::Array, of which this is an empty subclass retained to provide backwards compatibility.
+
+=head1 SEE ALSO
+
+L<Class::MakeMethods::Template::Array>.
+
+=cut \ No newline at end of file
diff --git a/lib/Class/MakeMethods/Template/StructBuiltin.pm b/lib/Class/MakeMethods/Template/StructBuiltin.pm
new file mode 100644
index 0000000..b3ddc21
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/StructBuiltin.pm
@@ -0,0 +1,148 @@
+package Class::MakeMethods::Template::StructBuiltin;
+
+use Class::MakeMethods::Template::Generic '-isasubclass';
+
+$VERSION = 1.008;
+use strict;
+require 5.00;
+use Carp;
+
+=head1 NAME
+
+Class::MakeMethods::Template::StructBuiltin
+
+=head1 SYNOPSIS
+
+ use Class::MakeMethods::Template::StructBuiltin (
+ -TargetClass => 'MyStat',
+ builtin_isa => [
+ '-{new_function}'=>'stat',
+ qw/ dev ino mode nlink /
+ ]
+ );
+
+
+=head1 DESCRIPTION
+
+This class generates a wrapper around some builtin function,
+storing the results in the object and providing a by-name interface.
+
+Takes a (core) function name, and a arrayref of return position names
+(we will call it pos_list). Creates:
+
+=over 4
+
+=item new
+
+Calls the core func with any given arguments, stores the result in the
+instance.
+
+=item x
+
+For each member of pos_list, creates a method of the same name which
+gets/sets the nth member of the returned list, where n is the position
+of x in pos_list.
+
+=item fields
+
+Returns pos_list, in the given order.
+
+=item dump
+
+Returns a list item name, item value, in order.
+
+=back
+
+Example Usage:
+
+ package Stat;
+
+ use Class::MakeMethods::Template::StructBuiltin
+ builtin_isa => [ '-{new_function}'=>'stat', qw/ dev ino mode nlink / ],
+
+ package main;
+
+ my $file = "$ENV{HOME}/.template";
+ my $s = Stat->new($file);
+ print "File $file has ", $s->nlink, " links\n";
+
+Note that (a) the new method does not check the return value of the
+function called (in the above example, if $file does not exist, you will
+silently get an empty object), and (b) if you really want the above
+example, see the core File::stat module. But you get the idea, I hope.
+
+=cut
+
+sub builtin_isa {
+ ( {
+ 'template' => {
+ default => {
+ '*'=>'get_set', 'dump'=>'dump', 'fields'=>'fields', 'new'=>'new_builtin'
+ },
+ },
+ 'behavior' => {
+ '-init' => sub {
+ my $m_info = $_[0];
+
+ $m_info->{class} ||= $m_info->{target_class};
+
+ my $class_info =
+ ( $Class::MakeMethods::Struct::builtin{$m_info->{class}} ||= [] );
+ if ( ! defined $m_info->{array_index} ) {
+ foreach ( 0..$#$class_info ) {
+ if ( $class_info->[$_] eq $m_info->{'name'} ) {
+ $m_info->{array_index} = $_; last }
+ }
+ if ( ! defined $m_info->{array_index} ) {
+ push @ $class_info, $m_info->{'name'};
+ $m_info->{array_index} = $#$class_info;
+ }
+ }
+
+ if (defined $m_info->{new_function} and ! ref $m_info->{new_function}) {
+ # NOTE Below comments found in original version of MethodMaker. -Simon
+ # Cuz neither \&{"CORE::$func"} or $CORE::{$func} work ... N.B. this
+ # only works for core functions that take only one arg. But I can't
+ # quite figure out how to pass in the list without it getting
+ # evaluated in a scalar context. Hmmm.
+ $m_info->{new_function} = eval "sub {
+ scalar \@_ ? CORE::$m_info->{new_function}(shift)
+ : CORE::$m_info->{new_function}
+ }";
+ }
+
+ return;
+ },
+
+ 'new_builtin' => sub { my $m_info = $_[0]; sub {
+ my $class = shift;
+ my $function = $m_info->{new_function};
+ my $self = [ &$function(@_) ];
+ bless $self, $class;
+ }},
+
+ 'fields' => sub { my $m_info = $_[0]; sub {
+ my $class_info =
+ ( $Class::MakeMethods::Struct::builtin{$m_info->{class}} ||= [] );
+ @$class_info;
+ }},
+ 'dump' => sub { my $m_info = $_[0]; sub {
+ my $self = shift;
+ my $class_info =
+ ( $Class::MakeMethods::Struct::builtin{$m_info->{class}} ||= [] );
+ my @keys = @$class_info;
+ map ($keys[$_], $self->[$_]), 0 .. $#keys;
+ }},
+
+ 'get_set' => sub { my $m_info = $_[0]; sub {
+ my $self = shift;
+ if ( @_ ) {
+ $self->[ $m_info->{array_index} ] = shift;
+ }
+ $self->[ $m_info->{array_index} ];
+ }},
+ },
+ } )
+}
+
+1;
diff --git a/lib/Class/MakeMethods/Template/Universal.pm b/lib/Class/MakeMethods/Template/Universal.pm
new file mode 100644
index 0000000..9535209
--- /dev/null
+++ b/lib/Class/MakeMethods/Template/Universal.pm
@@ -0,0 +1,415 @@
+package Class::MakeMethods::Template::Universal;
+
+use Class::MakeMethods::Template '-isasubclass';
+
+$VERSION = 1.008;
+use strict;
+require 5.00;
+require Carp;
+
+=head1 NAME
+
+Class::MakeMethods::Template::Universal - Meta-methods for any type of object
+
+=head1 SYNOPSIS
+
+ package MyObject;
+ use Class::MakeMethods::Template::Universal (
+ 'no_op' => [ 'twiddle' ],
+ 'croak' => [ 'fail', { croak_msg => 'Curses!' } ]
+ );
+
+ package main;
+
+ MyObject->twiddle; # Does nothing
+ if ( $foiled ) { MyObject->fail() } # Dies with croak_msg
+
+=head1 DESCRIPTION
+
+=head1 UNIVERSAL META-METHODS
+
+The following meta-methods and behaviors are applicable across
+multiple types of classes and objects.
+
+=head2 Universal:generic
+
+This is not a directly-invokable method type, but instead provides code expressions for use in other method-generators.
+
+You can use any of these features in your meta-method interfaces without explicitly importing them.
+
+B<Modifiers>
+
+=over 4
+
+=item *
+
+--private
+
+Causes the method to croak if it is called from outside of the package which originally declared it.
+
+Note that this protection can currently be circumvented if your class provides the method_init behavior, or another subroutine that calls methods by name.
+
+=item *
+
+--protected
+
+Causes the method to croak if it is called from a package other than the declaring package and its inheritors.
+
+Note that this protection can currently be circumvented if your class provides the method_init behavior, or another subroutine that calls methods by name.
+
+=item *
+
+--public
+
+Cancels any previous -private or -protected declaration.
+
+=item *
+
+--self_closure
+
+Causes the method to return a function reference which is bound to the arguments provided when it is first called.
+
+For examples of usage, see the test scripts in t/*closure.t.
+
+=item *
+
+--lvalue
+
+Adds the ":lvalue" attribute to the subroutine declaration.
+
+For examples of usage, see the test scripts in t/*lvalue.t.
+
+=item *
+
+--warn_calls
+
+For diagnostic purposes, call warn with the object reference, method name, and arguments before executing the body of the method.
+
+
+=back
+
+
+B<Behaviors>
+
+=over 4
+
+=item *
+
+attributes
+
+Runtime access to method parameters.
+
+=item *
+
+no_op -- See below.
+
+=item *
+
+croak -- See below.
+
+=item *
+
+method_init -- See below.
+
+=back
+
+=cut
+
+sub generic {
+ {
+ 'code_expr' => {
+ '_SELF_' => '$self',
+ '_SELF_CLASS_' => '(ref _SELF_ || _SELF_)',
+ '_SELF_INSTANCE_' => '(ref _SELF_ ? _SELF_ : undef)',
+ '_CLASS_FROM_INSTANCE_' => '(ref _SELF_ || croak "Can\'t invoke _STATIC_ATTR_{name} as a class method")',
+ '_ATTR_{}' => '$m_info->{*}',
+ '_STATIC_ATTR_{}' => '_ATTR_{*}',
+ '_ATTR_REQUIRED_{}' =>
+ '(_ATTR_{*} or Carp::croak("No * parameter defined for _ATTR_{name}"))',
+ '_ATTR_DEFAULT_{}' =>
+ sub { my @a = split(' ',$_[0],2); "(_ATTR_{$a[0]} || $a[1])" },
+
+ _ACCESS_PRIVATE_ => '( ( (caller)[0] eq _ATTR_{target_class} ) or croak "Attempted access to private method _ATTR_{name}")',
+ _ACCESS_PROTECTED_ => '( UNIVERSAL::isa((caller)[0], _ATTR_{target_class}) or croak "Attempted access to protected method _ATTR_{name}" )',
+
+ '_CALL_METHODS_FROM_HASH_' => q{
+ # Accept key-value attr list, or reference to unblessed hash of attrs
+ my @args = (scalar @_ == 1 and ref($_[0]) eq 'HASH') ? %{$_[0]} : @_;
+ while ( scalar @args ) { local $_ = shift(@args); $self->$_( shift(@args) ) }
+ },
+
+ },
+ 'modifier' => {
+ 'self_closure' => q{ my @args = @_; return sub { unshift @_, @args; * } },
+ 'warn_calls' => q{ warn $self."->_STATIC_ATTR_{name}(".join(', ',@_).")\n"; * },
+ 'public' => q{ * },
+ 'private' => q{ _ACCESS_PRIVATE_; * },
+ 'protected' => q{ _ACCESS_PROTECTED_; * },
+ '-folding' => [
+ # Public is the default; all three options are mutually exclusive.
+ '-public' => '',
+ '-private -public' => '-public',
+ '-protected -public' => '-public',
+ '-private -protected' => '-protected',
+ '-protected -private' => '-private',
+ ],
+ 'lvalue' => { _SUB_ATTRIBS_ => ': lvalue' },
+ },
+ 'behavior' => {
+ -import => {
+ 'Template::Universal:no_op' => 'no_op',
+ 'Template::Universal:croak' => 'croak',
+ 'Template::Universal:method_init' => 'method_init',
+ },
+ attributes => sub {
+ my $m_info = $_[0];
+ return sub {
+ my $self = shift;
+ if ( scalar @_ == 0 ) {
+ return $m_info;
+ } elsif ( scalar @_ == 1 ) {
+ return $m_info->{ shift() };
+ } else {
+ %$m_info = ( %$m_info, @_ );
+ }
+ }
+ },
+ },
+ }
+}
+
+########################################################################
+
+=head2 no_op
+
+For each meta-method, creates a method with an empty body.
+
+ use Class::MakeMethods::Template::Universal (
+ 'no_op' => [ 'foo bar baz' ],
+ );
+
+You might want to create and use such methods to provide hooks for
+subclass activity.
+
+No interfaces or parameters supported.
+
+=cut
+
+sub no_op {
+ {
+ 'interface' => {
+ default => 'no_op',
+ 'no_op' => 'no_op'
+ },
+ 'behavior' => {
+ no_op => sub { my $m_info = $_[0]; sub { } },
+ },
+ }
+}
+
+########################################################################
+
+=head2 croak
+
+For each meta-method, creates a method which will croak if called.
+
+ use Class::MakeMethods::Template::Universal (
+ 'croak' => [ 'foo bar baz' ],
+ );
+
+This is intended to support the use of abstract methods, that must
+be overidden in a useful subclass.
+
+If each subclass is expected to provide an implementation of a given method, using this abstract method will replace the generic error message below with the clearer, more explicit error message that follows it:
+
+ Can't locate object method "foo" via package "My::Subclass"
+ The "foo" method is abstract and can not be called on My::Subclass
+
+However, note that the existence of this method will be detected by UNIVERSAL::can(), so it is not suitable for use in optional interfaces, for which you may wish to be able to detect whether the method is supported or not.
+
+The -unsupported and -prohibited interfaces provide alternate error
+messages, or a custom error message can be provided using the
+'croak_msg' parameter.
+
+=cut
+
+sub abstract { 'croak --abstract' }
+
+sub croak {
+ {
+ 'interface' => {
+ default => 'croak',
+ 'croak' => 'croak',
+ 'abstract' => {
+ '*'=>'croak', -params=> { 'croak_msg' =>
+ q/Can't locate abstract method "*" declared in "*{target_class}", called from "CALLCLASS"./
+ }
+ },
+ 'abstract_minimal' => {
+ '*'=>'croak', -params=> { 'croak_msg' =>
+ "The * method is abstract and can not be called" }
+ },
+ 'unsupported' => {
+ '*'=>'croak', -params=> { 'croak_msg' =>
+ "The * method does not support this operation" }
+ },
+ 'prohibited' => {
+ '*'=>'croak', -params=> { 'croak_msg' =>
+ "The * method is not allowed to perform this activity" }
+ },
+ },
+ 'behavior' => {
+ croak => sub {
+ my $m_info = $_[0];
+ sub {
+ $m_info->{'croak_msg'} =~ s/CALLCLASS/ ref( $_[0] ) || $_[0] /ge
+ if $m_info->{'croak_msg'};
+ Carp::croak( $m_info->{'croak_msg'} );
+ }
+ },
+ },
+ }
+}
+
+########################################################################
+
+=head2 method_init
+
+Creates a method that accepts a hash of key-value pairs, or a
+reference to hash of such pairs. For each pair, the key is interpreted
+as the name of a method to call, and the value is the argument to
+be passed to that method.
+
+Sample declaration and usage:
+
+ package MyObject;
+ use Class::MakeMethods::Template::Universal (
+ method_init => 'init',
+ );
+ ...
+
+ my $object = MyObject->new()
+ $object->init( foo => 'Foozle', bar => 'Barbados' );
+
+ # Equivalent to:
+ $object->foo('Foozle');
+ $object->bar('Barbados');
+
+You might want to create and use such methods to allow easy initialization of multiple object or class parameters in a single call.
+
+B<Note>: including methods of this type will circumvent the protection of C<private> and C<protected> methods, because it an outside caller can cause an object to call specific methods on itself, bypassing the privacy protection.
+
+=cut
+
+sub method_init {
+ {
+ 'interface' => {
+ default => 'method_init',
+ 'method_init' => 'method_init'
+ },
+ 'code_expr' => {
+ '-import' => { 'Template::Universal:generic' => '*' },
+ },
+ 'behavior' => {
+ method_init => q{
+ _CALL_METHODS_FROM_HASH_
+ return $self;
+ }
+ },
+ }
+}
+
+########################################################################
+
+=head2 forward_methods
+
+Creates a method which delegates to an object provided by another method.
+
+Example:
+
+ use Class::MakeMethods::Template::Universal
+ forward_methods => [
+ --target=> 'whistle', w,
+ [ 'x', 'y' ], { target=> 'xylophone' },
+ { name=>'z', target=>'zither', target_args=>[123], method_name=>do_zed },
+ ];
+
+Example: The above defines that method C<w> will be handled by the
+calling C<w> on the object returned by C<whistle>, whilst methods C<x>
+and C<y> will be handled by C<xylophone>, and method C<z> will be handled
+by calling C<do_zed> on the object returned by calling C<zither(123)>.
+
+B<Interfaces>:
+
+=over 4
+
+=item forward (default)
+
+Calls the method on the target object. If the target object is missing, croaks at runtime with a message saying "Can't forward bar because bar is empty."
+
+=item delegate
+
+Calls the method on the target object, if present. If the target object is missing, returns nothing.
+
+=back
+
+B<Parameters>: The following additional parameters are supported:
+
+=over 4
+
+=item target
+
+I<Required>. The name of the method that will provide the object that will handle the operation.
+
+=item target_args
+
+Optional ref to an array of arguments to be passed to the target method.
+
+=item method_name
+
+The name of the method to call on the handling object. Defaults to the name of the meta-method being created.
+
+=back
+
+=cut
+
+sub forward_methods {
+ {
+ 'interface' => {
+ default => 'forward',
+ 'forward' => 'forward'
+ },
+ 'params' => { 'method_name' => '*' },
+ 'behavior' => {
+ 'forward' => sub { my $m_info = $_[0]; sub {
+ my $target = $m_info->{'target'};
+ my @args = $m_info->{'target_args'} ? @{$m_info->{'target_args'}} : ();
+ my $obj = (shift)->$target(@args)
+ or Carp::croak("Can't forward $m_info->{name} because $m_info->{target} is empty");
+ my $method = $m_info->{'method_name'};
+ $obj->$method(@_);
+ }},
+ 'delegate' => sub { my $m_info = $_[0]; sub {
+ my $target = $m_info->{'target'};
+ my @args = $m_info->{'target_args'} ? @{$m_info->{'target_args'}} : ();
+ my $obj = (shift)->$target(@args)
+ or return;
+ my $method = $m_info->{'method_name'};
+ $obj->$method(@_);
+ }},
+ },
+ }
+}
+
+
+########################################################################
+
+=head1 SEE ALSO
+
+See L<Class::MakeMethods> for general information about this distribution.
+
+See L<Class::MakeMethods::Template> for information about this family of subclasses.
+
+=cut
+
+1;