The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
=head1 MooseX::ShortCut::BuildInstance

This module is a shortcut to build L<Moose> instances on the fly.

=head1 SYNOPSIS
    
	#!perl
	package Mineral;
	use Moose;

	has 'type' =>( is => 'ro' );

	package Identity;
	use Moose::Role;

	has 'name' =>( is => 'ro' );

	use MooseX::ShortCut::BuildInstance qw( build_instance );
	use Test::More;
	use Test::Moose;

	my 	$paco = build_instance(
			package => 'Pet::Rock',
			superclasses =>['Mineral'],
			roles =>['Identity'],
			type => 'Quartz',
			name => 'Paco',
		);

	does_ok( $paco, 'Identity', 'Check that the ' . $paco->meta->name . 
		' has an -Identity-' );
	say 'My ' . $paco->meta->name . ' made from -' . $paco->type . '- (a ' .
		( join ', ', $paco->meta->superclasses ) . ') is called -' . 
		$paco->name . "-\n";
	done_testing();
    
    ##############################################################################
    #     Output of SYNOPSIS
    # 01:ok 1 - Check that the Pet::Rock has an -Identity-
    # 02:My Pet::Rock made from -Quartz- (a Mineral) is called -Paco-
    # 03:1..1
    ##############################################################################

    
=head1 DESCRIPTION

This module is a shortcut to custom build L<Moose> class instances on the fly.  
The goal is to compose unique instances of Moose classes on the fly using a single 
set of information describing defininition for attributes, methods, inherited classes 
and roles as well as any instance settings to apply in a 
L<DCI|https://en.wikipedia.org/wiki/Data,_Context,_and_Interaction> fashion.  
This package will check for and fill in any missing pieces as needed so that your 
call can either be complex or very simple.  The goal is to provide configurable 
instance building without stringing together a series of Class-E<gt>method( %args ) 
calls.

Even though this is a Moose based class it provides a functional interface.

=head1 WARNING

Moose (and I think perl 5) can't have two classes with the same name but
different guts coexisting! This means that if you build a class (package) name 
on the fly while building an instance and then recompose a new class (package) with 
the same name but different functionality (different attributes, methods, inherited 
classes or roles) while composing a new instance on the fly then all calls 
to the old instance will use the new class functionality for execution. (Usually 
causing hard to troubleshoot failures)

MooseX::ShortCut::BuildInstance will warn if you overwrite named classes (packages)
built on top of another class (package) also built by MooseX::ShortCut::BuildInstance.  
If you are using the 'build_instance' method to generate multiple instances of 
the same class (by 'package' name) with different attribute settings but built 
with the same functionality then you need to understand the purpose of the 
L<$re_use_classes|/$MooseX::ShortCut::BuildInstance::re_use_classes> global variable.  
An alternative to multiple calls straight to 'build_instance' is to call 
L<build_class|/build_class( %args|\%args )> separatly and then just call -E<gt>new 
against the resulting class name over and over again.  Another alternative is to 
leave the 'package' argument out of 'build_instance' and let this class create a 
unique by-instance anonymous class/package name.

=head1 Functions for Export

=head2 build_instance( %args|\%args )

=over

B<Definition:> This method is used to create a Moose instance on the fly.  
I<It assumes that you do not have the class pre-built and will look for the 
needed information to compose a new class as well.>  Basically this passes the 
%args intact to L<build_class|/build_class( %args|\%args )> first.  All the 
relevant class building pieces will be used and removed from the args and then 
this method will run $returned_class_name->new( %remaining_args ) with what is 
left.

B<Accepts:> a hash or hashref of arguments.  They must include the 
necessary information to build a class.  I<(if you already have a class just 
call $class-E<gt>new( %args ); instead of this method!)> This hashref can also 
contain any attribute settings for the instance as well.  See 
L<build_class|/build_class( %args|\%args )> for more information.

B<Returns:> This will return a blessed instance of your new class with 
the passed attribute settings implemented.

=back

=head2 build_class( %args|\%args )

=over

B<Definition:> This function is used to compose a Moose class on the fly.  The 
the goal is to allow for as much or as little class definition as you want to be 
provided by one function call.  The goal is also to remove as much of the boilerplate 
and logic sequences for class building as possible and let this package handle that.  
The function begins by using the L<Moose::Meta::Class>-E<gt>class(%args) method.  
For this part the function specifically uses the argument callouts 'package', 
'superclasses', and 'roles'.  Any necessary missing pieces will be provided. I<Even 
though L<Moose::Meta::Class>-E<gt>class(%args) allows for the package name to be called 
as the first element of an odd numbered list this implementation does not.  To define 
a 'package' name it must be set as the value of the 'package' key in the %args.>  
This function then takes the following arguements; 'add_attributes', 'add_methods', 
and 'add_roles_in_sequence' and implements them in that order.   The 
implementation of these values is done with L<Moose::Util> 'apply_all_roles' 
and the meta capability in L<Moose>.

B<Accepts:> a hash or hashref of arguments.  I<These keys are always used 
to build the class.  They are never passed on to %remaining_args.>  The six 
key-E<gt>value pairs use are;

=over

B<package:> This is the name (a string) that the new instance of 
a this class is blessed under.  If this key is not provided the package 
will generate a generic name.  This will L<overwrite|/WARNING> any class 
built earlier with the same name.

=over

B<accepts:> a string

=back

B<superclasses:> this is intentionally the same key from 
Moose::Meta::Class-E<gt>create.

=over

B<accepts:> a recognizable (by Moose) class name

=back

B<roles:> this is intentionally the same key from Moose::Meta::Class
-E<gt>create.

=over

B<accepts:> a recognizable (by Moose) class name

=back

B<add_attributes:> this will add attributes to the class using the 
L<Moose::Meta::Class>-E<gt>add_attribute method.  Because these definitions 
are passed as key / value pairs in a hash ref they are not added in 
any specific order.

=over

B<accepts:> a hash ref where the keys are attribute names and the values 
are hash refs of the normal definitions used to define a Moose attribute.

=back


B<add_methods:>  this will add methods to the class using the 
L<Moose::Meta::Class>-E<gt>add_method method.  Because these definitions 
are passed as key / value pairs in a hash ref they are not added in 
any specific order.

=over

B<accepts:> a hash ref where the keys are method names and the values 
are anonymous subroutines or subroutine references.

=back

B<add_roles_in_sequence:> this will compose, in sequence, each role in 
the array ref into the class built on the prior three arguments using 
L<Moose::Util> apply_all_roles.  This will allow an added role to 
'require' elements of a role earlier in the sequence.  The roles 
implemented with the L<role|/roles:> key are installed first and in a 
group. Then these roles are installed one at a time.

=over

B<accepts:> an array ref list of roles recognizable (by Moose) as roles

=back

=back

B<Returns:> This will check the caller and see if it wants an array or a 
scalar.  In array context it returns the new class name and a hash ref of the 
unused hash key/value pairs.  These are presumably the arguments for the 
instance.  If the requested return is a scalar it just returns the name of 
the newly created class.

=back

=head3 should_re_use_classes( $bool )

=over

This sets/changes the global variable 
L<MooseX::ShortCut::BuildInstance::re_use_classes
|/$MooseX::ShortCut::BuildInstance::re_use_classes>

=back

=head3 set_class_immutability( $bool )

=over

This sets/changes the global variable 
L<MooseX::ShortCut::BuildInstance::make_classes_immutable
|/$MooseX::ShortCut::BuildInstance::make_classes_immutable>

=back

=head1 GLOBAL VARIABLES

=head4 $ENV{Smart_Comments}

The module uses L<Smart::Comments|https://metacpan.org/module/Smart::Comments> 
if the '-ENV' option is set.  The 'use' is encapsulated in an 'if' block 
triggered by the environmental variable to comfort non-believers.  Setting the 
variable $ENV{Smart_Comments} will load and turn on smart comment reporting.  
There are three levels of 'Smartness' available in this module '### #### #####'.

=head4 $MooseX::ShortCut::BuildInstance::instance_count

This is an integer that increments and appends to the anonymous package name 
for each new anonymous package created.

=head4 $MooseX::ShortCut::BuildInstance::built_classes

This is a hashref that tracks the class names ('package's) built buy this class 
to manage duplicate build behaviour.

=head4 $MooseX::ShortCut::BuildInstance::re_use_classes

This is a boolean (1|0) variable that tracks if the class should overwrite or 
re-use a package name (and the defined class) from a prior 'build_class' call.  
If the package name is overwritten it will L<cluck|https://metacpan.org/pod/Carp#SYNOPSIS> 
in warning.  This can be changed with the exported method L<should_re_use_classes
|/should_re_use_classes( $bool )>.

=head4 $MooseX::ShortCut::BuildInstance::make_classes_immutable

This is a boolean (1|0) variable that manages whether a class is immutabilized at the end of 
creation.  This can be changed with the exported method L<set_class_immutability
|/set_class_immutability( $bool )>.

=head1 SUPPORT

=over

L<MooseX-ShortCut-BuildInstance/issues|https://github.com/jandrew/MooseX-ShortCut-BuildInstance/issues>

=back

=head1 TODO

=over

B<1.> Swap L<Smart::Comments|https://metacpan.org/module/Smart::Comments> 
for L<Log::Shiras|https://github.com/jandrew/Log-Shiras>

=over

My first attempt ran into some deep recursion issues since this is used 
heavily in my development of Log::Shiras already.

=back

=back

=head1 AUTHOR

=over

Jed Lund

jandrew@cpan.org

=back

=head1 COPYRIGHT

This program is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

The full text of the license can be found in the
LICENSE file included with this module.

This software is copyrighted (c) 2013, 2014 by Jed Lund

=head1 Dependencies

=over

L<version>

L<5.010|http://perldoc.perl.org/perl5100delta.html> (for use of 
L<defined or|http://perldoc.perl.org/perlop.html#Logical-Defined-Or> //)

L<Moose>

L<Moose::Meta::Class>

L<Carp> - cluck

L<Moose::Exporter>

L<Moose::Util> - apply_all_roles

L<Moose::Exporter>

L<Types::Standard>

L<Data::Dumper>

=back

=head1 SEE ALSO

=over

L<Moose::Meta::Class> ->create

L<Moose::Util> ->with_traits

L<MooseX::ClassCompositor>

L<Smart::Comments> - 
is used if the -ENV option is set

=back

=head1 Build/Install from Source

=over
	
B<1.> Download a compressed file with the code
	
B<2.> Extract the code from the compressed file.  If you are using tar this should work:

        tar -zxvf MooseX-ShortCut-BuildInstance-v1.xx.tar.gz

B<3.> Change (cd) into the extracted directory

=back

(For Windows find what version of make was used to compile your perl)

	perl  -V:make

Then
(for Windows substitute the correct make function (s/make/dmake/g)?)

	>perl Makefile.PL

	>make

	>make test

	>make install # As sudo/root

	>make clean
	
=cut