valkyrie 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -3
  3. data/.rubocop.yml +28 -0
  4. data/Gemfile +6 -1
  5. data/README.md +145 -10
  6. data/Rakefile +59 -1
  7. data/bin/console +1 -1
  8. data/config/valkyrie.yml +8 -0
  9. data/db/config.yml +17 -0
  10. data/db/migrate/20160111215816_enable_uuid_extension.rb +6 -0
  11. data/db/migrate/20161007101725_create_orm_resources.rb +10 -0
  12. data/db/migrate/20170124135846_add_model_type_to_orm_resources.rb +6 -0
  13. data/db/migrate/20170531004548_change_model_type_to_internal_model.rb +6 -0
  14. data/db/schema.rb +65 -0
  15. data/db/seeds.rb +8 -0
  16. data/lib/config/database_connection.rb +15 -0
  17. data/lib/generators/valkyrie/resource_generator.rb +27 -0
  18. data/lib/generators/valkyrie/templates/resource.rb.erb +9 -0
  19. data/lib/generators/valkyrie/templates/resource_spec.rb.erb +13 -0
  20. data/lib/valkyrie.rb +76 -1
  21. data/lib/valkyrie/adapter_container.rb +12 -0
  22. data/lib/valkyrie/change_set.rb +84 -0
  23. data/lib/valkyrie/decorators/decorator_list.rb +15 -0
  24. data/lib/valkyrie/decorators/decorator_with_arguments.rb +14 -0
  25. data/lib/valkyrie/derivative_service.rb +42 -0
  26. data/lib/valkyrie/engine.rb +10 -0
  27. data/lib/valkyrie/file_characterization_service.rb +42 -0
  28. data/lib/valkyrie/id.rb +32 -0
  29. data/lib/valkyrie/indexers/access_controls_indexer.rb +19 -0
  30. data/lib/valkyrie/local_file_service.rb +11 -0
  31. data/lib/valkyrie/metadata_adapter.rb +22 -0
  32. data/lib/valkyrie/persist_derivatives.rb +29 -0
  33. data/lib/valkyrie/persistence.rb +14 -0
  34. data/lib/valkyrie/persistence/buffered_persister.rb +28 -0
  35. data/lib/valkyrie/persistence/composite_persister.rb +29 -0
  36. data/lib/valkyrie/persistence/delete_tracking_buffer.rb +21 -0
  37. data/lib/valkyrie/persistence/fedora.rb +11 -0
  38. data/lib/valkyrie/persistence/fedora/list_node.rb +88 -0
  39. data/lib/valkyrie/persistence/fedora/metadata_adapter.rb +45 -0
  40. data/lib/valkyrie/persistence/fedora/ordered_list.rb +146 -0
  41. data/lib/valkyrie/persistence/fedora/ordered_reader.rb +28 -0
  42. data/lib/valkyrie/persistence/fedora/persister.rb +47 -0
  43. data/lib/valkyrie/persistence/fedora/persister/model_converter.rb +199 -0
  44. data/lib/valkyrie/persistence/fedora/persister/orm_converter.rb +338 -0
  45. data/lib/valkyrie/persistence/fedora/persister/resource_factory.rb +21 -0
  46. data/lib/valkyrie/persistence/fedora/query_service.rb +80 -0
  47. data/lib/valkyrie/persistence/memory.rb +8 -0
  48. data/lib/valkyrie/persistence/memory/metadata_adapter.rb +22 -0
  49. data/lib/valkyrie/persistence/memory/persister.rb +58 -0
  50. data/lib/valkyrie/persistence/memory/query_service.rb +86 -0
  51. data/lib/valkyrie/persistence/postgres.rb +6 -0
  52. data/lib/valkyrie/persistence/postgres/metadata_adapter.rb +20 -0
  53. data/lib/valkyrie/persistence/postgres/orm.rb +9 -0
  54. data/lib/valkyrie/persistence/postgres/orm/resource.rb +7 -0
  55. data/lib/valkyrie/persistence/postgres/orm_converter.rb +118 -0
  56. data/lib/valkyrie/persistence/postgres/persister.rb +33 -0
  57. data/lib/valkyrie/persistence/postgres/queries.rb +8 -0
  58. data/lib/valkyrie/persistence/postgres/queries/find_inverse_references_query.rb +31 -0
  59. data/lib/valkyrie/persistence/postgres/queries/find_members_query.rb +33 -0
  60. data/lib/valkyrie/persistence/postgres/queries/find_references_query.rb +33 -0
  61. data/lib/valkyrie/persistence/postgres/query_service.rb +53 -0
  62. data/lib/valkyrie/persistence/postgres/resource_converter.rb +18 -0
  63. data/lib/valkyrie/persistence/postgres/resource_factory.rb +30 -0
  64. data/lib/valkyrie/persistence/solr.rb +6 -0
  65. data/lib/valkyrie/persistence/solr/metadata_adapter.rb +42 -0
  66. data/lib/valkyrie/persistence/solr/model_converter.rb +270 -0
  67. data/lib/valkyrie/persistence/solr/orm_converter.rb +252 -0
  68. data/lib/valkyrie/persistence/solr/persister.rb +32 -0
  69. data/lib/valkyrie/persistence/solr/queries.rb +11 -0
  70. data/lib/valkyrie/persistence/solr/queries/default_paginator.rb +16 -0
  71. data/lib/valkyrie/persistence/solr/queries/find_all_query.rb +33 -0
  72. data/lib/valkyrie/persistence/solr/queries/find_by_id_query.rb +24 -0
  73. data/lib/valkyrie/persistence/solr/queries/find_inverse_references_query.rb +30 -0
  74. data/lib/valkyrie/persistence/solr/queries/find_members_query.rb +43 -0
  75. data/lib/valkyrie/persistence/solr/queries/find_references_query.rb +34 -0
  76. data/lib/valkyrie/persistence/solr/query_service.rb +48 -0
  77. data/lib/valkyrie/persistence/solr/repository.rb +36 -0
  78. data/lib/valkyrie/persistence/solr/resource_factory.rb +24 -0
  79. data/lib/valkyrie/rdf_patches.rb +17 -0
  80. data/lib/valkyrie/resource.rb +106 -0
  81. data/lib/valkyrie/resource/access_controls.rb +13 -0
  82. data/lib/valkyrie/specs/shared_specs.rb +10 -0
  83. data/lib/valkyrie/specs/shared_specs/change_set_persister.rb +60 -0
  84. data/lib/valkyrie/specs/shared_specs/derivative_service.rb +30 -0
  85. data/lib/valkyrie/specs/shared_specs/file.rb +12 -0
  86. data/lib/valkyrie/specs/shared_specs/file_characterization_service.rb +33 -0
  87. data/lib/valkyrie/specs/shared_specs/metadata_adapter.rb +10 -0
  88. data/lib/valkyrie/specs/shared_specs/persister.rb +154 -0
  89. data/lib/valkyrie/specs/shared_specs/queries.rb +128 -0
  90. data/lib/valkyrie/specs/shared_specs/resource.rb +71 -0
  91. data/lib/valkyrie/specs/shared_specs/storage_adapter.rb +44 -0
  92. data/lib/valkyrie/storage.rb +8 -0
  93. data/lib/valkyrie/storage/disk.rb +55 -0
  94. data/lib/valkyrie/storage/fedora.rb +71 -0
  95. data/lib/valkyrie/storage/memory.rb +31 -0
  96. data/lib/valkyrie/storage_adapter.rb +100 -0
  97. data/lib/valkyrie/types.rb +34 -0
  98. data/lib/valkyrie/value_mapper.rb +67 -0
  99. data/lib/valkyrie/version.rb +2 -1
  100. data/lib/valkyrie/vocab/pcdm_use.rb +73 -0
  101. data/valkyrie.gemspec +33 -7
  102. metadata +462 -7
  103. data/.travis.yml +0 -5
data/db/seeds.rb ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ # This file should contain all the record creation needed to seed the database with its default values.
3
+ # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup).
4
+ #
5
+ # Examples:
6
+ #
7
+ # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
8
+ # Character.create(name: 'Luke', movie: movies.first)
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ require 'active_record'
3
+ require 'erb'
4
+
5
+ module DatabaseConnection
6
+ def self.connect!(env)
7
+ # Ref https://github.com/puma/puma#clustered-mode
8
+ ActiveSupport.on_load(:active_record) do
9
+ ::ActiveRecord::Base.connection_pool.disconnect! if ::ActiveRecord::Base.connected?
10
+ ::ActiveRecord::Base.configurations = YAML.safe_load(ERB.new(File.read("db/config.yml")).result) || {}
11
+ config = ::ActiveRecord::Base.configurations[env.to_s]
12
+ ::ActiveRecord::Base.establish_connection(config)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+ require 'rails/generators'
3
+ require 'rails/generators/model_helpers'
4
+
5
+ class Valkyrie::ResourceGenerator < Rails::Generators::NamedBase
6
+ # Include ModelHelpers to warn about pluralization when generating new models or scaffolds
7
+ include Rails::Generators::ModelHelpers
8
+
9
+ source_root File.expand_path('../templates', __FILE__)
10
+
11
+ argument :attributes, type: :array, default: [], banner: 'field:type field:type'
12
+
13
+ def create_model
14
+ template('resource.rb.erb', File.join('app/models', class_path, "#{file_name}.rb"))
15
+ end
16
+
17
+ def create_model_spec
18
+ return unless rspec_installed?
19
+ template('resource_spec.rb.erb', File.join('spec/models', class_path, "#{file_name}_spec.rb"))
20
+ end
21
+
22
+ private
23
+
24
+ def rspec_installed?
25
+ defined?(RSpec) && defined?(RSpec::Rails)
26
+ end
27
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ # Generated with `rails generate valkyrie:model <%= class_name %>`
3
+ class <%= class_name %> < Valkyrie::Resource
4
+ include Valkyrie::Resource::AccessControls
5
+ attribute :id, Valkyrie::Types::ID.optional
6
+ <%- attributes.each do |att| -%>
7
+ attribute :<%= att.name %>, Valkyrie::Types::<%= (att.type == :array) ? 'Array' : 'Set' %>
8
+ <%- end -%>
9
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ # Generated with `rails generate valkyrie:model <%= class_name %>`
3
+ require 'rails_helper'
4
+ require 'valkyrie/specs/shared_specs'
5
+
6
+ RSpec.describe <%= class_name %> do
7
+ let(:model_klass) { described_class }
8
+ it_behaves_like "a Valkyrie::Resource"
9
+
10
+ it "has tests" do
11
+ skip "Add your tests here"
12
+ end
13
+ end
data/lib/valkyrie.rb CHANGED
@@ -1,5 +1,80 @@
1
+ # frozen_string_literal: true
1
2
  require "valkyrie/version"
3
+ require "ostruct"
4
+ require 'active_support'
5
+ require 'active_support/core_ext'
6
+ require 'dry-types'
7
+ require 'dry-struct'
8
+ require 'draper'
9
+ require 'active_record'
10
+ require 'reform'
11
+ require 'reform/active_record'
12
+ require 'rdf'
13
+ require 'valkyrie/rdf_patches'
14
+ require 'json/ld'
15
+ require 'logger'
16
+ require 'active_triples'
17
+ require 'rdf/vocab'
18
+ require 'active_fedora'
19
+ require 'hydra-access-controls'
20
+ require 'ruby_tika_app'
2
21
 
22
+ # frozen_string_literal: true
3
23
  module Valkyrie
4
- # Your code goes here...
24
+ require 'valkyrie/id'
25
+ require 'valkyrie/change_set'
26
+ require 'valkyrie/value_mapper'
27
+ require 'valkyrie/persistence'
28
+ require 'valkyrie/types'
29
+ require 'valkyrie/resource'
30
+ require 'valkyrie/derivative_service'
31
+ require 'valkyrie/storage_adapter'
32
+ require 'valkyrie/metadata_adapter'
33
+ require 'valkyrie/adapter_container'
34
+ require 'valkyrie/file_characterization_service'
35
+ require 'valkyrie/decorators/decorator_list'
36
+ require 'valkyrie/decorators/decorator_with_arguments'
37
+ require 'valkyrie/resource/access_controls'
38
+ require 'valkyrie/indexers/access_controls_indexer'
39
+ require 'valkyrie/storage'
40
+ require 'valkyrie/vocab/pcdm_use'
41
+ require 'generators/valkyrie/resource_generator'
42
+ require 'valkyrie/engine' if defined?(Rails)
43
+ def config
44
+ @config ||= Config.new(
45
+ YAML.safe_load(ERB.new(File.read(config_root_path.join("config", "valkyrie.yml"))).result)[environment]
46
+ )
47
+ end
48
+
49
+ def environment
50
+ Rails.env
51
+ end
52
+
53
+ def config_root_path
54
+ if const_defined?(:Rails) && Rails.root
55
+ Rails.root
56
+ else
57
+ Pathname.new(Dir.pwd)
58
+ end
59
+ end
60
+
61
+ def logger
62
+ @logger ||= Logger.new(STDOUT)
63
+ end
64
+
65
+ def logger=(logger)
66
+ @logger = logger
67
+ end
68
+
69
+ class Config < OpenStruct
70
+ def metadata_adapter
71
+ Valkyrie::MetadataAdapter.find(super.to_sym)
72
+ end
73
+
74
+ def storage_adapter
75
+ Valkyrie::StorageAdapter.find(super.to_sym)
76
+ end
77
+ end
78
+
79
+ module_function :config, :logger, :logger=, :config_root_path, :environment
5
80
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module Valkyrie
3
+ class AdapterContainer
4
+ # Wraps up an individual persister and query service to conform to the
5
+ # adapter interface. Useful for decorated persisters.
6
+ attr_reader :persister, :query_service
7
+ def initialize(persister:, query_service:)
8
+ @persister = persister
9
+ @query_service = query_service
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+ require 'reform/form/coercion'
3
+ require 'reform/form/active_model/validations'
4
+ module Valkyrie
5
+ ##
6
+ # Standard change set object for Valkyrie.
7
+ # ChangeSets are a way to group together properties that should be applied to
8
+ # an underlying resource. They are often used for powering HTML Forms or
9
+ # storing virtual attributes for special synchronization with a resource.
10
+ # @example Define a change set
11
+ # class BookChangeSet < Valkyrie::ChangeSet
12
+ # self.fields = [:title, :author]
13
+ # validates :title, presence: true
14
+ # property :title, multiple: false, required: true
15
+ # end
16
+ class ChangeSet < Reform::Form
17
+ include Reform::Form::ActiveModel::Validations
18
+ feature Coercion
19
+ class_attribute :fields
20
+ self.fields = []
21
+
22
+ property :append_id, virtual: true
23
+
24
+ # Set ID of record this one should be appended to.
25
+ # @param append_id [Valkyrie::ID]
26
+ def append_id=(append_id)
27
+ super(Valkyrie::ID.new(append_id))
28
+ end
29
+
30
+ # Returns whether or not a given field has multiple values.
31
+ # @param field [Symbol]
32
+ # @return [Boolean]
33
+ def multiple?(field)
34
+ self.class.definitions[field.to_s][:multiple] != false
35
+ end
36
+
37
+ # Returns whether or not a given field is required.
38
+ # @param field [Symbol]
39
+ # @return [Boolean]
40
+ def required?(field)
41
+ self.class.definitions[field.to_s][:required]
42
+ end
43
+
44
+ # Quick setter for fields that should be in a changeset. Defaults to multiple,
45
+ # not required, with an empty array default.
46
+ # @param fields [Array<Symbol>]
47
+ def self.fields=(fields)
48
+ singleton_class.class_eval do
49
+ remove_possible_method(:fields)
50
+ define_method(:fields) { fields }
51
+ end
52
+
53
+ fields.each do |field|
54
+ property field, default: []
55
+ end
56
+ fields
57
+ end
58
+
59
+ # Returns value for a given property.
60
+ # @param key [Symbol]
61
+ def [](key)
62
+ send(key) if respond_to?(key)
63
+ end
64
+
65
+ delegate :attributes, to: :resource
66
+
67
+ delegate :internal_resource, :created_at, :updated_at, :model_name, to: :resource
68
+
69
+ # Prepopulates all fields with defaults defined in the changeset. This is an
70
+ # override of Reform::Form's method to allow for single-valued fields to
71
+ # prepopulate appropriately.
72
+ def prepopulate!(_options = {})
73
+ self.class.definitions.select { |_field, definition| definition[:multiple] == false }.each do |field, _definition|
74
+ value = Array.wrap(send(field.to_s)).first
75
+ send("#{field}=", value)
76
+ end
77
+ self
78
+ end
79
+
80
+ def resource
81
+ model
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ module Valkyrie::Decorators
3
+ class DecoratorList
4
+ attr_reader :decorators
5
+ def initialize(*decorators)
6
+ @decorators = decorators
7
+ end
8
+
9
+ def new(undecorated_object)
10
+ decorators.inject(undecorated_object) do |obj, decorator|
11
+ decorator.new(obj)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ module Valkyrie::Decorators
3
+ class DecoratorWithArguments
4
+ attr_reader :decorator, :args
5
+ def initialize(decorator, *args)
6
+ @decorator = decorator
7
+ @args = args
8
+ end
9
+
10
+ def new(item)
11
+ decorator.new(item, *args)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+ require 'hydra/derivatives'
3
+ module Valkyrie
4
+ ##
5
+ # Container for registering DerivativeServices.
6
+ #
7
+ # To add a new service:
8
+ # DerivativeService.services << MyDerivativeService
9
+ class DerivativeService
10
+ require 'valkyrie/local_file_service'
11
+ require 'valkyrie/persist_derivatives'
12
+ Hydra::Derivatives.source_file_service = Valkyrie::LocalFileService
13
+ Hydra::Derivatives.output_file_service = Valkyrie::PersistDerivatives
14
+ class_attribute :services
15
+ self.services = []
16
+ # Returns a derivative service for a change_set.
17
+ # @param resource [Valkyrie::ChangeSet]
18
+ # @return [Valkyrie::DerivativeService]
19
+ def self.for(change_set)
20
+ services.map { |service| service.new(change_set) }.find(&:valid?) ||
21
+ new(change_set)
22
+ end
23
+ attr_reader :change_set
24
+ delegate :mime_type, :uri, to: :change_set
25
+ # @param resource [Valkyrie::Resource]
26
+ def initialize(change_set)
27
+ @change_set = change_set
28
+ end
29
+
30
+ # Deletes any derivatives generated.
31
+ def cleanup_derivatives; end
32
+
33
+ # Creates derivatives.
34
+ def create_derivatives; end
35
+
36
+ # Returns true if the given resource is valid for this derivative service.
37
+ # @return [Boolean]
38
+ def valid?
39
+ true
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ ##
3
+ # This engine exists for the sole purpose of enabling the
4
+ # `valkyrie_engine:install:migrations` rake task from an including Rails
5
+ # application. It technically enables a whole host of other functionality -
6
+ # don't use it, please.
7
+ module Valkyrie
8
+ class Engine < Rails::Engine
9
+ end
10
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+ require 'ruby_tika_app'
3
+
4
+ module Valkyrie
5
+ # Abstract base class for file characterization
6
+ # registers file characterization service a ValkyrieFileCharacterization service
7
+ # initializes the interface for file characterization
8
+ # @since 0.1.0
9
+ class FileCharacterizationService
10
+ class_attribute :services
11
+ self.services = []
12
+ # initializes the file characterization service
13
+ # @param file_node [FileNode] the FileNode to be characterized
14
+ # @param persister [AppendingPersister] the Persister used to save the FileNode
15
+ # @return [TikaFileCharacterizationService] the file characterization service, currently only TikaFileCharacterizationService is implemented
16
+ def self.for(file_node:, persister:)
17
+ services.map { |service| service.new(file_node: file_node, persister: persister) }.find(&:valid?) ||
18
+ new(file_node: file_node, persister: persister)
19
+ end
20
+ attr_reader :file_node, :persister
21
+ delegate :mime_type, :height, :width, :checksum, to: :file_node
22
+ def initialize(file_node:, persister:)
23
+ @file_node = file_node
24
+ @persister = persister
25
+ end
26
+
27
+ # characterizes the file_node passed into this service
28
+ # Default options are:
29
+ # save: true
30
+ # @param save [Boolean] should the persister save the file_node after Characterization
31
+ # @return [FileNode]
32
+ def characterize(save: true)
33
+ persister.save(resource: @file_node) if save
34
+ @file_node
35
+ end
36
+
37
+ # Stub function that sets this service as valid for all FileNode types
38
+ def valid?
39
+ true
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ module Valkyrie
3
+ class ID
4
+ attr_reader :id
5
+ delegate :empty?, to: :id
6
+ def initialize(id)
7
+ @id = id.to_s
8
+ end
9
+
10
+ def to_s
11
+ id
12
+ end
13
+
14
+ delegate :hash, to: :state
15
+
16
+ def eql?(other)
17
+ other.class == self.class && other.state == state
18
+ end
19
+ alias == eql?
20
+
21
+ def to_uri
22
+ return RDF::Literal.new(id.to_s, datatype: RDF::URI("http://example.com/valkyrie_id")) if id.to_s.include?("://")
23
+ ::RDF::URI(ActiveFedora::Base.id_to_uri(id))
24
+ end
25
+
26
+ protected
27
+
28
+ def state
29
+ [@id]
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ module Valkyrie::Indexers
3
+ class AccessControlsIndexer
4
+ attr_reader :resource
5
+ def initialize(resource:)
6
+ @resource = resource
7
+ end
8
+
9
+ def to_solr
10
+ return {} unless resource.respond_to?(:read_users)
11
+ {
12
+ Hydra.config[:permissions][:read].group => resource.read_groups,
13
+ Hydra.config[:permissions][:read].individual => resource.read_users,
14
+ Hydra.config[:permissions][:edit].individual => resource.edit_users,
15
+ Hydra.config[:permissions][:edit].group => resource.edit_groups
16
+ }
17
+ end
18
+ end
19
+ end