ld4l-ore_rdf 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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
+