hydra-pcdm 0.0.1

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 (65) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +26 -0
  4. data/.travis.yml +14 -0
  5. data/CONTRIBUTING.md +115 -0
  6. data/Gemfile +13 -0
  7. data/LICENSE +12 -0
  8. data/README.md +87 -0
  9. data/Rakefile +20 -0
  10. data/config/jetty.yml +6 -0
  11. data/hydra-pcdm.gemspec +30 -0
  12. data/lib/hydra/pcdm/collection_indexer.rb +12 -0
  13. data/lib/hydra/pcdm/models/collection.rb +6 -0
  14. data/lib/hydra/pcdm/models/concerns/collection_behavior.rb +79 -0
  15. data/lib/hydra/pcdm/models/concerns/object_behavior.rb +104 -0
  16. data/lib/hydra/pcdm/models/file.rb +20 -0
  17. data/lib/hydra/pcdm/models/object.rb +6 -0
  18. data/lib/hydra/pcdm/object_indexer.rb +10 -0
  19. data/lib/hydra/pcdm/services/collection/add_collection.rb +20 -0
  20. data/lib/hydra/pcdm/services/collection/add_object.rb +19 -0
  21. data/lib/hydra/pcdm/services/collection/add_related_object.rb +21 -0
  22. data/lib/hydra/pcdm/services/collection/get_collections.rb +18 -0
  23. data/lib/hydra/pcdm/services/collection/get_objects.rb +18 -0
  24. data/lib/hydra/pcdm/services/collection/get_related_objects.rb +17 -0
  25. data/lib/hydra/pcdm/services/collection/remove_collection.rb +36 -0
  26. data/lib/hydra/pcdm/services/collection/remove_object.rb +43 -0
  27. data/lib/hydra/pcdm/services/collection/remove_related_object.rb +36 -0
  28. data/lib/hydra/pcdm/services/file/add_type.rb +20 -0
  29. data/lib/hydra/pcdm/services/file/get_mime_type.rb +11 -0
  30. data/lib/hydra/pcdm/services/object/add_object.rb +20 -0
  31. data/lib/hydra/pcdm/services/object/add_related_object.rb +21 -0
  32. data/lib/hydra/pcdm/services/object/get_objects.rb +18 -0
  33. data/lib/hydra/pcdm/services/object/get_related_objects.rb +17 -0
  34. data/lib/hydra/pcdm/services/object/remove_object.rb +43 -0
  35. data/lib/hydra/pcdm/services/object/remove_related_object.rb +36 -0
  36. data/lib/hydra/pcdm/version.rb +5 -0
  37. data/lib/hydra/pcdm/vocab/ebucore_terms.rb +33 -0
  38. data/lib/hydra/pcdm/vocab/pcdm_terms.rb +87 -0
  39. data/lib/hydra/pcdm/vocab/sweetjpl_terms.rb +10 -0
  40. data/lib/hydra/pcdm.rb +69 -0
  41. data/spec/hydra/pcdm/collection_indexer_spec.rb +26 -0
  42. data/spec/hydra/pcdm/models/collection_spec.rb +82 -0
  43. data/spec/hydra/pcdm/models/file_spec.rb +56 -0
  44. data/spec/hydra/pcdm/models/object_spec.rb +141 -0
  45. data/spec/hydra/pcdm/object_indexer_spec.rb +20 -0
  46. data/spec/hydra/pcdm/services/collection/add_collection_spec.rb +197 -0
  47. data/spec/hydra/pcdm/services/collection/add_object_spec.rb +132 -0
  48. data/spec/hydra/pcdm/services/collection/add_related_object_spec.rb +94 -0
  49. data/spec/hydra/pcdm/services/collection/get_collections_spec.rb +40 -0
  50. data/spec/hydra/pcdm/services/collection/get_objects_spec.rb +40 -0
  51. data/spec/hydra/pcdm/services/collection/get_related_objects_spec.rb +37 -0
  52. data/spec/hydra/pcdm/services/collection/remove_collection_spec.rb +143 -0
  53. data/spec/hydra/pcdm/services/collection/remove_object_spec.rb +180 -0
  54. data/spec/hydra/pcdm/services/collection/remove_related_object_spec.rb +146 -0
  55. data/spec/hydra/pcdm/services/file/add_type_spec.rb +19 -0
  56. data/spec/hydra/pcdm/services/file/get_mime_type_spec.rb +24 -0
  57. data/spec/hydra/pcdm/services/object/add_object_spec.rb +186 -0
  58. data/spec/hydra/pcdm/services/object/add_related_object_spec.rb +94 -0
  59. data/spec/hydra/pcdm/services/object/get_objects_spec.rb +33 -0
  60. data/spec/hydra/pcdm/services/object/get_related_objects_spec.rb +39 -0
  61. data/spec/hydra/pcdm/services/object/remove_object_spec.rb +158 -0
  62. data/spec/hydra/pcdm/services/object/remove_related_object_spec.rb +126 -0
  63. data/spec/hydra/pcdm_spec.rb +56 -0
  64. data/spec/spec_helper.rb +34 -0
  65. metadata +215 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9c4ca4330987a12626e2dd8a45e54d08e83b8c07
4
+ data.tar.gz: 99e3953956fe7a5a45b6c14bbee233d14e32eb2a
5
+ SHA512:
6
+ metadata.gz: 5a0af66d3e277f5d2f05dbb2e96043742f1faeec169641cf64058c3a89dc7762bfd93ca7ed48055c621fa0cc3a463b8492d5dc3d0351a996e248a138c081ae66
7
+ data.tar.gz: 43f4e5f13d121da66b59c54a496b538d2cd8bbb74b4be5fa8bfb60944f793d485313e2aa1d0aec23e5bceb6dbd0a6f4ae09f7eaaff141f355ff913ff650d31bc
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.gitignore ADDED
@@ -0,0 +1,26 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ .idea
24
+ .ruby-gemset
25
+ .ruby-version
26
+ jetty
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ language: ruby
2
+ cache: bundler
3
+ sudo: false
4
+ bundler_args: --without debug
5
+ env:
6
+ global:
7
+ - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
8
+ rvm:
9
+ - 2.1
10
+ - 2.2
11
+ - jruby-head
12
+ matrix:
13
+ allow_failures:
14
+ - rvm: jruby-head
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,115 @@
1
+ # How to Contribute
2
+
3
+ We want your help to make Project Hydra great.
4
+ There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things.
5
+
6
+ ## Hydra Project Intellectual Property Licensing and Ownership
7
+
8
+ All code contributors must have an Individual Contributor License Agreement (iCLA) on file with the Hydra Project Steering Group.
9
+ If the contributor works for an institution, the institution must have a Corporate Contributor License Agreement (cCLA) on file.
10
+
11
+ https://wiki.duraspace.org/display/hydra/Hydra+Project+Intellectual+Property+Licensing+and+Ownership
12
+
13
+ You should also add yourself to the `CONTRIBUTORS.md` file in the root of the project.
14
+
15
+ ## Contribution Tasks
16
+
17
+ * Reporting Issues
18
+ * Making Changes
19
+ * Submitting Changes
20
+ * Merging Changes
21
+
22
+ ### Reporting Issues
23
+
24
+ * Make sure you have a [GitHub account](https://github.com/signup/free)
25
+ * Submit a [Github issue](./issues) by:
26
+ * Clearly describing the issue
27
+ * Provide a descriptive summary
28
+ * Explain the expected behavior
29
+ * Explain the actual behavior
30
+ * Provide steps to reproduce the actual behavior
31
+
32
+ ### Making Changes
33
+
34
+ * Fork the repository on GitHub
35
+ * Create a topic branch from where you want to base your work.
36
+ * This is usually the master branch.
37
+ * To quickly create a topic branch based on master; `git branch fix/master/my_contribution master`
38
+ * Then checkout the new branch with `git checkout fix/master/my_contribution`.
39
+ * Please avoid working directly on the `master` branch.
40
+ * You may find the [hub suite of commands](https://github.com/defunkt/hub) helpful
41
+ * Make commits of logical units.
42
+ * Your commit should include a high level description of your work in HISTORY.textile
43
+ * Check for unnecessary whitespace with `git diff --check` before committing.
44
+ * Make sure your commit messages are [well formed](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
45
+ * If you created an issue, you can close it by including "Closes #issue" in your commit message. See [Github's blog post for more details](https://github.com/blog/1386-closing-issues-via-commit-messages)
46
+
47
+ ```
48
+ Present tense short summary (50 characters or less)
49
+
50
+ More detailed description, if necessary. It should be wrapped to 72
51
+ characters. Try to be as descriptive as you can, even if you think that
52
+ the commit content is obvious, it may not be obvious to others. You
53
+ should add such description also if it's already present in bug tracker,
54
+ it should not be necessary to visit a webpage to check the history.
55
+
56
+ Include Closes #<issue-number> when relavent.
57
+
58
+ Description can have multiple paragraphs and you can use code examples
59
+ inside, just indent it with 4 spaces:
60
+
61
+ class PostsController
62
+ def index
63
+ respond_with Post.limit(10)
64
+ end
65
+ end
66
+
67
+ You can also add bullet points:
68
+
69
+ - you can use dashes or asterisks
70
+
71
+ - also, try to indent next line of a point for readability, if it's too
72
+ long to fit in 72 characters
73
+ ```
74
+
75
+ * Make sure you have added the necessary tests for your changes.
76
+ * Run _all_ the tests to assure nothing else was accidentally broken.
77
+ * When you are ready to submit a pull request
78
+
79
+ ### Submitting Changes
80
+
81
+ * Read the article ["Using Pull Requests"](https://help.github.com/articles/using-pull-requests) on GitHub.
82
+ * Make sure your branch is up to date with its parent branch (i.e. master)
83
+ * `git checkout master`
84
+ * `git pull --rebase`
85
+ * `git checkout <your-branch>`
86
+ * `git rebase master`
87
+ * It is likely a good idea to run your tests again.
88
+ * If you've made more than one commit take a moment to consider whether squashing commits together would help improve their logical grouping.
89
+ * [Detailed Walkthrough of One Pull Request per Commit](http://ndlib.github.io/practices/one-commit-per-pull-request/)
90
+ * `git rebase --interactive HEAD~<number-of-commits>` ([See Github help](https://help.github.com/articles/interactive-rebase))
91
+ * To determine the number of commits on your branch: `git log master..<your-branch> --oneline | wc -l`
92
+ * Squashing your branch's changes into one commit is "good form" and helps the person merging your request to see everything that is going on.
93
+ * Push your changes to a topic branch in your fork of the repository.
94
+ * Submit a pull request from your fork to the project.
95
+
96
+ ### Merging Changes
97
+
98
+ * It is considered "poor from" to merge your own request.
99
+ * Please take the time to review the changes and get a sense of what is being changed. Things to consider:
100
+ * Does the commit message explain what is going on?
101
+ * Does the code changes have tests? _Not all changes need new tests, some changes are refactorings_
102
+ * Does the commit contain more than it should? Are two separate concerns being addressed in one commit?
103
+ * Did the Travis tests complete successfully?
104
+ * If you are uncertain, bring other contributors into the conversation by creating a comment that includes their @username.
105
+ * If you like the pull request, but want others to chime in, create a +1 comment and tag a user.
106
+
107
+ ## New Developers
108
+ A great way to get new developers involved and to learn the process is to have them go through the Hierarchy of Promises and create a pull request to improve it.
109
+
110
+ # Additional Resources
111
+
112
+ * [General GitHub documentation](http://help.github.com/)
113
+ * [GitHub pull request documentation](http://help.github.com/send-pull-requests/)
114
+ * [Pro Git](http://git-scm.com/book) is both a free and excellent book about Git.
115
+ * [A Git Config for Contributing](http://ndlib.github.io/practices/my-typical-per-project-git-config/)
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activefedora-aggregation', github: 'projecthydra-labs/activefedora-aggregation'
4
+ gem 'active-fedora', github: 'projecthydra/active_fedora'
5
+
6
+
7
+ unless ENV['CI']
8
+ gem 'pry'
9
+ gem 'pry-byebug'
10
+ end
11
+
12
+ # Specify your gem's dependencies in hydra-pcdm.gemspec
13
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,12 @@
1
+ ##########################################################################
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
data/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # Hydra::PCDM
2
+ [![Build Status](https://travis-ci.org/projecthydra-labs/hydra-pcdm.svg?branch=master)](https://travis-ci.org/projecthydra-labs/hydra-pcdm)
3
+ [![Coverage Status](https://coveralls.io/repos/projecthydra-labs/hydra-pcdm/badge.svg?branch=master)](https://coveralls.io/r/projecthydra-labs/hydra-pcdm?branch=master)
4
+
5
+ Hydra implementation of Portland Common Data Models (PCDM)
6
+
7
+ ## Installation
8
+
9
+ Add these lines to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'active-fedora', github: 'projecthydra/active_fedora' # hydra-pcdm requires an unreleased version of ActiveFedora
13
+ gem 'hydra-pcdm', github: 'projecthydra-labs/hydra-pcdm'
14
+ ```
15
+
16
+ Substitute another branch name for 'master' to test out a branch under development.
17
+ <!-- Temporarily comment out until gem is published.
18
+ gem 'hydra-pcdm'
19
+ -->
20
+
21
+ And then execute:
22
+ ```
23
+ $ bundle
24
+ ```
25
+ <!-- Temporarily comment out until gem is published.
26
+ Or install it yourself as:
27
+
28
+ $ gem install hydra-pcdm
29
+ -->
30
+
31
+ ## Access Controls
32
+ We are using [Web ACL](http://www.w3.org/wiki/WebAccessControl) as implemented by [hydra-access](https://github.com/projecthydra/hydra-head/tree/master/hydra-access-controls) controls
33
+
34
+ ## PCDM Model
35
+
36
+ Reference: [Portland Common Data Model](https://wiki.duraspace.org/x/9IoOB)
37
+
38
+
39
+ ### Model Definition
40
+
41
+ ![PCDM Model Definition](https://wiki.duraspace.org/download/attachments/68061940/coll-object-file.png?version=1&modificationDate=1425932362178&api=v2)
42
+
43
+
44
+ ### Example
45
+
46
+ To test the model and provide clarity we have included a sample mode that exercises the interfaces provided by the gem.
47
+ The sample model may change over time to reflect the state of the gam and what it supports.
48
+
49
+ ![Sandwich Objet Model](https://docs.google.com/drawings/d/1wI4H3AH9pdIPllKIMO356c1cFHUN57azDlgIqMVODSw/pub?w=1369&h=727)
50
+
51
+ ## Usage
52
+
53
+ Hydra-pcdm provides three classes:
54
+ ```
55
+ Hydra::PCDM::Object
56
+ Hydra::PCDM::Collection
57
+ Hydra::PCDM::File
58
+ ```
59
+
60
+ A `Hydra::PCDM::File` is a NonRDFSource &emdash; a bitstream. You can use this to store content. A PCDM::File is contained by a PCDM::Object. A `File` has some attached technical metadata, but no descriptive metadata. A `Hydra::PCDM::Object` contains files and other objects and may have descriptive metadata. A `Hydra::PCDM::Collection` can contain other `Collection`s or `Object`s but not `File`s. A `Collection` also may have descriptive metadata.
61
+
62
+ Typically usage involves extending the behavior provided by this gem. In your application you can write something like this:
63
+
64
+ ```ruby
65
+
66
+ class Book < ActiveFedora::Base
67
+ include Hydra::PCDM::ObjectBehavior
68
+ end
69
+
70
+ class Collection < ActiveFedora::Base
71
+ include Hydra::PCDM::CollectionBehavior
72
+ end
73
+
74
+ c1 = Collection.create
75
+ b1 = Book.create
76
+
77
+ c1.members = [b1]
78
+ # c1.members << b1 # This should work in the future
79
+ c1.save
80
+
81
+ f1 = b1.files.build
82
+ f1.content = "The quick brown fox jumped over the lazy dog."
83
+ b1.save
84
+ ```
85
+
86
+ ## How to contribute
87
+ If you'd like to contribute to this effort, please check out the [Contributing Guide](CONTRIBUTING.md)
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'jettywrapper'
3
+ require 'rspec/core'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+ Jettywrapper.hydra_jetty_version = "master"
8
+
9
+ desc 'Spin up hydra-jetty and run specs'
10
+ task ci: ['jetty:clean'] do
11
+ puts 'running continuous integration'
12
+ jetty_params = Jettywrapper.load_config
13
+ jetty_params[:startup_wait]= 90
14
+ error = Jettywrapper.wrap(jetty_params) do
15
+ Rake::Task['spec'].invoke
16
+ end
17
+ raise "test failures: #{error}" if error
18
+ end
19
+
20
+ task default: :ci
data/config/jetty.yml ADDED
@@ -0,0 +1,6 @@
1
+ default:
2
+ startup_wait: 90
3
+ jetty_port: 8983
4
+ java_opts:
5
+ - "-Xmx256m"
6
+ - "-XX:MaxPermSize=128m"
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hydra/pcdm/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "hydra-pcdm"
8
+ spec.version = Hydra::PCDM::VERSION
9
+ spec.authors = ["E. Lynette Rayle"]
10
+ spec.email = ["elr37@cornell.edu"]
11
+ spec.summary = %q{Portland Common Data Model (PCDM)}
12
+ spec.description = %q{Portland Common Data Model (PCDM)}
13
+ spec.homepage = "https://github.com/projecthydra-labs/hydra-pcdm"
14
+ spec.license = "APACHE2"
15
+ spec.required_ruby_version = '>= 1.9.3'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency 'activefedora-aggregation', '~> 0.2.0'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.6'
25
+ spec.add_development_dependency 'jettywrapper', '>= 2.0.0'
26
+ spec.add_development_dependency 'rake'
27
+ spec.add_development_dependency 'coveralls'
28
+ spec.add_development_dependency 'rspec'
29
+
30
+ end
@@ -0,0 +1,12 @@
1
+ module Hydra::PCDM
2
+ class CollectionIndexer < ObjectIndexer
3
+
4
+ def generate_solr_document
5
+ super.tap do |solr_doc|
6
+ solr_doc["members_ssim"] = object.member_ids
7
+ solr_doc["child_collections_ssim"] = object.child_collections.map { |o| o.id }
8
+ end
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+ module Hydra::PCDM
2
+ class Collection < ActiveFedora::Base
3
+ include Hydra::PCDM::CollectionBehavior
4
+ end
5
+ end
6
+
@@ -0,0 +1,79 @@
1
+ require 'active_fedora/aggregation'
2
+
3
+ module Hydra::PCDM
4
+ module CollectionBehavior
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ type RDFVocabularies::PCDMTerms.Collection
9
+
10
+ aggregates :members, predicate: RDFVocabularies::PCDMTerms.hasMember,
11
+ class_name: "ActiveFedora::Base"
12
+
13
+ indirectly_contains :related_objects, has_member_relation: RDF::Vocab::ORE.aggregates,
14
+ inserted_content_relation: RDF::Vocab::ORE.proxyFor, class_name: "ActiveFedora::Base",
15
+ through: 'ActiveFedora::Aggregation::Proxy', foreign_key: :target
16
+ end
17
+
18
+ module ClassMethods
19
+ def indexer
20
+ Hydra::PCDM::CollectionIndexer
21
+ end
22
+ end
23
+
24
+ # behavior:
25
+ # 1) Hydra::PCDM::Collection can aggregate (pcdm:hasMember) Hydra::PCDM::Collection (no infinite loop, e.g., A -> B -> C -> A)
26
+ # 2) Hydra::PCDM::Collection can aggregate (pcdm:hasMember) Hydra::PCDM::Object
27
+ # 3) Hydra::PCDM::Collection can aggregate (ore:aggregates) Hydra::PCDM::Object (Object related to the Collection)
28
+
29
+ # 4) Hydra::PCDM::Collection can NOT aggregate non-PCDM object
30
+ # 5) Hydra::PCDM::Collection can NOT contain (pcdm:hasFile) Hydra::PCDM::File
31
+
32
+ # 6) Hydra::PCDM::Collection can have descriptive metadata
33
+ # 7) Hydra::PCDM::Collection can have access metadata
34
+
35
+ def child_collections= collections
36
+ raise ArgumentError, "each collection must be a pcdm collection" unless collections.all? { |c| Hydra::PCDM.collection? c }
37
+ raise ArgumentError, "a collection can't be an ancestor of itself" if collection_ancestor?(collections)
38
+ self.members = objects + collections
39
+ end
40
+
41
+ def child_collections
42
+ members.to_a.select { |m| Hydra::PCDM.collection? m }
43
+ end
44
+
45
+ def objects= objects
46
+ raise ArgumentError, "each object must be a pcdm object" unless objects.all? { |o| Hydra::PCDM.object? o }
47
+ self.members = child_collections + objects
48
+ end
49
+
50
+ def objects
51
+ members.to_a.select { |m| Hydra::PCDM.object? m }
52
+ end
53
+
54
+ def collection_ancestor? collections
55
+ collections.each do |check|
56
+ return true if check.id == self.id
57
+ return true if ancestor?(check)
58
+ end
59
+ false
60
+ end
61
+
62
+ def ancestor? collection
63
+ return true if collection.id == self.id
64
+ return false if collection.child_collections.empty?
65
+ current_collections = collection.child_collections
66
+ next_batch = []
67
+ while !current_collections.empty? do
68
+ current_collections.each do |c|
69
+ return true if c.id == self.id
70
+ next_batch += c.child_collections
71
+ end
72
+ current_collections = next_batch
73
+ end
74
+ false
75
+ end
76
+
77
+ end
78
+ end
79
+
@@ -0,0 +1,104 @@
1
+ require 'active_fedora/aggregation'
2
+
3
+ module Hydra::PCDM
4
+
5
+ # behavior:
6
+ # 1) Hydra::PCDM::Object can aggregate (pcdm:hasMember) Hydra::PCDM::Object
7
+ # 2) Hydra::PCDM::Object can aggregate (ore:aggregates) Hydra::PCDM::Object (Object related to the Object)
8
+ # 3) Hydra::PCDM::Object can contain (pcdm:hasFile) Hydra::PCDM::File
9
+ # 4) Hydra::PCDM::Object can contain (pcdm:hasRelatedFile) Hydra::PCDM::File
10
+ # 5) Hydra::PCDM::Object can NOT aggregate Hydra::PCDM::Collection
11
+ # 6) Hydra::PCDM::Object can NOT aggregate non-PCDM object
12
+ # 7) Hydra::PCDM::Object can have descriptive metadata
13
+ # 8) Hydra::PCDM::Object can have access metadata
14
+ module ObjectBehavior
15
+ extend ActiveSupport::Concern
16
+
17
+ included do
18
+ type RDFVocabularies::PCDMTerms.Object
19
+
20
+ aggregates :members, predicate: RDFVocabularies::PCDMTerms.hasMember,
21
+ class_name: "ActiveFedora::Base"
22
+
23
+ indirectly_contains :related_objects, has_member_relation: RDF::Vocab::ORE.aggregates,
24
+ inserted_content_relation: RDF::Vocab::ORE.proxyFor, class_name: "ActiveFedora::Base",
25
+ through: 'ActiveFedora::Aggregation::Proxy', foreign_key: :target
26
+
27
+ directly_contains :files, has_member_relation: RDFVocabularies::PCDMTerms.hasFile,
28
+ class_name: "Hydra::PCDM::File"
29
+
30
+ end
31
+
32
+ module ClassMethods
33
+ def indexer
34
+ Hydra::PCDM::ObjectIndexer
35
+ end
36
+ end
37
+
38
+ def objects= objects
39
+ raise ArgumentError, "each object must be a pcdm object" unless objects.all? { |o| Hydra::PCDM.object? o }
40
+ raise ArgumentError, "an object can't be an ancestor of itself" if object_ancestor?(objects)
41
+ self.members = objects
42
+ end
43
+
44
+ def objects
45
+ members.to_a.select { |m| Hydra::PCDM.object? m }
46
+ end
47
+
48
+ def object_ancestor? objects
49
+ objects.each do |check|
50
+ return true if check.id == self.id
51
+ return true if ancestor?(check)
52
+ end
53
+ false
54
+ end
55
+
56
+ def ancestor? object
57
+ return true if object.id == self.id
58
+ return false if object.objects.empty?
59
+ current_objects = object.objects
60
+ next_batch = []
61
+ while !current_objects.empty? do
62
+ current_objects.each do |c|
63
+ return true if c.id == self.id
64
+ next_batch += c.objects
65
+ end
66
+ current_objects = next_batch
67
+ end
68
+ false
69
+ end
70
+
71
+ def contains= files
72
+ # check that file is an instance of Hydra::PCDM::File
73
+ raise ArgumentError, "each file must be a pcdm file" unless
74
+ files.all? { |f| Hydra::PCDM.file? f }
75
+ super(files)
76
+ end
77
+
78
+ # Returns directly contained files that have the requested RDF Type
79
+ # @param [RDF::URI] uri for the desired Type
80
+ # @example
81
+ # filter_files_by_type(::RDF::URI("http://pcdm.org/ExtractedText"))
82
+ def filter_files_by_type uri
83
+ self.files.reject do |file|
84
+ file.metadata_node.query(predicate: RDF.type, object: uri).map(&:object).empty?
85
+ end
86
+ end
87
+
88
+ # Finds or Initializes directly contained file with the requested RDF Type
89
+ # @param [RDF::URI] uri for the desired Type
90
+ # @example
91
+ # file_of_type(::RDF::URI("http://pcdm.org/ExtractedText"))
92
+ def file_of_type uri
93
+ matching_files = filter_files_by_type(uri)
94
+ if matching_files.empty?
95
+ file = self.files.build
96
+ Hydra::PCDM::AddTypeToFile.call(file, uri)
97
+ else
98
+ return matching_files.first
99
+ end
100
+ end
101
+
102
+ end
103
+ end
104
+
@@ -0,0 +1,20 @@
1
+ module Hydra::PCDM
2
+ class File < ActiveFedora::File
3
+ include ActiveFedora::WithMetadata
4
+
5
+ metadata do
6
+ configure type: RDFVocabularies::PCDMTerms.File
7
+ property :label, predicate: ::RDF::RDFS.label
8
+
9
+ property :file_name, predicate: EBUCoreVocabularies::EBUCoreTerms.filename
10
+ property :file_size, predicate: EBUCoreVocabularies::EBUCoreTerms.fileSize
11
+ property :date_created, predicate: EBUCoreVocabularies::EBUCoreTerms.dateCreated
12
+ property :has_mime_type, predicate: EBUCoreVocabularies::EBUCoreTerms.hasMimeType
13
+ property :date_modified, predicate: EBUCoreVocabularies::EBUCoreTerms.dateModified
14
+ property :byte_order, predicate: SweetjplVocabularies::SweetjplTerms.byteOrder
15
+
16
+ # This is a server-managed predicate which means Fedora does not let us change it.
17
+ property :file_hash, predicate: RDF::Vocab::PREMIS.hasMessageDigest
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,6 @@
1
+ module Hydra::PCDM
2
+ class Object < ActiveFedora::Base
3
+ include Hydra::PCDM::ObjectBehavior
4
+ end
5
+ end
6
+
@@ -0,0 +1,10 @@
1
+ module Hydra::PCDM
2
+ class ObjectIndexer < ActiveFedora::IndexingService
3
+ def generate_solr_document
4
+ super.tap do |solr_doc|
5
+ solr_doc["objects_ssim"] = object.objects.map { |o| o.id }
6
+ end
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,20 @@
1
+ module Hydra::PCDM
2
+ class AddCollectionToCollection
3
+
4
+ ##
5
+ # Add a collection to a collection.
6
+ #
7
+ # @param [Hydra::PCDM::Collection] :parent_collection to which to add collection
8
+ # @param [Hydra::PCDM::Collection] :child_collection being added
9
+ #
10
+ # @return [Hydra::PCDM::Collection] the updated pcdm collection
11
+
12
+ def self.call( parent_collection, child_collection )
13
+ raise ArgumentError, "parent_collection must be a pcdm collection" unless Hydra::PCDM.collection? parent_collection
14
+ raise ArgumentError, "child_collection must be a pcdm collection" unless Hydra::PCDM.collection? child_collection
15
+ raise ArgumentError, "a collection can't be an ancestor of itself" if parent_collection.ancestor? child_collection
16
+ parent_collection.members << child_collection
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module Hydra::PCDM
2
+ class AddObjectToCollection
3
+
4
+ ##
5
+ # Add an object to a collection.
6
+ #
7
+ # @param [Hydra::PCDM::Collection] :parent_collection to which to add object
8
+ # @param [Hydra::PCDM::Object] :child_object being added
9
+ #
10
+ # @return [Hydra::PCDM::Collection] the updated pcdm collection
11
+
12
+ def self.call( parent_collection, child_object )
13
+ raise ArgumentError, "parent_collection must be a pcdm collection" unless Hydra::PCDM.collection? parent_collection
14
+ raise ArgumentError, "child_object must be a pcdm object" unless Hydra::PCDM.object? child_object
15
+ parent_collection.members << child_object
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ module Hydra::PCDM
2
+ class AddRelatedObjectToCollection
3
+
4
+ ##
5
+ # Add a related object to a collection.
6
+ #
7
+ # @param [Hydra::PCDM::Collection] :parent_collection to which to add the related object
8
+ # @param [Hydra::PCDM::Object] :child_related_object being added
9
+ #
10
+ # @return [Hydra::PCDM::Collection] the updated pcdm collection
11
+
12
+ def self.call( parent_collection, child_related_object )
13
+ raise ArgumentError, 'parent_collection must be a pcdm object' unless Hydra::PCDM.collection? parent_collection
14
+ raise ArgumentError, 'child_related_object must be a pcdm object' unless Hydra::PCDM.object? child_related_object
15
+
16
+ # parent_collection.related_objects = parent_collection.related_objects.to_a + child_related_object
17
+ parent_collection.related_objects << child_related_object
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ module Hydra::PCDM
2
+ class GetCollectionsFromCollection
3
+
4
+ ##
5
+ # Get member collections from a collection in order.
6
+ #
7
+ # @param [Hydra::PCDM::Collection] :parent_collection in which the child collections are members
8
+ #
9
+ # @return [Array<Hydra::PCDM::Collection>] all member collections
10
+
11
+ def self.call( parent_collection )
12
+ raise ArgumentError, "parent_collection must be a pcdm collection" unless Hydra::PCDM.collection? parent_collection
13
+
14
+ parent_collection.child_collections
15
+ end
16
+
17
+ end
18
+ end