File Coverage

blib/lib/WWW/Patent/Page.pm
Criterion Covered Total %
statement 206 238 86.5
branch 80 100 80.0
condition 31 56 55.3
subroutine 18 20 90.0
pod 4 4 100.0
total 339 418 81.1


line stmt bran cond sub pod time code
1             package WWW::Patent::Page; #modeled vaguely on LWP::UserAgent
2 5     5   1114892 use strict;
  5         12  
  5         226  
3 5     5   27 use warnings;
  5         14  
  5         143  
4 5     5   772308 use diagnostics;
  5         1949307  
  5         64  
5 5     5   2050 use Carp qw(carp cluck confess);
  5         11  
  5         505  
6 5     5   416115 use English qw( -no_match_vars );
  5         819871  
  5         36  
7            
8             #use HTML::Display; ## comment out after completion; used for testing. see sub request
9             #my $browser = HTML::Display->new(class => 'HTML::Display::Win32::IE',); #comment out after completion; used for testing. see sub request
10            
11            
12             # use criticism 'brutal'; # handled in tests; author only
13             # $ prove -l lib --verbose t/999_critic.t # example of using prove
14             require LWP::UserAgent;
15 5     5   61908 use WWW::Patent::Page::Response;
  5         15  
  5         193  
16            
17             #use HTTP::Cache::Transparent;
18             #HTTP::Cache::Transparent::init( {
19             # BasePath => '/tmp/cache' ,
20             # NoUpdate => 60 * 60 *24 * 7 * 52 # seconds 2 minutes 2 hours 2 days 2 weeks 2 years = 1 year
21             #});
22            
23 5     5   30 use subs qw( new country_known get_page _load_modules _agent _load_country_known );
  5         8  
  5         20  
24             my (%METHODS, %_country_known);
25             my (%MODULES, $default_country, $default_office, @modules_to_load);
26            
27 5     5   5889 use version; our $VERSION = qv('0.109.0'); # January, 2012
  5         17278  
  5         39  
28 5     5   555 use base qw( LWP::UserAgent );
  5         13  
  5         9918  
29             %_country_known = _load_country_known();
30            
31             # user set variables:
32             @modules_to_load = (
33             'USPTO',
34             #'MICROPATENT',
35             #'JPO_IPDI' ,
36             # 'ESPACE_EP', # 'ESPACE_EP' bad August 2009 due to captcha use
37             # , 'OPEN_PATENT_SERVICES' # Watch this space!
38             );
39            
40             # if you write your own module; please send to wanda_b_Anon@yahoo.com for distribution
41            
42             $default_country = 'US';
43             # $default_office = 'ESPACE_EP'; # they support many countries/entities
44             $default_office = 'USPTO'; # 'ESPACE_EP' bad August 2009 due to captcha use
45            
46             sub new {
47 9     9   1145746 my ($class, $doc_id, %passed_parm);
48 9 100       57 if (@_ % 2) {($class, %passed_parm) = (@_);}
  7         34  
  2         7  
49             else {($class, $doc_id, %passed_parm) = (@_);}
50            
51             # if an odd number of parameters is passed, the first is the doc_id
52             # the other pairs are the hash of values, including UserAgent settings
53            
54             # my ($class) = shift @_;
55 9         254 my %parent_parms = (
56             agent => "WWW::Patent::Page/$VERSION",
57            
58             # cookie_jar => {},
59             );
60 9         201 my %default_parameter = (
61             'is_success' => undef,
62             'message' => undef,
63             'office' => $default_office, # USPTO is provided
64             'office_username' => undef, # e.g. MicroPatent account
65             'office_password' => undef, # e.g. MicroPatent password
66             'session_token' => undef, # e.g. session number in Micropatent, from username and password
67             'country' => $default_country, #US is provided
68             'doc_id' => undef, # US_6,123,456 as entered
69             'doc_id_standardized' => undef, # US6123456 sparse
70             'doc_id_commified' => undef, # US6,123,456
71             'doc_type' => undef, # PP, RE, D, etc
72             'format' => 'pdf', # pdf html
73             'page' => undef,
74            
75             # 'version' => undef,
76             'comment' => undef,
77             'kind' => undef, # A B etc (not yet used)
78             'number' => undef, # 6123456
79             'tempdir' => undef, # directory for temp files USPTO_pdf
80             );
81            
82             # my %passed_parms;
83 9 100       153 if ($doc_id) {
84 2         5 $default_parameter{'doc_id'} = $doc_id;
85 2         4 $passed_parm{'doc_id'} = $doc_id;
86             }
87            
88             # if an odd number of parameters is passed, the first is the doc_id
89             # the other pairs are the hash of values, including UserAgent settings
90             # %passed_parm = @_;
91            
92             # if ( defined($passed_parm{'country'} or defined($passed_parm{'number'}) { delete $passed_parm{'doc_id'}; $self->{'patent'}->{'doc_id'} = undef }
93             # Keep the patent-specific parms before creating the object.
94             # (the parameters defined above are the only user exposed parameters allowed)
95 9         55 while (my ($key, $value) = each %passed_parm) {
96 3 50       11 if (exists $default_parameter{$key}) {
97 3         11 $default_parameter{$key} = $value;
98             }
99             else {
100 0         0 $parent_parms{$key} = $value;
101             }
102             }
103 9         116 my $self = $class->SUPER::new(%parent_parms);
104 9   33     23437 bless $self, ref $class || $class; # or is it: bless $self, $class;
105            
106             # Use the patent parms now that we have a patent object.
107 9         71 for my $parm (keys %default_parameter) {
108 153         324 $self->{'patent'}->{$parm} = $default_parameter{$parm};
109             }
110            
111 9         102 $self->cookie_jar({});
112 9         66354 $self->env_proxy(); # get the proxy stuff set up from the environment via LWP::UserAgent
113             # $self->proxy(['http', 'ftp'], 'http://localhost:5364/'); #Howard P. Katseff, "Web Scraping Proxy" wsp http://www.research.att.com/~hpk/
114 9         121559 $self->timeout(240); # set to timeout to 240 seconds from the traditional 180 seconds
115 9         162 push @{$self->requests_redirectable}, 'POST'; # redirect HTTP 1.1 302s LWP::UserAgent
  9         218  
116 9 50       151 if (!defined $self->agent) {$self->agent = $class->_agent}
  0         0  
117 9         567 $self->_load_modules(@modules_to_load); # list your custom modules here,
118             # and put them into the folder that holds the others, e.g. USPTO.pm
119 9 50 33     51 if ( defined $passed_parm{'country'}
120             and defined $passed_parm{'number'})
121             {
122 0         0 delete $passed_parm{'doc_id'};
123 0         0 $self->{'patent'}->{'doc_id'} = $passed_parm{'country'} . $passed_parm{'number'};
124             }
125 9 100       112 if ($self->{'patent'}->{'doc_id'}) { # if called with doc ID, parse it- unless it seems to be parsed already
126 2         6 $self->parse_doc_id();
127             }
128 9         107 return $self;
129             }
130            
131             sub country_known {
132 2     2   3489 my $self = shift;
133 2         4 my ($country_in_question) = shift;
134 2 100       8 if (exists $_country_known{$country_in_question}) {
135 1         6 return ($_country_known{$country_in_question});
136             }
137             else {
138 1         5 return (undef);
139             }
140             }
141            
142             sub parse_doc_id {
143 195     195 1 128857 my ($self, $id) = (@_);
144 195         567 $self->{'patent'}->{'message'} = q{};
145 195 100       569 if (!$id) {
146 22 50 0     87 $id = $self->{'patent'}->{'doc_id'}
147             or (carp 'No document id to parse' and return);
148             }
149 195         372 my ($found, $country, $type, $number, $kind, $comment) = (undef, undef, undef, undef, undef, undef);
150            
151             # start country parsing
152 195 100       1549 if ( $id =~ m{^ # anchor to beginning of string
153             [, _\.\t-]* #separator(s) (optional)
154             (\D\D){0,1} # country (optional) (well, sometimes the type, if country not supplied because known by other means)
155             [, _\.\t-]* #separator(s) (optional)
156             (D|PP|RE|T|H|RX|AI|d|pp|re|t|h|rx|ai|S|M|s|m){0,1} # type, if accompanied by country (use below also!)
157             [, _\.\t-]* #separator(s) (optional)
158             ([, _\d-]+) # "number" REQUIRED to have digits - with interspersed separator(s) (optional)
159             [, _\.\t-]* #separator(s) (optional)
160             (
161             A$|A[, _\.\t-]+|B$|B[, _\.\t-]+|D$|D[, _\.\t-]+|E$|E[, _\.\t-]+|H$|H[, _\.\t-]+|
162             L$|L[, _\.\t-]+|M$|M[, _\.\t-]+|O$|O[, _\.\t-]+|P$|P[, _\.\t-]+|S$|S[, _\.\t-]+|
163             T$|T[, _\.\t-]+|U$|U[, _\.\t-]+|W$|W[, _\.\t-]+|X$|X[, _\.\t-]+|Y$|Y[, _\.\t-]+|
164             Z$|Z[, _\.\t-]+|
165             A0|A1|A2|A3|A4|A5|A6|A7|A8|A9|B1|B2|B3|B4|B5|B6|B8|B9|C$|C0|C1|C2|C3|C4|C5|
166             C8|C[, _\.\t-]+|F1|F2|H1|H2|P1|P2|P3|P4|P9|T1|T2|T3|T4|T5|T9|U0|U1|U2|U3|U4|
167             U8|W1|W2|X0|X1|X2|Y1|Y2|Y3|Y4|Y5|Y6|Y8|
168            
169             a$|a[, _\.\t-]+|b$|b[, _\.\t-]+|d$|d[, _\.\t-]+|e$|e[, _\.\t-]+|h$|h[, _\.\t-]+|
170             l$|l[, _\.\t-]+|m$|m[, _\.\t-]+|o$|o[, _\.\t-]+|p$|p[, _\.\t-]+|s$|s[, _\.\t-]+|
171             t$|t[, _\.\t-]+|u$|u[, _\.\t-]+|w$|w[, _\.\t-]+|x$|x[, _\.\t-]+|y$|y[, _\.\t-]+|
172             z$|z[, _\.\t-]+|
173             a0|a1|a2|a3|a4|a5|a6|a7|a8|a9|b1|b2|b3|b4|b5|b6|b8|b9|c$|c0|c1|c2|c3|c4|c5|
174             c8|c[, _\.\t-]+|f1|f2|h1|h2|p1|p2|p3|p4|p9|t1|t2|t3|t4|t5|t9|u0|u1|u2|u3|u4|
175             u8|w1|w2|x0|x1|x2|y1|y2|y3|y4|y5|y6|y8
176            
177             ){0,1}
178             # kind code (eats up separator required before comment)
179             (.*) # comment (optional, if used, required to be preceded by at least one separator)
180             }mx
181             )
182             {
183 193         484 $country = $1;
184 193         466 $type = $2;
185 193         357 $number = $3;
186 193         318 $kind = $4;
187 193         338 $comment = $5;
188            
189 193 100       489 if ($country) {$country = uc $country;}
  159         267  
  34         63  
190             else {$country = $default_country}
191            
192             # $type = $2;
193 193 100       624 if ($type) {
  106         137  
194 87         159 $type = uc $type;
195             } #actually, required to be upper case
196             else {$type = undef;}
197 193 100 66     909 if ((!defined $type) && !$type && (!$_country_known{$country})) {
      33        
198 34 100       186 if ($country =~ m/(D|PP|RE|T|H|RX|AI|d|pp|re|t|h|rx|ai|S|M|s|m)/mx) {
199 32         41 $type = $country;
200 32         54 $country = $default_country;
201             }
202             else {
203            
204             # carp "unrecognized _country or type: country: from '$id' ";
205 2         6 $self->{'patent'}->{'country'} = undef;
206 2         4 $self->{'patent'}->{'is_success'} = undef;
207 2         6 $self->{'patent'}->{'message'} = "unrecognized _country or type: country: from '$id'";
208 2         6 return (undef);
209             }
210             }
211            
212 191 50 66     1252 if ( (!exists $_country_known{$country})
      33        
213             || ($type
214             && (!$type =~ m/(^D$|^PP$|RE|T|H|RX|AI|d|pp|re|t|h|rx|ai)/mx))
215             )
216             {
217            
218             # carp "unrecognized _country or type: country: '$country' type: '$type' from '$id' ";
219 0         0 $self->{'patent'}->{'country'} = undef;
220 0         0 $self->{'patent'}->{'is_success'} = undef;
221 0         0 $self->{'patent'}->{'message'} = "unrecognized _country or type: country: '$country' type: '$type' from '$id'";
222 0         0 return (undef);
223             }
224            
225             # $number = $3;
226 191 50       493 if ($number) {$number =~ s/[, _\- ]//mxg;}
  191         723  
  0         0  
227             else {print "\nno number!!!\n"}
228            
229             # $kind = $4;
230 191 100       457 if ($kind) {$kind = uc $kind}
  47         76  
231 191 100       501 if ($kind) {$kind =~ s/[, _\- ]//mxg;}
  47         83  
232            
233             # $comment = $5;
234 191 100       390 if ($comment) {
235 25         99 $comment =~ s/^[,_\- ]*//mxg;
236 25         153 $comment =~ s/[,_\- ]*$//mxg;
237             }
238            
239 191         433 $self->{'patent'}->{'country'} = $country;
240 191         441 $self->{'patent'}->{'doc_type'} = $type;
241 191         505 $self->{'patent'}->{'number'} = $number;
242 191         289 $self->{'patent'}->{'kind'} = $kind;
243 191         349 $self->{'patent'}->{'comment'} = $comment;
244             }
245             else {
246 2         438 carp "document id '$id'\nnot parsed.";
247 2         2703 $self->{'patent'}{'is_success'} = undef;
248 2         11 $self->{'patent'}{'message'} = "document id '$id' not parsed.";
249 2         8 return (undef);
250             }
251             ## Japanese number fiddling- later, this bind of crap may go into JPO_IPDI_parse_doc_id
252            
253 191 100       558 if ($self->{'patent'}->{'country'} eq 'JP') {
254            
255             # print "country = jp type = $self->{'patent'}->{'doc_type'}\n";
256 21 100 100     379 if (uc($self->{'patent'}->{'doc_type'}) eq 'H' or uc($self->{'patent'}->{'doc_type'}) eq 'S' or uc($self->{'patent'}->{'doc_type'}) eq 'T' or uc($self->{'patent'}->{'doc_type'}) eq 'M') {
    100 66        
      66        
      66        
      66        
      66        
257 12         32 my $year = substr($self->{'patent'}->{'number'}, 0, 2); # Heisei < 10 must have 0 prefix
258 12         48 $self->{'patent'}->{'number'} =~ s{^\d\d}{}xm;
259 12         30 $self->{'patent'}->{'doc_type'} .= "$year-";
260             }
261             # elsif (uc($self->{'patent'}->{'doc_type'}) eq 'S') {
262             # my $year = substr($self->{'patent'}->{'number'}, 0, 2); # Heisei < 10 must have 0 prefix
263             # $self->{'patent'}->{'number'} =~ s{^\d\d}{}xm;
264             # $self->{'patent'}->{'doc_type'} .= "$year-";
265             # }
266             # elsif (uc($self->{'patent'}->{'doc_type'}) eq 'T') {
267             # my $year = substr($self->{'patent'}->{'number'}, 0, 2); # Heisei < 10 must have 0 prefix
268             # $self->{'patent'}->{'number'} =~ s{^\d\d}{}xm;
269             # $self->{'patent'}->{'doc_type'} = "$year-";
270             # }
271             # elsif (uc($self->{'patent'}->{'doc_type'}) eq 'M') {
272             # my $year = substr($self->{'patent'}->{'number'}, 0, 2); # Heisei < 10 must have 0 prefix
273             # $self->{'patent'}->{'number'} =~ s{^\d\d}{}xm;
274             # $self->{'patent'}->{'doc_type'} .= "$year-";
275             # }
276             elsif ( (substr($self->{'patent'}->{'number'}, 3, 1) ne q(-))
277             and (length($self->{'patent'}->{'number'}) > 7)
278             and (substr($self->{'patent'}->{'number'}, 0, 4) > 1992)
279             and substr($self->{'patent'}->{'number'}, 0, 4) <= ((localtime(time))[5] + 1900))
280             {
281 5         13964 $self->{'patent'}->{'number'} =~ s{^(\d\d\d\d)}{$1-}xm;
282             }
283             }
284            
285 191         10682 $found = undef;
286 191 50       552 if (defined $self->{'patent'}->{'country'}) {
  0         0  
287 191         795 $found .= " country:$self->{'patent'}->{'country'} ";
288             }
289             else {$found .= ' country: "" ';}
290 191 100       472 if (defined $self->{'patent'}->{'doc_type'}) {
  72         124  
291 119         280 $found .= " type:$self->{'patent'}->{'doc_type'} ";
292             }
293             else {$found .= ' doc_type: "" ';}
294 191 50       623 if (defined $self->{'patent'}->{'number'}) {
  0         0  
295 191         496 $found .= " number:$self->{'patent'}->{'number'} ";
296             }
297             else {$found .= ' number: "" ';}
298 191 100       380 if (defined $self->{'patent'}->{'kind'}) {
  144         237  
299 47         89 $found .= " kind:$self->{'patent'}->{'kind'} ";
300             }
301             else {$found .= ' kind: "" ';}
302 191 50       615 if (defined $self->{'patent'}->{'comment'}) {
  0         0  
303 191         428 $found .= " comment:$self->{'patent'}->{'comment'} ";
304             }
305             else {$found .= ' comment: "" ';}
306            
307 191 100 100     1872 if ( $self->{'patent'}->{'doc_type'}
    100 100        
    100          
308             && $self->{'patent'}->{'kind'})
309             {
310 21         258 $self->{'patent'}->{'doc_id_standardized'} = $self->{'patent'}->{'country'}
311             . $self->{'patent'}->{'doc_type'}
312             . $self->{'patent'}->{'number'}
313             . $self->{'patent'}->{'kind'};
314             }
315             elsif ((!$self->{'patent'}->{'doc_type'})
316             && (!$self->{'patent'}->{'kind'}))
317             {
318 46         232 $self->{'patent'}->{'doc_id_standardized'} = $self->{'patent'}->{'country'} . $self->{'patent'}->{'number'};
319             }
320             elsif (!$self->{'patent'}->{'kind'}) {
321 98         315 $self->{'patent'}->{'doc_id_standardized'}
322             = $self->{'patent'}->{'country'} . $self->{'patent'}->{'doc_type'} . $self->{'patent'}->{'number'};
323             }
324             else {
325 26         104 $self->{'patent'}->{'doc_id_standardized'}
326             = $self->{'patent'}->{'country'} . $self->{'patent'}->{'number'} . $self->{'patent'}->{'kind'};
327             }
328 191         657 return $found;
329             }
330            
331             sub get_page {
332 23     23   3093 my $self = shift;
333 23         45 my $count;
334 23 100       134 if (@_ % 2) {
335 14         68 $self->{'patent'}->{'doc_id'} = shift @_;
336             }
337 23         121 my %passed_parm = @_;
338            
339             # Keep the patent-specific parms before USING the object.
340             # (the parameters defined above are the only user exposed parameters allowed)
341 23         130 while (my ($key, $value) = each %passed_parm) {
342 64 50       221 if (exists $self->{$key}) {
    50          
343 0         0 $self->{$key} = $value;
344             }
345             elsif (exists $self->{'patent'}->{$key}) {
346 64         238 $self->{'patent'}->{$key} = $value;
347             }
348             }
349 23 100       157 if ($self->{'patent'}->{'doc_id'}) {$self->parse_doc_id();}
  20         87  
350 23         34 my $response = WWW::Patent::Page::Response->new(%{$self->{'patent'}}); # make it here to run sanity tests
  23         4625  
351 23 100       118 if (!$response->get_parameter('country')) {
352 2         9 $response->set_parameter('is_success', undef);
353 2         5 $response->set_parameter('message', 'no country defined');
354            
355             # print "no country defined\n";
356 2         6 return $response;
357             }
358 21 50       77 if (!$_country_known{$response->get_parameter('country')}) {
359 0         0 $response->set_parameter('is_success', undef);
360 0         0 $response->set_parameter('message', q{country '} . $response->get_parameter('country') . q{' not recognized});
361            
362             # print "country not recognized";
363 0         0 return $response;
364             }
365 21 100       69 if (!$response->get_parameter('number')) {
366 1         5 $response->set_parameter('is_success', undef);
367 1         4 $response->set_parameter('message', 'no patent number defined');
368 1         3 return $response;
369             }
370 20 100       65 if (!$response->get_parameter('office')) {
371 1         5 $response->set_parameter('is_success', undef);
372 1         4 $response->set_parameter('message', 'no office defined');
373 1         4 return $response;
374             }
375 19 100       60 if (!$response->get_parameter('format')) {
376 3         8 $response->set_parameter('is_success', undef);
377 3         8 $response->set_parameter('message', 'no format defined');
378 3         10 return $response;
379             }
380 16         84 my $provide_doc = "$self->{'patent'}->{'office'}" . '_' . "$self->{'patent'}->{'format'}";
381 16 100       73 if (!exists $METHODS{$provide_doc}) {
382 2         11 $response->set_parameter('is_success', undef);
383 2         11 $response->set_parameter('message', "method '$provide_doc' not provided");
384 2         7 return $response;
385             }
386 14 50       49 my $function_reference = $METHODS{$provide_doc}
387             or carp "No method '$provide_doc'";
388            
389             # print "pass hash\n";
390 14 50       25 $response = &{$function_reference}($self, $response) # pass our hash to a specific fetcher
  14         67  
391             or carp "No response for method '$provide_doc'";
392            
393             # print "hash back\n";
394 13 50       55 if (!$response) {carp 'no response to return'}
  0         0  
395 13         101 return $response;
396             }
397            
398             sub terms {
399 2     2 1 822 my $self = shift; # pass $self, then optionally the office whose terms you need, or use that office set in $self
400 2         5 my $office;
401 2 50       1554 if (@_ % 2) {$office = shift @_}
  0         0  
  2         13  
402             else {$office = $self->{'patent'}->{'office'}}
403 2 50       29 if (!exists $METHODS{$office . '_terms'}) {
404 0         0 carp "Undefined method $office" . '_terms in Patent:Document::Retrieve';
405 0         0 return ( 'WWW::Patent::Page uses publicly available information that may be subject to copyright.' . "\n"
406             . 'The user is responsible for observing intellectual property rights. ');
407             }
408 2         7 my $terms = $office . '_terms';
409 2         5 my $function_reference = $METHODS{$terms};
410 2         4 return &{$function_reference}($self);
  2         13  
411             }
412            
413             sub request {
414             # intercept the LWP request to allow various things
415 30     30 1 66 my $self = shift;
416 30         60 my $count = 0;
417             # my $response=$HTTP::Response->new();
418 30         311 my $response = LWP::UserAgent::request($self, @_);
419 30   100     15520076 while (($count < 2) && (! $response->is_success) ) { # make $count assignable at start-up, configurable
420 2         58 $count++;
421 2 50       10 if ( $response->code == 500 ) { sleep 5; $response = LWP::UserAgent::request($self, @_); cluck 'server responded with code 500, internal server error, trying again for you in case they got their act together in the last few seconds' } # second chance
  2         10000276  
  2         27  
  2         9749  
422 2 50       4521 if ( $response->code == 503 ) { sleep 5; $response = LWP::UserAgent::request($self, @_); cluck 'server responded with code 503, Service Unavailable, trying again for you in case it became available in the last few seconds' } # second chance
  0         0  
  0         0  
  0         0  
423             }
424 30 100       752 if ( ! $response->is_success) {confess 'original url = "'.$_[0]->as_string().'", request that caused this response = "' . $response->request()->as_string.'", response code = "', $response->code(),'" = "'.$response->message.'", response as string = "'.$response->as_string. q(") ; }
  1         22  
425             # my $browser = HTML::Display->new(class => 'HTML::Display::Win32::IE',); # this will open a new window for every page of html!
426             # $browser->display(html => $response->content); # for testing to see the web pages
427 29         520 return $response;
428             }
429            
430             sub login {
431 0     0 1 0 my $self = shift; # pass $self, then optionally the office whose terms you need, or use that office set in $self
432 0   0     0 my $username = shift || $self->{'patent'}->{'office_username'};
433 0   0     0 my $password = shift || $self->{'patent'}->{'office_password'};
434 0         0 my $login = $self->{'patent'}->{'office'} . '_login';
435            
436             # print $login ;
437 0         0 my $function_reference = $METHODS{$login};
438            
439             # print $$function_reference ;
440 0         0 return &{$function_reference}($self, $username, $password);
  0         0  
441             }
442 0     0   0 sub _agent {return "WWW::Patent::Page/$WWW::Patent::Page::VERSION"}
443            
444             sub _load_modules {
445 9     9   25 my ($class, @modules) = (@_); # pass a list of the modules that will be available;
446             # add more to your call for this, for custom modules for other patent offices
447 9   33     37 my $baseclass = ref $class || $class;
448            
449             # Go to each module and use them. Also record what methods
450             # they support and enter them into the %METHODS hash.
451 9         22 foreach my $module (@modules) {
452 9         31 my $modpath = "${baseclass}::${module}";
453 9 100       46 if (!defined $MODULES{$modpath}) { # unless already visited
454             # Have to use an eval here because perl doesn't like to use strings.
455 5     5   6901 eval "use $modpath;";
  5         18  
  5         147  
  5         457  
456 5 50       36 if ($EVAL_ERROR) {carp $EVAL_ERROR}
  0         0  
457 5         21 $MODULES{$modpath} = 1;
458            
459             # Methodhash will continue method-name, function ref
460             # pairs.
461 5         31 my %methodhash = $modpath->methods;
462 5         17 my ($method, $value);
463 5         38 while (($method, $value) = each %methodhash) {
464 25         95 $METHODS{$method} = $value;
465             }
466             }
467             }
468 9         36 return;
469             }
470            
471             sub _load_country_known {
472            
473             # from HANDBOOK ON INDUSTRIAL PROPERTY INFORMATION AND DOCUMENTATION
474             # Standard ST.3
475             # see http://www.wipo.int/scit/en/standards/pdf/03-03-01.pdf
476             # these codes reflect the versions used since 1978
477             # e.g. Algeria used to be AG, which is now Antigua, and Algeria is DZ.
478             # where no conflicts exist, antiquated codes are included
479             # such as CS for Czechoslovakia along with CZ for Czech Republic
480             # and SU for Soviet Union.
481             # Conflicts exist for International Patent Institute IB
482             # and Democratic Yemen SY
483             # see below for list by country, alphabetical
484             return (
485 5     5   1431 'AE' => 'United Arab Emirates',
486             'AF' => 'Afghanistan',
487             'AG' => 'Antigua and Barbuda',
488             'AI' => 'Anguilla',
489             'AL' => 'Albania',
490             'AM' => 'Armenia',
491             'AN' => 'Netherlands Antilles',
492             'AO' => 'Angola',
493             'AP' => 'African Regional Intellectual Property Organization',
494             'AR' => 'Argentina',
495             'AT' => 'Austria',
496             'AU' => 'Australia',
497             'AW' => 'Aruba',
498             'AZ' => 'Azerbaijan',
499             'BA' => 'Bosnia and Herzegovina',
500             'BB' => 'Barbados',
501             'BD' => 'Bangladesh',
502             'BE' => 'Belgium',
503             'BF' => 'Burkina Faso',
504             'BG' => 'Bulgaria',
505             'BH' => 'Bahrain',
506             'BI' => 'Burundi',
507             'BJ' => 'Benin',
508             'BM' => 'Bermuda',
509             'BN' => 'Brunei Darussalam',
510             'BO' => 'Bolivia',
511             'BR' => 'Brazil',
512             'BS' => 'Bahamas',
513             'BT' => 'Bhutan',
514             'BV' => 'Bouvet Island',
515             'BW' => 'Botswana',
516             'BX' => 'Benelux Trademark Office',
517             'BY' => 'Belarus',
518             'BZ' => 'Belize',
519             'CA' => 'Canada',
520             'CD' => 'Democratic Republic of the Congo',
521             'CF' => 'Central African Republic',
522             'CG' => 'Congo',
523             'CH' => 'Switzerland',
524             'CI' => 'Côte d’Ivoire',
525             'CK' => 'Cook Islands',
526             'CL' => 'Chile',
527             'CM' => 'Cameroon',
528             'CN' => 'China',
529             'CO' => 'Colombia',
530             'CR' => 'Costa Rica',
531             'CS' => 'Czechoslovakia',
532             'CU' => 'Cuba',
533             'CV' => 'Cape Verde',
534             'CY' => 'Cyprus',
535             'CZ' => 'Czech Republic',
536             'DD' => 'Germany (Democratic Republic)',
537             'DE' => 'Germany',
538             'DJ' => 'Djibouti',
539             'DK' => 'Denmark',
540             'DL' => 'Germany (Democratic Republic)',
541             'DM' => 'Dominica',
542             'DO' => 'Dominican Republic',
543             'DZ' => 'Algeria',
544             'EA' => 'Eurasian Patent Organization',
545             'EC' => 'Ecuador',
546             'EE' => 'Estonia',
547             'EG' => 'Egypt',
548             'EH' => 'Western Sahara',
549             'EM' => 'Office for Harmonization in the Internal Market',
550             'EP' => 'European Patent Office',
551             'ER' => 'Eritrea',
552             'ES' => 'Spain',
553             'ET' => 'Ethiopia',
554             'FI' => 'Finland',
555             'FJ' => 'Fiji',
556             'FK' => 'Falkland Islands (Malvinas)',
557             'FO' => 'Faroe Islands',
558             'FR' => 'France',
559             'GA' => 'Gabon',
560             'GB' => 'United Kingdom',
561             'GC' => 'Patent Office of the Cooperation Council for the Arab States of the Gulf',
562             'GD' => 'Grenada',
563             'GE' => 'Georgia',
564             'GG' => 'Guernsey',
565             'GH' => 'Ghana',
566             'GI' => 'Gibraltar',
567             'GL' => 'Greenland',
568             'GM' => 'Gambia',
569             'GN' => 'Guinea',
570             'GQ' => 'Equatorial Guinea',
571             'GR' => 'Greece',
572             'GS' => 'South Georgia and the South Sandwich Islands',
573             'GT' => 'Guatemala',
574             'GW' => 'Guinea-Bissau',
575             'GY' => 'Guyana',
576             'HK' => 'The Hong Kong Special Administrative Region of the People’s Republic of China',
577             'HN' => 'Honduras',
578             'HR' => 'Croatia',
579             'HT' => 'Haiti',
580             'HU' => 'Hungary',
581             'IB' => 'International Bureau of the World Intellectual Property Organization',
582             'ID' => 'Indonesia',
583             'IE' => 'Ireland',
584             'IL' => 'Israel',
585             'IM' => 'Isle of Man',
586             'IN' => 'India',
587             'IQ' => 'Iraq',
588             'IR' => 'Iran (Islamic Republic of)',
589             'IS' => 'Iceland',
590             'IT' => 'Italy',
591             'JE' => 'Jersey',
592             'JM' => 'Jamaica',
593             'JO' => 'Jordan',
594             'JP' => 'Japan',
595             'KE' => 'Kenya',
596             'KG' => 'Kyrgyzstan',
597             'KH' => 'Cambodia',
598             'KI' => 'Kiribati',
599             'KM' => 'Comoros',
600             'KN' => 'Saint Kitts and Nevis',
601             'KP' => 'Democratic People’s Republic of Korea',
602             'KR' => 'Republic of Korea',
603             'KW' => 'Kuwait',
604             'KY' => 'Cayman Islands',
605             'KZ' => 'Kazakhstan',
606             'LA' => 'Lao People’s Democratic Republic',
607             'LB' => 'Lebanon',
608             'LC' => 'Saint Lucia',
609             'LI' => 'Liechtenstein',
610             'LK' => 'Sri Lanka',
611             'LR' => 'Liberia',
612             'LS' => 'Lesotho',
613             'LT' => 'Lithuania',
614             'LU' => 'Luxembourg',
615             'LV' => 'Latvia',
616             'LY' => 'Libyan Arab Jamahiriya',
617             'MA' => 'Morocco',
618             'MC' => 'Monaco',
619             'MD' => 'Republic of Moldova',
620             'ME' => 'Montenegro',
621             'MG' => 'Madagascar',
622             'MK' => 'The former Yugoslav Republic of Macedonia',
623             'ML' => 'Mali',
624             'MM' => 'Myanmar',
625             'MN' => 'Mongolia',
626             'MO' => 'Macao',
627             'MP' => 'Northern Mariana Islands',
628             'MR' => 'Mauritania',
629             'MS' => 'Montserrat',
630             'MT' => 'Malta',
631             'MU' => 'Mauritius',
632             'MV' => 'Maldives',
633             'MW' => 'Malawi',
634             'MX' => 'Mexico',
635             'MY' => 'Malaysia',
636             'MZ' => 'Mozambique',
637             'NA' => 'Namibia',
638             'NE' => 'Niger',
639             'NG' => 'Nigeria',
640             'NI' => 'Nicaragua',
641             'NL' => 'Netherlands',
642             'NO' => 'Norway',
643             'NP' => 'Nepal',
644             'NR' => 'Nauru',
645             'NZ' => 'New Zealand',
646             'OA' => 'African Intellectual Property Organization',
647             'OM' => 'Oman',
648             'PA' => 'Panama',
649             'PE' => 'Peru',
650             'PG' => 'Papua New Guinea',
651             'PH' => 'Philippines',
652             'PK' => 'Pakistan',
653             'PL' => 'Poland',
654             'PT' => 'Portugal',
655             'PW' => 'Palau',
656             'PY' => 'Paraguay',
657             'QA' => 'Qatar',
658             'QZ' => 'Community Plant Variety Office (European Community) (CPVO)',
659             'RO' => 'Romania',
660             'RS' => 'Serbia',
661             'RU' => 'Russian Federation',
662             'RW' => 'Rwanda',
663             'SA' => 'Saudi Arabia',
664             'SB' => 'Solomon Islands',
665             'SC' => 'Seychelles',
666             'SD' => 'Sudan',
667             'SE' => 'Sweden',
668             'SG' => 'Singapore',
669             'SH' => 'Saint Helena',
670             'SI' => 'Slovenia',
671             'SK' => 'Slovakia',
672             'SL' => 'Sierra Leone',
673             'SM' => 'San Marino',
674             'SN' => 'Senegal',
675             'SO' => 'Somalia',
676             'SR' => 'Suriname',
677             'ST' => 'Sao Tome and Principe',
678             'SU' => 'Soviet Union',
679             'SV' => 'El Salvador',
680             'SY' => 'Syrian Arab Republic',
681             'SZ' => 'Swaziland',
682             'TC' => 'Turks and Caicos Islands',
683             'TD' => 'Chad',
684             'TG' => 'Togo',
685             'TH' => 'Thailand',
686             'TJ' => 'Tajikistan',
687             'TL' => 'Timor–Leste',
688             'TM' => 'Turkmenistan',
689             'TN' => 'Tunisia',
690             'TO' => 'Tonga',
691             'TR' => 'Turkey',
692             'TT' => 'Trinidad and Tobago',
693             'TV' => 'Tuvalu',
694             'TW' => 'Taiwan, Province of China',
695             'TZ' => 'United Republic of Tanzania',
696             'UA' => 'Ukraine',
697             'UG' => 'Uganda',
698             'US' => 'United States of America',
699             'UY' => 'Uruguay',
700             'UZ' => 'Uzbekistan',
701             'VA' => 'Holy See',
702             'VC' => 'Saint Vincent and the Grenadines',
703             'VE' => 'Venezuela',
704             'VG' => 'Virgin Islands (British)',
705             'VN' => 'Viet Nam',
706             'VU' => 'Vanuatu',
707             'WO' => 'World Intellectual Property Organization',
708             'WS' => 'Samoa',
709             'YD' => 'Yemen (Democratic)',
710             'YE' => 'Yemen',
711             'ZA' => 'South Africa',
712             'ZM' => 'Zambia',
713             'ZW' => 'Zimbabwe',
714             );
715            
716             # alphabetical by country
717             # Afghanistan _ AF
718             # African Intellectual Property Organization _ OA
719             # African Regional Intellectual Property Organization _ AP
720             # Albania _ AL
721             # Algeria _ DZ
722             # Angola _ AO
723             # Anguilla _ AI
724             # Antigua and Barbuda _ AG
725             # Argentina _ AR
726             # Armenia _ AM
727             # Aruba _ AW
728             # Australia _ AU
729             # Austria _ AT
730             # Azerbaijan _ AZ
731             # Bahamas _ BS
732             # Bahrain _ BH
733             # Bangladesh _ BD
734             # Barbados _ BB
735             # Belarus _ BY
736             # Belgium _ BE
737             # Belize _ BZ
738             # Benelux Trademark Office _ BX
739             # Benin _ BJ
740             # Bermuda _ BM
741             # Bhutan _ BT
742             # Bolivia _ BO
743             # Bosnia and Herzegovina _ BA
744             # Botswana _ BW
745             # Bouvet Island _ BV
746             # Brazil _ BR
747             # Brunei Darussalam _ BN
748             # Bulgaria _ BG
749             # Burkina Faso _ BF
750             # Burundi _ BI
751             # Cambodia _ KH
752             # Cameroon _ CM
753             # Canada _ CA
754             # Cape Verde _ CV
755             # Cayman Islands _ KY
756             # Central African Republic _ CF
757             # Chad _ TD
758             # Chile _ CL
759             # China _ CN
760             # Colombia _ CO
761             # Community Plant Variety Office (European Community) (CPVO) _ QZ
762             # Comoros _ KM
763             # Congo _ CG
764             # Cook Islands _ CK
765             # Costa Rica _ CR
766             # Croatia _ HR
767             # Cuba _ CU
768             # Cyprus _ CY
769             # Czech Republic _ CZ
770             # Czechoslovakia _ CS
771             # Côte d’Ivoire _ CI
772             # Democratic People’s Republic of Korea _ KP
773             # Democratic Republic of the Congo _ CD
774             # Denmark _ DK
775             # Djibouti _ DJ
776             # Dominica _ DM
777             # Dominican Republic _ DO
778             # Ecuador _ EC
779             # Egypt _ EG
780             # El Salvador _ SV
781             # Equatorial Guinea _ GQ
782             # Eritrea _ ER
783             # Estonia _ EE
784             # Ethiopia _ ET
785             # Eurasian Patent Organization _ EA
786             # European Patent Office _ EP
787             # Falkland Islands (Malvinas) _ FK
788             # Faroe Islands _ FO
789             # Fiji _ FJ
790             # Finland _ FI
791             # France _ FR
792             # Gabon _ GA
793             # Gambia _ GM
794             # Georgia _ GE
795             # Germany _ DE
796             # Germany (Democratic Republic) _ DD
797             # Germany (Democratic Republic) _ DL
798             # Ghana _ GH
799             # Gibraltar _ GI
800             # Greece _ GR
801             # Greenland _ GL
802             # Grenada _ GD
803             # Guatemala _ GT
804             # Guernsey _ GG
805             # Guinea _ GN
806             # Guinea-Bissau _ GW
807             # Guyana _ GY
808             # Haiti _ HT
809             # Holy See _ VA
810             # Honduras _ HN
811             # Hungary _ HU
812             # Iceland _ IS
813             # India _ IN
814             # Indonesia _ ID
815             # International Bureau of the World Intellectual Property Organization _ IB
816             # Iran (Islamic Republic of) _ IR
817             # Iraq _ IQ
818             # Ireland _ IE
819             # Isle of Man _ IM
820             # Israel _ IL
821             # Italy _ IT
822             # Jamaica _ JM
823             # Japan _ JP
824             # Jersey _ JE
825             # Jordan _ JO
826             # Kazakhstan _ KZ
827             # Kenya _ KE
828             # Kiribati _ KI
829             # Kuwait _ KW
830             # Kyrgyzstan _ KG
831             # Lao People’s Democratic Republic _ LA
832             # Latvia _ LV
833             # Lebanon _ LB
834             # Lesotho _ LS
835             # Liberia _ LR
836             # Libyan Arab Jamahiriya _ LY
837             # Liechtenstein _ LI
838             # Lithuania _ LT
839             # Luxembourg _ LU
840             # Macao _ MO
841             # Madagascar _ MG
842             # Malawi _ MW
843             # Malaysia _ MY
844             # Maldives _ MV
845             # Mali _ ML
846             # Malta _ MT
847             # Mauritania _ MR
848             # Mauritius _ MU
849             # Mexico _ MX
850             # Monaco _ MC
851             # Mongolia _ MN
852             # Montenegro _ ME
853             # Montserrat _ MS
854             # Morocco _ MA
855             # Mozambique _ MZ
856             # Myanmar _ MM
857             # Namibia _ NA
858             # Nauru _ NR
859             # Nepal _ NP
860             # Netherlands _ NL
861             # Netherlands Antilles _ AN
862             # New Zealand _ NZ
863             # Nicaragua _ NI
864             # Niger _ NE
865             # Nigeria _ NG
866             # Northern Mariana Islands _ MP
867             # Norway _ NO
868             # Office for Harmonization in the Internal Market _ EM
869             # Oman _ OM
870             # Pakistan _ PK
871             # Palau _ PW
872             # Panama _ PA
873             # Papua New Guinea _ PG
874             # Paraguay _ PY
875             # Patent Office of the Cooperation Council for the Arab States of the Gulf _ GC
876             # Peru _ PE
877             # Philippines _ PH
878             # Poland _ PL
879             # Portugal _ PT
880             # Qatar _ QA
881             # Republic of Korea _ KR
882             # Republic of Moldova _ MD
883             # Romania _ RO
884             # Russian Federation _ RU
885             # Rwanda _ RW
886             # Saint Helena _ SH
887             # Saint Kitts and Nevis _ KN
888             # Saint Lucia _ LC
889             # Saint Vincent and the Grenadines _ VC
890             # Samoa _ WS
891             # San Marino _ SM
892             # Sao Tome and Principe _ ST
893             # Saudi Arabia _ SA
894             # Senegal _ SN
895             # Serbia _ RS
896             # Seychelles _ SC
897             # Sierra Leone _ SL
898             # Singapore _ SG
899             # Slovakia _ SK
900             # Slovenia _ SI
901             # Solomon Islands _ SB
902             # Somalia _ SO
903             # South Africa _ ZA
904             # South Georgia and the South Sandwich Islands _ GS
905             # Soviet Union _ SU
906             # Spain _ ES
907             # Sri Lanka _ LK
908             # Sudan _ SD
909             # Suriname _ SR
910             # Swaziland _ SZ
911             # Sweden _ SE
912             # Switzerland _ CH
913             # Syrian Arab Republic _ SY
914             # Taiwan, Province of China _ TW
915             # Tajikistan _ TJ
916             # Thailand _ TH
917             # The Hong Kong Special Administrative Region of the People’s Republic of China _ HK
918             # The former Yugoslav Republic of Macedonia _ MK
919             # Timor–Leste _ TL
920             # Togo _ TG
921             # Tonga _ TO
922             # Trinidad and Tobago _ TT
923             # Tunisia _ TN
924             # Turkey _ TR
925             # Turkmenistan _ TM
926             # Turks and Caicos Islands _ TC
927             # Tuvalu _ TV
928             # Uganda _ UG
929             # Ukraine _ UA
930             # United Arab Emirates _ AE
931             # United Kingdom _ GB
932             # United Republic of Tanzania _ TZ
933             # United States of America _ US
934             # Uruguay _ UY
935             # Uzbekistan _ UZ
936             # Vanuatu _ VU
937             # Venezuela _ VE
938             # Viet Nam _ VN
939             # Virgin Islands (British) _ VG
940             # Western Sahara _ EH
941             # World Intellectual Property Organization _ WO
942             # Yemen _ YE
943             # Yemen (Democratic) _ YD
944             # Zambia _ ZM
945             # Zimbabwe _ ZW
946            
947             }
948            
949             1; #this line is important and will help the module return a true value
950             __END__