Lines 16-22
Link Here
|
16 |
# along with Koha; if not, see <http://www.gnu.org/licenses>. |
16 |
# along with Koha; if not, see <http://www.gnu.org/licenses>. |
17 |
|
17 |
|
18 |
use Modern::Perl; |
18 |
use Modern::Perl; |
19 |
use Encode; |
19 |
use utf8; |
20 |
|
20 |
|
21 |
use Test::More tests => 8; |
21 |
use Test::More tests => 8; |
22 |
use Test::Exception; |
22 |
use Test::Exception; |
Lines 209-218
subtest 'get_elasticsearch_mappings() tests' => sub {
Link Here
|
209 |
|
209 |
|
210 |
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () tests' => sub { |
210 |
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () tests' => sub { |
211 |
|
211 |
|
212 |
plan tests => 70; |
212 |
plan tests => 81; |
213 |
|
213 |
|
214 |
t::lib::Mocks::mock_preference( 'marcflavour', 'MARC21' ); |
214 |
t::lib::Mocks::mock_preference( 'marcflavour', 'MARC21' ); |
215 |
t::lib::Mocks::mock_preference( 'ElasticsearchMARCFormat', 'ISO2709' ); |
215 |
t::lib::Mocks::mock_preference( 'ElasticsearchMARCFormat', 'base64ISO2709' ); |
216 |
|
216 |
|
217 |
my @mappings = ( |
217 |
my @mappings = ( |
218 |
{ |
218 |
{ |
Lines 426-431
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () tests'
Link Here
|
426 |
marc_type => 'marc21', |
426 |
marc_type => 'marc21', |
427 |
marc_field => '522a', |
427 |
marc_field => '522a', |
428 |
}, |
428 |
}, |
|
|
429 |
{ |
430 |
name => 'local-number', |
431 |
type => 'string', |
432 |
facet => 0, |
433 |
suggestible => 0, |
434 |
searchable => 1, |
435 |
sort => 1, |
436 |
marc_type => 'marc21', |
437 |
marc_field => '999c', |
438 |
}, |
429 |
); |
439 |
); |
430 |
|
440 |
|
431 |
my $se = Test::MockModule->new('Koha::SearchEngine::Elasticsearch'); |
441 |
my $se = Test::MockModule->new('Koha::SearchEngine::Elasticsearch'); |
Lines 458-464
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () tests'
Link Here
|
458 |
my $long_callno = '1234567890' x 30; |
468 |
my $long_callno = '1234567890' x 30; |
459 |
|
469 |
|
460 |
my $marc_record_1 = MARC::Record->new(); |
470 |
my $marc_record_1 = MARC::Record->new(); |
461 |
$marc_record_1->leader(' cam 22 a 4500'); |
471 |
$marc_record_1->leader(' cam a22 a 4500'); |
462 |
$marc_record_1->append_fields( |
472 |
$marc_record_1->append_fields( |
463 |
MARC::Field->new( '001', '123' ), |
473 |
MARC::Field->new( '001', '123' ), |
464 |
MARC::Field->new( '007', 'ku' ), |
474 |
MARC::Field->new( '007', 'ku' ), |
Lines 479-486
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () tests'
Link Here
|
479 |
MARC::Field->new( '952', '', '', 0 => 0, g => '127.20', o => $callno2, l => 2 ), |
489 |
MARC::Field->new( '952', '', '', 0 => 0, g => '127.20', o => $callno2, l => 2 ), |
480 |
MARC::Field->new( '952', '', '', 0 => 1, g => '0.00', o => $long_callno, l => 1 ), |
490 |
MARC::Field->new( '952', '', '', 0 => 1, g => '0.00', o => $long_callno, l => 1 ), |
481 |
); |
491 |
); |
|
|
492 |
|
482 |
my $marc_record_2 = MARC::Record->new(); |
493 |
my $marc_record_2 = MARC::Record->new(); |
483 |
$marc_record_2->leader(' cam 22 a 4500'); |
494 |
$marc_record_2->leader(' cam a22 a 4500'); |
484 |
$marc_record_2->append_fields( |
495 |
$marc_record_2->append_fields( |
485 |
MARC::Field->new( '008', '901111s19uu xxk|||| |00| ||eng c' ), |
496 |
MARC::Field->new( '008', '901111s19uu xxk|||| |00| ||eng c' ), |
486 |
MARC::Field->new( '100', '', '', a => 'Author 2' ), |
497 |
MARC::Field->new( '100', '', '', a => 'Author 2' ), |
Lines 493-499
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () tests'
Link Here
|
493 |
); |
504 |
); |
494 |
|
505 |
|
495 |
my $marc_record_3 = MARC::Record->new(); |
506 |
my $marc_record_3 = MARC::Record->new(); |
496 |
$marc_record_3->leader(' cam 22 a 4500'); |
507 |
$marc_record_3->leader(' cam a22 a 4500'); |
497 |
$marc_record_3->append_fields( |
508 |
$marc_record_3->append_fields( |
498 |
MARC::Field->new( '008', '901111s19uu xxk|||| |00| ||eng c' ), |
509 |
MARC::Field->new( '008', '901111s19uu xxk|||| |00| ||eng c' ), |
499 |
MARC::Field->new( '100', '', '', a => 'Author 2' ), |
510 |
MARC::Field->new( '100', '', '', a => 'Author 2' ), |
Lines 506-512
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () tests'
Link Here
|
506 |
); |
517 |
); |
507 |
|
518 |
|
508 |
my $marc_record_4 = MARC::Record->new(); |
519 |
my $marc_record_4 = MARC::Record->new(); |
509 |
$marc_record_4->leader(' cam 22 a 4500'); |
520 |
$marc_record_4->leader(' cam a22 a 4500'); |
510 |
$marc_record_4->append_fields( |
521 |
$marc_record_4->append_fields( |
511 |
MARC::Field->new( '008', '901111s19uu xxk|||| |00| ||eng c' ), |
522 |
MARC::Field->new( '008', '901111s19uu xxk|||| |00| ||eng c' ), |
512 |
MARC::Field->new( '100', '', '', a => 'Author 2' ), |
523 |
MARC::Field->new( '100', '', '', a => 'Author 2' ), |
Lines 628-634
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () tests'
Link Here
|
628 |
ok( defined $docs->[0]->{marc_format}, 'First document marc_format field should be set' ); |
639 |
ok( defined $docs->[0]->{marc_format}, 'First document marc_format field should be set' ); |
629 |
is( $docs->[0]->{marc_format}, 'base64ISO2709', 'First document marc_format should be set correctly' ); |
640 |
is( $docs->[0]->{marc_format}, 'base64ISO2709', 'First document marc_format should be set correctly' ); |
630 |
|
641 |
|
631 |
my $decoded_marc_record = $see->decode_record_from_result( $docs->[0] ); |
642 |
my $decoded_marc_record = $see->search_document_marc_record_decode($docs->[0]); |
632 |
|
643 |
|
633 |
ok( $decoded_marc_record->isa('MARC::Record'), "base64ISO2709 record successfully decoded from result" ); |
644 |
ok( $decoded_marc_record->isa('MARC::Record'), "base64ISO2709 record successfully decoded from result" ); |
634 |
is( |
645 |
is( |
Lines 747-766
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () tests'
Link Here
|
747 |
# Marc serialization format fallback for records exceeding ISO2709 max record size |
758 |
# Marc serialization format fallback for records exceeding ISO2709 max record size |
748 |
|
759 |
|
749 |
my $large_marc_record = MARC::Record->new(); |
760 |
my $large_marc_record = MARC::Record->new(); |
750 |
$large_marc_record->leader(' cam 22 a 4500'); |
761 |
$large_marc_record->leader(' cam a22 a 4500'); |
751 |
|
762 |
|
752 |
$large_marc_record->append_fields( |
763 |
$large_marc_record->append_fields( |
753 |
MARC::Field->new( '100', '', '', a => 'Author 1' ), |
764 |
MARC::Field->new( '100', '', '', a => 'Author 1' ), |
754 |
MARC::Field->new( '110', '', '', a => 'Corp Author' ), |
765 |
MARC::Field->new( '110', '', '', a => 'Corp Author' ), |
755 |
MARC::Field->new( '210', '', '', a => 'Title 1' ), |
766 |
MARC::Field->new( '210', '', '', a => 'Title 1' ), |
756 |
MARC::Field->new( '245', '', '', a => 'Title:', b => 'large record' ), |
767 |
# "|" is for testing escaping for multiple values with custom format |
757 |
MARC::Field->new( '999', '', '', c => '1234567' ), |
768 |
MARC::Field->new( '245', '', '', a => 'Title:', b => 'large | record' ), |
|
|
769 |
MARC::Field->new( '999', '', '', c => '1234569' ), |
758 |
); |
770 |
); |
759 |
|
771 |
|
760 |
my $item_field = MARC::Field->new( |
772 |
my $item_field = MARC::Field->new( |
761 |
'952', '', '', o => '123456789123456789123456789', p => '123456789', |
773 |
'952', '', '', o => '123456789123456789123456789', p => '123456789', |
762 |
z => Encode::decode( 'UTF-8', 'To naprawdę bardzo długa notatka. Myślę, że będzie sprawiać kłopoty.' ) |
774 |
z => 'To naprawdę bardzo długa notatka. Myślę, że będzie sprawiać kłopoty.' |
763 |
); |
775 |
); |
|
|
776 |
|
764 |
my $items_count = 1638; |
777 |
my $items_count = 1638; |
765 |
while ( --$items_count ) { |
778 |
while ( --$items_count ) { |
766 |
$large_marc_record->append_fields($item_field); |
779 |
$large_marc_record->append_fields($item_field); |
Lines 773-779
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () tests'
Link Here
|
773 |
'For record exceeding max record size marc_format should be set correctly' |
786 |
'For record exceeding max record size marc_format should be set correctly' |
774 |
); |
787 |
); |
775 |
|
788 |
|
776 |
$decoded_marc_record = $see->decode_record_from_result( $docs->[0] ); |
789 |
$decoded_marc_record = $see->search_document_marc_record_decode( $docs->[0] ); |
777 |
|
790 |
|
778 |
ok( $decoded_marc_record->isa('MARC::Record'), "MARCXML record successfully decoded from result" ); |
791 |
ok( $decoded_marc_record->isa('MARC::Record'), "MARCXML record successfully decoded from result" ); |
779 |
is( |
792 |
is( |
Lines 781-786
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () tests'
Link Here
|
781 |
"Decoded MARCXML record has same data as original record" |
794 |
"Decoded MARCXML record has same data as original record" |
782 |
); |
795 |
); |
783 |
|
796 |
|
|
|
797 |
# Search export functionality |
798 |
# Koha::SearchEngine::Elasticsearch::search_documents_encode() |
799 |
my @source_docs = ($marc_record_1, $marc_record_2, $large_marc_record); |
800 |
my @es_response_docs; |
801 |
my $records_data; |
802 |
|
803 |
for my $es_marc_format ('MARCXML', 'ARRAY', 'base64ISO2709') { |
804 |
|
805 |
t::lib::Mocks::mock_preference('ElasticsearchMARCFormat', $es_marc_format); |
806 |
|
807 |
$docs = $see->marc_records_to_documents(\@source_docs); |
808 |
|
809 |
# Emulate Elasticsearch response docs structure |
810 |
@es_response_docs = map { { _source => $_ } } @{$docs}; |
811 |
|
812 |
$records_data = $see->search_documents_encode(\@es_response_docs, 'ISO2709'); |
813 |
|
814 |
# $large_marc_record should not have been encoded as ISO2709 |
815 |
# since exceeds maximum size, see above |
816 |
my @tmp = ($marc_record_1, $marc_record_2); |
817 |
is( |
818 |
$records_data->{ISO2709}, |
819 |
join('', map { $_->as_usmarc() } @tmp), |
820 |
"ISO2709 encoded records from Elasticsearch result are identical with source records using index format \"$es_marc_format\"" |
821 |
); |
822 |
|
823 |
my $expected_marc_xml = join("\n", |
824 |
MARC::File::XML::header(), |
825 |
MARC::File::XML::record($large_marc_record, 'MARC21'), |
826 |
MARC::File::XML::footer() |
827 |
); |
828 |
|
829 |
is( |
830 |
$records_data->{MARCXML}, |
831 |
$expected_marc_xml, |
832 |
"Record from search result encoded as MARCXML since exceeding ISO2709 maximum size is identical with source record using index format \"$es_marc_format\"" |
833 |
); |
834 |
|
835 |
$records_data = $see->search_documents_encode(\@es_response_docs, 'MARCXML'); |
836 |
|
837 |
$expected_marc_xml = join("\n", |
838 |
MARC::File::XML::header(), |
839 |
join("\n", map { MARC::File::XML::record($_, 'MARC21') } @source_docs), |
840 |
MARC::File::XML::footer() |
841 |
); |
842 |
|
843 |
is( |
844 |
$records_data->{MARCXML}, |
845 |
$expected_marc_xml, |
846 |
"MARCXML encoded records from Elasticsearch result are identical with source records using index format \"$es_marc_format\"" |
847 |
); |
848 |
} |
849 |
|
850 |
my $custom_formats = <<'END'; |
851 |
- name: Biblionumbers |
852 |
fields: [local-number] |
853 |
multiple: ignore |
854 |
- name: Title and author |
855 |
fields: [title, author] |
856 |
multiple: join |
857 |
END |
858 |
t::lib::Mocks::mock_preference('ElasticsearchSearchResultExportCustomFormats', $custom_formats); |
859 |
$custom_formats = C4::Context->yaml_preference('ElasticsearchSearchResultExportCustomFormats'); |
860 |
|
861 |
# Biblionumbers custom format |
862 |
$records_data = $see->search_documents_custom_format_encode(\@es_response_docs, $custom_formats->[0]); |
863 |
# UTF-8 encode? |
864 |
is( |
865 |
$records_data, |
866 |
"1234567\n1234568\n1234569", |
867 |
"Records where correctly encoded for the custom format \"Biblionumbers\"" |
868 |
); |
869 |
|
870 |
# Title and author custom format |
871 |
$records_data = $see->search_documents_custom_format_encode(\@es_response_docs, $custom_formats->[1]); |
872 |
|
873 |
my $encoded_data = join( |
874 |
"\n", |
875 |
"\"Title:|first record|Title: first record\",\"Author 1|Corp Author\"", |
876 |
"\"\",\"Author 2\"", |
877 |
"\"Title:|large \\| record|Title: large \\| record\",\"Author 1|Corp Author\"" |
878 |
); |
879 |
|
880 |
is( |
881 |
$records_data, |
882 |
$encoded_data, |
883 |
"Records where correctly encoded for the custom format \"Title and author\"" |
884 |
); |
885 |
|
784 |
push @mappings, { |
886 |
push @mappings, { |
785 |
name => 'title', |
887 |
name => 'title', |
786 |
type => 'string', |
888 |
type => 'string', |
Lines 824-830
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () tests'
Link Here
|
824 |
|
926 |
|
825 |
pop @mappings; |
927 |
pop @mappings; |
826 |
my $marc_record_with_blank_field = MARC::Record->new(); |
928 |
my $marc_record_with_blank_field = MARC::Record->new(); |
827 |
$marc_record_with_blank_field->leader(' cam 22 a 4500'); |
929 |
$marc_record_with_blank_field->leader(' cam a22 a 4500'); |
828 |
|
930 |
|
829 |
$marc_record_with_blank_field->append_fields( |
931 |
$marc_record_with_blank_field->append_fields( |
830 |
MARC::Field->new( '100', '', '', a => '' ), |
932 |
MARC::Field->new( '100', '', '', a => '' ), |
Lines 837-843
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () tests'
Link Here
|
837 |
is_deeply( $docs->[0]->{author__suggestion}, [], 'No value placed into suggestion if mapped marc field is blank' ); |
939 |
is_deeply( $docs->[0]->{author__suggestion}, [], 'No value placed into suggestion if mapped marc field is blank' ); |
838 |
|
940 |
|
839 |
my $marc_record_with_large_field = MARC::Record->new(); |
941 |
my $marc_record_with_large_field = MARC::Record->new(); |
840 |
$marc_record_with_large_field->leader(' cam 22 a 4500'); |
942 |
$marc_record_with_large_field->leader(' cam a22 a 4500'); |
841 |
|
943 |
|
842 |
my $xs = 'X' x 8191; |
944 |
my $xs = 'X' x 8191; |
843 |
my $ys = 'Y' x 8191; |
945 |
my $ys = 'Y' x 8191; |
Lines 867-873
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () tests'
Link Here
|
867 |
|
969 |
|
868 |
is( $docs->[0]->{marc_format}, 'MARCXML', 'For record with large field marc_format should be set correctly' ); |
970 |
is( $docs->[0]->{marc_format}, 'MARCXML', 'For record with large field marc_format should be set correctly' ); |
869 |
|
971 |
|
870 |
$decoded_marc_record = $see->decode_record_from_result( $docs->[0] ); |
972 |
$decoded_marc_record = $see->search_document_marc_record_decode( $docs->[0] ); |
871 |
|
973 |
|
872 |
ok( $decoded_marc_record->isa('MARC::Record'), "MARCXML record successfully decoded from result" ); |
974 |
ok( $decoded_marc_record->isa('MARC::Record'), "MARCXML record successfully decoded from result" ); |
873 |
is( |
975 |
is( |
Lines 923-929
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents_array () t
Link Here
|
923 |
{ index => $Koha::SearchEngine::Elasticsearch::BIBLIOS_INDEX } ); |
1025 |
{ index => $Koha::SearchEngine::Elasticsearch::BIBLIOS_INDEX } ); |
924 |
|
1026 |
|
925 |
my $marc_record_1 = MARC::Record->new(); |
1027 |
my $marc_record_1 = MARC::Record->new(); |
926 |
$marc_record_1->leader(' cam 22 a 4500'); |
1028 |
$marc_record_1->leader(' cam a22 a 4500'); |
927 |
$marc_record_1->append_fields( |
1029 |
$marc_record_1->append_fields( |
928 |
MARC::Field->new( '001', '123' ), |
1030 |
MARC::Field->new( '001', '123' ), |
929 |
MARC::Field->new( '020', '', '', a => '1-56619-909-3' ), |
1031 |
MARC::Field->new( '020', '', '', a => '1-56619-909-3' ), |
Lines 934-940
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents_array () t
Link Here
|
934 |
MARC::Field->new( '999', '', '', c => '1234567' ), |
1036 |
MARC::Field->new( '999', '', '', c => '1234567' ), |
935 |
); |
1037 |
); |
936 |
my $marc_record_2 = MARC::Record->new(); |
1038 |
my $marc_record_2 = MARC::Record->new(); |
937 |
$marc_record_2->leader(' cam 22 a 4500'); |
1039 |
$marc_record_2->leader(' cam a22 a 4500'); |
938 |
$marc_record_2->append_fields( |
1040 |
$marc_record_2->append_fields( |
939 |
MARC::Field->new( '100', '', '', a => 'Author 2' ), |
1041 |
MARC::Field->new( '100', '', '', a => 'Author 2' ), |
940 |
|
1042 |
|
Lines 956-962
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents_array () t
Link Here
|
956 |
|
1058 |
|
957 |
is( $docs->[0]->{marc_format}, 'ARRAY', 'First document marc_format should be set correctly' ); |
1059 |
is( $docs->[0]->{marc_format}, 'ARRAY', 'First document marc_format should be set correctly' ); |
958 |
|
1060 |
|
959 |
my $decoded_marc_record = $see->decode_record_from_result( $docs->[0] ); |
1061 |
my $decoded_marc_record = $see->search_document_marc_record_decode( $docs->[0] ); |
960 |
|
1062 |
|
961 |
ok( $decoded_marc_record->isa('MARC::Record'), "ARRAY record successfully decoded from result" ); |
1063 |
ok( $decoded_marc_record->isa('MARC::Record'), "ARRAY record successfully decoded from result" ); |
962 |
is( |
1064 |
is( |
Lines 970-976
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () authori
Link Here
|
970 |
plan tests => 5; |
1072 |
plan tests => 5; |
971 |
|
1073 |
|
972 |
t::lib::Mocks::mock_preference( 'marcflavour', 'MARC21' ); |
1074 |
t::lib::Mocks::mock_preference( 'marcflavour', 'MARC21' ); |
973 |
t::lib::Mocks::mock_preference( 'ElasticsearchMARCFormat', 'ISO2709' ); |
1075 |
t::lib::Mocks::mock_preference( 'ElasticsearchMARCFormat', 'base64ISO2709' ); |
974 |
|
1076 |
|
975 |
my $builder = t::lib::TestBuilder->new; |
1077 |
my $builder = t::lib::TestBuilder->new; |
976 |
my $auth_type = |
1078 |
my $auth_type = |
Lines 1091-1096
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents with Inclu
Link Here
|
1091 |
MARC::Field->new( 150, '', '', a => 'Foo' ), |
1193 |
MARC::Field->new( 150, '', '', a => 'Foo' ), |
1092 |
MARC::Field->new( 450, '', '', a => 'Bar' ), |
1194 |
MARC::Field->new( 450, '', '', a => 'Bar' ), |
1093 |
); |
1195 |
); |
|
|
1196 |
$authority_record->encoding('UTF-8'); |
1197 |
|
1094 |
$dbh->do( |
1198 |
$dbh->do( |
1095 |
"INSERT INTO auth_header (datecreated,marcxml) values (NOW(),?)", undef, |
1199 |
"INSERT INTO auth_header (datecreated,marcxml) values (NOW(),?)", undef, |
1096 |
( $authority_record->as_xml_record('MARC21') ) |
1200 |
( $authority_record->as_xml_record('MARC21') ) |
Lines 1136-1142
subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents with Inclu
Link Here
|
1136 |
{ index => $Koha::SearchEngine::Elasticsearch::BIBLIOS_INDEX } ); |
1240 |
{ index => $Koha::SearchEngine::Elasticsearch::BIBLIOS_INDEX } ); |
1137 |
|
1241 |
|
1138 |
my $marc_record_1 = MARC::Record->new(); |
1242 |
my $marc_record_1 = MARC::Record->new(); |
1139 |
$marc_record_1->leader(' cam 22 a 4500'); |
1243 |
$marc_record_1->leader(' cam a22 a 4500'); |
1140 |
$marc_record_1->append_fields( |
1244 |
$marc_record_1->append_fields( |
1141 |
MARC::Field->new( '001', '123' ), |
1245 |
MARC::Field->new( '001', '123' ), |
1142 |
MARC::Field->new( '245', '', '', a => 'Title' ), |
1246 |
MARC::Field->new( '245', '', '', a => 'Title' ), |
Lines 1174-1180
subtest 'marc_records_to_documents should set the "available" field' => sub {
Link Here
|
1174 |
$see->get_elasticsearch_mappings(); |
1278 |
$see->get_elasticsearch_mappings(); |
1175 |
|
1279 |
|
1176 |
my $marc_record_1 = MARC::Record->new(); |
1280 |
my $marc_record_1 = MARC::Record->new(); |
1177 |
$marc_record_1->leader(' cam 22 a 4500'); |
1281 |
$marc_record_1->leader(' cam a22 a 4500'); |
1178 |
$marc_record_1->append_fields( |
1282 |
$marc_record_1->append_fields( |
1179 |
MARC::Field->new( '245', '', '', a => 'Title' ), |
1283 |
MARC::Field->new( '245', '', '', a => 'Title' ), |
1180 |
); |
1284 |
); |
1181 |
- |
|
|