/**
  * 
  * process demand of ListRecords, and return part of <LifeRecords> in the result.
  * making of <record> uses record function.
  * @see record
  * 
  * @param args: hash contained demand of arguments. array( 'identifier' => identifier of items )
  * @return <ListRecords> in XML  success
  * @return <error> in XML  failure
  * 
  */
 function ListRecords($args)
 {
     $xconfig_handler =& xoonips_getormhandler('xoonips', 'config');
     $from = 0;
     $until = 0;
     $set = null;
     $start_iid = 0;
     $limit_row = REPOSITORY_RESPONSE_LIMIT_ROW;
     $expire_term = REPOSITORY_RESUMPTION_TOKEN_EXPIRE_TERM;
     foreach (array('from', 'until', 'resumptionToken', 'set') as $k) {
         if (isset($args[$k])) {
             ${$k} = $args[$k];
         }
     }
     if ($from != 0) {
         $from = ISO8601toUTC($from);
     }
     if ($until != 0) {
         $until = ISO8601toUTC($until);
     }
     if (isset($resumptionToken)) {
         $result = getResumptionToken($resumptionToken);
         if (!$result) {
             return parent::error('badResumptionToken', '');
         }
         if (isset($result['args']['from'])) {
             $from = ISO8601toUTC($result['args']['from']);
         }
         if (isset($result['args']['until'])) {
             $until = ISO8601toUTC($result['args']['until']);
         }
         if (isset($result['last_item_id'])) {
             $start_iid = $result['last_item_id'] + 1;
         }
         if (isset($result['limit_row'])) {
             $limit_row = $result['limit_row'];
         }
         if (isset($result['args']['set'])) {
             $set = $result['args']['set'];
         }
         if (isset($result['publish_date'])) {
             //expire resumptionToken if repository is modified after resumptionToken has published
             $iids = array();
             if (RES_OK == xnp_selective_harvesting((int) $result['publish_date'], 0, null, 0, 1, $iids)) {
                 if (count($iids) > 0) {
                     expireResumptionToken($resumptionToken);
                     return parent::error('badResumptionToken', 'repository has been modified');
                 }
             }
         }
     }
     $identifiers = array();
     if (RES_OK != xnp_selective_harvesting((int) $from, (int) $until, $set, (int) $start_iid, (int) $limit_row, $identifiers) || count($identifiers) == 0) {
         return parent::error('noRecordsMatch', '');
     }
     $iids = array();
     foreach ($identifiers as $i) {
         $iids[] = $i['item_id'];
     }
     if (isset($resumptionToken) && count($iids) < $limit_row) {
         expireResumptionToken($resumptionToken);
     } else {
         if (count($iids) == 0) {
             return parent::error('noRecordsMatch', '');
         }
     }
     if (count($iids) == $limit_row) {
         $resumptionToken = session_id();
         setResumptionToken($resumptionToken, $this->metadataPrefix, 'ListRecords', $args, max($iids), $limit_row, time() + $expire_term);
         $resumptionToken = "<resumptionToken>{$resumptionToken}</resumptionToken>\n";
     } else {
         $resumptionToken = "";
     }
     $index_tree_list = xnpListIndexTree(XOONIPS_LISTINDEX_PUBLICONLY, true);
     $nijc_code = $xconfig_handler->getValue('repository_nijc_code');
     if (!empty($nijc_code)) {
         $records = array();
         $errors = array();
         foreach ($identifiers as $item) {
             list($xml, $result) = $this->record($item, $index_tree_list);
             if ($result) {
                 $records[] = $xml;
             } else {
                 $errors[] = $xml;
             }
         }
         if (count($identifiers) == 0) {
             return parent::error('noRecordsMatch', '');
         } else {
             return "<ListRecords>\n" . implode("\n", $records) . $resumptionToken . "</ListRecords>\n";
         }
     } else {
         return parent::error('idDoesNotExist', 'nijc_code is not configured');
     }
 }
 function ListSets($args)
 {
     $attrs = array_merge($args, array('verb' => 'ListSets'));
     $limit_row = REPOSITORY_RESPONSE_LIMIT_ROW;
     $path_alllist = null;
     $msg = null;
     $start_index = 0;
     $resumptionToken = null;
     $resumptionToken_msg = "";
     // get item type list
     $itemtypes = null;
     xnp_get_item_types($itemtypes);
     // check resumptionToken parameter.
     if (isset($args['resumptionToken'])) {
         $resumptionToken = $args['resumptionToken'];
         $result = getResumptionToken($resumptionToken);
         // echo "result="; var_dump($result); echo "\n";
         if (count($result) > 1) {
             if (isset($result['last_item_id'])) {
                 $start_index = $result['last_item_id'];
             }
             if (isset($result['args']['item_all_count'])) {
                 $item_all_count = $result['args']['item_all_count'];
             }
             //expire resumptionToken if index tree is modified after resumptionToken has published
             $path_alllist = xnpListIndexTree(XOONIPS_LISTINDEX_PUBLICONLY);
             if (!$path_alllist || count($path_alllist) + count($itemtypes) != $item_all_count) {
                 expireResumptionToken($args['resumptionToken']);
                 $msg = $this->error('badResumptionToken', 'repository has been modified');
             }
         } else {
             $msg = $this->error('badResumptionToken', '');
         }
     }
     if (!$msg) {
         // list sets
         if (!$path_alllist) {
             $path_alllist = xnpListIndexTree(XOONIPS_LISTINDEX_PUBLICONLY);
         }
         $spec_list = $path_alllist;
         // add item type
         if ($itemtypes) {
             foreach ($itemtypes as $v) {
                 $spec_list[] = $v;
             }
         }
         // create string by item index and item type
         $ct = min($start_index + $limit_row, count($spec_list));
         for ($i = $start_index; $i < $ct; $i++) {
             $v = $spec_list[$i];
             if (isset($v['id_fullpath'])) {
                 $path_ar = explode(",", $v['id_fullpath']);
                 $spec = "index" . implode(":index", $path_ar);
                 $setname = $v['fullpath'];
             } else {
                 $spec = $v['name'];
                 $setname = $v['display_name'];
             }
             if (extension_loaded('mbstring')) {
                 $setname = mb_convert_encoding($setname, "UTF-8", _CHARSET);
             } else {
                 $setname = utf8_encode($setname);
             }
             $setname = htmlspecialchars($setname, ENT_QUOTES);
             $msg .= "    <set>\n" . "        <setSpec>" . $spec . "</setSpec>\n" . "        <setName>" . $setname . "</setName>\n" . "    </set>\n";
         }
         // set or expire resumption token
         $leftcount = count($spec_list) - $start_index;
         if ($resumptionToken && $leftcount < $limit_row) {
             expireResumptionToken($resumptionToken);
         }
         if ($leftcount > $limit_row) {
             $args['item_all_count'] = count($spec_list);
             // set optional value(count).
             $resumptionToken = session_id();
             setResumptionToken($resumptionToken, '', 'ListSets', $args, $ct, $limit_row, time() + REPOSITORY_RESUMPTION_TOKEN_EXPIRE_TERM);
             $resumptionToken_msg = "<resumptionToken>{$resumptionToken}</resumptionToken>\n";
         } else {
             $resumptionToken_msg = "";
         }
         return $this->header() . $this->request($attrs) . "<ListSets>\n" . $msg . $resumptionToken_msg . "</ListSets>\n" . $this->footer();
     } else {
         // error
         return $this->header() . $this->request($attrs) . $msg . $this->footer();
     }
 }