File Coverage

blib/lib/CAD/Drawing/IO/FlatYAML.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package CAD::Drawing::IO::FlatYAML;
2             our $VERSION = '0.01';
3              
4 1     1   1315 use CAD::Drawing;
  0            
  0            
5             use CAD::Drawing::Defined;
6              
7             use warnings;
8             use strict;
9             use Carp;
10              
11             my $dbg = 0;
12              
13             =pod
14              
15             =head1 NAME
16              
17             CAD::Drawing::IO::FlatYAML - Fast distributed YAML file methods.
18              
19             =head1 DESCRIPTION
20              
21             This module is a first attempt at creating a "reference implementation"
22             of the specification for the first generation hub format of the
23             uber-converter project. See
24             http://ericwilhelm.homeip.net/uber-converter/ for more information about
25             this specification.
26              
27             =head1 AUTHOR
28              
29             Eric L. Wilhelm
30              
31             http://scratchcomputing.com
32              
33             =head1 COPYRIGHT
34              
35             This module is copyright (C) 2004-2006 by Eric L. Wilhelm.
36              
37             =head1 LICENSE
38              
39             This module is distributed under the same terms as Perl. See the Perl
40             source package for details.
41              
42             You may use this software under one of the following licenses:
43              
44             (1) GNU General Public License
45             (found at http://www.gnu.org/copyleft/gpl.html)
46             (2) Artistic License
47             (found at http://www.perl.com/pub/language/misc/Artistic.html)
48              
49             =head1 NO WARRANTY
50              
51             This software is distributed with ABSOLUTELY NO WARRANTY. The author,
52             his former employer, and any other contributors will in no way be held
53             liable for any loss or damages resulting from its use.
54              
55             =head1 Modifications
56              
57             The source code of this module is made freely available and
58             distributable under the GPL or Artistic License. Modifications to and
59             use of this software must adhere to one of these licenses. Changes to
60             the code should be noted as such and this notification (as well as the
61             above copyright information) must remain intact on all copies of the
62             code.
63              
64             Additionally, while the author is actively developing this code,
65             notification of any intended changes or extensions would be most helpful
66             in avoiding repeated work for all parties involved. Please contact the
67             author with any such development plans.
68              
69             =head1 SEE ALSO
70              
71             CAD::Drawing
72             CAD::Drawing::IO
73              
74             =cut
75             ########################################################################
76              
77             =head1 Requisite Plug-in Functions
78              
79             See CAD::Drawing::IO for a description of the plug-in architecture.
80              
81             The command-line type specification for this module is 'ysplit'.
82              
83             =cut
84             ########################################################################
85             # the following are required to be a disc I/O plugin:
86             our $can_save_type = "ysplit";
87             our $can_load_type = $can_save_type;
88             our $is_inherited = 1;
89              
90             =head2 check_type
91              
92             Returns true if $type is "ysplit" or $filename is a directory (need a tag?)
93              
94             $fact = check_type($filename, $type);
95              
96             =cut
97             sub check_type {
98             my ($filename, $type) = @_;
99             if(defined($type)) {
100             ($type eq "ysplit") && return("ysplit");
101             return();
102             }
103             elsif((-d $filename) && (0)) { # FIXME: this needs something
104             return("ysplit");
105             }
106             elsif(($filename =~ s/^ysplit://) and (-d $filename)) {
107             return("ysplit");
108             }
109             return();
110             } # end subroutine check_type definition
111             ########################################################################
112              
113             =head1 Load/Save Methods
114              
115             Concept here is to strip data down to the absolute bare minumum in an
116             effort to find a generic and extensible incarnation of same.
117              
118             =cut
119             ########################################################################
120             our %type_translate = (
121             arcs => 'arc',
122             plines => 'polyline',
123             circles => 'circle',
124             points => 'point',
125             texts => 'text',
126             lines => 'line',
127             );
128             our %key_translate = (
129             pt => 'point',
130             pts => 'points',
131             rad => 'radius',
132             angs => 'angles',
133             );
134             our %key_ok = map({$_ => 1} qw(
135             closed
136             color
137             linetype
138             height
139             string
140             angle
141             ));
142             our %key_skip = map({$_ => 1} qw(
143             addr
144             ));
145             # not sure about this (our addr->{id} has nothing to do with the yaml id)
146             our %key_missing = map({$_ => 1} qw(
147             id
148             ));
149             # always using internal keys
150             our %key_out_mod = (
151             color => sub {
152             my $c = shift;
153             ($c == 256) and return("#bylayer");
154             return($aci2hex[$c]);
155             },
156             );
157             # always using external keys
158             our %key_in_mod = (
159             );
160              
161             =head2 save
162              
163             Saves data into $toplevel_directory into a file for each id.
164              
165             save($drw, $toplevel_directory, \%options);
166              
167             Requires that the directory exists and is empty (?)
168              
169             Selective saves not yet supported.
170              
171             Needs a clear_all_like => $regex option.
172              
173             =cut
174             sub save{
175             my $dbg = 0;
176             my $self = shift;
177             $dbg && print "here\n";
178             my ($dir, $opt) = @_;
179             (-d $dir) or die "no $dir\n";
180             $dir =~ s#/*$#/#;
181             my @exists = glob($dir . "*") and die "EXISTING DATA IN $dir\n ";
182             my %data = (
183             dir => $dir,
184             );
185             $dbg && print "saving out $dir\n";
186             my $count = 0; # turns into filename...
187             foreach my $layer (keys(%{$self->{g}})) {
188             foreach my $ent (keys(%{$self->{g}{$layer}})) {
189             foreach my $id (keys(%{$self->{g}{$layer}{$ent}})) {
190             my %addr = (
191             "layer" => $layer,
192             "type" => $ent,
193             "id" => $id,
194             );
195             my $obj = $self->getobj(\%addr);
196             my $type = $type_translate{$ent};
197             defined($type) or die "no such type $ent\n";
198             my %yobj = (
199             layer => $layer,
200             type => $type,
201             ID => $count, # NOTE THIS!
202             );
203             foreach my $key (keys(%$obj)) {
204             my $alt_key = $key;
205             if($key_ok{$key}) {
206             # unchanged
207             }
208             elsif($alt_key = $key_translate{$key}) {
209             # different
210             }
211             elsif($key_skip{$key}) {
212             next;
213             }
214             else {
215             warn("$key not found in transforms!\n");
216             next;
217             }
218             my $val = $obj->{$key};
219             if($key_out_mod{$key}) {
220             $val = $key_out_mod{$key}->($val);
221             # die "get $val from $obj->{$key} for $key\n";
222             }
223             $yobj{$alt_key} = $val;
224             }
225             # sorry, no zero-padding here (does the spec allow it?)
226             my $filename = $dir . $count . ".yml";
227             YAML::DumpFile($filename, \%yobj);
228             $count++;
229             }
230             }
231             }
232              
233             return($count);
234             } # end subroutine save definition
235             ########################################################################
236              
237             =head2 load
238              
239             load($drw, $toplevel_directory, \%options);
240              
241             %options may include selective-load arguments
242              
243             =cut
244             sub load{
245             my $self = shift;
246             my ($dir, $opts) = @_;
247             $dir =~ s/^ysplit://;
248             (-d $dir) or croak("no such directory: $dir\n");
249             my %opt;
250             (ref($opts) eq "HASH") && (%opt = %$opts);
251             my @layers;
252             my ($s, $n) = check_select(\%opt);
253             # this has to get the list of all files,
254             # go through them,
255             # check select/not for layer, color, etc
256              
257              
258              
259             } # end subroutine load definition
260             ########################################################################
261              
262             =head1 Naming Functions
263              
264             =head2 _dir_list
265              
266             @list = _dir_list($dir);
267              
268             =cut
269             sub _dir_list {
270             my $dir = shift;
271             opendir(DIR, $dir);
272             my @list = grep(! /^\.+$/, readdir(DIR));
273             closedir(DIR);
274             # print "listed @list\n";exit;
275             return(@list);
276             } # end subroutine _dir_list definition
277             ########################################################################
278              
279             =head2 keymap_in
280              
281             Remaps keys (and possibly data) into the input version.
282              
283             ($key, $value) = keymap_in($key, $value);
284              
285             =cut
286             sub keymap_in {
287             } # end subroutine keymap_in definition
288             ########################################################################
289              
290             =head2 keymap_out
291              
292             Remaps keys (and possibly data) into the output version.
293              
294             ($key, $value) = keymap_out($key, $value);
295              
296             =cut
297             sub keymap_out {
298             my ($k, $v) = @_;
299             unless($key_translate{$k}) {
300             warn("no translate for $k\n");
301             return($k, $v);
302             }
303             return($key_translate{$k}, $v);
304             } # end subroutine keymap_out definition
305             ########################################################################
306              
307              
308             =head1 Inherited Methods
309              
310             =head2 clear_flatyml
311              
312             Removes items from the flat directory $dir.
313              
314             Defaults to removing all.
315              
316             $drw->clear_flatyml($dir, \%options);
317              
318             =over
319              
320             =item Available options:
321              
322             like => qr/regex/, # if regex matches layer name
323             not_like => qr/regex/, # negative of above (compounded)
324              
325             =item check_select() options:
326              
327             %options is passed through CAD::Drawing::Defined::check_select(), so the selections returned by it will be utilized here.
328              
329             select_layers => \@layer_list,
330             select_types => \@types_list,
331              
332             Returns the number of items removed or undef() if $dir does not exist.
333              
334             =back
335              
336             =cut
337             sub clear_flatyml {
338             my $self = shift;
339             my ($dir, $opts) = @_;
340             $dir =~ s#/*$#/#;
341             my %opt;
342             (ref($opts) eq "HASH") && (%opt = %$opts);
343             my $like = $opt{like};
344             my $notlike = $opt{not_like};
345             my ($s, $n) = check_select(\%opt);
346             (-d $dir) or return();
347             my @kill_layers = _dir_list($dir);
348             if($like) {
349             (ref($like) eq "Regexp") or
350             croak("$like is not a regex");
351             @kill_layers = grep(/$like/, @kill_layers);
352             $dbg && print "now ", scalar(@kill_layers), "\n";
353             }
354             if($notlike) {
355             (ref($notlike) eq "Regexp") or
356             croak("$notlike is not a regex");
357             @kill_layers = grep(! /$notlike/, @kill_layers);
358             $dbg && print "now ", scalar(@kill_layers), "\n";
359             }
360             my $count;
361             die "needs work";
362             # must we read-in every file to get properties associated with ID's etc?
363             # XXX none of this is correct:
364             foreach my $layer (@kill_layers) {
365             $s->{l} && ($s->{l}{$layer} || next);
366             $n->{l} && ($n->{l}{$layer} && next);
367             my $ldir = $dir . $layer . "/";
368             my @types = _dir_list($ldir);
369             $dbg && print "removing $layer\n";
370             my $tfail = 0;
371             foreach my $type (@types) {
372             $s->{t} && ($s->{t}{$type} || next);
373             $n->{t} && ($n->{t}{$type} && next);
374             $dbg && print "$type\n";
375             my $tdir = $ldir . $type . "/";
376             my @items = _dir_list($tdir);
377             $dbg && print "items: @items\n";
378             my $ifail = 0;
379             foreach my $item (@items) {
380             my $file = $tdir . $item;
381             if(unlink($file)) {
382             $count ++;
383             }
384             else {
385             carp("unlink failed on $file");
386             $ifail++;
387             }
388             }
389             unless($ifail) {
390             unless(rmdir($tdir)) {
391             carp("rmdir failed on $tdir");
392             $tfail++;
393             }
394             }
395             } # end foreach $type
396             unless($tfail) {
397             unless(rmdir($ldir)) {
398             carp("rmdir failed on $ldir");
399             }
400             }
401             }
402              
403             return($count);
404              
405             } # end subroutine clear_flatyml definition
406             ########################################################################
407              
408              
409              
410             1;