Bugzilla – Attachment 7086 Details for
Bug 7284
Authority matching algorithm improvements
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 7284: Use the new linking for cataloguing
Bug-7284-Use-the-new-linking-for-cataloguing.patch (text/plain), 21.82 KB, created by
Jared Camins-Esakov
on 2012-01-07 22:33:37 UTC
(
hide
)
Description:
Bug 7284: Use the new linking for cataloguing
Filename:
MIME Type:
Creator:
Jared Camins-Esakov
Created:
2012-01-07 22:33:37 UTC
Size:
21.82 KB
patch
obsolete
>From 4e6ad5337bf77df223733254314c01426f75737c Mon Sep 17 00:00:00 2001 >From: Jared Camins-Esakov <jcamins@cpbibliography.com> >Date: Sat, 7 Jan 2012 10:37:18 -0500 >Subject: [PATCH] Bug 7284: Use the new linking for cataloguing >Content-Type: text/plain; charset="UTF-8" > >Replace the old BiblioAddAuthorities subroutines with calls into the new >C4::Linker routines. >--- > C4/Biblio.pm | 73 ++++++++++++++- > C4/Heading.pm | 13 +++ > C4/Search.pm | 101 -------------------- > acqui/addorderiso2709.pl | 4 +- > acqui/neworderempty.pl | 4 +- > cataloguing/addbiblio.pl | 91 +----------------- > .../atomicupdate/bug_7284_authority_linking_pt1 | 1 + > installer/data/mysql/sysprefs.sql | 1 + > .../en/modules/admin/preferences/authorities.pref | 8 ++ > 9 files changed, 98 insertions(+), 198 deletions(-) > >diff --git a/C4/Biblio.pm b/C4/Biblio.pm >index 7015e0a..00b7ad4 100644 >--- a/C4/Biblio.pm >+++ b/C4/Biblio.pm >@@ -115,6 +115,7 @@ BEGIN { > # To link headings in a bib record > # to authority records. > push @EXPORT, qw( >+ &BiblioAutoLink > &LinkBibHeadingsToAuthorities > ); > >@@ -458,9 +459,39 @@ sub DelBiblio { > return; > } > >+=head2 BiblioAutoLink >+ >+ my $headings_linked = BiblioAutoLink($record, $frameworkcode) >+ >+Automatically links headings in a bib record to authorities. >+ >+=cut >+ >+sub BiblioAutoLink { >+ my $record = shift; >+ my $frameworkcode = shift; >+ my ($num_headings_changed, %results); >+ >+ my $linker_module = "C4::Linker::" . (C4::Context->preference("LinkerModule") || 'Default'); >+ eval { >+ eval "require $linker_module"; >+ }; >+ if ($@){ >+ $linker_module = 'C4::Linker::Default'; >+ eval "require $linker_module"; >+ } >+ if ($@) { >+ return 0, 0; >+ } >+ >+ my $linker = $linker_module->new(); >+ my ($headings_changed, undef) = LinkBibHeadingsToAuthorities($linker, $record); >+ return $headings_changed; >+} >+ > =head2 LinkBibHeadingsToAuthorities > >- my $headings_linked = LinkBibHeadingsToAuthorities($marc); >+ my $num_headings_changed, %results = LinkBibHeadingsToAuthorities($linker, $marc); > > Links bib headings to authority records by checking > each authority-controlled field in the C<MARC::Record> >@@ -481,6 +512,7 @@ sub LinkBibHeadingsToAuthorities { > my $linker = shift; > my $bib = shift; > my %results; >+ require C4::AuthoritiesMarc; > > my $num_headings_changed = 0; > foreach my $field ( $bib->fields() ) { >@@ -504,12 +536,47 @@ sub LinkBibHeadingsToAuthorities { > $field->add_subfields( '9', $authid ); > $num_headings_changed++; > } else { >- if ( defined $current_link && C4::Context->preference('LinkerKeepStale')) { >+ if (defined $current_link && C4::Context->preference('LinkerKeepStale')) { > $results{'fuzzy'}->{$heading->display_form()}++; >- } else { >+ } elsif (C4::Context->preference('AutoCreateAuthorities')) { >+ my $authtypedata=C4::AuthoritiesMarc::GetAuthType($heading->auth_type()); >+ my $marcrecordauth=MARC::Record->new(); >+ if (C4::Context->preference('marcflavour') eq 'MARC21') { >+ $marcrecordauth->leader(' nz a22 o 4500'); >+ SetMarcUnicodeFlag($marcrecordauth, 'MARC21'); >+ } >+ my $authfield=MARC::Field->new($authtypedata->{auth_tag_to_report},'','',"a"=>"".$field->subfield('a')); >+ map { $authfield->add_subfields($_->[0]=>$_->[1]) if ($_->[0]=~/[A-z]/ && $_->[0] ne "a" )} $field->subfields(); >+ $marcrecordauth->insert_fields_ordered($authfield); >+ >+# bug 2317: ensure new authority knows it's using UTF-8; currently >+# only need to do this for MARC21, as MARC::Record->as_xml_record() handles >+# automatically for UNIMARC (by not transcoding) >+# FIXME: AddAuthority() instead should simply explicitly require that the MARC::Record >+# use UTF-8, but as of 2008-08-05, did not want to introduce that kind >+# of change to a core API just before the 3.0 release. >+ >+ if (C4::Context->preference('marcflavour') eq 'MARC21') { >+ $marcrecordauth->insert_fields_ordered(MARC::Field->new('667','','','a'=>"Machine generated authority record.")); >+ my $cite = $bib->author() . ", " . $bib->title_proper() . ", " . $bib->publication_date() . " "; >+ $cite =~ s/^[\s\,]*//; >+ $cite =~ s/[\s\,]*$//; >+ $cite = "Work cat.: (" . C4::Context->preference('MARCOrgCode') . ")". $bib->subfield('999','c') . ": " . $cite; >+ $marcrecordauth->insert_fields_ordered(MARC::Field->new('670','','','a'=>$cite)); >+ } >+ >+# warn "AUTH RECORD ADDED : ".$marcrecordauth->as_formatted; >+ >+ $authid=C4::AuthoritiesMarc::AddAuthority($marcrecordauth,'',$heading->auth_type()); >+ $field->add_subfields( '9', $authid ); >+ $num_headings_changed++; >+ $results{'added'}->{$heading->display_form()}++; >+ } elsif (defined $current_link) { > $field->delete_subfield( code => '9' ); > $num_headings_changed++; > $results{'unlinked'}->{$heading->display_form()}++; >+ } else { >+ $results{'unlinked'}->{$heading->display_form()}++; > } > } > >diff --git a/C4/Heading.pm b/C4/Heading.pm >index f9f3156..a51f9aa 100644 >--- a/C4/Heading.pm >+++ b/C4/Heading.pm >@@ -84,6 +84,19 @@ sub new_from_bib_field { > return $self; > } > >+=head2 auth_type >+ >+ my $auth_type = $heading->auth_type(); >+ >+Return the auth_type of the heading. >+ >+=cut >+ >+sub auth_type { >+ my $self = shift; >+ return $self->{'auth_type'}; >+} >+ > =head2 field > > my $field = $heading->field(); >diff --git a/C4/Search.pm b/C4/Search.pm >index 4a8de5c..ba132be 100644 >--- a/C4/Search.pm >+++ b/C4/Search.pm >@@ -68,9 +68,7 @@ This module provides searching functions for Koha's bibliographic databases > &NZgetRecords > &AddSearchHistory > &GetDistinctValues >- &BiblioAddAuthorities > ); >-#FIXME: i had to add BiblioAddAuthorities here because in Biblios.pm it caused circular dependencies (C4::Search uses C4::Biblio, and BiblioAddAuthorities uses SimpleSearch from C4::Search) > > # make all your functions, whether exported or not; > >@@ -2638,105 +2636,6 @@ sub z3950_search_args { > return $array; > } > >-=head2 BiblioAddAuthorities >- >-( $countlinked, $countcreated ) = BiblioAddAuthorities($record, $frameworkcode); >- >-this function finds the authorities linked to the biblio >- * search in the authority DB for the same authid (in $9 of the biblio) >- * search in the authority DB for the same 001 (in $3 of the biblio in UNIMARC) >- * search in the authority DB for the same values (exactly) (in all subfields of the biblio) >-OR adds a new authority record >- >-=over 2 >- >-=item C<input arg:> >- >- * $record is the MARC record in question (marc blob) >- * $frameworkcode is the bibliographic framework to use (if it is "" it uses the default framework) >- >-=item C<Output arg:> >- >- * $countlinked is the number of authorities records that are linked to this authority >- * $countcreated >- >-=item C<BUGS> >- * I had to add this to Search.pm (instead of the logical Biblio.pm) because of a circular dependency (this sub uses SimpleSearch, and Search.pm uses Biblio.pm) >- >-=back >- >-=cut >- >- >-sub BiblioAddAuthorities{ >- my ( $record, $frameworkcode ) = @_; >- my $dbh=C4::Context->dbh; >- my $query=$dbh->prepare(qq| >-SELECT authtypecode,tagfield >-FROM marc_subfield_structure >-WHERE frameworkcode=? >-AND (authtypecode IS NOT NULL AND authtypecode<>\"\")|); >-# SELECT authtypecode,tagfield >-# FROM marc_subfield_structure >-# WHERE frameworkcode=? >-# AND (authtypecode IS NOT NULL OR authtypecode<>\"\")|); >- $query->execute($frameworkcode); >- my ($countcreated,$countlinked); >- while (my $data=$query->fetchrow_hashref){ >- foreach my $field ($record->field($data->{tagfield})){ >- next if ($field->subfield('3')||$field->subfield('9')); >- # No authorities id in the tag. >- # Search if there is any authorities to link to. >- my $query='at='.$data->{authtypecode}.' '; >- map {$query.= ' and he,ext="'.$_->[1].'"' if ($_->[0]=~/[A-z]/)} $field->subfields(); >- my ($error, $results, $total_hits)=SimpleSearch( $query, undef, undef, [ "authorityserver" ] ); >- # there is only 1 result >- if ( $error ) { >- warn "BIBLIOADDSAUTHORITIES: $error"; >- return (0,0) ; >- } >- if ( @{$results} == 1 ) { >- my $marcrecord = MARC::File::USMARC::decode($results->[0]); >- $field->add_subfields('9'=>$marcrecord->field('001')->data); >- $countlinked++; >- } elsif ( @{$results} > 1 ) { >- #More than One result >- #This can comes out of a lack of a subfield. >-# my $marcrecord = MARC::File::USMARC::decode($results->[0]); >-# $record->field($data->{tagfield})->add_subfields('9'=>$marcrecord->field('001')->data); >- $countlinked++; >- } else { >- #There are no results, build authority record, add it to Authorities, get authid and add it to 9 >- ###NOTICE : This is only valid if a subfield is linked to one and only one authtypecode >- ###NOTICE : This can be a problem. We should also look into other types and rejected forms. >- my $authtypedata=C4::AuthoritiesMarc::GetAuthType($data->{authtypecode}); >- next unless $authtypedata; >- my $marcrecordauth=MARC::Record->new(); >- my $authfield=MARC::Field->new($authtypedata->{auth_tag_to_report},'','',"a"=>"".$field->subfield('a')); >- map { $authfield->add_subfields($_->[0]=>$_->[1]) if ($_->[0]=~/[A-z]/ && $_->[0] ne "a" )} $field->subfields(); >- $marcrecordauth->insert_fields_ordered($authfield); >- >- # bug 2317: ensure new authority knows it's using UTF-8; currently >- # only need to do this for MARC21, as MARC::Record->as_xml_record() handles >- # automatically for UNIMARC (by not transcoding) >- # FIXME: AddAuthority() instead should simply explicitly require that the MARC::Record >- # use UTF-8, but as of 2008-08-05, did not want to introduce that kind >- # of change to a core API just before the 3.0 release. >- if (C4::Context->preference('marcflavour') eq 'MARC21') { >- SetMarcUnicodeFlag($marcrecordauth, 'MARC21'); >- } >- >-# warn "AUTH RECORD ADDED : ".$marcrecordauth->as_formatted; >- >- my $authid=AddAuthority($marcrecordauth,'',$data->{authtypecode}); >- $countcreated++; >- $field->add_subfields('9'=>$authid); >- } >- } >- } >- return ($countlinked,$countcreated); >-} >- > =head2 GetDistinctValues($field); > > C<$field> is a reference to the fields array >diff --git a/acqui/addorderiso2709.pl b/acqui/addorderiso2709.pl >index bbfd3b7..660d633 100755 >--- a/acqui/addorderiso2709.pl >+++ b/acqui/addorderiso2709.pl >@@ -33,7 +33,7 @@ use C4::Input; > use C4::Output; > use C4::ImportBatch; > use C4::Matcher; >-use C4::Search qw/FindDuplicate BiblioAddAuthorities/; >+use C4::Search qw/FindDuplicate/; > use C4::Acquisition; > use C4::Biblio; > use C4::Items; >@@ -183,7 +183,7 @@ if ($op eq ""){ > SetImportRecordStatus( $biblio->{'import_record_id'}, 'imported' ); > # 2nd add authorities if applicable > if (C4::Context->preference("BiblioAddsAuthorities")){ >- my ($countlinked,$countcreated)=BiblioAddAuthorities($marcrecord, $cgiparams->{'frameworkcode'}); >+ my $headings_linked =BiblioAutoLink($marcrecord, $cgiparams->{'frameworkcode'}); > } > } else { > SetImportRecordStatus( $biblio->{'import_record_id'}, 'imported' ); >diff --git a/acqui/neworderempty.pl b/acqui/neworderempty.pl >index 459dfe8..ba856b2 100755 >--- a/acqui/neworderempty.pl >+++ b/acqui/neworderempty.pl >@@ -86,7 +86,7 @@ use C4::Input; > use C4::Koha; > use C4::Branch; # GetBranches > use C4::Members; >-use C4::Search qw/FindDuplicate BiblioAddAuthorities/; >+use C4::Search qw/FindDuplicate/; > > #needed for z3950 import: > use C4::ImportBatch qw/GetImportRecordMarc SetImportRecordStatus/; >@@ -148,7 +148,7 @@ if ( $ordernumber eq '' and defined $params->{'breedingid'}){ > } > #from this point: add a new record > if (C4::Context->preference("BiblioAddsAuthorities")){ >- my ($countlinked,$countcreated)=BiblioAddAuthorities($marcrecord, $params->{'frameworkcode'}); >+ my $headings_linked=BiblioAutoLink($marcrecord, $params->{'frameworkcode'}); > } > my $bibitemnum; > $params->{'frameworkcode'} or $params->{'frameworkcode'} = ""; >diff --git a/cataloguing/addbiblio.pl b/cataloguing/addbiblio.pl >index 71d43d7..e602bf8 100755 >--- a/cataloguing/addbiblio.pl >+++ b/cataloguing/addbiblio.pl >@@ -736,95 +736,6 @@ sub build_tabs { > $template->param( BIG_LOOP => \@BIG_LOOP ); > } > >-# >-# sub that tries to find authorities linked to the biblio >-# the sub : >-# - search in the authority DB for the same authid (in $9 of the biblio) >-# - search in the authority DB for the same 001 (in $3 of the biblio in UNIMARC) >-# - search in the authority DB for the same values (exactly) (in all subfields of the biblio) >-# if the authority is found, the biblio is modified accordingly to be connected to the authority. >-# if the authority is not found, it's added, and the biblio is then modified to be connected to the authority. >-# >- >-sub BiblioAddAuthorities{ >- my ( $record, $frameworkcode ) = @_; >- my $dbh=C4::Context->dbh; >- my $query=$dbh->prepare(qq| >-SELECT authtypecode,tagfield >-FROM marc_subfield_structure >-WHERE frameworkcode=? >-AND (authtypecode IS NOT NULL AND authtypecode<>\"\")|); >-# SELECT authtypecode,tagfield >-# FROM marc_subfield_structure >-# WHERE frameworkcode=? >-# AND (authtypecode IS NOT NULL OR authtypecode<>\"\")|); >- $query->execute($frameworkcode); >- my ($countcreated,$countlinked); >- while (my $data=$query->fetchrow_hashref){ >- foreach my $field ($record->field($data->{tagfield})){ >- next if ($field->subfield('3') || $field->subfield('9')); >- # No authorities id in the tag. >- # Search if there is any authorities to link to. >- my $query='at='.$data->{authtypecode}.' '; >- map {$query.= ' and he,ext="'.$_->[1].'"' if ($_->[0]=~/[A-z]/)} $field->subfields(); >- my ($error, $results, $total_hits)=SimpleSearch( $query, undef, undef, [ "authorityserver" ] ); >- # there is only 1 result >- if ( $error ) { >- warn "BIBLIOADDSAUTHORITIES: $error"; >- return (0,0) ; >- } >- if ( @{$results} == 1) { >- my $marcrecord = MARC::File::USMARC::decode($results->[0]); >- $field->add_subfields('9'=>$marcrecord->field('001')->data); >- $countlinked++; >- } elsif (@{$results} > 1) { >- #More than One result >- #This can comes out of a lack of a subfield. >-# my $marcrecord = MARC::File::USMARC::decode($results->[0]); >-# $record->field($data->{tagfield})->add_subfields('9'=>$marcrecord->field('001')->data); >- $countlinked++; >- } else { >- #There are no results, build authority record, add it to Authorities, get authid and add it to 9 >- ###NOTICE : This is only valid if a subfield is linked to one and only one authtypecode >- ###NOTICE : This can be a problem. We should also look into other types and rejected forms. >- my $authtypedata=GetAuthType($data->{authtypecode}); >- next unless $authtypedata; >- my $marcrecordauth=MARC::Record->new(); >- if (C4::Context->preference('marcflavour') eq 'MARC21') { >- $marcrecordauth->leader(' nz a22 o 4500'); >- SetMarcUnicodeFlag($marcrecordauth, 'MARC21'); >- } >- my $authfield=MARC::Field->new($authtypedata->{auth_tag_to_report},'','',"a"=>"".$field->subfield('a')); >- map { $authfield->add_subfields($_->[0]=>$_->[1]) if ($_->[0]=~/[A-z]/ && $_->[0] ne "a" )} $field->subfields(); >- $marcrecordauth->insert_fields_ordered($authfield); >- >- # bug 2317: ensure new authority knows it's using UTF-8; currently >- # only need to do this for MARC21, as MARC::Record->as_xml_record() handles >- # automatically for UNIMARC (by not transcoding) >- # FIXME: AddAuthority() instead should simply explicitly require that the MARC::Record >- # use UTF-8, but as of 2008-08-05, did not want to introduce that kind >- # of change to a core API just before the 3.0 release. >- >- if (C4::Context->preference('marcflavour') eq 'MARC21') { >- $marcrecordauth->insert_fields_ordered(MARC::Field->new('667','','','a'=>"Machine generated authority record.")); >- my $cite = $record->author() . ", " . $record->title_proper() . ", " . $record->publication_date() . " "; >- $cite =~ s/^[\s\,]*//; >- $cite =~ s/[\s\,]*$//; >- $cite = "Work cat.: (" . C4::Context->preference('MARCOrgCode') . ")". $record->subfield('999','c') . ": " . $cite; >- $marcrecordauth->insert_fields_ordered(MARC::Field->new('670','','','a'=>$cite)); >- } >- >-# warn "AUTH RECORD ADDED : ".$marcrecordauth->as_formatted; >- >- my $authid=AddAuthority($marcrecordauth,'',$data->{authtypecode}); >- $countcreated++; >- $field->add_subfields('9'=>$authid); >- } >- } >- } >- return ($countlinked,$countcreated); >-} >- > # ======================== > # MAIN > #========================= >@@ -957,7 +868,7 @@ if ( $op eq "addbiblio" ) { > my $oldbibnum; > my $oldbibitemnum; > if (C4::Context->preference("BiblioAddsAuthorities")){ >- my ($countlinked,$countcreated)=BiblioAddAuthorities($record,$frameworkcode); >+ my ($countlinked,$countcreated)=BiblioAutoLink($record,$frameworkcode); > } > if ( $is_a_modif ) { > ModBiblioframework( $biblionumber, $frameworkcode ); >diff --git a/installer/data/mysql/atomicupdate/bug_7284_authority_linking_pt1 b/installer/data/mysql/atomicupdate/bug_7284_authority_linking_pt1 >index ca9a940..c2b95d9 100644 >--- a/installer/data/mysql/atomicupdate/bug_7284_authority_linking_pt1 >+++ b/installer/data/mysql/atomicupdate/bug_7284_authority_linking_pt1 >@@ -6,4 +6,5 @@ my $dbh=C4::Context->dbh; > $dbh->do("INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerModule','Default','Chooses which linker module to use (see documentation).','Default|FirstMatchLastMatch','Choice');"); > $dbh->do("INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerRelink',1,'If ON the authority linker will relink headings that have previously been linked every time it runs.',NULL,'YesNo');"); > $dbh->do("INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerKeepStale',0,'If ON the authority linker will keep existing authority links for headings where it is unable to find a match.',NULL,'YesNo');"); >+$dbh->do("INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('AutoCreateAuthorities',0,'Automatically create authorities that do not exist when cataloging records.',NULL,'YesNo');"); > print "Upgrade done (Configured bug 7284, improved authority matching)\n"; >diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql >index 49a62e1..8b961e6 100755 >--- a/installer/data/mysql/sysprefs.sql >+++ b/installer/data/mysql/sysprefs.sql >@@ -330,6 +330,7 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES > INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('EasyAnalyticalRecords','0','If on, display in the catalogue screens tools to easily setup analytical record relationships','','YesNo'); > INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacShowRecentComments',0,'If ON a link to recent comments will appear in the OPAC masthead',NULL,'YesNo'); > INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('CircAutoPrintQuickSlip', '1', 'Choose what should happen when an empty barcode field is submitted in circulation: Display a print quick slip window or Clear the screen.',NULL,'YesNo'); >+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('AutoCreateAuthorities',0,'Automatically create authorities that do not exist when cataloging records.',NULL,'YesNo'); > INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerModule','Default','Chooses which linker module to use (see documentation).','Default|FirstMatch|LastMatch','Choice'); > INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerRelink',1,'If ON the authority linker will relink headings that have previously been linked every time it runs.',NULL,'YesNo'); > INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerKeepStale',0,'If ON the authority linker will keep existing authority links for headings where it is unable to find a match.',NULL,'YesNo'); >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/authorities.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/authorities.pref >index 60a6b5d..8b36122 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/authorities.pref >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/authorities.pref >@@ -9,6 +9,14 @@ Authorities: > no: "don't allow" > - them to automatically create new authority records if needed, rather than having to reference existing authorities. > - >+ - When editing records, >+ - pref: AutoCreateAuthorities >+ default: yes >+ choices: >+ yes: generate >+ no: "do not generate" >+ - authority records that are missing (BiblioAddsAuthorities must be set to "allow" for this to have any effect). >+ - > - pref: dontmerge > default: yes > choices: >-- >1.7.2.5
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 7284
:
7083
|
7084
|
7085
|
7086
|
7087
|
7091
|
7266
|
7323
|
7457
|
7548
|
7688
|
7714
|
7788
|
7829
|
7938
|
8060
|
8066
|
8137
|
8862
|
8864