File Coverage

blib/lib/Treex/PML/Backend/Storable.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 Treex::PML::Backend::Storable;
2 1     1   867 use Treex::PML;
  0            
  0            
3             use Storable qw(nstore_fd fd_retrieve);
4             use Treex::PML::IO qw( close_backend);
5             use strict;
6              
7             use vars qw($VERSION);
8             BEGIN {
9             $VERSION='2.21'; # version template
10             }
11             use UNIVERSAL::DOES;
12             use Scalar::Util qw(blessed reftype refaddr);
13              
14             sub test {
15             my ($f,$encoding)=@_;
16             if (ref($f)) {
17             return $f->getline()=~/^pst0/;
18             } else {
19             my $fh = open_backend($f,"r");
20             my $test = $fh && test($fh,$encoding);
21             close_backend($fh);
22             return $test;
23             }
24             }
25              
26             sub open_backend {
27             Treex::PML::IO::open_backend(@_[0,1]);
28             }
29              
30             sub read {
31             my ($fd,$fs)=@_;
32             binmode($fd);
33             my $restore = fd_retrieve($fd);
34              
35             my $api_version = $restore->[6];
36             unless ($Treex::PML::COMPATIBLE_API_VERSION{ $api_version }) {
37             $api_version='0.001' unless defined $api_version;
38             warn "Warning: the binary file ".$fs->filename." is a dump of structures created by possibly incompatible Treex::PML API version $api_version (the current Treex::PML API version is $Treex::PML::API_VERSION)\n";
39             }
40              
41             # support for old Fslib-based documents:
42             if (ref($restore->[0]) eq 'FSFormat' and not defined($Fslib::VERSION)) {
43             # upgrade to Treex::PML
44             # warn "Warning: Detected Fslib-based file and Fslib is not loaded: upgrading to Treex::PML!\n";
45             upgrade_from_fslib($restore);
46             }
47              
48             $fs->changeTail(@{$restore->[2]});
49             $fs->[13]=$restore->[3]; # metaData
50             my $appData = delete $fs->[13]->{'StorableBackend:savedAppData'};
51             if ($appData) {
52             $fs->changeAppData($_,$appData->{$_}) foreach keys(%$appData);
53             }
54             $fs->changePatterns(@{$restore->[4]});
55             $fs->changeHint($restore->[5]);
56              
57             # place to update some internal stuff if necessary
58             my $schema = $fs->metaData('schema');
59             if (ref($schema) and !$schema->{-api_version}) {
60             $schema->convert_from_hash();
61             $schema->post_process();
62             }
63             $fs->changeFS($restore->[0]);
64             $fs->changeTrees(@{$restore->[1]});
65             $fs->FS->renew_specials();
66              
67             # $fs->_weakenLinks;
68             }
69              
70              
71             sub write {
72             my ($fd,$fs)=@_;
73             binmode($fd);
74             my $metaData = { %{$fs->[13]} };
75             my $ref = $fs->appData('ref');
76             $metaData->{'StorableBackend:savedAppData'}||={};
77             foreach my $savedAppData ($metaData->{'StorableBackend:savedAppData'}) {
78             $savedAppData->{'id-hash'} = $fs->appData('id-hash');
79             $savedAppData->{'ref'} = {
80             map {
81             my $val = $ref->{$_};
82             UNIVERSAL::DOES::does($val,'Treex::PML::Instance') ? ($_ => $val) : ()
83             } keys %$ref
84             } if ref $ref;
85             }
86             nstore_fd([$fs->FS,
87             $fs->treeList,
88             [$fs->tail],
89             $metaData,
90             [$fs->patterns],
91             $fs->hint,
92             $Treex::PML::API_VERSION
93             ],$fd);
94             }
95              
96             sub upgrade_from_fslib {
97             my @next = @_;
98             my %seen;
99             $seen{refaddr($_)}=1 for @next;
100             while (@next) {
101             my $object = shift @next;
102             my $ref = ref($object);
103             next unless $ref;
104             my $is = blessed($object);
105             if (defined $is) {
106             if ($is =~ /^Treex/) {
107             } elsif ($is eq 'FSNode') {
108             bless $object, 'Treex::PML::Node';
109             } elsif ($is eq 'Fslib::Type') {
110             bless $object, 'Treex::PML::Backend::Storable::CopmpatType';
111             } elsif ($is =~ /^Fslib::(.*)$/) {
112             bless $object, qq{Treex::PML::$1};
113             } elsif ($is =~ /^PMLSchema(::.*)?$/) {
114             bless $object, qq{Treex::PML::Schema$1};
115             } elsif ($is eq 'FSFile') {
116             bless $object, 'Treex::PML::Document';
117             } elsif ($is eq 'FSFormat') {
118             bless $object, 'Treex::PML::FSFormat';
119             } elsif ($is eq 'PMLInstance') {
120             bless $object, 'Treex::PML::Instance';
121             }
122             $ref = reftype($object);
123             }
124             for (($ref eq 'HASH') ? values(%$object)
125             : ($ref eq 'ARRAY') ? @$object
126             : ($ref eq 'SCALAR') ? $$object : ()) {
127             my $key = refaddr($_) || next;
128             push @next, $_ unless ($seen{$key}++);
129             }
130             }
131             }
132              
133             package Treex::PML::Backend::Storable::CopmpatType;
134             use Carp;
135             use warnings;
136             use strict;
137             use vars qw($AUTOLOAD);
138             # This is handler for obsoleted class 'Fslib::Type'
139             # which has no API-compatible counterpart in Treex::PML.
140             # The object is a pair (ARRAYref) containing PML schema and type declaration.
141             sub schema {
142             my ($self)=@_;
143             return $self->[0];
144             }
145             sub type_decl {
146             my ($self)=@_;
147             return $self->[1];
148             }
149             # delegate every method to the type
150             sub AUTOLOAD {
151             my $self = shift;
152             croak "$self is not an object" unless ref($self);
153             my $name = $AUTOLOAD;
154             $name =~ s/.*://; # strip fully-qualified portion
155             return $self->[1]->$name(@_);
156             }
157              
158             1;
159             __END__