ld4l-ore_rdf 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +25 -0
  4. data/.travis.yml +12 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE.txt +14 -0
  7. data/README.md +171 -0
  8. data/Rakefile +2 -0
  9. data/ld4l-ore_rdf.gemspec +45 -0
  10. data/lib/ld4l/ore_rdf/configuration.rb +41 -0
  11. data/lib/ld4l/ore_rdf/models/aggregation.rb +50 -0
  12. data/lib/ld4l/ore_rdf/models/aggregation_resource.rb +98 -0
  13. data/lib/ld4l/ore_rdf/models/proxy_resource.rb +54 -0
  14. data/lib/ld4l/ore_rdf/services/aggregation/add_aggregated_resource.rb +49 -0
  15. data/lib/ld4l/ore_rdf/services/aggregation/add_aggregated_resources.rb +28 -0
  16. data/lib/ld4l/ore_rdf/services/aggregation/create.rb +39 -0
  17. data/lib/ld4l/ore_rdf/services/aggregation/destroy.rb +47 -0
  18. data/lib/ld4l/ore_rdf/services/aggregation/destroy_with_id.rb +22 -0
  19. data/lib/ld4l/ore_rdf/services/aggregation/find.rb +72 -0
  20. data/lib/ld4l/ore_rdf/services/aggregation/persist.rb +34 -0
  21. data/lib/ld4l/ore_rdf/services/aggregation/resume.rb +30 -0
  22. data/lib/ld4l/ore_rdf/services/proxy/create.rb +64 -0
  23. data/lib/ld4l/ore_rdf/services/proxy/find.rb +93 -0
  24. data/lib/ld4l/ore_rdf/version.rb +5 -0
  25. data/lib/ld4l/ore_rdf/vocab/co.rb +27 -0
  26. data/lib/ld4l/ore_rdf/vocab/dcterms.rb +6 -0
  27. data/lib/ld4l/ore_rdf/vocab/iana.rb +9 -0
  28. data/lib/ld4l/ore_rdf/vocab/ore.rb +16 -0
  29. data/lib/ld4l/ore_rdf.rb +76 -0
  30. data/spec/ld4l/ore_rdf/configuration_spec.rb +174 -0
  31. data/spec/ld4l/ore_rdf/models/aggregation_resource_spec.rb +830 -0
  32. data/spec/ld4l/ore_rdf/models/aggregation_spec.rb +9 -0
  33. data/spec/ld4l/ore_rdf/models/proxy_resource_spec.rb +690 -0
  34. data/spec/ld4l/ore_rdf/services/aggregation/add_aggregated_resource_spec.rb +36 -0
  35. data/spec/ld4l/ore_rdf/services/aggregation/add_aggregated_resources_spec.rb +78 -0
  36. data/spec/ld4l/ore_rdf/services/aggregation/create_spec.rb +62 -0
  37. data/spec/ld4l/ore_rdf/services/aggregation/destroy_spec.rb +169 -0
  38. data/spec/ld4l/ore_rdf/services/aggregation/find_spec.rb +198 -0
  39. data/spec/ld4l/ore_rdf/services/aggregation/persist_spec.rb +13 -0
  40. data/spec/ld4l/ore_rdf/services/aggregation/resume_spec.rb +46 -0
  41. data/spec/ld4l/ore_rdf/services/proxy/create_spec.rb +143 -0
  42. data/spec/ld4l/ore_rdf/services/proxy/find_spec.rb +138 -0
  43. data/spec/ld4l/ore_rdf_spec.rb +53 -0
  44. data/spec/spec_helper.rb +23 -0
  45. metadata +259 -0
@@ -0,0 +1,54 @@
1
+ module LD4L
2
+ module OreRDF
3
+ class ProxyResource < ActiveTriples::Resource
4
+
5
+ class << self; attr_reader :localname_prefix end
6
+ @localname_prefix="px"
7
+
8
+ # configure :base_uri => LD4L::OreRDF.configuration.base_uri, repository => :default
9
+ configure :type => RDFVocabularies::ORE.Proxy, :base_uri => LD4L::OreRDF.configuration.base_uri, :repository => :default
10
+
11
+ property :proxy_for, :predicate => RDFVocabularies::ORE.proxyFor
12
+ property :proxy_in, :predicate => RDFVocabularies::ORE.proxyIn, :class_name => LD4L::OreRDF::AggregationResource
13
+ property :next_proxy, :predicate => RDFVocabularies::IANA.next, :class_name => LD4L::OreRDF::ProxyResource
14
+ property :prev_proxy, :predicate => RDFVocabularies::IANA.prev, :class_name => LD4L::OreRDF::ProxyResource
15
+ property :contributor, :predicate => RDF::DC.contributor, :class_name => LD4L::FoafRDF::Person # TODO User who added this item to the Aggregation (default=Aggregation's owner)
16
+
17
+
18
+ # --------------------- #
19
+ # HELPER METHODS #
20
+ # --------------------- #
21
+
22
+
23
+ ########### NEED TO MOVE TO SERVICE OBJECT ####################
24
+
25
+
26
+ # Returns an array of the LD4L::OreRDF::ProxyResource instances for the items in the aggregation
27
+ # TODO: How to begin at start and limit to number of returned items, effectively handling ranges of data.
28
+ def self.get_range( aggregation, start=0, limit=nil )
29
+ # TODO: Stubbed to return all items. Need to implement start and limit features.
30
+
31
+ # argument validation
32
+ # raise ArgumentError, 'Argument must be a string with at least one character' unless
33
+ # tag_value.kind_of?(String) && tag_value.size > 0
34
+
35
+ graph = ActiveTriples::Repositories.repositories[repository]
36
+ query = RDF::Query.new({
37
+ :proxy => {
38
+ RDF.type => RDFVocabularies::ORE.Proxy,
39
+ RDFVocabularies::ORE.proxyIn => aggregation,
40
+ }
41
+ })
42
+
43
+ proxies = []
44
+ results = query.execute(graph)
45
+ results.each do |r|
46
+ proxy_uri = r.to_hash[:proxy]
47
+ proxy = LD4L::OreRDF::ProxyResource.new(proxy_uri)
48
+ proxies << proxy
49
+ end
50
+ proxies
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,49 @@
1
+ module LD4L
2
+ module OreRDF
3
+ class AddAggregatedResource
4
+
5
+ ##
6
+ # Add a single item URI to the items for the aggregation.
7
+ # Optionally insert the item at the passed position. Append when position is nil.
8
+ # NOTE: Ordered lists is currently not supported. TODO: Implement ordered lists.
9
+ # TODO: WARNING: This does not look like it would scale. Getting all, adding to array, and setting all. Very costly when there are 10s of thousands.
10
+
11
+ ##
12
+ # Adds a resource to the list of aggregated resources for the aggregation inserting at the specified position or
13
+ # appends to the end if position is not specified. Creates a proxy object for the resource.
14
+ #
15
+ # @param [LD4L::OreRDF::Aggregation] :aggregation to which to add resource
16
+ # @param [RDF::URI] :resource - URI for the resources to be aggregated
17
+ # @param [insert_position] :position from beginning of the list of proxies when positive; position from the
18
+ # end of the list of proxies when negative
19
+ #
20
+ # @returns [LD4L::OreRDF::ProxyResource] the proxy created for the resource
21
+ def self.call(aggregation,resource,insert_position=nil)
22
+ raise ArgumentError, "resource must be either a string representation of an URI or an instance of RDF::URI" unless
23
+ resource.kind_of?(String) || resource.kind_of?(RDF::URI)
24
+
25
+ resource = RDF::URI(resource) unless resource.kind_of?(RDF::URI)
26
+
27
+ # validate aggregation is of correct type
28
+ raise ArgumentError, "aggregation is not LD4L::OreRDF::Aggregation" unless
29
+ aggregation.kind_of?(LD4L::OreRDF::Aggregation)
30
+
31
+
32
+ # aggregates = get_values('aggregates')
33
+ # aggregates << resource_uri
34
+ # set_value('aggregates',aggregates)
35
+
36
+ aggregates = aggregation.aggregates.dup
37
+ aggregates << resource
38
+ aggregation.aggregates = aggregates
39
+
40
+ LD4L::OreRDF::CreateProxy.call(
41
+ :resource => resource,
42
+ :aggregation => aggregation,
43
+ :insert_position => insert_position)
44
+ end
45
+
46
+ end
47
+ end
48
+ end
49
+
@@ -0,0 +1,28 @@
1
+ module LD4L
2
+ module OreRDF
3
+ class AddAggregatedResources
4
+
5
+ ##
6
+ # Adds each resource in the resource_array to the list of aggregated resources for the aggregation beginning at
7
+ # the specified position or appends to the end if position is not specified. Creates a proxy object for each
8
+ # resource.
9
+ #
10
+ # @param [LD4L::OreRDF::Aggregation] :aggregation to which to add resource
11
+ # @param [Array<RDF::URI>] resources - array of URIs for the resources to be aggregated
12
+ # @param [insert_position] :position from beginning of the list of proxies when positive; position from the
13
+ # end of the list of proxies when negative
14
+ #
15
+ # @returns [Array<LD4L::OreRDF::ProxyResource>] the proxies created for the resources
16
+ def self.call(aggregation,resources,insert_position=nil)
17
+ proxy_array = []
18
+ resources.each do |resource_uri|
19
+ # TODO should insert_position be different with each iteration; otherwise, won't they go in backwards???
20
+ proxy_array << LD4L::OreRDF::AddAggregatedResource.call(aggregation,resource_uri,insert_position)
21
+ end
22
+ proxy_array
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,39 @@
1
+ module LD4L
2
+ module OreRDF
3
+ class CreateAggregation
4
+
5
+
6
+
7
+
8
+ # TODO Should this service take an array of resources for the aggregation to aggregate?
9
+
10
+
11
+
12
+ ##
13
+ # Create an ore aggregation in one step passing in the required information.
14
+ #
15
+ # @param [Hash] options the options to use while generating the aggregation
16
+ # @option options [String, RDF::URI] :id - uri or localname to use for the rdf_subject of the new aggregation (optional)
17
+ # - full URI - [String, RDF::URI] used as passed in
18
+ # - partial id - [String] uri generated from base_uri + localname_prefix + id
19
+ # - nil - uri generated from base_uri + localname_prefix + minted localname
20
+ # @option options [String] :title - title of the aggregation (optional)
21
+ # @option options [String] :description - description of the aggregation (optional)
22
+ # @option options [String, LD4L::FoafRDF::Person] :owner - owner of the aggregation (optional)
23
+ #
24
+ # @returns an instance of the new aggregation (not persisted)
25
+ def self.call( options = {} )
26
+ id = options[:id] || ActiveTriples::LocalName::Minter.generate_local_name(
27
+ LD4L::OreRDF::AggregationResource, 10, { :prefix => LD4L::OreRDF::AggregationResource.localname_prefix})
28
+ aggregation_resource = LD4L::OreRDF::AggregationResource.new(id)
29
+ aggregation_resource.title = options[:title] || []
30
+ aggregation_resource.description = options[:description] || []
31
+ aggregation_resource.owner = options[:owner] || []
32
+
33
+ aggregation = LD4L::OreRDF::Aggregation.new :aggregation_resource => aggregation_resource
34
+ aggregation
35
+ end
36
+ end
37
+ end
38
+ end
39
+
@@ -0,0 +1,47 @@
1
+ module LD4L
2
+ module OreRDF
3
+ class DestroyAggregation
4
+
5
+ ##
6
+ # Destroy the aggregation and all associated proxies.
7
+ #
8
+ # @param [LD4L::OreRDF::Aggregation] aggregation to be destroyed
9
+ #
10
+ # @returns [TrueClass,Hash]
11
+ # true if aggregation resource is empty
12
+ # true if aggregation resource is not persisted
13
+ # true if aggregation resource and all proxy resources were destroyed; otherwise,
14
+ # returns Hash with
15
+ # :aggregation_resource_destroyed is true if aggregation_resource successfully destroyed; otherwise, false
16
+ # :percent_proxies_destroyed is % of proxies successfully destroyed
17
+ def self.call( aggregation )
18
+ raise ArgumentError, 'aggregation must be an LD4L::OreRDF::Aggregation' unless
19
+ aggregation && aggregation.kind_of?(LD4L::OreRDF::Aggregation)
20
+
21
+ return true unless aggregation.aggregation_resource
22
+ return true unless ActiveTriples::Resource.uri_persisted?(aggregation.aggregation_resource.rdf_subject)
23
+
24
+ # have to get actual persisted proxy resources since the ones in the object may not have been persisted
25
+ proxy_resources = LD4L::OreRDF::FindProxies.call(
26
+ :aggregation => aggregation.aggregation_resource,
27
+ :repository => LD4L::OreRDF::ProxyResource.repository,
28
+ :resume => true
29
+ )
30
+
31
+ count = 0
32
+ total = proxy_resources.size
33
+ proxy_resources.each { |id,proxy| count += 1 if proxy.destroy! }
34
+ percent_proxies = total > 0 ? count/total : 1
35
+ agg_destroyed = percent_proxies == 1 ? aggregation.aggregation_resource.destroy! : false
36
+ all_destroyed = agg_destroyed && (percent_proxies == 1)
37
+ ret = all_destroyed ? all_destroyed :
38
+ {
39
+ :aggregation_resource_destroyed => agg_destroyed,
40
+ :percent_proxies_destroyed => percent_proxies
41
+ }
42
+ ret
43
+ end
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,22 @@
1
+ module LD4L
2
+ module OreRDF
3
+ class DestroyAggregationWithID
4
+
5
+ ##
6
+ # Destroy the aggregation and all associated proxies.
7
+ #
8
+ # @param [String,RDF::URI] uri of aggregation resource to destroy
9
+ #
10
+ # @returns [TrueClass,Hash]
11
+ # true if aggregation and all proxies destroyed; otherwise,
12
+ # returns Hash with
13
+ # :aggregation_resource_destroyed is true if aggregation_resource successfully destroyed; otherwise, false
14
+ # :percent_proxies_destroyed is % of proxies successfully destroyed
15
+ def self.call( id )
16
+ aggregation = LD4L::OreRDF::ResumeAggregation.call(id)
17
+ LD4L::OreRDF::DestroyAggregation.call(aggregation)
18
+ end
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,72 @@
1
+ module LD4L
2
+ module OreRDF
3
+ class FindAggregations
4
+
5
+ ##
6
+ # Find aggregations matching the specified criteria.
7
+ #
8
+ # @param [Hash] options the options to use to find aggregations
9
+ # @option options [Hash<Object,Object>] :criteria for finding aggregations (ex. RDF::DC.title=>'My Aggregation') (default - nil for all aggregations)
10
+ # @option options [Hash<Symbol><Object>] :properties to return with the aggregation uri (ex. :first_proxy=>RDFVocabularies::IANA.first) (default - nil aggregation uri only)
11
+ # @option options [Symbol] :repository to search (default - :default)
12
+ # @option options [TrueClass,FalseClass] :resume if true, find and resume; otherwise, find only (default - false)
13
+ #
14
+ # @returns [Array<RDF::URI>,Hash<RDF::URI,LD4L::OreRDF::Aggregation,Hash<RDF::URI,Hash<Object,Object>]
15
+ # if resume==false, returns URIs of matching aggregation resources + specified properties' values;
16
+ # otherwise, returns resumed instances of matching aggregations and their proxies
17
+ #
18
+ # @example Search for all aggregations
19
+ # all_aggs = LD4L::OreRDF.FindAggregations
20
+ def self.call( options={} )
21
+ repository = options[:repository] || :default
22
+ raise ArgumentError, 'repository must be a symbol' unless repository.kind_of?(Symbol)
23
+ raise ArgumentError, 'repository must be a registered repository' unless
24
+ ActiveTriples::Repositories.repositories.has_key?(repository)
25
+
26
+ resume = options[:resume] || false
27
+ raise ArgumentError, 'resume must be true or false' unless
28
+ resume.kind_of?(TrueClass) || resume.kind_of?(FalseClass)
29
+
30
+ criteria = options[:criteria] || nil
31
+ raise ArgumentError, 'criteria must be a hash of attribute-value pairs for searching for aggregations' unless
32
+ criteria.nil? || criteria.kind_of?(Hash)
33
+ criteria = criteria ? criteria.dup : {}
34
+ criteria[RDF.type] = RDFVocabularies::ORE.Aggregation
35
+
36
+ # properties are ignored when resume==true because all properties are returned as part of the resumed aggregations
37
+ properties = options[:properties] || nil
38
+ raise ArgumentError, 'properties must be an array of predicates' unless
39
+ properties.nil? || properties.kind_of?(Hash) || resume
40
+ properties.each_key { |k| criteria[properties[k]] = k unless criteria.has_key?(properties[k]) } unless
41
+ properties.nil? || resume
42
+ process_properties = properties.nil? || resume ? false : true
43
+
44
+ graph = ActiveTriples::Repositories.repositories[repository]
45
+ query = RDF::Query.new({ :aggregation => criteria })
46
+
47
+ process_properties || resume ? aggregations = {} : aggregations = []
48
+ results = query.execute(graph)
49
+ results.each do |r|
50
+ h = r.to_hash
51
+ uri = h[:aggregation]
52
+ if resume
53
+ # if resume, return Hash of aggregation uri => resumed aggregation for each found
54
+ aggregations[uri] = LD4L::OreRDF::ResumeAggregation.call(uri)
55
+ elsif process_properties
56
+ # if properties, return Hash of aggregation uri => Hash of property => value for each found
57
+ properties = h
58
+ properties.delete(:aggregation)
59
+ aggregations[uri] = properties
60
+ else
61
+ # if no properties && not resumed, return array of aggregation uris
62
+ aggregations << uri
63
+ end
64
+ end
65
+
66
+ aggregations
67
+ end
68
+
69
+ end
70
+ end
71
+ end
72
+
@@ -0,0 +1,34 @@
1
+ module LD4L
2
+ module OreRDF
3
+ class PersistAggregation
4
+
5
+ ##
6
+ # Persist the aggregation and all associated proxies.
7
+ #
8
+ # @param [LD4L::OreRDF::Aggregation] aggregation to be persisted
9
+ #
10
+ # @returns [TrueClass,Hash]
11
+ # true if aggregation resource and all proxy resources were persisted; otherwise,
12
+ # returns Hash with
13
+ # :aggregation_resource_persisted is true if aggregation_resource successfully persisted; otherwise, false
14
+ # :percent_proxies_persisted is % of proxies successfully persisted
15
+ def self.call( aggregation )
16
+ raise ArgumentError, 'aggregation must be an LD4L::OreRDF::Aggregation' unless
17
+ aggregation && aggregation.kind_of?(LD4L::OreRDF::Aggregation)
18
+
19
+ count = 0
20
+ agg_persisted = aggregation.aggregation_resource.persist!
21
+ aggregation.proxy_resources.each { |proxy| count += 1 if proxy.persist! } if agg_persisted
22
+ percent_proxies = aggregation.proxy_resources.size > 0 ? count/aggregation.proxy_resources.size : 1
23
+ all_persisted = agg_persisted && (percent_proxies == 1)
24
+ ret = all_persisted ? all_persisted :
25
+ {
26
+ :aggregation_resource_persisted => agg_persisted,
27
+ :percent_proxies_persisted => percent_proxies
28
+ }
29
+ ret
30
+ end
31
+ end
32
+ end
33
+ end
34
+
@@ -0,0 +1,30 @@
1
+ module LD4L
2
+ module OreRDF
3
+ class ResumeAggregation
4
+
5
+ ##
6
+ # Resume the aggregation and all associated proxies.
7
+ #
8
+ # @param [String,RDF::URI] uri of aggregation resource to resume
9
+ #
10
+ # @returns
11
+ def self.call( id )
12
+ raise ArgumentError, 'id must be a local name string, uri string, or RDF::URI' unless
13
+ id && ( id.kind_of?(String) || id.kind_of?(RDF::URI) )
14
+
15
+ aggregation_resource = LD4L::OreRDF::AggregationResource.new(id)
16
+ return nil unless ActiveTriples::Resource.uri_persisted?(aggregation_resource.rdf_subject)
17
+
18
+ proxy_resources = LD4L::OreRDF::FindProxies.call(
19
+ :aggregation => aggregation_resource,
20
+ :repository => LD4L::OreRDF::ProxyResource.repository,
21
+ :resume => true
22
+ )
23
+ LD4L::OreRDF::Aggregation.new(
24
+ :aggregation_resource => aggregation_resource,
25
+ :proxy_resources => proxy_resources.values)
26
+ end
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,64 @@
1
+ module LD4L
2
+ module OreRDF
3
+ class CreateProxy
4
+
5
+ ##
6
+ # Create an ore proxy in one step passing in the required information.
7
+ #
8
+ # @param [Hash] options the options to use while generating the proxy
9
+ # @option options [LD4L::OreRDF::AggregationResource] :aggregation - aggregation to which the resource is being added (required)
10
+ # @option options [String, RDF::URI] :resource - resource uri for the resource being added to the aggregation (required)
11
+ # @option options [String, RDF::URI] :id - uri or localname to use for the rdf_subject of the new proxy (optional)(default - mint)
12
+ # - full URI - [String, RDF::URI] used as passed in
13
+ # - partial id - [String] uri generated from base_uri + localname_prefix + id
14
+ # - nil - uri generated from base_uri + localname_prefix + minted localname
15
+ # @option options [Integer] :insert_position - used for ordered lists to place an item at a specific location (optional)(default - appends)
16
+ # @option options [String, LD4L::FoafRDF::Person] :contributor - person adding the resource (optional)(default - list owner)
17
+ #
18
+ # @returns an instance of the new proxy (not persisted)
19
+ def self.call( options = {} )
20
+ # validate aggregation was passed in and of correct type
21
+ aggregation = options[:aggregation] || nil
22
+ raise ArgumentError, "aggregation is required" if aggregation.nil?
23
+ raise ArgumentError, "aggregation is not LD4L::OreRDF::Aggregation" unless
24
+ aggregation.kind_of?(LD4L::OreRDF::Aggregation)
25
+
26
+ # validate resource was passed in and of correct type
27
+ resource = options[:resource] || nil
28
+ raise ArgumentError, "resource is required" if resource.nil?
29
+ raise ArgumentError, "resource must be either a string representation of an URI or an instance of RDF::URI" unless
30
+ resource.kind_of?(String) || resource.kind_of?(RDF::URI)
31
+
32
+ # make sure resource is an RDF::URI
33
+ resource = RDF::URI(resource) unless resource.kind_of?(RDF::URI)
34
+
35
+ # mint an id if needed
36
+ id = options[:id] ||
37
+ ActiveTriples::LocalName::Minter.generate_local_name(
38
+ LD4L::OreRDF::ProxyResource, 10, { :prefix => LD4L::OreRDF::ProxyResource.localname_prefix },
39
+ LD4L::OreRDF.configuration.localname_minter )
40
+
41
+ # create the proxy and set properties
42
+ proxy = LD4L::OreRDF::ProxyResource.new(id)
43
+ proxy.proxy_for = resource
44
+ proxy.proxy_in = aggregation.aggregation_resource
45
+ proxy.contributor = options[:contributor] || [] # TODO default to aggregation.owner
46
+
47
+ insert_position = options[:insert_position] || nil
48
+ unless insert_position.nil?
49
+ # TODO: handle inserting item into an ordered list at position specified
50
+ # set next_proxy and prev_proxy
51
+ # update other items that are near it
52
+ # TODO: what happens if prev and next aren't set on the
53
+ end
54
+
55
+ # TODO - defaulting to appending proxy to the end
56
+ # TODO - need to update next_proxy, prev_proxy related to ordering
57
+ aggregation << proxy
58
+ proxy
59
+ end
60
+
61
+ end
62
+ end
63
+ end
64
+