ldp_nr.py 3.7 KB

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