active-triples 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e1dcbe5917c46ab351078d1c6e7b2be54d66c68f
4
+ data.tar.gz: 5cc8dfc6dfbba4a833566f568d395a15ba79c535
5
+ SHA512:
6
+ metadata.gz: 17d3134eb50d437947dada9a3eadd4b298968c2fef571e25796de38f4b6de48b3eef9935fcfd9c0a5cd9089570ddd4f4fdcd40a9e1a499d5521026e1d8de020b
7
+ data.tar.gz: 6beee86d363f0791be42dbd5507a6dad99fa3e7ceb2beedacd39d704ee63ade58dba85fec512d0f5d25fdbf60088844b7aaeb9b3917a70ef697d020193782c9f
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ Gemfile.lock
5
+ tmp/*
6
+ .sass-cache
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ anguage: ruby
2
+ bundler_args: --without debug
3
+ script: "bundle exec rspec spec"
4
+ rvm:
5
+ - 1.9.3
6
+ - 2.0.0
7
+ - 2.1.0
8
+ - 2.1.1
9
+ - jruby-19mode
10
+ matrix:
11
+ allow_failures:
12
+ - rvm: jruby-19mode
data/AUTHORS ADDED
@@ -0,0 +1,2 @@
1
+ Tom Johnson (thomas.johnson@oregonstate.edu)
2
+ Trey Terrell
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <http://unlicense.org/>
data/README.md ADDED
@@ -0,0 +1,38 @@
1
+ ActiveTriples
2
+ ==============
3
+
4
+ [![Build Status](https://travis-ci.org/no-reply/ActiveTriples.png?branch=master)](https://travis-ci.org/no-reply/ActiveTriples)
5
+
6
+ Modeling RDF graphs in Ruby.
7
+
8
+ How to Use
9
+ -----------
10
+
11
+ ```ruby
12
+ class Thing < ActiveTriples::Resource
13
+ configure :type => RDF::OWL.Thing, :base_uri => 'http://example.org/things#'
14
+ property :title, :predicate => RDF::DC.title
15
+ property :description, :predicate => RDF::DC.description
16
+ property :creator, :predicate => RDF::DC.creator, :class_name => 'Person'
17
+ end
18
+
19
+ obj = Thing.new('123')
20
+ obj.title = 'Resource'
21
+ obj.description = 'A resource in an RDF graph.'
22
+
23
+ obj.dump :ntriples
24
+ # => "<http://example.org/things#123> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Thing> .\n<http://example.org/things#123> <http://purl.org/dc/terms/title> \"Resource\" .\n<http://example.org/things#123> <http://purl.org/dc/terms/description> \"A resource in an RDF graph.\" .\n"
25
+
26
+ class Person < ActiveTriples::Resource
27
+ configure :type => RDF::FOAF.Person, :base_uri => 'http://example.org/people#'
28
+ property :name, :predicate => RDF::FOAF.name
29
+ end
30
+
31
+ obj.creator = Person.new
32
+ obj.creator
33
+ # => [#<Person:0x3fbe84ac9234(default)>]
34
+
35
+ obj.creator.first.name = 'Herman Melville'
36
+ obj.dump :ntriples
37
+ # => "<http://example.org/things#123> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Thing> .\n<http://example.org/things#123> <http://purl.org/dc/terms/title> \"Resource\" .\n<http://example.org/things#123> <http://purl.org/dc/terms/description> \"A resource in an RDF graph.\" .\n<http://example.org/things#123> <http://purl.org/dc/terms/creator> _:g70087502237940 .\n_:g70087502237940 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .\n"
38
+ ```
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "active_triples/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "active-triples"
7
+ s.version = ActiveTriples::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Tom Johnson", "Trey Terrell"]
10
+ s.homepage = 'https://github.com/no-reply/ActiveTriples'
11
+ s.email = 'thomas.johnson@oregonstate.edu'
12
+ s.summary = %q{RDF graphs in ActiveModel wrappers.}
13
+ s.description = %q{ActiveTriples provides tools for modeling RDF as discrete resources.}
14
+ s.license = "Public Domain"
15
+ s.required_ruby_version = '>= 1.9.3'
16
+
17
+ s.add_dependency('rdf', '~> 1.1')
18
+ s.add_dependency('linkeddata', '~> 1.1')
19
+ s.add_dependency('activemodel')
20
+ s.add_dependency('deprecation', '~> 0.1')
21
+ s.add_dependency('activesupport')
22
+
23
+ s.add_development_dependency('rdoc')
24
+ s.add_development_dependency('rspec')
25
+ s.add_development_dependency('webmock')
26
+ s.add_development_dependency('nokogiri')
27
+
28
+ s.files = `git ls-files`.split("\n")
29
+ s.test_files = `git ls-files -- {spec}/*`.split("\n")
30
+
31
+ s.extra_rdoc_files = [
32
+ "LICENSE",
33
+ "README.md"
34
+ ]
35
+ end
@@ -0,0 +1,29 @@
1
+ require 'rdf'
2
+ require 'active_triples/version'
3
+
4
+ module ActiveTriples
5
+ autoload :Resource, 'active_triples/resource'
6
+ autoload :List, 'active_triples/list'
7
+ autoload :Term, 'active_triples/term'
8
+ autoload :Indexing, 'active_triples/indexing'
9
+ autoload :Configurable, 'active_triples/configurable'
10
+ autoload :Properties, 'active_triples/properties'
11
+ autoload :Repositories, 'active_triples/repositories'
12
+ autoload :NodeConfig, 'active_triples/node_config'
13
+ autoload :NestedAttributes, 'active_triples/nested_attributes'
14
+
15
+ def self.class_from_string(class_name, container_class=Kernel)
16
+ container_class = container_class.name if container_class.is_a? Module
17
+ container_parts = container_class.split('::')
18
+ (container_parts + class_name.split('::')).flatten.inject(Kernel) do |mod, class_name|
19
+ if mod == Kernel
20
+ Object.const_get(class_name)
21
+ elsif mod.const_defined? class_name.to_sym
22
+ mod.const_get(class_name)
23
+ else
24
+ container_parts.pop
25
+ class_from_string(class_name, container_parts.join('::'))
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,61 @@
1
+ require 'deprecation'
2
+
3
+ module ActiveTriples
4
+ ##
5
+ # Module to include configurable class-wide properties common to
6
+ # Resource and RDFDatastream. It does its work at the class level,
7
+ # and is meant to be extended.
8
+ #
9
+ # Define properties at the class level with:
10
+ #
11
+ # configure base_uri: "http://oregondigital.org/resource/", repository: :parent
12
+ # Available properties are base_uri, rdf_label, type, and repository
13
+ module Configurable
14
+ extend Deprecation
15
+
16
+ def base_uri
17
+ nil
18
+ end
19
+
20
+ def rdf_label
21
+ nil
22
+ end
23
+
24
+ def type
25
+ nil
26
+ end
27
+
28
+ def rdf_type(value)
29
+ Deprecation.warn Configurable, "rdf_type is deprecated and will be removed in active-fedora 8.0.0. Use configure type: instead.", caller
30
+ configure type: value
31
+ end
32
+
33
+ def repository
34
+ :parent
35
+ end
36
+
37
+ # API method for configuring class properties an RDF Resource may need.
38
+ # This is an alternative to overriding the methods extended with this module.
39
+ def configure(options = {})
40
+ {
41
+ base_uri: options[:base_uri],
42
+ rdf_label: options[:rdf_label],
43
+ type: options[:type],
44
+ repository: options[:repository]
45
+ }.each do |name, value|
46
+ if value
47
+ value = self.send("transform_#{name}", value) if self.respond_to?("transform_#{name}")
48
+ define_singleton_method(name) do
49
+ value
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ def transform_type(value)
56
+ RDF::URI.new(value).tap do |value|
57
+ Resource.type_registry[value] = self
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,76 @@
1
+ module ActiveFedora
2
+ module Rdf
3
+ module Indexing
4
+ extend Deprecation
5
+ extend ActiveSupport::Concern
6
+
7
+ # In active_fedora 8, we can get the prefix part from Datastream.prefix
8
+ def apply_prefix(name)
9
+ "#{dsid.underscore}__#{name}"
10
+ end
11
+
12
+ def prefix(name)
13
+ Deprecation.warn Indexing, "prefix is deprecated. Use apply_prefix instead. In active-fedora 8, the prefix method will just return the prefix to be applied, and will not do the applying. This will enable conformity between OmDatastream and RdfDatastream"
14
+ apply_prefix(name)
15
+ end
16
+
17
+ def to_solr(solr_doc = Hash.new) # :nodoc:
18
+ fields.each do |field_key, field_info|
19
+ values = resource.get_values(field_key)
20
+ Array(values).each do |val|
21
+ if val.kind_of? RDF::URI
22
+ val = val.to_s
23
+ elsif val.kind_of? Rdf::Resource
24
+ val = val.solrize
25
+ end
26
+ self.class.create_and_insert_terms(apply_prefix(field_key), val, field_info[:behaviors], solr_doc)
27
+ end
28
+ end
29
+ solr_doc
30
+ end
31
+
32
+ # Gives the primary solr name for a column. If there is more than one indexer on the field definition, it gives the first
33
+ def primary_solr_name(field)
34
+ config = self.class.config_for_term_or_uri(field)
35
+ return nil unless config # punt on index names for deep nodes!
36
+ if behaviors = config.behaviors
37
+ behaviors.each do |behavior|
38
+ result = ActiveFedora::SolrService.solr_name(apply_prefix(field), behavior, type: config.type)
39
+ return result if Solrizer::DefaultDescriptors.send(behavior).evaluate_suffix(:text).stored?
40
+ end
41
+ raise RuntimeError "no stored fields were found"
42
+ end
43
+ end
44
+
45
+ module ClassMethods
46
+ def prefix(dsid, name)
47
+ Deprecation.warn Indexing, "prefix is deprecated and will be removed in active-fedora 8.0.0.", caller
48
+ "#{dsid.underscore}__#{name}".to_sym
49
+ end
50
+
51
+ # Gives the datatype for a column.
52
+ def type(field)
53
+ config_for_term_or_uri(field).type
54
+ end
55
+ end
56
+
57
+ private
58
+ # returns a Hash, e.g.: {field => {:values => [], :type => :something, :behaviors => []}, ...}
59
+ def fields
60
+ field_map = {}.with_indifferent_access
61
+
62
+ self.class.properties.each do |name, config|
63
+ type = config[:type]
64
+ behaviors = config[:behaviors]
65
+ next unless type and behaviors
66
+ next if config[:class_name] && config[:class_name] < ActiveFedora::Base
67
+ resource.query(:subject => rdf_subject, :predicate => config[:predicate]).each_statement do |statement|
68
+ field_map[name] ||= {:values => [], :type => type, :behaviors => behaviors}
69
+ field_map[name][:values] << statement.object.to_s
70
+ end
71
+ end
72
+ field_map
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,155 @@
1
+ module ActiveTriples
2
+ ##
3
+ # An implementation of RDF::List intregrated with ActiveTriples.
4
+ #
5
+ # A thoughtful reflection period is encouraged before using the
6
+ # rdf:List concept in your data. The community may pursue other
7
+ # options for ordered sets.
8
+ class List < RDF::List
9
+ include ActiveTriples::NestedAttributes
10
+ extend Configurable
11
+ extend Properties
12
+
13
+ delegate :rdf_subject, :mark_for_destruction, :marked_for_destruction?, :set_value, :get_values, :parent, :dump, :attributes=, to: :resource
14
+ alias_method :to_ary, :to_a
15
+
16
+ class << self
17
+ def from_uri(uri, vals)
18
+ list = ListResource.from_uri(uri, vals)
19
+ self.new(list.rdf_subject, list)
20
+ end
21
+ end
22
+
23
+ def resource
24
+ graph
25
+ end
26
+
27
+ def initialize(*args)
28
+ super
29
+ parent = graph.parent if graph.respond_to? :parent
30
+ @graph = ListResource.new(subject) << graph unless graph.kind_of? Resource
31
+ graph << parent if parent
32
+ graph.list = self
33
+ graph.singleton_class.properties = self.class.properties
34
+ graph.singleton_class.properties.keys.each do |property|
35
+ graph.singleton_class.send(:register_property, property)
36
+ end
37
+ graph.insert RDF::Statement.new(subject, RDF.type, RDF.List)
38
+ graph.reload
39
+ end
40
+
41
+ def []=(idx, value)
42
+ raise IndexError "index #{idx} too small for array: minimum 0" if idx < 0
43
+
44
+ if idx >= length
45
+ (idx - length).times do
46
+ self << RDF::OWL.Nothing
47
+ end
48
+ return self << value
49
+ end
50
+ each_subject.with_index do |v, i|
51
+ next unless i == idx
52
+ resource.set_value(v, RDF.first, value)
53
+ end
54
+ end
55
+
56
+ ##
57
+ # Override to return AF::Rdf::Resources as values, where
58
+ # appropriate.
59
+ def each(&block)
60
+ return super unless block_given?
61
+
62
+ super do |value|
63
+ block.call(node_from_value(value))
64
+ end
65
+ end
66
+
67
+ ##
68
+ # Do these like #each.
69
+ def first
70
+ node_from_value(super)
71
+ end
72
+
73
+ def shift
74
+ node_from_value(super)
75
+ end
76
+
77
+ ##
78
+ # Find an AF::Rdf::Resource from the value returned by RDF::List
79
+ def node_from_value(value)
80
+ if value.kind_of? RDF::Resource
81
+ type_uri = resource.query([value, RDF.type, nil]).to_a.first.try(:object)
82
+ klass = ActiveTriples::Resource.type_registry[type_uri]
83
+ klass ||= Resource
84
+ return klass.from_uri(value,resource)
85
+ end
86
+ value
87
+ end
88
+
89
+ ##
90
+ # This class is the graph/Resource that backs the List and
91
+ # supplies integration with the rest of ActiveTriples
92
+ class ListResource < Resource
93
+ attr_reader :list
94
+
95
+ def list=(list)
96
+ @list ||= list
97
+ end
98
+
99
+ def attributes=(values)
100
+ raise ArgumentError, "values must be a Hash, you provided #{values.class}" unless values.kind_of? Hash
101
+ values.with_indifferent_access.each do |key, value|
102
+ if self.singleton_class.properties.keys.map{ |k| "#{k}_attributes"}.include?(key)
103
+ klass = properties[key[0..-12]]['class_name']
104
+ klass = ActiveTriples.class_from_string(klass, final_parent.class) if klass.is_a? String
105
+ value.is_a?(Hash) ? attributes_hash_to_list(values[key], klass) : attributes_to_list(value, klass)
106
+ values.delete key
107
+ end
108
+ end
109
+ persist!
110
+ super
111
+ end
112
+
113
+ private
114
+ def attributes_to_list(value, klass)
115
+ value.each do |entry|
116
+ item = klass.new()
117
+ item.attributes = entry
118
+ list << item
119
+ end
120
+ end
121
+
122
+ def attributes_hash_to_list(value, klass)
123
+ value.each do |counter, attr|
124
+ item = klass.new()
125
+ item.attributes = attr if attr
126
+ list[counter.to_i] = item
127
+ end
128
+ end
129
+ end
130
+
131
+ ##
132
+ # Monkey patch to allow lists to have subject URIs.
133
+ # Overrides RDF::List to prevent URI subjects
134
+ # from being replaced with nodes.
135
+ #
136
+ # @NOTE Lists built this way will return false for #valid?
137
+ def <<(value)
138
+ value = case value
139
+ when nil then RDF.nil
140
+ when RDF::Value then value
141
+ when Array then RDF::List.new(nil, graph, value)
142
+ else value
143
+ end
144
+
145
+ if empty?
146
+ resource.set_value(RDF.first, value)
147
+ resource.insert([subject, RDF.rest, RDF.nil])
148
+ resource << value if value.kind_of? Resource
149
+ return self
150
+ end
151
+ super
152
+ resource << value if value.kind_of? Resource
153
+ end
154
+ end
155
+ end