ldp_nr.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import pdb
  2. from rdflib import Graph
  3. from rdflib.namespace import RDF, XSD
  4. from rdflib.resource import Resource
  5. from rdflib.term import URIRef, Literal, Variable
  6. from lakesuperior.env import env
  7. from lakesuperior.dictionaries.namespaces import ns_collection as nsc
  8. from lakesuperior.model.ldpr import Ldpr
  9. from lakesuperior.model.ldp_rs import LdpRs
  10. nonrdfly = env.app_globals.nonrdfly
  11. class LdpNr(Ldpr):
  12. '''LDP-NR (Non-RDF Source).
  13. Definition: https://www.w3.org/TR/ldp/#ldpnr
  14. '''
  15. base_types = {
  16. nsc['fcrepo'].Binary,
  17. nsc['fcrepo'].Resource,
  18. nsc['ldp'].Resource,
  19. nsc['ldp'].NonRDFSource,
  20. }
  21. def __init__(self, uuid, stream=None, mimetype=None,
  22. disposition=None, **kwargs):
  23. '''
  24. Extends Ldpr.__init__ by adding LDP-NR specific parameters.
  25. '''
  26. super().__init__(uuid, **kwargs)
  27. self._imr_options = {}
  28. if stream:
  29. self.workflow = self.WRKF_INBOUND
  30. self.stream = stream
  31. else:
  32. self.workflow = self.WRKF_OUTBOUND
  33. if not mimetype:
  34. self.mimetype = (
  35. self.metadata.value(nsc['ebucore'].hasMimeType)
  36. if self.is_stored
  37. else 'application/octet-stream')
  38. else:
  39. self.mimetype = mimetype
  40. self.disposition = disposition
  41. @property
  42. def filename(self):
  43. return self.imr.value(nsc['ebucore'].filename)
  44. @property
  45. def local_path(self):
  46. cksum_term = self.imr.value(nsc['premis'].hasMessageDigest)
  47. cksum = str(cksum_term.identifier.replace('urn:sha1:',''))
  48. return nonrdfly.local_path(cksum)
  49. def create_or_replace_rsrc(self, create_only=False):
  50. '''
  51. Create a new binary resource with a corresponding RDF representation.
  52. @param file (Stream) A Stream resource representing the uploaded file.
  53. '''
  54. # Persist the stream.
  55. self.digest, self.size = nonrdfly.persist(self.stream)
  56. # Try to persist metadata. If it fails, delete the file.
  57. self._logger.debug('Persisting LDP-NR triples in {}'.format(self.uri))
  58. try:
  59. ev_type = super().create_or_replace_rsrc(create_only)
  60. except:
  61. # self.digest is also the file UID.
  62. nonrdfly.delete(self.digest)
  63. raise
  64. else:
  65. return ev_type
  66. def patch_metadata(self, update_str):
  67. '''
  68. Update resource metadata by applying a SPARQL-UPDATE query.
  69. @param update_str (string) SPARQL-Update staements.
  70. '''
  71. self.handling = 'lenient' # FCREPO does that and Hyrax requires it.
  72. return self._sparql_update(update_str)
  73. ## PROTECTED METHODS ##
  74. def _add_srv_mgd_triples(self, create=False):
  75. '''
  76. Add all metadata for the RDF representation of the LDP-NR.
  77. @param stream (BufferedIO) The uploaded data stream.
  78. @param mimetype (string) MIME type of the uploaded file.
  79. @param disposition (defaultdict) The `Content-Disposition` header
  80. content, parsed through `parse_rfc7240`.
  81. '''
  82. super()._add_srv_mgd_triples(create)
  83. # File size.
  84. self._logger.debug('Data stream size: {}'.format(self.size))
  85. self.provided_imr.set(nsc['premis'].hasSize, Literal(self.size))
  86. # Checksum.
  87. cksum_term = URIRef('urn:sha1:{}'.format(self.digest))
  88. self.provided_imr.set(nsc['premis'].hasMessageDigest, cksum_term)
  89. # MIME type.
  90. self.provided_imr.set(nsc['ebucore']['hasMimeType'],
  91. Literal(self.mimetype))
  92. # File name.
  93. self._logger.debug('Disposition: {}'.format(self.disposition))
  94. try:
  95. self.provided_imr.set(nsc['ebucore']['filename'], Literal(
  96. self.disposition['attachment']['parameters']['filename']))
  97. except (KeyError, TypeError) as e:
  98. pass