1package Biber::Section;
2use v5.16;
3use strict;
4use warnings;
5
6use Biber::Entries;
7use Biber::Utils;
8use List::Util qw( first );
9
10=encoding utf-8
11
12=head1 NAME
13
14Biber::Section
15
16=head2 new
17
18    Initialize a Biber::Section object
19
20=cut
21
22sub new {
23  my ($class, %params) = @_;
24  my $self = bless {%params}, $class;
25  $self->{bibentries} = new Biber::Entries;
26  $self->{keytorelclone} = {};
27  $self->{relclonetokey} = {};
28  $self->{relkeys} = {};
29  $self->{allkeys} = 0;
30  $self->{citekeys} = [];
31  $self->{citekeys_h} = {}; # For faster hash-based lookup of individual keys
32  $self->{labelcache_l} = {};
33  $self->{everykey} = {};
34  $self->{everykey_lc} = {};
35  $self->{bcfkeycache} = {};
36  $self->{labelcache_v} = {};
37  $self->{sortcache} = [];
38  $self->{dkeys} = {};
39  $self->{keytods} = {};
40  $self->{orig_order_citekeys} = [];
41  $self->{undef_citekeys} = [];
42  $self->{citekey_alias} = {};
43  return $self;
44}
45
46=head2 reset_caches
47
48    Reset section caches which need it
49
50=cut
51
52sub reset_caches {
53  my $self = shift;
54  $self->{sortcache} = [];
55  $self->{labelcache_l} = {};
56  $self->{labelcache_v} = {};
57  $self->{bcfkeycache} = {};
58  return;
59}
60
61=head2 set_keytods
62
63  Save information about citekey->datasource name mapping. Used for error reporting.
64
65=cut
66
67sub set_keytods {
68  my ($self, $key, $ds) = @_;
69  $self->{keytods}{$key} = $ds;
70  return;
71}
72
73=head2 get_keytods
74
75  Get information about citekey->datasource name mapping. Used for error reporting.
76
77=cut
78
79sub get_keytods {
80  my ($self, $key) = @_;
81  return $self->{keytods}{$key};
82}
83
84=head2 has_badcasekey
85
86    Returns a value to say if we've seen a key differing only in case before
87    <previouskey>  - we've seen a differently cased variant of this key so we can warn about this
88    undef  - Not seen this key at all in any case variant before
89
90=cut
91
92sub has_badcasekey {
93  my ($self, $key) = @_;
94  my $ckey = $self->{everykey_lc}{lc($key)};
95  return undef unless $ckey;
96  return $ckey ne $key ? $ckey : undef;
97}
98
99
100=head2 add_related
101
102    Record that a key is used as a related entry
103
104=cut
105
106sub add_related {
107  my ($self, $key) = @_;
108  $self->{relkeys}{$key} = 1;
109  return;
110}
111
112=head2 is_related
113
114    Check if a key is used as a related entry key
115
116=cut
117
118sub is_related {
119  my ($self, $key) = @_;
120  return $self->{relkeys}{$key};
121}
122
123
124=head2 keytorelclone
125
126    Record a key<->clone key mapping.
127
128=cut
129
130sub keytorelclone {
131  my ($self, $key, $clonekey) = @_;
132  $self->{keytorelclone}{$key} = $clonekey;
133  $self->{relclonetokey}{$clonekey} = $key;
134  return;
135}
136
137
138=head2 get_keytorelclone
139
140    Fetch a related entry clone key, given a cite key
141
142=cut
143
144sub get_keytorelclone {
145  my ($self, $key) = @_;
146  return $self->{keytorelclone}{$key};
147}
148
149=head2 get_relclonetokey
150
151    Fetch a related entry key, given a clone key
152
153=cut
154
155sub get_relclonetokey {
156  my ($self, $key) = @_;
157  return $self->{relclonetokey}{$key};
158}
159
160
161=head2 has_keytorelclone
162
163    Return boolean saying if a cite key has a related entry clone in the current section
164
165=cut
166
167sub has_keytorelclone {
168  my ($self, $key) = @_;
169  return defined($self->{keytorelclone}{$key}) ? 1 : 0;
170}
171
172=head2 has_relclonetokey
173
174    Return boolean saying if a related clone key has a citekey in the current section
175
176=cut
177
178sub has_relclonetokey {
179  my ($self, $key) = @_;
180  return defined($self->{relclonetokey}{$key}) ? 1 : 0;
181}
182
183=head2 add_everykey
184
185    Adds a datasource key to the section list of all datasource keys
186
187=cut
188
189sub add_everykey {
190  my ($self, $key) = @_;
191  $self->{everykey}{$key} = 1;
192  $self->{everykey_lc}{lc($key)} = $key;
193  return;
194}
195
196=head2 del_everykeys
197
198  Delete everykey cache. For use in tests.
199
200=cut
201
202sub del_everykeys {
203  my $self = shift;
204  $self->{everykey} = undef
205  $self->{everykey_lc} = undef;
206  return;
207}
208
209=head2 has_everykey
210
211    Returns a boolean to say if we've seen a key in any datasource for this section.
212    This used to be an array ref which was checked using first() and it
213    was twenty times slower.
214
215=cut
216
217sub has_everykey {
218  my ($self, $key) = @_;
219  return $self->{everykey}{$key} ? 1 : 0;
220}
221
222
223=head2 set_allkeys
224
225    Sets flag to say citekey '*' occurred in citekeys
226    We allow setting it to false too because it's useful in tests
227
228=cut
229
230sub set_allkeys {
231  my ($self, $val) = @_;
232  $self->{allkeys} = $val;
233  return;
234}
235
236=head2 is_allkeys
237
238    Checks flag which says citekey '*' occurred in citekeys
239
240=cut
241
242sub is_allkeys {
243  my $self = shift;
244  return $self->{allkeys};
245}
246
247
248=head2 bibentry
249
250    Returns a Biber::Entry object for the given citation key
251    Understands citekey aliases
252
253=cut
254
255sub bibentry {
256  my ($self, $key) = @_;
257  if (my $realkey = $self->get_citekey_alias($key)) {
258    return $self->bibentries->entry($realkey);
259  }
260  else {
261    return $self->bibentries->entry($key);
262  }
263}
264
265=head2 bibentries
266
267    Return Biber::Entries object for this section
268
269=cut
270
271sub bibentries {
272  my $self = shift;
273  return $self->{bibentries};
274}
275
276=head2 del_bibentries
277
278    Delete all Biber::Entry objects from the Biber::Section object
279
280=cut
281
282sub del_bibentries {
283  my $self = shift;
284  $self->{bibentries} = new Biber::Entries;
285  return;
286}
287
288
289=head2 set_citekeys
290
291    Sets the citekeys in a Biber::Section object
292
293=cut
294
295sub set_citekeys {
296  my $self = shift;
297  my $keys = shift;
298  map { $self->{citekeys_h}{$_} = 1} @$keys;
299  $self->{citekeys} = $keys;
300  return;
301}
302
303=head2 set_orig_order_citekeys
304
305    Sets the original order of citekeys in a Biber::Section object
306
307=cut
308
309sub set_orig_order_citekeys {
310  my $self = shift;
311  my $keys = shift;
312  $self->{orig_order_citekeys} = $keys;
313  return;
314}
315
316
317=head2 get_citekeys
318
319    Gets the citekeys of a Biber::Section object
320    Returns a normal array
321
322=cut
323
324sub get_citekeys {
325  my $self = shift;
326  return @{$self->{citekeys}};
327}
328
329=head2 get_static_citekeys
330
331    Gets the citekeys of a Biber::Section object
332    excluding dynamic set entry keys
333    Returns a normal array
334
335=cut
336
337sub get_static_citekeys {
338  my $self = shift;
339  return reduce_array($self->{citekeys}, $self->dynamic_set_keys);
340}
341
342
343=head2 add_undef_citekey
344
345    Adds a citekey to the Biber::Section object as an undefined
346    key. This allows us to output this information to the .bbl and
347    so biblatex can do better reporting to external utils like latexmk
348
349=cut
350
351sub add_undef_citekey {
352  my $self = shift;
353  my $key = shift;
354  push @{$self->{undef_citekeys}}, $key;
355  return;
356}
357
358=head2 get_undef_citekeys
359
360    Gets the list of undefined citekeys of a Biber::Section object
361    Returns a normal array
362
363=cut
364
365sub get_undef_citekeys {
366  my $self = shift;
367  return @{$self->{undef_citekeys}};
368}
369
370=head2 get_orig_order_citekeys
371
372    Gets the citekeys of a Biber::Section object in their original order
373    This is just to ensure we have a method that will return this, just in
374    case we mess about with the order at some point. This is needed by
375    citeorder sorting.
376
377=cut
378
379sub get_orig_order_citekeys {
380  my $self = shift;
381  return @{$self->{orig_order_citekeys}};
382}
383
384=head2 has_citekey
385
386    Returns true when $key is in the Biber::Section object
387    Understands key alaises
388
389=cut
390
391sub has_citekey {
392  my $self = shift;
393  my $key = shift;
394  return $self->{citekeys_h}{$self->get_citekey_alias($key) || $key} ? 1 : 0;
395}
396
397
398=head2 del_citekey
399
400    Deletes a citekey from a Biber::Section object
401
402=cut
403
404sub del_citekey {
405  my $self = shift;
406  my $key = shift;
407  return unless $self->has_citekey($key);
408  $self->{citekeys}            = [ grep {$_ ne $key} @{$self->{citekeys}} ];
409  $self->{orig_order_citekeys} = [ grep {$_ ne $key} @{$self->{orig_order_citekeys}} ];
410  delete $self->{citekeys_h}{$key};
411  return;
412}
413
414=head2 del_citekeys
415
416    Deletes all citekeys from a Biber::Section object
417
418=cut
419
420sub del_citekeys {
421  my $self = shift;
422  $self->{citekeys}            = [];
423  $self->{citekeys_h}          = {};
424  $self->{orig_order_citekeys} = [];
425  return;
426}
427
428=head2 add_citekeys
429
430    Adds citekeys to the Biber::Section object
431
432=cut
433
434sub add_citekeys {
435  my $self = shift;
436  my @keys = @_;
437  foreach my $key (@keys) {
438    next if $self->has_citekey($key);
439    $self->{citekeys_h}{$key} = 1;
440    push @{$self->{citekeys}}, $key;
441    push @{$self->{orig_order_citekeys}}, $key;
442  }
443  return;
444}
445
446
447=head2 set_citekey_alias
448
449    Set citekey alias information
450
451=cut
452
453sub set_citekey_alias {
454  my $self = shift;
455  my ($alias, $key) = @_;
456  $self->{citekey_alias}{$alias} = $key;
457  return;
458}
459
460=head2 get_citekey_alias
461
462    Get citekey alias information
463
464=cut
465
466sub get_citekey_alias {
467  my $self = shift;
468  my $alias = shift;
469  return $self->{citekey_alias}{$alias};
470}
471
472=head2 del_citekey_alias
473
474    Delete citekey alias
475
476=cut
477
478sub del_citekey_alias {
479  my $self = shift;
480  my $alias = shift;
481  delete($self->{citekey_alias}{$alias});
482  return;
483}
484
485
486=head2 get_citekey_aliases
487
488    Get a list of all citekey aliases for the section
489
490=cut
491
492sub get_citekey_aliases {
493  my $self = shift;
494  return ( keys %{$self->{citekey_alias}} );
495}
496
497
498=head2 set_labelcache_v
499
500    Sets the variable label disambiguation cache for a field
501
502=cut
503
504sub set_labelcache_v {
505  my ($self, $field, $cache) = @_;
506  $self->{labelcache_v}{$field} = $cache;
507  return;
508}
509
510=head2 get_labelcache_v
511
512    Gets the variable label disambiguation cache for a field
513
514=cut
515
516sub get_labelcache_v {
517  my ($self, $field) = @_;
518  return $self->{labelcache_v}{$field};
519}
520
521=head2 set_labelcache_l
522
523    Sets the list label disambiguation cache for a field
524
525=cut
526
527sub set_labelcache_l {
528  my ($self, $field, $cache) = @_;
529  $self->{labelcache_l}{$field} = $cache;
530  return;
531}
532
533=head2 get_labelcache_l
534
535    Gets the list label disambiguation cache for a field
536
537=cut
538
539sub get_labelcache_l {
540  my ($self, $field) = @_;
541  return $self->{labelcache_l}{$field};
542}
543
544
545
546=head2 is_dynamic_set
547
548    Test if a key is a dynamic set
549
550=cut
551
552sub is_dynamic_set {
553  my $self = shift;
554  my $dkey = shift;
555  return defined($self->{dkeys}{$dkey}) ? 1 : 0;
556}
557
558=head2 set_dynamic_set
559
560    Record a mapping of dynamic key to member keys
561
562=cut
563
564sub set_dynamic_set {
565  my $self = shift;
566  my $dkey = shift;
567  my @members = @_;
568  $self->{dkeys}{$dkey} = \@members;
569  return;
570}
571
572=head2 get_dynamic_set
573
574    Retrieve member keys for a dynamic set key
575    Check that reference returning anything to stop spurious warnings
576    about empty dereference in return.
577
578=cut
579
580sub get_dynamic_set {
581  my $self = shift;
582  my $dkey = shift;
583  if (my $set_members = $self->{dkeys}{$dkey}) {
584    return @$set_members;
585  }
586  else {
587    return ();
588  }
589}
590
591=head2 dynamic_set_keys
592
593    Retrieve all dynamic set keys
594
595=cut
596
597sub dynamic_set_keys {
598  my $self = shift;
599  return [keys %{$self->{dkeys}}];
600}
601
602=head2 has_dynamic_sets
603
604    Returns true of false depending on whether the section has any dynamic set keys
605
606=cut
607
608sub has_dynamic_sets {
609  my $self = shift;
610  return defined($self->{dkeys}) ? 1 : 0;
611}
612
613
614=head2 add_datasource
615
616    Adds a data source to a section
617
618=cut
619
620sub add_datasource {
621  my $self = shift;
622  my $source = shift;
623  push @{$self->{datasources}}, $source;
624  return;
625}
626
627=head2 set_datasources
628
629    Sets the data sources for a section
630
631=cut
632
633sub set_datasources {
634  my $self = shift;
635  my $sources = shift;
636  $self->{datasources} = $sources;
637  return;
638}
639
640
641=head2 get_datasources
642
643    Gets an array of data sources for this section
644
645=cut
646
647sub get_datasources {
648  my $self = shift;
649  if (exists($self->{datasources})) {
650    return $self->{datasources};
651  }
652  else {
653    return undef;
654  }
655}
656
657
658=head2 add_sort_cache
659
660    Adds a scheme/keys pair to the sort cache:
661    [$scheme, $keys, $sortinitdata, $extraalphadata, $extrayeardata ]
662
663=cut
664
665sub add_sort_cache {
666  my $self = shift;
667  my $cacheitem = shift;
668  push @{$self->{sortcache}}, $cacheitem;
669  return;
670}
671
672
673=head2 get_sort_cache
674
675    Retrieves the sort cache
676
677=cut
678
679sub get_sort_cache {
680  my $self = shift;
681  return $self->{sortcache};
682}
683
684
685
686=head2 number
687
688    Gets the section number of a Biber::Section object
689
690=cut
691
692sub number {
693  my $self = shift;
694  return $self->{number};
695}
696
6971;
698
699__END__
700
701=head1 AUTHORS
702
703François Charette, C<< <firmicus at ankabut.net> >>
704Philip Kime C<< <philip at kime.org.uk> >>
705
706=head1 BUGS
707
708Please report any bugs or feature requests on our Github tracker at
709L<https://github.com/plk/biber/issues>.
710
711=head1 COPYRIGHT & LICENSE
712
713Copyright 2009-2015 François Charette and Philip Kime, all rights reserved.
714
715This module is free software.  You can redistribute it and/or
716modify it under the terms of the Artistic License 2.0.
717
718This program is distributed in the hope that it will be useful,
719but without any warranty; without even the implied warranty of
720merchantability or fitness for a particular purpose.
721
722=cut
723