Source for file HarmoniRecordStructure.class.php

Documentation is available at HarmoniRecordStructure.class.php

  1. <?php
  2. require_once(OKI2."osid/repository/RecordStructure.php");
  3. require_once(HARMONI."/oki2/repository/HarmoniPartStructure.class.php");
  4. require_once(HARMONI."/oki2/repository/HarmoniPartIterator.class.php");
  5.  
  6.  
  7. /**
  8. * Each Asset has one of the AssetType supported by the Repository. There are
  9. * also zero or more RecordStructures required by the Repository for each
  10. * AssetType. RecordStructures provide structural information. The values for
  11. * a given Asset's RecordStructure are stored in a Record. RecordStructures
  12. * can contain sub-elements which are referred to as PartStructures. The
  13. * structure defined in the RecordStructure and its PartStructures is used in
  14. * for any Records for the Asset. Records have Parts which parallel
  15. * PartStructures.
  16. *
  17. * <p>
  18. * OSID Version: 2.0
  19. * </p>
  20. *
  21. * @package harmoni.osid_v2.repository
  22. *
  23. * @copyright Copyright &copy;2005, Middlebury College
  24. * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
  25. *
  26. * @version $Id: HarmoniRecordStructure.class.php,v 1.36 2007/09/04 20:25:43 adamfranco Exp $
  27. */
  28.  
  29. class HarmoniRecordStructure
  30. extends RecordStructure
  31. {
  32. var $_schema;
  33. var $_createdParts;
  34. function HarmoniRecordStructure( $schema, $repositoryId ) {
  35. ArgumentValidator::validate($repositoryId, ExtendsValidatorRule::getRule("Id"));
  36. $this->_schema =$schema;
  37. $this->_repositoryId =$repositoryId;
  38. // create an array of created PartStructures so we can return references to
  39. // them instead of always making new ones.
  40. $this->_createdParts = array();
  41. }
  42. /**
  43. * Get the display name for this RecordStructure.
  44. *
  45. * @return string
  46. *
  47. * @throws object RepositoryException An exception with one of
  48. * the following messages defined in
  49. * org.osid.repository.RepositoryException may be thrown: {@link }
  50. * org.osid.repository.RepositoryException#OPERATION_FAILED
  51. * OPERATION_FAILED}, {@link }
  52. * org.osid.repository.RepositoryException#PERMISSION_DENIED
  53. * PERMISSION_DENIED}, {@link }
  54. * org.osid.repository.RepositoryException#CONFIGURATION_ERROR
  55. * CONFIGURATION_ERROR}, {@link }
  56. * org.osid.repository.RepositoryException#UNIMPLEMENTED
  57. * UNIMPLEMENTED}
  58. *
  59. * @access public
  60. */
  61. function getDisplayName () {
  62. return $this->_schema->getDisplayName();
  63. }
  64.  
  65. /**
  66. * Update the display name for this RecordStructure.
  67. *
  68. * @param string $displayName
  69. *
  70. * @throws object RepositoryException An exception with one of
  71. * the following messages defined in
  72. * org.osid.repository.RepositoryException may be thrown: {@link }
  73. * org.osid.repository.RepositoryException#OPERATION_FAILED
  74. * OPERATION_FAILED}, {@link }
  75. * org.osid.repository.RepositoryException#PERMISSION_DENIED
  76. * PERMISSION_DENIED}, {@link }
  77. * org.osid.repository.RepositoryException#CONFIGURATION_ERROR
  78. * CONFIGURATION_ERROR}, {@link }
  79. * org.osid.repository.RepositoryException#UNIMPLEMENTED
  80. * UNIMPLEMENTED}
  81. *
  82. * @access public
  83. */
  84. function updateDisplayName ( $displayName ) {
  85. $this->_schema->updateDisplayName($displayName);
  86. $schemaManager = Services::getService("SchemaManager");
  87. $schemaManager->synchronize($this->_schema);
  88. }
  89.  
  90. /**
  91. * Get the description for this RecordStructure.
  92. *
  93. * @return string
  94. *
  95. * @throws object RepositoryException An exception with one of
  96. * the following messages defined in
  97. * org.osid.repository.RepositoryException may be thrown: {@link }
  98. * org.osid.repository.RepositoryException#OPERATION_FAILED
  99. * OPERATION_FAILED}, {@link }
  100. * org.osid.repository.RepositoryException#PERMISSION_DENIED
  101. * PERMISSION_DENIED}, {@link }
  102. * org.osid.repository.RepositoryException#CONFIGURATION_ERROR
  103. * CONFIGURATION_ERROR}, {@link }
  104. * org.osid.repository.RepositoryException#UNIMPLEMENTED
  105. * UNIMPLEMENTED}
  106. *
  107. * @access public
  108. */
  109. function getDescription () {
  110. return $this->_schema->getDescription();
  111. }
  112. /**
  113. * Update the description for this RecordStructure.
  114. *
  115. * @param string $description
  116. *
  117. * @throws object RepositoryException An exception with one of
  118. * the following messages defined in
  119. * org.osid.repository.RepositoryException may be thrown: {@link }
  120. * org.osid.repository.RepositoryException#OPERATION_FAILED
  121. * OPERATION_FAILED}, {@link }
  122. * org.osid.repository.RepositoryException#PERMISSION_DENIED
  123. * PERMISSION_DENIED}, {@link }
  124. * org.osid.repository.RepositoryException#CONFIGURATION_ERROR
  125. * CONFIGURATION_ERROR}, {@link }
  126. * org.osid.repository.RepositoryException#UNIMPLEMENTED
  127. * UNIMPLEMENTED}
  128. *
  129. * @access public
  130. */
  131. function updateDescription ( $description ) {
  132. $this->_schema->updateDescription($description);
  133. $schemaManager = Services::getService("SchemaManager");
  134. $schemaManager->synchronize($this->_schema);
  135. }
  136.  
  137. /**
  138. * Get the unique Id for this RecordStructure.
  139. *
  140. * @return object Id
  141. *
  142. * @throws object RepositoryException An exception with one of
  143. * the following messages defined in
  144. * org.osid.repository.RepositoryException may be thrown: {@link }
  145. * org.osid.repository.RepositoryException#OPERATION_FAILED
  146. * OPERATION_FAILED}, {@link }
  147. * org.osid.repository.RepositoryException#PERMISSION_DENIED
  148. * PERMISSION_DENIED}, {@link }
  149. * org.osid.repository.RepositoryException#CONFIGURATION_ERROR
  150. * CONFIGURATION_ERROR}, {@link }
  151. * org.osid.repository.RepositoryException#UNIMPLEMENTED
  152. * UNIMPLEMENTED}
  153. *
  154. * @access public
  155. */
  156. function getId () {
  157. $idManager = Services::getService("Id");
  158. return $idManager->getId($this->_schema->getID());
  159. }
  160.  
  161. /**
  162. * Get the PartStructure in the RecordStructure with the specified Id.
  163. * @param object $infoPartId
  164. * @return object PartStructure
  165. * @throws osid.dr.DigitalRepositoryException An exception with one of the following messages defined in osid.dr.DigitalRepositoryException may be thrown: {@link DigitalRepositoryException#OPERATION_FAILED OPERATION_FAILED}, {@link DigitalRepositoryException#PERMISSION_DENIED PERMISSION_DENIED}, {@link DigitalRepositoryException#CONFIGURATION_ERROR CONFIGURATION_ERROR}, {@link DigitalRepositoryException#UNIMPLEMENTED UNIMPLEMENTED}
  166. */
  167. function getPartStructure($partId) {
  168. ArgumentValidator::validate($partId, ExtendsValidatorRule::getRule("Id"));
  169. if (!isset($this->_createdParts[$partId->getIdString()])) {
  170. $this->_schema->load();
  171. // Check that the schema field exists
  172. if (!$this->_schema->fieldExists($partId->getIdString()))
  173. throwError(new Error(
  174. "Unknown PartStructure ID: ".$partId->getIdString(),
  175. "Repository", true));
  176. $schemaField =$this->_schema->getField($partId->getIdString());
  177. // Check that the schema field is active
  178. if (!$schemaField->isActive())
  179. throwError(new Error(
  180. "Unknown [Inactive] PartStructure ID: ".$partId->getIdString(),
  181. "Repository", true));
  182. $this->_createdParts[$partId->getIdString()] = new HarmoniPartStructure(
  183. $this, $schemaField, $this->_repositoryId);
  184. }
  185. return $this->_createdParts[$partId->getIdString()];
  186. }
  187.  
  188. /**
  189. * Get all the PartStructures in the RecordStructure. Iterators return a
  190. * set, one at a time.
  191. *
  192. * @return object PartStructureIterator
  193. *
  194. * @throws object RepositoryException An exception with one of
  195. * the following messages defined in
  196. * org.osid.repository.RepositoryException may be thrown: {@link }
  197. * org.osid.repository.RepositoryException#OPERATION_FAILED
  198. * OPERATION_FAILED}, {@link }
  199. * org.osid.repository.RepositoryException#PERMISSION_DENIED
  200. * PERMISSION_DENIED}, {@link }
  201. * org.osid.repository.RepositoryException#CONFIGURATION_ERROR
  202. * CONFIGURATION_ERROR}, {@link }
  203. * org.osid.repository.RepositoryException#UNIMPLEMENTED
  204. * UNIMPLEMENTED}
  205. *
  206. * @access public
  207. */
  208. function getPartStructures () {
  209. $this->_schema->load();
  210. $array = array();
  211. foreach ($this->_schema->getAllIDs() as $id) {
  212. $fieldDef =$this->_schema->getField($id);
  213. if (!isset($this->_createdParts[$id]))
  214. $this->_createdParts[$id] = new HarmoniPartStructure($this, $fieldDef, $this->_repositoryId);
  215. }
  216. $obj = new HarmoniRecordStructureIterator($this->_createdParts);
  217. return $obj;
  218. }
  219.  
  220. /**
  221. * Get the schema for this RecordStructure. The schema is defined by the
  222. * implementation, e.g. Dublin Core.
  223. *
  224. * @return string
  225. *
  226. * @throws object RepositoryException An exception with one of
  227. * the following messages defined in
  228. * org.osid.repository.RepositoryException may be thrown: {@link }
  229. * org.osid.repository.RepositoryException#OPERATION_FAILED
  230. * OPERATION_FAILED}, {@link }
  231. * org.osid.repository.RepositoryException#PERMISSION_DENIED
  232. * PERMISSION_DENIED}, {@link }
  233. * org.osid.repository.RepositoryException#CONFIGURATION_ERROR
  234. * CONFIGURATION_ERROR}, {@link }
  235. * org.osid.repository.RepositoryException#UNIMPLEMENTED
  236. * UNIMPLEMENTED}
  237. *
  238. * @access public
  239. */
  240. function getSchema () {
  241. $other = $this->_schema->getOtherParameters();
  242. if (isset($other['schema'])) return $other['schema'];
  243. return "Harmoni DataManager User-defined Schema: ".$this->_schema->getID();
  244. }
  245.  
  246. /**
  247. * Return true if this RecordStructure is repeatable; false otherwise.
  248. * This is determined by the implementation.
  249. *
  250. * @return boolean
  251. *
  252. * @throws object RepositoryException An exception with one of
  253. * the following messages defined in
  254. * org.osid.repository.RepositoryException may be thrown: {@link }
  255. * org.osid.repository.RepositoryException#OPERATION_FAILED
  256. * OPERATION_FAILED}, {@link }
  257. * org.osid.repository.RepositoryException#PERMISSION_DENIED
  258. * PERMISSION_DENIED}, {@link }
  259. * org.osid.repository.RepositoryException#CONFIGURATION_ERROR
  260. * CONFIGURATION_ERROR}, {@link }
  261. * org.osid.repository.RepositoryException#UNIMPLEMENTED
  262. * UNIMPLEMENTED}
  263. *
  264. * @access public
  265. */
  266. function isRepeatable () {
  267. die ("Method <b>".__FUNCTION__."()</b> declared in interface<b> ".__CLASS__."</b> has not been overloaded in a child class.");
  268. }
  269.  
  270. /**
  271. * Get the format for this RecordStructure. The format is defined by the
  272. * implementation, e.g. XML.
  273. *
  274. * @return string
  275. *
  276. * @throws object RepositoryException An exception with one of
  277. * the following messages defined in
  278. * org.osid.repository.RepositoryException may be thrown: {@link }
  279. * org.osid.repository.RepositoryException#OPERATION_FAILED
  280. * OPERATION_FAILED}, {@link }
  281. * org.osid.repository.RepositoryException#PERMISSION_DENIED
  282. * PERMISSION_DENIED}, {@link }
  283. * org.osid.repository.RepositoryException#CONFIGURATION_ERROR
  284. * CONFIGURATION_ERROR}, {@link }
  285. * org.osid.repository.RepositoryException#UNIMPLEMENTED
  286. * UNIMPLEMENTED}
  287. *
  288. * @access public
  289. */
  290. function getFormat () {
  291. $other = $this->_schema->getOtherParameters();
  292. if (isset($other['format'])) return $other['format'];
  293. return _("Plain Text - UTF-8 encoding");
  294. }
  295. /**
  296. * Update the format for this RecordStructure.
  297. *
  298. * @param string $format
  299. *
  300. * @throws object RepositoryException An exception with one of
  301. * the following messages defined in
  302. * org.osid.repository.RepositoryException may be thrown: {@link }
  303. * org.osid.repository.RepositoryException#OPERATION_FAILED
  304. * OPERATION_FAILED}, {@link }
  305. * org.osid.repository.RepositoryException#PERMISSION_DENIED
  306. * PERMISSION_DENIED}, {@link }
  307. * org.osid.repository.RepositoryException#CONFIGURATION_ERROR
  308. * CONFIGURATION_ERROR}, {@link }
  309. * org.osid.repository.RepositoryException#UNIMPLEMENTED
  310. * UNIMPLEMENTED}
  311. *
  312. * @access public
  313. */
  314. function updateFormat ( $format ) {
  315. $other = $this->_schema->getOtherParameters();
  316. $other['format'] = $format;
  317. $this->_schema->updateOtherParameters($other);
  318. $schemaManager = Services::getService("SchemaManager");
  319. $schemaManager->synchronize($this->_schema);
  320. }
  321. /**
  322. * Get the Type for this RecordStructure.
  323. *
  324. * @return object Type
  325. *
  326. * @throws object RepositoryException An exception with one of
  327. * the following messages defined in
  328. * org.osid.repository.RepositoryException may be thrown: {@link }
  329. * org.osid.repository.RepositoryException#OPERATION_FAILED
  330. * OPERATION_FAILED}, {@link }
  331. * org.osid.repository.RepositoryException#PERMISSION_DENIED
  332. * PERMISSION_DENIED}, {@link }
  333. * org.osid.repository.RepositoryException#CONFIGURATION_ERROR
  334. * CONFIGURATION_ERROR}, {@link }
  335. * org.osid.repository.RepositoryException#UNIMPLEMENTED
  336. * UNIMPLEMENTED}
  337. *
  338. * @access public
  339. */
  340. function getType () {
  341. $type = new Type("RecordStructures", "edu.middlebury.harmoni", "DataManagerPrimatives", "RecordStructures stored in the Harmoni DataManager.");
  342. return $type;
  343. }
  344.  
  345.  
  346. /**
  347. * Validate a Record against its RecordStructure. Return true if valid;
  348. * false otherwise. The status of the Asset holding this Record is not
  349. * changed through this method. The implementation may throw an Exception
  350. * for any validation failures and use the Exception's message to identify
  351. * specific causes.
  352. *
  353. * @param object Record $record
  354. *
  355. * @return boolean
  356. *
  357. * @throws object RepositoryException An exception with one of
  358. * the following messages defined in
  359. * org.osid.repository.RepositoryException may be thrown: {@link }
  360. * org.osid.repository.RepositoryException#OPERATION_FAILED
  361. * OPERATION_FAILED}, {@link }
  362. * org.osid.repository.RepositoryException#PERMISSION_DENIED
  363. * PERMISSION_DENIED}, {@link }
  364. * org.osid.repository.RepositoryException#CONFIGURATION_ERROR
  365. * CONFIGURATION_ERROR}, {@link }
  366. * org.osid.repository.RepositoryException#UNIMPLEMENTED
  367. * UNIMPLEMENTED}, {@link }
  368. * org.osid.repository.RepositoryException#NULL_ARGUMENT
  369. * NULL_ARGUMENT}
  370. *
  371. * @access public
  372. */
  373. function validateRecord ( $record ) {
  374. // all we can really do is make sure the DataSet behind the Record is of the correct
  375. // type to match this RecordStructure (DataSetTypeDefinition).
  376. return true; // for now
  377. }
  378.  
  379. /**
  380. * Create an PartStructure in this RecordStructure. This is not part of the Repository OSID at
  381. * the time of this writing, but is needed for dynamically created
  382. * RecordStructures/PartStructures.
  383. *
  384. * @param string $displayName The DisplayName of the new RecordStructure.
  385. * @param string $description The Description of the new RecordStructure.
  386. * @param object Type $type One of the InfoTypes supported by this implementation.
  387. * E.g. string, shortstring, blob, datetime, integer, float,
  388. *
  389. * @param boolean $isMandatory True if the PartStructure is Mandatory.
  390. * @param boolean $isRepeatable True if the PartStructure is Repeatable.
  391. * @param boolean $isPopulatedByDR True if the PartStructure is PopulatedBy the DR.
  392. * @param optional object $id An optional {@link HarmoniId} object for this part structure.
  393. *
  394. * @return object PartStructure The newly created PartStructure.
  395. */
  396. function createPartStructure($displayName, $description, $partType, $isMandatory, $isRepeatable, $isPopulatedByRepository, $theid=null) {
  397. ArgumentValidator::validate($displayName, StringValidatorRule::getRule());
  398. ArgumentValidator::validate($description, StringValidatorRule::getRule());
  399. ArgumentValidator::validate($partType, ExtendsValidatorRule::getRule("Type"));
  400. ArgumentValidator::validate($isMandatory, BooleanValidatorRule::getRule());
  401. ArgumentValidator::validate($isRepeatable, BooleanValidatorRule::getRule());
  402. ArgumentValidator::validate($isPopulatedByRepository, BooleanValidatorRule::getRule());
  403. if ($theid == null) {
  404. $idManager = Services::getService("Id");
  405. $id =$idManager->createId();
  406. $label = $id->getIdString();
  407. } else {
  408. // check if this ID follows our Schema's ID
  409. $id =$theid;
  410. if (strpos($id->getIdString(), $this->_schema->getID()) != 0) {
  411. throwError(new Error("Could not create PartStructure -- the passed ID does not conform to the Schema's internal ID: ".$this->_schema->getID(), "Repository", true));
  412. }
  413. $label = str_replace($this->_schema->getID() . ".", "", $id->getIdString());
  414. }
  415. $fieldDef = new SchemaField($label, $displayName, $partType->getKeyword(), $description, $isRepeatable, $isMandatory);
  416. $schema =$this->_schema->deepCopy();
  417. $schema->addField($fieldDef);
  418. $sm = Services::getService("SchemaManager");
  419. $sm->synchronize($schema);
  420. $this->_schema =$sm->getSchemaByID($this->_schema->getID());
  421.  
  422. $idString = $this->_schema->getFieldIDFromLabel($label);
  423. $this->_createdParts[$idString] = new HarmoniPartStructure($this,
  424. $fieldDef, $this->_repositoryId);
  425. return $this->_createdParts[$idString];
  426. }
  427.  
  428. /**
  429. * Get the possible types for PartStructures.
  430. *
  431. * WARNING: NOT IN OSID - Use at your own risk.
  432. *
  433. * @return object TypeIterator The Types supported in this implementation.
  434. */
  435. function getPartStructureTypes() {
  436. $types = array();
  437. $typeMgr = Services::getService("DataTypeManager");
  438. foreach ($typeMgr->getRegisteredTypes() as $dataType) {
  439. $types[] = new HarmoniType ("Repository","edu.middlebury.harmoni",$dataType);
  440. }
  441. $typeIterator = new HarmoniTypeIterator($types);
  442. return $typeIterator;
  443. }
  444. /**
  445. * Convert this PartStructure and all of its associated Parts to a new type.
  446. * Usage of this method may cause data-loss if the types are do not convert well.
  447. *
  448. * WARNING: NOT IN OSID
  449. *
  450. * @param object Id $partStructureId
  451. * @param object Type $type
  452. * @return void
  453. * @access public
  454. * @since 6/8/06
  455. */
  456. function convertPartStructureToType ( $partStructureId, $type, $statusStars = null ) {
  457. $oldPartStructure =$this->getPartStructure($partStructureId);
  458. $newPartStructure =$this->createPartStructure(
  459. $oldPartStructure->getDisplayName(),
  460. $oldPartStructure->getDescription(),
  461. $type,
  462. $oldPartStructure->isMandatory(),
  463. $oldPartStructure->isRepeatable(),
  464. $oldPartStructure->isPopulatedByRepository());
  465. // Convert the Data
  466. $repositoryManager = Services::getService("Repository");
  467. $myRecordStructureId =$this->getId();
  468. $repositories =$repositoryManager->getRepositories();
  469. while($repositories->hasNext()) {
  470. $repository =$repositories->next();
  471. $recordStructures =$repository->getRecordStructures();
  472. while($recordStructures->hasNext()) {
  473. $recordStructure =$recordStructures->next();
  474. // If the current Repository has this record structure, convert
  475. // the records for it in its assets.
  476. if ($myRecordStructureId->isEqual($recordStructure->getId())) {
  477. $assets =$repository->getAssets();
  478. if (!is_null($statusStars))
  479. $statusStars->initializeStatistics($assets->count());
  480. while ($assets->hasNext()) {
  481. $asset =$assets->next();
  482. $records =$asset->getRecordsByRecordStructure(
  483. $myRecordStructureId);
  484. while ($records->hasNext()) {
  485. $record =$records->next();
  486. $parts =$record->getPartsByPartStructure($partStructureId);
  487. while ($parts->hasNext()) {
  488. $oldPart =$parts->next();
  489. $oldValue =$oldPart->getValue();
  490. $oldValueString = $oldValue->asString();
  491. $newPart =$record->createPart(
  492. $newPartStructure->getId(),
  493. $oldPart->getValue());
  494. $record->deletePart($oldPart->getId());
  495. $newValue =$newPart->getValue();
  496. $newValueString = $newValue->asString();
  497. if ($oldValueString != $newValueString) {
  498. throwError(new Error("'$newValueString' should be equal to '$oldValueString'", "repository"));
  499. }
  500. }
  501. }
  502. if (!is_null($statusStars))
  503. $statusStars->updateStatistics();
  504. }
  505. }
  506. }
  507. }
  508.  
  509. // Delete the old part Structure
  510. $this->deletePartStructure($partStructureId);
  511. return $newPartStructure;
  512. }
  513. /**
  514. * Delete a PartStucture
  515. *
  516. * @param object Id $partStructureId
  517. * @return void
  518. * @access public
  519. * @since 6/8/06
  520. */
  521. function deletePartStructure ( $partStructureId ) {
  522. // Delete the Structure
  523. $schemaMgr = Services::getService("SchemaManager");
  524. $recordMgr = Services::getService("RecordManager");
  525. $partStructure =$this->getPartStructure($partStructureId);
  526. $dummyValues = array(String::withValue('4000-02-05'));
  527. $recordIdsWithValues = $recordMgr->getRecordSetIDsBySearch(
  528. new FieldValueSearch(
  529. $this->_schema->getID(),
  530. $this->_schema->getFieldLabelFromID($partStructureId->getIdString()),
  531. new HarmoniIterator($dummyValues),
  532. SEARCH_TYPE_NOT_IN_LIST));
  533. if (count($recordIdsWithValues)) {
  534. throwError(new Error(
  535. RepositoryException::OPERATION_FAILED()
  536. ." when deleting RecordStructure: '"
  537. .$recordStructureId->getIdString()
  538. ."', Records exist for this RecordStructure.",
  539. "Repository", 1));
  540. }
  541. $sm = Services::getService("SchemaManager");
  542. $this->_schema->deleteField($partStructureId->getIdString());
  543. $sm->synchronize($this->_schema);
  544. $partStructure = null;
  545. }
  546. }

Documentation generated on Wed, 19 Sep 2007 10:24:14 -0400 by phpDocumentor 1.3.0RC3