ldp_nr.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. from rdflib import Graph
  2. from rdflib.namespace import RDF, XSD
  3. from rdflib.resource import Resource
  4. from rdflib.term import URIRef, Literal, Variable
  5. from lakesuperior.config_parser import config
  6. from lakesuperior.dictionaries.namespaces import ns_collection as nsc
  7. from lakesuperior.model.ldpr import Ldpr, transactional, must_exist
  8. from lakesuperior.model.ldp_rs import LdpRs
  9. from lakesuperior.util.digest import Digest
  10. class LdpNr(Ldpr):
  11. '''LDP-NR (Non-RDF Source).
  12. Definition: https://www.w3.org/TR/ldp/#ldpnr
  13. '''
  14. base_types = {
  15. nsc['fcrepo'].Binary,
  16. nsc['fcrepo'].Resource,
  17. nsc['ldp'].Resource,
  18. nsc['ldp'].NonRDFSource,
  19. }
  20. @property
  21. def nonrdfly(self):
  22. '''
  23. Load non-RDF (binary) store layout.
  24. '''
  25. if not hasattr(self, '_nonrdfly'):
  26. self._nonrdfly = __class__.load_layout('non_rdf')
  27. return self._nonrdfly
  28. @property
  29. def filename(self):
  30. return self.imr.value(nsc['ebucore'].filename)
  31. @property
  32. def local_path(self):
  33. cksum_term = self.imr.value(nsc['premis'].hasMessageDigest)
  34. cksum = str(cksum_term.identifier.replace('urn:sha1:',''))
  35. return self.nonrdfly.local_path(cksum)
  36. ## LDP METHODS ##
  37. def get(self, **kwargs):
  38. return LdpRs(self.uuid).get(**kwargs)
  39. @transactional
  40. def post(self, stream, mimetype=None, disposition=None):
  41. '''
  42. Create a new binary resource with a corresponding RDF representation.
  43. @param file (Stream) A Stream resource representing the uploaded file.
  44. '''
  45. # Persist the stream.
  46. uuid = self.nonrdfly.persist(stream)
  47. # Gather RDF metadata.
  48. self._add_metadata(stream, mimetype=mimetype, disposition=disposition)
  49. # Try to persist metadata. If it fails, delete the file.
  50. self._logger.debug('Persisting LDP-NR triples in {}'.format(
  51. self.urn))
  52. try:
  53. rsrc = self.rdfly.create_rsrc(self.imr)
  54. except:
  55. self.nonrdfly.delete(uuid)
  56. else:
  57. return rsrc
  58. def put(self, stream, **kwargs):
  59. return self.post(stream, **kwargs)
  60. ## PROTECTED METHODS ##
  61. def _add_metadata(self, stream, mimetype='application/octet-stream',
  62. disposition=None):
  63. '''
  64. Add all metadata for the RDF representation of the LDP-NR.
  65. @param stream (BufferedIO) The uploaded data stream.
  66. @param mimetype (string) MIME type of the uploaded file.
  67. @param disposition (defaultdict) The `Content-Disposition` header
  68. content, parsed through `parse_rfc7240`.
  69. '''
  70. # File size.
  71. self._logger.debug('Data stream size: {}'.format(stream.limit))
  72. self.stored_or_new_imr.add(nsc['premis'].hasSize, Literal(stream.limit,
  73. datatype=XSD.long))
  74. # Checksum.
  75. cksum_term = URIRef('urn:sha1:{}'.format(self.uuid))
  76. self.imr.add(nsc['premis'].hasMessageDigest, cksum_term)
  77. # MIME type.
  78. self.imr.add(nsc['ebucore']['hasMimeType'], Literal(
  79. mimetype, datatype=XSD.string))
  80. # File name.
  81. self._logger.debug('Disposition: {}'.format(disposition))
  82. try:
  83. self.imr.add(nsc['ebucore']['filename'], Literal(
  84. disposition['attachment']['parameters']['filename'],
  85. datatype=XSD.string))
  86. except KeyError:
  87. pass