use
5.008000;
our
$VERSION
=
'v4.1.1'
;
sub
FORMAT_USMARC {
'1.2.840.10003.5.10'
}
sub
FORMAT_XML {
'1.2.840.10003.5.109.10'
}
sub
FORMAT_JSON {
'1.2.840.10003.5.1000.81.3'
}
sub
ATTRSET_BIB1 {
'1.2.840.10003.3.1'
}
sub
new {
my
$class
=
shift
();
my
(
$cfgbase
) =
@_
;
my
$this
=
bless
{
cfgbase
=>
$cfgbase
||
'config'
,
sessions
=> {},
},
$class
;
$this
->{server} = Net::Z3950::SimpleServer->new(
GHANDLE
=>
$this
,
INIT
=> \
&_init_handler_wrapper
,
SEARCH
=> \
&_search_handler_wrapper
,
FETCH
=> \
&_fetch_handler_wrapper
,
DELETE
=> \
&_delete_handler_wrapper
,
SORT
=> \
&_sort_handler_wrapper
,
);
return
$this
;
}
sub
getSession {
my
$this
=
shift
();
my
(
$name
) =
@_
;
if
(!
$this
->{sessions}->{
$name
}) {
my
$session
= new Net::Z3950::FOLIO::Session(
$this
,
$name
);
$this
->{sessions}->{
$name
} =
$session
;
$session
->reloadConfigFile();
$session
->login(
$this
->{user},
$this
->{pass})
if
!
$session
->{cfg}->{nologin};
}
return
$this
->{sessions}->{
$name
};
}
sub
_init_handler_wrapper { _eval_wrapper(\
&_init_handler
,
@_
) }
sub
_search_handler_wrapper { _eval_wrapper(\
&_search_handler
,
@_
) }
sub
_fetch_handler_wrapper { _eval_wrapper(\
&_fetch_handler
,
@_
) }
sub
_delete_handler_wrapper { _eval_wrapper(\
&_delete_handler
,
@_
) }
sub
_sort_handler_wrapper { _eval_wrapper(\
&_sort_handler
,
@_
) }
sub
_eval_wrapper {
my
$coderef
=
shift
();
my
$args
=
shift
();
eval
{
&$coderef
(
$args
,
@_
);
};
if
(
ref
$@ && $@->isa(
'ZOOM::Exception'
)) {
if
($@->diagset() eq
'Bib-1'
) {
$args
->{ERR_CODE} = $@->code();
$args
->{ERR_STR} = $@->addinfo();
}
else
{
$args
->{ERR_CODE} = 100;
$args
->{ERR_STR} = $@->message() || $@->addinfo();
}
if
($@->isa(
'Net::Z3950::FOLIO::SurrogateDiagnostic'
)) {
$args
->{SUR_FLAG} = 1;
$args
->{RECORD} =
""
;
}
}
elsif
($@) {
die
$@;
}
}
sub
_init_handler {
my
(
$args
) =
@_
;
my
$ghandle
=
$args
->{GHANDLE};
$args
->{IMP_ID} =
'81'
;
$args
->{IMP_VER} =
$Net::Z3950::FOLIO::VERSION
;
$args
->{IMP_NAME} =
'z2folio gateway'
;
$ghandle
->{user} =
$args
->{USER};
$ghandle
->{pass} =
$args
->{PASS};
}
sub
_search_handler {
my
(
$args
) =
@_
;
my
$ghandle
=
$args
->{GHANDLE};
my
$bases
=
$args
->{DATABASES};
_throw(111, 1)
if
@$bases
!= 1;
my
$base
=
$bases
->[0];
my
$session
=
$ghandle
->getSession(
$base
);
$args
->{HANDLE} =
$session
;
$session
->maybeRefreshToken();
if
(
$args
->{CQL}) {
$session
->{cql} =
$args
->{CQL};
}
else
{
my
$type1
=
$args
->{RPN}->{query};
$session
->{cql} =
$type1
->toCQL(
$session
,
$args
->{RPN}->{attributeSet});
warn
"search: translated '"
.
$args
->{QUERY} .
"' to '"
.
$session
->{cql} .
"'\n"
;
}
$session
->{sortspec} =
undef
;
$args
->{HITS} =
$session
->rerunSearch(
$args
->{SETNAME});
}
sub
_fetch_handler {
my
(
$args
) =
@_
;
my
$session
=
$args
->{HANDLE};
_throw(30,
$args
->{SETNAME})
if
!
$session
;
$session
->maybeRefreshToken();
my
$rs
=
$session
->{resultsets}->{
$args
->{SETNAME}};
_throw(30,
$args
->{SETNAME})
if
!
$rs
;
my
$index1
=
$args
->{OFFSET};
_throw(13,
$index1
)
if
$index1
< 1 ||
$index1
>
$rs
->totalCount();
my
$rec
=
$rs
->record(
$index1
-1);
if
(!
defined
$rec
) {
my
$index0
=
$index1
- 1;
my
$chunkSize
=
$session
->{cfg}->{chunkSize} || 10;
my
$chunk
=
int
(
$index0
/
$chunkSize
);
$session
->doSearch(
$rs
,
$chunk
*
$chunkSize
,
$chunkSize
);
$rec
=
$rs
->record(
$index1
-1);
_throw(1,
"missing record"
)
if
!
defined
$rec
;
}
my
$comp
=
lc
(
$args
->{COMP} ||
''
);
my
$format
=
$args
->{REQ_FORM};
my
$res
;
if
(
$format
eq FORMAT_JSON) {
$res
=
$rec
->prettyJSON();
}
elsif
(
$format
eq FORMAT_XML &&
$comp
eq
'raw'
) {
$res
=
$rec
->prettyXML();
}
elsif
(
$format
eq FORMAT_XML &&
$comp
eq
'usmarc'
) {
my
$marc
=
$rec
->marcRecord();
$res
=
$marc
->as_xml_record();
}
elsif
(
$format
eq FORMAT_XML &&
$comp
eq
'opac'
) {
$res
= makeOPACXMLRecord(
$rec
);
}
elsif
(
$format
eq FORMAT_XML) {
_throw(25,
"XML records available in element-sets: raw, usmarc, opac"
);
}
elsif
(
$format
eq FORMAT_USMARC && (!
$comp
||
$comp
eq
'f'
||
$comp
eq
'b'
)) {
my
$marc
=
$rec
->marcRecord();
$res
=
$marc
->as_usmarc();
}
elsif
(
$format
eq FORMAT_USMARC) {
_throw(25,
"USMARC records available in element-sets: f, b"
);
}
else
{
_throw(239,
$format
);
}
$args
->{RECORD} =
$res
;
return
;
}
sub
_delete_handler {
my
(
$args
) =
@_
;
my
$session
=
$args
->{HANDLE};
$session
->maybeRefreshToken();
my
$setname
=
$args
->{SETNAME};
if
(
$session
->{resultsets}->{
$setname
}) {
$session
->{resultsets}->{
$setname
} =
undef
;
}
else
{
$args
->{STATUS} = 1;
}
return
;
}
sub
_sort_handler {
my
(
$args
) =
@_
;
my
$session
=
$args
->{HANDLE};
$session
->maybeRefreshToken();
my
$setnames
=
$args
->{INPUT};
_throw(230,
'1'
)
if
@$setnames
> 1;
my
$setname
=
$setnames
->[0];
my
$rs
=
$session
->{resultsets}->{
$setname
};
_throw(30,
$args
->{SETNAME})
if
!
$rs
;
my
$cqlSort
=
$session
->sortSpecs2CQL(
$args
->{SEQUENCE});
_throw(207, Dumper(
$args
->{SEQUENCE}))
if
!
$cqlSort
;
$session
->{sortspec} =
$cqlSort
;
$session
->rerunSearch(
$args
->{OUTPUT});
}
sub
launch_server {
my
$this
=
shift
();
my
(
$label
,
@argv
) =
@_
;
return
$this
->{server}->launch_server(
$label
,
@argv
);
}
sub
_throw {
my
(
$code
,
$addinfo
,
$diagset
,
$isSurrogate
) =
@_
;
$diagset
||=
"Bib-1"
;
if
(
$addinfo
=~ /^{/) {
my
$obj
= decode_json(
$addinfo
);
$addinfo
=
$obj
->{errors} ?
$obj
->{errors}->[0]->{message} :
$obj
->{errorMessage};
}
if
(
$isSurrogate
) {
die
new Net::Z3950::FOLIO::SurrogateDiagnostic(
$code
,
undef
,
$addinfo
,
$diagset
);
}
else
{
die
new ZOOM::Exception(
$code
,
undef
,
$addinfo
,
$diagset
);
}
}