1package Data::Localize::Trait::WithStorage;
2use Moo::Role;
3use Data::Localize;
4
5BEGIN {
6    if (Data::Localize::DEBUG) {
7        require Data::Localize::Log;
8        Data::Localize::Log->import;
9    }
10}
11
12has storage_class => (
13    is => 'ro',
14    default => sub {
15        return '+Data::Localize::Storage::Hash';
16    }
17);
18
19has storage_args => (
20    is => 'ro',
21    default => sub { +{} }
22);
23
24has 'load_from_storage' => (
25    is      => 'ro',
26    default => sub { [] },
27);
28
29has lexicon_map => (
30    is => 'ro',
31    default => sub { +{} },
32);
33
34after BUILD => sub {
35    my $self = shift;
36
37    my $langs = $self->load_from_storage;
38    if (! $langs || ! @$langs) {
39        if (Data::Localize::DEBUG) {
40            debugf("No languages to load");
41        }
42        return;
43    }
44    my $storage_class = $self->_canonicalize_storage_class;
45    my $storage_args  = $self->storage_args;
46    if (Data::Localize::DEBUG) {
47        debugf("Building lexicon map (%s)", $storage_class);
48    }
49
50    Module::Load::load( $storage_class );
51
52    unless ( $storage_class->is_volatile ) {
53        foreach my $lang ( @$langs ) {
54            if (Data::Localize::DEBUG) {
55                debugf("Loading storage for lang '%s'", $lang);
56            }
57            $storage_args->{lang} = $lang;
58
59            $self->set_lexicon_map(
60                $lang,
61                $storage_class->new( $storage_args )
62            );
63        }
64    }
65};
66
67sub get_lexicon_map {
68    my ($self, $key) = @_;
69    return $self->lexicon_map->{ $key };
70}
71
72sub set_lexicon_map {
73    my ($self, $key, $value) = @_;
74    return $self->lexicon_map->{ $key } = $value;
75}
76
77sub get_lexicon {
78    my ($self, $lang, $id) = @_;
79    my $lexicon = $self->get_lexicon_map($lang);
80    return () unless $lexicon;
81    $lexicon->get($id);
82}
83
84sub set_lexicon {
85    my ($self, $lang, $id, $value) = @_;
86    my $lexicon = $self->get_lexicon_map($lang);
87    if (! $lexicon) {
88        $lexicon = $self->_build_storage($lang);
89        $self->set_lexicon_map($lang, $lexicon);
90    }
91    $lexicon->set($id, $value);
92}
93
94sub merge_lexicon {
95    my ($self, $lang, $new_lexicon) = @_;
96
97    if (Data::Localize::DEBUG) {
98        debugf("Merging lexicon for lang '%s'", $lang);
99    }
100    my $lexicon = $self->get_lexicon_map($lang);
101    if (! $lexicon) {
102        $lexicon = $self->_build_storage($lang);
103        $self->set_lexicon_map($lang, $lexicon);
104    }
105    while (my ($key, $value) = each %$new_lexicon) {
106        if (Data::Localize::DEBUG) {
107            debugf("Setting lexicon '%s' on '%s'", $key, Scalar::Util::blessed $lexicon);
108        }
109        $lexicon->set($key, $value);
110    }
111}
112
113sub _build_storage {
114    my ($self, $lang) = @_;
115
116    my $class = $self->_canonicalize_storage_class;
117    my $args  = $self->storage_args;
118
119    Module::Load::load($class);
120
121    $args->{lang} = $lang;
122
123    if (Data::Localize::DEBUG) {
124        debugf("Creating storage '%s'", $class);
125    }
126    return $class->new( $args );
127}
128
129sub _canonicalize_storage_class {
130    my $self  = shift;
131    my $class = $self->storage_class;
132    if ($class !~ s/^\+//) {
133        $class = "Data::Localize::Storage::$class";
134    }
135    $class;
136}
137
138no Moo::Role;
139
1401;
141
142__END__
143
144=head1 NAME
145
146Data::Localize::Trait::WithStorage - Localizer With Configurable Storage
147
148=head1 METHODS
149
150=head2 get_lexicon($lang, $id)
151
152Gets the specified lexicon
153
154=head2 set_lexicon($lang, $id, $value)
155
156Sets the specified lexicon
157
158=head2 merge_lexicon
159
160Merges lexicon (may change...)
161
162=head2 get_lexicon_map($lang)
163
164Get the lexicon map for language $lang
165
166=head2 set_lexicon_map($lang, \%lexicons)
167
168Set the lexicon map for language $lang
169
170=cut
171