File Coverage

lib/ElasticSearchX/Model/Generator/AttributeGenerator.pm
Criterion Covered Total %
statement 17 19 89.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 24 26 92.3


line stmt bran cond sub pod time code
1 1     1   1018 use strict;
  1         2  
  1         32  
2 1     1   4 use warnings;
  1         2  
  1         49  
3              
4             package ElasticSearchX::Model::Generator::AttributeGenerator;
5             BEGIN {
6 1     1   25 $ElasticSearchX::Model::Generator::AttributeGenerator::AUTHORITY = 'cpan:KENTNL';
7             }
8             {
9             $ElasticSearchX::Model::Generator::AttributeGenerator::VERSION = '0.1.8';
10             }
11              
12             # ABSTRACT: Generator that emits 'has' declarations for type properties.
13              
14 1     1   21 use 5.10.0;
  1         3  
  1         38  
15 1     1   8940 use Moo;
  1         51921  
  1         8  
16 1     1   7798 use Data::Dump qw( pp );
  1         8458  
  1         115  
17 1     1   759 use MooseX::Has::Sugar qw( rw required weak_ref );
  0            
  0            
18              
19              
20             has 'generator_base' => rw, required, weak_ref, handles => [qw( document_generator typename_translator )];
21              
22              
23             sub expand_type {
24             my ($type) = shift;
25             state $known_types = {
26             string => 1,
27             float => 1,
28             integer => 1,
29             boolean => 1,
30             };
31             state $need_info_types = {
32             date => 1,
33             geo_point => 1,
34             nested => 1,
35             multi_field => 1,
36             };
37             if ( exists $known_types->{$type} ) {
38             return ( type => $type );
39             }
40             if ( exists $need_info_types->{$type} ) {
41              
42             # require Carp;
43             # Carp::carp("Dont understand $type");
44             return ();
45             }
46             else {
47             require Carp;
48             Carp::carp("Dont understand $type");
49             return ();
50             }
51             }
52              
53              
54              
55             sub _property_template_string {
56             return state $property_template = qq{ %-30s => %s,\n};
57             }
58              
59             sub fill_property_template {
60             my ( $self, @args ) = @_;
61             return sprintf $self->_property_template_string, $args[0], $args[1];
62             }
63              
64             sub _s_quote {
65             my ( $self, $var ) = @_;
66             my $back = chr(0x5C);
67             my $escape = chr(0x5C) . chr(0x27);
68             $escape = '[' . $escape . ']';
69             $var =~ s{($escape)}{ $back . $1 }gex;
70             return q{'} . $var . q{'};
71             }
72              
73              
74              
75             sub _attribute_template_string {
76             return state $attribute_template = qq{has %-30s => (\n%s\n);};
77             }
78              
79             sub fill_attribute_template {
80             my ( $self, @args ) = @_;
81             return sprintf $self->_attribute_template_string, $self->_s_quote( $args[0] ), $args[1];
82              
83             }
84              
85              
86             sub hash_to_proplist {
87             my ( $self, %hash ) = @_;
88             my $propdata = join q{}, map {
89             defined $hash{$_}
90             ? $self->fill_property_template( $self->_s_quote($_), $self->_s_quote( $hash{$_} ) )
91             : $self->fill_property_template( $self->_s_quote($_), 'undef' )
92             } sort keys %hash;
93             chomp $propdata;
94             return $propdata;
95             }
96              
97              
98             sub _inflate_attribute {
99             my ( $self, %config ) = @_;
100             my $content = $config{prefix};
101             $content .= $self->fill_attribute_template( $config{propertyname}, $self->hash_to_proplist( %{ $config{properties} } ) );
102             require ElasticSearchX::Model::Generator::Generated::Attribute;
103             return ElasticSearchX::Model::Generator::Generated::Attribute->new( content => $content );
104             }
105              
106              
107             sub _cleanup_properties {
108             my ( $self, %properties_in ) = @_;
109              
110             my %properties = ();
111              
112             my $passthrough = sub {
113             my $name = shift;
114             my $d = $properties_in{$name};
115             $properties{$name} = $properties_in{$name};
116             };
117             my $bool_passthrough = sub {
118             my $name = shift;
119             my $d = $properties_in{$name};
120             require Scalar::Util;
121             if ( Scalar::Util::blessed($d) and Scalar::Util::blessed($d) eq 'JSON::XS::Boolean' ) {
122             $properties{$name} = ( $d ? 1 : undef );
123             return;
124             }
125             if ( $d eq 'true' or $d eq 'false' ) {
126             $properties{$name} = ( $d eq 'true' ? 1 : undef );
127             return;
128             }
129             $properties{$name} = $properties_in{$name};
130             };
131             my $type_passthrough = sub {
132             my $name = shift;
133             my $d = $properties_in{$name};
134             %properties = ( %properties, expand_type($d) );
135             };
136             my %passthrough_fields = (
137             store => $passthrough,
138             boost => $passthrough,
139             index => $passthrough,
140             dynamic => $bool_passthrough,
141             analyzer => $bool_passthrough,
142             include_in_all => $passthrough,
143             include_in_parent => $passthrough,
144             include_in_root => $bool_passthrough,
145             term_vector => $passthrough,
146             not_analyzed => $passthrough,
147             type => $type_passthrough,
148             );
149             for my $propname ( keys %passthrough_fields ) {
150             next unless exists $properties_in{$propname};
151             $passthrough_fields{$propname}->($propname);
152             }
153             return %properties;
154              
155             }
156              
157              
158             sub generate {
159             my ( $self, %args ) = @_;
160              
161             my $definition = pp( \%args );
162             $definition =~ s/^/# /gsm;
163              
164             return $self->_inflate_attribute(
165             prefix => "$definition\n",
166             propertyname => $args{propertyname},
167             original_definition => \%args,
168             properties => {
169             is => 'rw',
170             $self->_cleanup_properties( %{ $args{propertydata} } )
171             }
172             );
173             }
174              
175             no Moo;
176             1;
177              
178             __END__
179              
180             =pod
181              
182             =encoding UTF-8
183              
184             =head1 NAME
185              
186             ElasticSearchX::Model::Generator::AttributeGenerator - Generator that emits 'has' declarations for type properties.
187              
188             =head1 VERSION
189              
190             version 0.1.8
191              
192             =head1 METHODS
193              
194             =head2 fill_property_template
195              
196             $string = $object->fill_property_template( $property_name, $property_value )
197              
198             my $data = $object->fill_property_template( foo => 'bar' );
199             # $data == " foo => bar,\n"
200             my $data = $object->fill_property_template(quote( 'foo' ) => quote( 'bar' ));
201             # $data == " \"foo\" => \"bar\",\n"
202              
203             =head2 fill_attribute_template
204              
205             $string = $object->fill_attribute_template( $attribute_name, $attribute_properties_definition )
206              
207             my $data = $object->fill_attribute_template( foo => ' is => rw =>, ' );
208             # $data ==
209             # has "foo" => (
210             # is => rw =>,
211             # );
212              
213             =head2 generate
214              
215             $generated_attribute = $attributegenerator->generate(
216             propertydata => ... Property definition from JSON ...
217             propertyname => ... Property name from JSON ...
218             index => ... Name of current index ...
219             typename => ... Name of the type we're generating ...
220             );
221              
222             $generated_attribute->isa(ESX:M:G:Generated::Attribute);
223              
224             =head1 ATTRIBUTES
225              
226             =head2 generator_base
227              
228             rw, required, weak_ref
229              
230             =head1 FUNCTIONS
231              
232             =head2 expand_type
233              
234             %attr = ( %attr, expand_type( $type ) );
235             %attr = ( %attr, expand_type( 'boolean' ) );
236              
237             =head2 hash_to_proplist
238              
239             $string = hash_to_proplist( %hash )
240              
241             my $data = hash_to_proplist(
242             is => rw =>,
243             required => 1,
244             foo => undef,
245             );
246             # $data = <<'EOF'
247             # "is" => "rw",
248             # "required" => "1",
249             # "foo" => undef,
250             # EOF
251              
252             =head1 PRIVATE METHODS
253              
254             =head2 _property_template_string
255              
256             =head2 _attribute_template_string
257              
258             =head2 _inflate_attribute
259              
260             my $attr = $self->_inflate_attribute(
261             prefix => $dump_comment,
262             propertyname => "name of property",
263             properties => \%cleaned_properties_for_has
264             original_definition => \%original_args_to_generate
265             );
266              
267             =head2 _cleanup_properties
268              
269             %cleaned_has_props = $self->_cleanup_properties(%source_props)
270              
271             =head1 AUTHOR
272              
273             Kent Fredric <kentfredric@gmail.com>
274              
275             =head1 COPYRIGHT AND LICENSE
276              
277             This software is copyright (c) 2013 by Kent Fredric <kentfredric@gmail.com>.
278              
279             This is free software; you can redistribute it and/or modify it under
280             the same terms as the Perl 5 programming language system itself.
281              
282             =cut