=encoding utf8

=head1 NAME

Module::Generic::Dynamic - Dynamic Object Class

=head1 SYNOPSIS

    package My::Module;
    use parent qw( Module::Generic::Dynamic );

    # Then, instantiating an object
    my $object = My::Module->new({
        name => $some_name,
        quantity => 20,
        metadata => $some_hash_reference,
        tags => [qw( product entrepreneurship capital )],
    });

    # Then the methods corresponding to the data keys can be accessed
    my $product_name = $object->name
    # etc

=head1 VERSION

    v1.2.4

=head1 DESCRIPTION

The purpose of this class/package is to provide a framework to create dynamically created class/package.

For more granular control over the method to be used for each data key-value, use L<Module::Generic/"_set_get_class">

=head1 METHODS

=head2 new

Provided with an hash reference of data, this will create dynamically a class based on the class/pacakge name used to call B<new>

It will then associate helper method sbased on the data type for each key of the hash reference. Precisely:

=over 4

=item * C<hash>

This would create method after the key name and a new class also based on the key name, and use the helper method L<Module::Generic/"_set_get_object">

=item * C<array>

If the array contains hash references, this will create a new class/package dynamically and create an object for each hash reference in the array using L<Module::Generic/"_set_get_object_array">

Otherwise, it will create the method using L<Module::Generic/"_set_get_array">

=item * C<string>

This would create a method using the helper method L<Module::Generic/"_set_get_scalar">

=item * C<boolean>

This would create a method using the helper method L<Module::Generic/"_set_get_boolean">

=back

=head1 SERIALISATION

=for Pod::Coverage FREEZE

=for Pod::Coverage STORABLE_freeze

=for Pod::Coverage STORABLE_thaw

=for Pod::Coverage THAW

=for Pod::Coverage TO_JSON

Serialisation by L<CBOR|CBOR::XS>, L<Sereal> and L<Storable::Improved> (or the legacy L<Storable>) is supported by this package. To that effect, the following subroutines are implemented: C<FREEZE>, C<THAW>, C<STORABLE_freeze> and C<STORABLE_thaw>

=head1 THREAD SAFETY WARNING

B<This module is not thread-safe.>

C<Module::Generic::Dynamic> dynamically creates packages and injects methods into symbol tables at runtime using C<eval>. In multi-threaded environments (Perl ithreads), this can cause:

=over 4

=item *

Race conditions between threads attempting to create the same symbol

=item *

Corrupted symbol tables if a method is installed while another thread is reading or writing from the same class

=back

=head2 Recommended Usage

=over 4

=item *

Use this module only during application initialisation, before any threads are spawned.

=item *

Avoid invoking C<new()> or triggering C<AUTOLOAD()> from within a thread.

=item *

If used in a persistent environment (like mod_perl), precompile structures at startup.

=back

=head1 ERROR HANDLING

Errors in C<new> and C<AUTOLOAD>, such as invalid parameters, return C<undef> with an error object accessible via C<< $obj->error >>. Check for errors to handle failures gracefully:

    my $obj = Module::Generic::Dynamic->new( %data );
    die( $obj->error ) if( !defined( $obj ) );

=head1 AUTHOR

Jacques Deguest E<lt>F<jack@deguest.jp>E<gt>

=head1 COPYRIGHT & LICENSE

Copyright (c) 2000-2024 DEGUEST Pte. Ltd.

You can use, copy, modify and redistribute this package and associated
files under the same terms as Perl itself.

=cut

