File Coverage

blib/lib/Treex/PML/Schema/Copy.pm
Criterion Covered Total %
statement 89 113 78.7
branch 27 44 61.3
condition 12 25 48.0
subroutine 13 15 86.6
pod 3 3 100.0
total 144 200 72.0


line stmt bran cond sub pod time code
1             package Treex::PML::Schema::Copy;
2              
3 6     6   35 use strict;
  6         12  
  6         158  
4 6     6   28 use warnings;
  6         11  
  6         142  
5              
6 6     6   28 use vars qw($VERSION);
  6         19  
  6         265  
7             BEGIN {
8 6     6   132 $VERSION='2.24'; # version template
9             }
10 6     6   31 no warnings 'uninitialized';
  6         12  
  6         238  
11 6     6   34 use Carp;
  6         11  
  6         305  
12 6     6   43 use Treex::PML::Schema::Constants;
  6         16  
  6         531  
13 6     6   36 use List::Util qw(first);
  6         9  
  6         373  
14 6     6   33 use base qw(Treex::PML::Schema::XMLNode);
  6         9  
  6         6051  
15              
16 0     0 1 0 sub get_decl_type { return(PML_COPY_DECL); }
17 0     0 1 0 sub get_decl_type_str { return('copy'); }
18              
19             sub simplify {
20 1     1 1 4 my ($copy,$opts)=@_;
21 1 50       6 return if $opts->{no_copy};
22 1         4 my $template_name = $copy->{template};
23 1         5 my $owner = _lookup_upwards($copy->{-parent},'template',$template_name);
24 1 50       4 unless ($owner) {
25 0         0 die "Could not find template $template_name\n";
26 0         0 return;
27             }
28 1         4 my $template = $owner->{template}{$template_name};
29             # print STDERR "Copying $copy->{template} as $copy->{prefix}\n";
30              
31 1 50       5 if (ref $template->{type}) {
32 1         2 my $parent = $copy->{-parent};
33 1   50     4 my $prefix = $copy->{prefix} || '';
34 1   50     8 $parent->{type}||={};
35 1         3 my (@new_types, @new_templates);
36 1         2 foreach my $t (values(%{$template->{type}})) {
  1         4  
37 4         13 my $new = $template->copy_decl($t);
38 4         14 _apply_prefix($copy,$template,$prefix,$new);
39 4         15 my $new2 = $parent->copy_decl($new);
40 4         18 push @new_types, $new2;
41             }
42 1         2 foreach my $t (values(%{$template->{template}})) {
  1         6  
43 0         0 my $new = $template->copy_decl($t);
44 0         0 _apply_prefix($copy,$template,$prefix,$new);
45 0         0 my $new2 = $parent->copy_decl($new);
46 0         0 push @new_templates, $new2;
47             }
48 1         3 for my $t (@new_types) {
49 4         12 my $name = $prefix.$t->{-name};
50             die "Type $name copied from $template_name already exists\n" if
51             exists $parent->{type}{$name}
52             or (exists $parent->{derive}{$name}
53             and $parent->{derive}{$name}{type} ne $name)
54 4 50 66     35 or exists $parent->{param}{$name};
      33        
      33        
55             # print STDERR "copying type $name into \n";
56 4         7 $t->{-name}=$name;
57 4         10 $parent->{type}{$name}=$t;
58             }
59 1         7 for my $t (@new_templates) {
60 0         0 my $name = $prefix.$t->{-name};
61             die "Template $name copied from $template_name already exists\n" if
62 0 0       0 exists $parent->{template}{$name};
63             # print STDERR "copying template $name\n";
64 0         0 $t->{-name}=$name;
65 0         0 $parent->{template}{$name}=$t;
66             }
67             }
68             }
69             # traverse declarations as long as there is one
70             # containing a hash key $what or one occurring in an array-ref $what
71             # with a Hash value containing the key $name
72             sub _lookup_upwards {
73 3     3   9 my ($parent, $what, $name)=@_;
74 3 100       10 if (ref($what) eq 'ARRAY') {
75 2         6 while ($parent) {
76             return $parent if
77 5 100   13   24 first { (ref($parent->{$_}) eq 'HASH') and exists($parent->{$_}{$name}) } @$what;
  13 100       44  
78 3         12 $parent = $parent->{-parent};
79             }
80             } else {
81 1         4 while ($parent) {
82 1 50 33     11 return $parent if (ref($parent->{$what}) eq 'HASH') and exists($parent->{$what}{$name});
83 0         0 $parent = $parent->{-parent};
84             }
85             }
86 0         0 return;
87             }
88              
89             sub _apply_prefix {
90 11     11   29 my ($copy,$template,$prefix,$type) = @_;
91 11 50       24 if (ref($type)) {
    0          
92 11 50       30 if (UNIVERSAL::isa($type,'HASH')) {
93 11 50 66     38 if (exists($type->{-name}) and $type->{-name} eq 'template') {
94             # hopefully a template
95 0 0       0 if ($type->{type}) {
96 0         0 _apply_prefix($copy,$template,$prefix,$_) for (values %{$type->{type}});
  0         0  
97             }
98 0         0 return;
99             }
100 11         18 my $ref = $type->{type};
101 11 100 66     34 if (defined($ref) and length($ref)) {
102 2         10 my $owner = _lookup_upwards($type->{-parent},['type','derive','param'],$ref);
103 2 50 33     12 if (defined $owner and $owner==$template) {
104             # the type is defined exactly on the level of the template
105 2 100       9 if (exists $copy->{let}{$ref}) {
106 1         3 my $let = $copy->{let}{$ref};
107 1 50       5 if ($let->{type}) {
108             $type->{type}=$let->{type}
109 0         0 } else {
110 1         3 delete $type->{type};
111 1         3 foreach my $d (qw(list alt structure container sequence cdata choice constant)) {
112 8 50       18 if (exists $type->{$d}) {
113 0         0 delete $type->{$d};
114 0         0 last;
115             }
116             }
117 1         2 delete $type->{-decl};
118 1         2 delete $type->{-resolved};
119 1         3 foreach my $d (qw(list alt structure container sequence cdata choice constant)) {
120 6 100       14 if (exists $let->{$d}) {
121 1         5 $type->{$d} = $type->copy_decl($let->{$d});
122 1         2 $type->{-decl}=$d;
123 1         3 last;
124             }
125             }
126             }
127             } else {
128 1         4 $type->{type} = $prefix.$ref; # do apply prefix
129             }
130             } else {
131 0         0 $type->{type} = $prefix.$ref; # do apply prefix
132             }
133             }
134             # traverse descendant type declarations
135 11         16 for my $d (qw(member attribute element)) {
136 29 100       66 if (ref($type->{$d})) {
137 3         6 _apply_prefix($copy,$template,$prefix,$_) for (values %{$type->{$d}});
  3         16  
138 3         7 return;
139             }
140             }
141 8         12 for my $d (qw(list alt structure container sequence)) {
142 36 100       127 if (ref($type->{$d})) {
143 3         19 _apply_prefix($copy,$template,$prefix,$type->{$d});
144 3         6 return;
145             }
146             }
147             }
148             } elsif (UNIVERSAL::isa($type,'ARRAY')) {
149 0           foreach my $d (@$type) {
150 0           _apply_prefix($copy,$template,$prefix,$d);
151             }
152             }
153             }
154              
155              
156             1;
157             __END__