Skip to content

Commit

Permalink
Abstract OAI sets, add virtual sets. refs #8238
Browse files Browse the repository at this point in the history
Mark Triggs has contributed work to abstract OAI-PMH sets and allow virtual
sets, such as a list of top-level descriptions, to be defined.

Detailed in: #136

* Generalise the OAI set implementation

  Allow OAI sets to be defined by arbitrary criteria rather than requiring
  them to correspond to a single collection.

* Change OAI terminology from "collection" to "OAI set"

  Reflect the fact that an OAI set may no longer correspond to a single
  collection.

* Add a new "virtual" OAI set matching top-level records

* Add new configuration option for additional OAI sets
  (disabled by default to preserve backward compatibility)

* If the requested OAI set doesn't exist, return an error.
  • Loading branch information
mcantelon committed Apr 7, 2015
1 parent 6ff196b commit 8d72f57
Show file tree
Hide file tree
Showing 18 changed files with 317 additions and 61 deletions.
10 changes: 9 additions & 1 deletion apps/qubit/modules/settings/actions/oaiAction.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ protected function populateOaiRepositoryForm()
$oaiRepositoryIdentifier = QubitOai::getRepositoryIdentifier();
$sampleOaiIdentifier = QubitOai::getSampleIdentifier();
$resumptionTokenLimit = QubitSetting::getByName('resumption_token_limit');
$oaiAdditionalSetsEnabled = QubitSetting::getByName('oai_additional_sets_enabled');

// Set defaults for global form
$this->oaiRepositoryForm->setDefaults(array(
Expand All @@ -80,7 +81,8 @@ protected function populateOaiRepositoryForm()
'oai_repository_identifier' => $oaiRepositoryIdentifier,
'oai_admin_emails' => $oaiAdminEmails,
'sample_oai_identifier' => $sampleOaiIdentifier,
'resumption_token_limit' => (isset($resumptionTokenLimit)) ? $resumptionTokenLimit->getValue(array('sourceCulture'=>true)) : null
'resumption_token_limit' => (isset($resumptionTokenLimit)) ? $resumptionTokenLimit->getValue(array('sourceCulture'=>true)) : null,
'oai_additional_sets_enabled' => (isset($oaiAdditionalSetsEnabled)) ? intval($oaiAdditionalSetsEnabled->getValue(array('sourceCulture'=>true))) : 0
));
}

Expand Down Expand Up @@ -119,6 +121,12 @@ protected function updateOaiRepositorySettings()
$setting->save();
}

// OAI additional sets enabled radio button
$oaiAdditionalSetsEnabledValue = $thisForm->getValue('oai_additional_sets_enabled');
$setting = QubitSetting::getByName('oai_additional_sets_enabled');
$setting->setValue($oaiAdditionalSetsEnabledValue, array('sourceCulture' => true));
$setting->save();

return $this;
}
}
8 changes: 7 additions & 1 deletion data/fixtures/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ QubitSetting:
name: version
editable: 0
deleteable: 0
value: 120
value: 122
milestone:
name: milestone
editable: 0
Expand Down Expand Up @@ -522,6 +522,12 @@ QubitSetting:
deleteable: 0
source_culture: en
value: ''
QubitSetting_oai_additional_sets_enabled:
name: oai_additional_sets_enabled
scope: oai
editable: 1
deleteable: 0
value: 0
QubitSetting_inherit_code_informationobject:
name: inherit_code_informationobject
editable: 1
Expand Down
73 changes: 39 additions & 34 deletions lib/QubitOai.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@

class QubitOai
{
/* Any custom OAI set implementations that are available (in addition to the
* standard collection sets) */
private static $additionalOaiSets = array();

/**
* Mail error report
*
Expand Down Expand Up @@ -202,72 +206,73 @@ public static function getMetadataFormats()
}

/**
* Load array of collections
* Load array of OAI sets
*
* @return array associative array of collection information
* @return array of available OAI sets
*/
public static function getCollectionArray()
public static function getOaiSets()
{
$collections = QubitInformationObject::getCollections();
$collectionTable = array();
$oaiSets = array();

foreach ($collections as $collection)
{
$collectionTable[] = array('setSpec'=>$collection->getOaiIdentifier(), 'lft' => $collection->getLft(), 'rgt' => $collection->getRgt());
$oaiSets[] = new QubitOaiCollectionSet($collection);
}
return $collectionTable;

$useAdditionalOaiSets = QubitSetting::getByName('oai_additional_sets_enabled');

if ($useAdditionalOaiSets && $useAdditionalOaiSets->value) {
foreach (QubitOai::$additionalOaiSets as $oaiSet)
{
$oaiSets[] = $oaiSet;
}
}

return $oaiSets;
}

/**
* Returns collection identifier for the element with $left element
* Add a new OAI set to the available list
*
* @param int $left left side of information object
* @return string oai identifier of the element's collection
*/
public static function getSetSpec($left, $collectionTable)
public static function addOaiSet($oaiSet)
{
foreach ($collectionTable as $collection)
{
if ($collection['lft'] <= $left AND $collection['rgt'] > $left)
{
return $collection['setSpec'];
}
}
return 'None';
QubitOai::$additionalOaiSets[] = $oaiSet;
}

/**
* Returns collection info for the element with $setSpec
* Returns the setSpec for the OAI set containiner $record
*
* @param int $setSpec left side of information object
* @param mixed $record, an Information Object record
* @param array of available OAI sets
* @return string oai identifier of the element's collection
*/
public static function getCollectionInfo($setSpec, $collectionsTable)
public static function getSetSpec($record, $oaiSets)
{
foreach ($collectionsTable as $collection)
foreach ($oaiSets as $oaiSet)
{
if ($collection['setSpec'] == $setSpec)
{
return $collection;
if ($oaiSet->contains($record)) {
return $oaiSet->setSpec();
}
}
return false;
return 'None';
}

/**
* Gets limits of the collection
* Returns the OAI set matching $setSpec
*
* @param string $setSpec the collection id
* @return array associative array of collection with setSpec
* @param string $setSpec, the setSpec of an OAI set
* @return QubitOaiSet/boolean the OAI set matched (or false if none matched)
*/
public static function getCollectionLimits($setSpec)
public static function getMatchingOaiSet($setSpec, $oaiSets)
{
$collectionTable = oai::getCollectionArray();
foreach ($collectionTable as $collection)
foreach ($oaiSets as $oaiSet)
{
if ($collection['setSpec'] == $setSpec)
if ($oaiSet->setSpec() == $setSpec)
{
return $collection;
return $oaiSet;
}
}
return false;
Expand Down
10 changes: 7 additions & 3 deletions lib/form/SettingsOaiRepositoryForm.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ public function configure()
'oai_admin_emails' => new sfWidgetFormTextarea,
'oai_repository_identifier' => new sfWidgetFormInput(array(), array('class'=>'disabled', 'disabled'=>true)),
'sample_oai_identifier' => new sfWidgetFormInput(array(), array('class'=>'disabled', 'disabled'=>true)),
'resumption_token_limit' => new sfWidgetFormInput
'resumption_token_limit' => new sfWidgetFormInput,
'oai_additional_sets_enabled' => new sfWidgetFormSelectRadio(array('choices'=>array(1=>'yes', 0=>'no')), array('class'=>'radio'))
));

// Add labels
Expand All @@ -50,7 +51,8 @@ public function configure()
'oai_admin_emails' => $i18n->__('Administrator email(s)'),
'oai_repository_identifier' => $i18n->__('OAI repository identifier'),
'sample_oai_identifier' => $i18n->__('Sample OAI identifier'),
'resumption_token_limit' => $i18n->__('Resumption token limit')
'resumption_token_limit' => $i18n->__('Resumption token limit'),
'oai_additional_sets_enabled' => $i18n->__('Enable additional OAI sets')
));

// Add helper text
Expand All @@ -60,7 +62,8 @@ public function configure()
'oai_admin_emails' => $i18n->__('Enter the email address(es) of at least one administrator for the repository. Multiple addresses can be entered, separated by commas. The address(es) will be exposed as part of a response to an Identify request.'),
'oai_repository_identifier' => $i18n->__('This is an auto-generated setting that produces an OAI compliant repository identifier, which includes the OAI repository code value if it is set'),
'sample_oai_identifier' => $i18n->__('This is an example of the auto-generated, OAI compliant identifier which is created for each item in this particular OAI repository'),
'resumption_token_limit' => $i18n->__('The number of entities to include in a single OAI response list before inserting a resumption token')
'resumption_token_limit' => $i18n->__('The number of entities to include in a single OAI response list before inserting a resumption token'),
'oai_additional_sets_enabled' => $i18n->__('If "no", just show one OAI set per collection')
));

// Reference image max. width validator
Expand All @@ -82,6 +85,7 @@ public function configure()
$this->validatorSchema['oai_admin_emails'] = new sfValidatorString(array('required' => false));
$this->validatorSchema['oai_repository_identifier'] = new sfValidatorString(array('required' => false));
$this->validatorSchema['sample_oai_identifier'] = new sfValidatorString(array('required' => false));
$this->validatorSchema['oai_additional_sets_enabled'] = new sfValidatorInteger(array('required' => false));

// Set decorator
$decorator = new QubitWidgetFormSchemaFormatterList($this->widgetSchema);
Expand Down
3 changes: 1 addition & 2 deletions lib/model/QubitInformationObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,7 @@ public static function getUpdatedRecords($from = '', $until = '', $offset = 0, $

if ($set != '')
{
$criteria->add(QubitInformationObject::LFT, $set['lft'], Criteria::GREATER_EQUAL);
$criteria->add(QubitInformationObject::RGT, $set['rgt'], Criteria::LESS_EQUAL);
$set->apply($criteria);
}

$criteria->add(QubitInformationObject::PARENT_ID, null, Criteria::ISNOTNULL);
Expand Down
53 changes: 53 additions & 0 deletions lib/oai/QubitOaiCollectionSet.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

/*
* This file is part of the Access to Memory (AtoM) software.
*
* Access to Memory (AtoM) is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Access to Memory (AtoM) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Access to Memory (AtoM). If not, see <http://www.gnu.org/licenses/>.
*/

/**
* An OAI set for a single collection
*
* @package AccesstoMemory
* @subpackage oai
* @author Mark Triggs <mark@teaspoon-consulting.com>
*/

class QubitOaiCollectionSet implements QubitOaiSet
{
private $collection;

public function __construct($collection) {
$this->collection = $collection;
}

public function contains($record) {
$lft = $record->getLft();
return ($this->collection['lft'] <= $lft AND $this->collection['rgt'] > $lft);
}

public function setSpec() {
return $this->collection->getOaiIdentifier();
}

public function getName() {
return new sfIsadPlugin($this->collection);
}

public function apply($criteria) {
$criteria->add(QubitInformationObject::LFT, $this->collection['lft'], Criteria::GREATER_EQUAL);
$criteria->add(QubitInformationObject::RGT, $this->collection['rgt'], Criteria::LESS_EQUAL);
}
}
64 changes: 64 additions & 0 deletions lib/oai/QubitOaiSet.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

/*
* This file is part of the Access to Memory (AtoM) software.
*
* Access to Memory (AtoM) is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Access to Memory (AtoM) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Access to Memory (AtoM). If not, see <http://www.gnu.org/licenses/>.
*/

/**
* The interface provided by OAI set implementations
*
* @package AccesstoMemory
* @subpackage oai
* @author Mark Triggs <mark@teaspoon-consulting.com>
*/

interface QubitOaiSet
{
/**
* Query OAI set membership by record
*
* @param mixed $record A record that can be part of an OAI set
*
* @return boolean true if $record is contained in this OAI set.
*/

public function contains($record);

/**
* The OAI set specification for the current set
*
* @return string An OAI set specification
*/

public function setSpec();

/**
* The name of the current OAI set
*
* @return string A display name
*/

public function getName();

/**
* Apply the current set's restrictions to $criteria
*
* @param Criteria $criteria The search criteria to be modified
*
*/

public function apply($criteria);
}
51 changes: 51 additions & 0 deletions lib/oai/QubitOaiTopLevelSet.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

/*
* This file is part of the Access to Memory (AtoM) software.
*
* Access to Memory (AtoM) is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Access to Memory (AtoM) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Access to Memory (AtoM). If not, see <http://www.gnu.org/licenses/>.
*/

/**
* An OAI set for all top-level (collection) records
*
* @package AccesstoMemory
* @subpackage oai
* @author Mark Triggs <mark@teaspoon-consulting.com>
*/

class QubitOaiTopLevelSet implements QubitOaiSet
{
public function contains($record) {
/* Allow the collection set to take responsibility for records to preserve
* the current behaviour. */
return false;
}

public function setSpec() {
return "oai:virtual:top-level-records";
}

public function getName() {
return "Top-level collection record set";
}

public function apply($criteria) {
$criteria->addAlias('parent', QubitInformationObject::TABLE_NAME);
$criteria->addJoin(QubitInformationObject::PARENT_ID, 'parent.id');

$criteria->add(QubitInformationObject::RGT, QubitInformationObject::RGT.' > ('.QubitInformationObject::LFT.' + 1)', Criteria::CUSTOM);
$criteria->add('parent.lft', 1);
}
}
Loading

0 comments on commit 8d72f57

Please sign in to comment.