class RDF::LDP::DirectContainer

An extension of `RDF::LDP::Container` implementing direct containment. This adds the concepts of a membership resource, predicate, and triples to the Basic Container's containment triples.

When the membership resource is an `RDFSource`, the membership triple is added/removed from its graph when the resource created/deleted within the container. When the membership resource is a `NonRDFSource`, the triple is added/removed on its description's graph instead.

A membership constant URI and membership predicate MUST be specified as described in LDP–exactly one of each. If none is given, we default to the container itself as a membership resource and `ldp:member` as predicate. If more than one of either is given, all `#add/#remove` (POST/DELETE) requests will fail.

@see www.w3.org/TR/ldp/#dfn-linked-data-platform-direct-container

definition of LDP Direct Container

Constants

MEMBERSHIP_RESOURCE_URI
MEMBER_URI
RELATION_TERMS

Public Class Methods

to_uri() click to toggle source
# File lib/rdf/ldp/direct_container.rb, line 27
def self.to_uri
  RDF::Vocab::LDP.DirectContainer
end

Public Instance Methods

add(resource, transaction = nil) click to toggle source

Adds a member `resource` to the container. Handles containment and adds membership triple to the memebership resource.

@see RDF::LDP::Container#add

Calls superclass method RDF::LDP::Container#add
# File lib/rdf/ldp/direct_container.rb, line 67
def add(resource, transaction = nil)
  process_membership_resource(resource,
                              transaction) do |container, quad, subject|
    super(subject, transaction) # super handles nil transaction case
    target = transaction || container.graph
    target.insert(quad)
  end
  self
end
container_class() click to toggle source

@return [RDF::URI] a URI representing the container type

# File lib/rdf/ldp/direct_container.rb, line 33
def container_class
  CONTAINER_CLASSES[:direct]
end
create(input, content_type) click to toggle source

Creates and inserts default relation triples if none are given.

@note the addition of default triples is handled in a separate

transaction. It is possible for the second transaction to fail, causing
the resource to persist in an invalid state. It is also possible for a
read to occur between the two transactions.

@todo Make atomic. Consider just raising an error instead of adding

triples. There's a need to handle this issue for repositories with
snapshot reads, as well as those without.

@see Container#create

Calls superclass method RDF::LDP::Container#create
# File lib/rdf/ldp/direct_container.rb, line 49
def create(input, content_type)
  super

  graph.transaction(mutable: true) do |tx|
    tx.insert(default_member_relation_statement) if
      member_relation_statements.empty?
    tx.insert(default_membership_resource_statement) if
      membership_resource_statements.empty?
  end

  self
end
make_membership_triple(resource) click to toggle source

@param [RDF::Term] resource a member for this container

@return [RDF::URI] the membership triple representing membership of the

`resource` parameter in this container

@see www.w3.org/TR/ldp/#dfn-membership-triples

# File lib/rdf/ldp/direct_container.rb, line 134
def make_membership_triple(resource)
  predicate = membership_predicate
  return RDF::Statement(membership_constant_uri, predicate, resource) if
    member_relation_statements.first.predicate == RELATION_TERMS.first
  RDF::Statement(resource, predicate, membership_constant_uri)
end
membership_constant_uri() click to toggle source

Gives the membership constant URI. If none is present in the container state, we add the current resource as a membership constant.

@return [RDF::URI] the membership constant uri for the container

@raise [RDF::LDP::NotAcceptable] if multiple membership constant uris

exist

@see www.w3.org/TR/ldp/#dfn-membership-triples

# File lib/rdf/ldp/direct_container.rb, line 102
def membership_constant_uri
  statements = membership_resource_statements
  return statements.first.object if statements.count == 1

  raise(NotAcceptable, 'An LDP-DC MUST have exactly one membership ' \
                       "resource; found #{statements.count}.")
end
membership_predicate() click to toggle source

Gives the membership predicate. If none is present in the container state, we add the current resource as a membership constant.

@return [RDF::URI] the membership predicate

@raise [RDF::LDP::NotAcceptable] if multiple membership predicates exist

@see www.w3.org/TR/ldp/#dfn-membership-predicate

# File lib/rdf/ldp/direct_container.rb, line 119
def membership_predicate
  statements = member_relation_statements
  return statements.first.object if statements.count == 1

  raise(NotAcceptable, 'An LDP-DC MUST have exactly one member ' \
                       "relation triple; found #{statements.count}.")
end
remove(resource, transaction = nil) click to toggle source

Removes a member `resource` to the container. Handles containment and removes membership triple to the memebership resource.

@see RDF::LDP::Container#remove

Calls superclass method RDF::LDP::Container#remove
# File lib/rdf/ldp/direct_container.rb, line 82
def remove(resource, transaction = nil)
  process_membership_resource(resource,
                              transaction) do |container, quad, subject|
    super(subject, transaction) # super handles nil transaction case
    target = transaction || container.graph
    target.delete(quad)
  end
  self
end

Private Instance Methods

default_member_relation_statement() click to toggle source
# File lib/rdf/ldp/direct_container.rb, line 172
def default_member_relation_statement
  RDF::Statement(subject_uri, RELATION_TERMS.first, MEMBER_URI)
end
default_membership_resource_statement() click to toggle source
# File lib/rdf/ldp/direct_container.rb, line 168
def default_membership_resource_statement
  RDF::Statement(subject_uri, MEMBERSHIP_RESOURCE_URI, subject_uri)
end
member_relation_statements() click to toggle source
# File lib/rdf/ldp/direct_container.rb, line 147
def member_relation_statements
  graph.query([subject_uri, nil, nil]).select do |st|
    RELATION_TERMS.include?(st.predicate)
  end
end
membership_resource() click to toggle source
# File lib/rdf/ldp/direct_container.rb, line 153
def membership_resource
  uri = membership_constant_uri
  uri = uri.fragment ? (uri.root / uri.request_uri) : uri
  resource = RDF::LDP::Resource.find(uri, @data)
  return resource.description if resource.non_rdf_source?
  resource
end
membership_resource_statements() click to toggle source
# File lib/rdf/ldp/direct_container.rb, line 143
def membership_resource_statements
  graph.query([subject_uri, MEMBERSHIP_RESOURCE_URI, :o])
end
process_membership_resource(resource, _transaction = nil, member = nil) { |self, membership_triple, resource| ... } click to toggle source
# File lib/rdf/ldp/direct_container.rb, line 161
def process_membership_resource(resource, _transaction = nil, member = nil)
  membership_triple = make_membership_triple((member || resource).to_uri)

  membership_triple.graph_name = subject_uri
  yield(self, membership_triple, resource) if block_given?
end