hydra-pcdm 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +26 -0
- data/.travis.yml +14 -0
- data/CONTRIBUTING.md +115 -0
- data/Gemfile +13 -0
- data/LICENSE +12 -0
- data/README.md +87 -0
- data/Rakefile +20 -0
- data/config/jetty.yml +6 -0
- data/hydra-pcdm.gemspec +30 -0
- data/lib/hydra/pcdm/collection_indexer.rb +12 -0
- data/lib/hydra/pcdm/models/collection.rb +6 -0
- data/lib/hydra/pcdm/models/concerns/collection_behavior.rb +79 -0
- data/lib/hydra/pcdm/models/concerns/object_behavior.rb +104 -0
- data/lib/hydra/pcdm/models/file.rb +20 -0
- data/lib/hydra/pcdm/models/object.rb +6 -0
- data/lib/hydra/pcdm/object_indexer.rb +10 -0
- data/lib/hydra/pcdm/services/collection/add_collection.rb +20 -0
- data/lib/hydra/pcdm/services/collection/add_object.rb +19 -0
- data/lib/hydra/pcdm/services/collection/add_related_object.rb +21 -0
- data/lib/hydra/pcdm/services/collection/get_collections.rb +18 -0
- data/lib/hydra/pcdm/services/collection/get_objects.rb +18 -0
- data/lib/hydra/pcdm/services/collection/get_related_objects.rb +17 -0
- data/lib/hydra/pcdm/services/collection/remove_collection.rb +36 -0
- data/lib/hydra/pcdm/services/collection/remove_object.rb +43 -0
- data/lib/hydra/pcdm/services/collection/remove_related_object.rb +36 -0
- data/lib/hydra/pcdm/services/file/add_type.rb +20 -0
- data/lib/hydra/pcdm/services/file/get_mime_type.rb +11 -0
- data/lib/hydra/pcdm/services/object/add_object.rb +20 -0
- data/lib/hydra/pcdm/services/object/add_related_object.rb +21 -0
- data/lib/hydra/pcdm/services/object/get_objects.rb +18 -0
- data/lib/hydra/pcdm/services/object/get_related_objects.rb +17 -0
- data/lib/hydra/pcdm/services/object/remove_object.rb +43 -0
- data/lib/hydra/pcdm/services/object/remove_related_object.rb +36 -0
- data/lib/hydra/pcdm/version.rb +5 -0
- data/lib/hydra/pcdm/vocab/ebucore_terms.rb +33 -0
- data/lib/hydra/pcdm/vocab/pcdm_terms.rb +87 -0
- data/lib/hydra/pcdm/vocab/sweetjpl_terms.rb +10 -0
- data/lib/hydra/pcdm.rb +69 -0
- data/spec/hydra/pcdm/collection_indexer_spec.rb +26 -0
- data/spec/hydra/pcdm/models/collection_spec.rb +82 -0
- data/spec/hydra/pcdm/models/file_spec.rb +56 -0
- data/spec/hydra/pcdm/models/object_spec.rb +141 -0
- data/spec/hydra/pcdm/object_indexer_spec.rb +20 -0
- data/spec/hydra/pcdm/services/collection/add_collection_spec.rb +197 -0
- data/spec/hydra/pcdm/services/collection/add_object_spec.rb +132 -0
- data/spec/hydra/pcdm/services/collection/add_related_object_spec.rb +94 -0
- data/spec/hydra/pcdm/services/collection/get_collections_spec.rb +40 -0
- data/spec/hydra/pcdm/services/collection/get_objects_spec.rb +40 -0
- data/spec/hydra/pcdm/services/collection/get_related_objects_spec.rb +37 -0
- data/spec/hydra/pcdm/services/collection/remove_collection_spec.rb +143 -0
- data/spec/hydra/pcdm/services/collection/remove_object_spec.rb +180 -0
- data/spec/hydra/pcdm/services/collection/remove_related_object_spec.rb +146 -0
- data/spec/hydra/pcdm/services/file/add_type_spec.rb +19 -0
- data/spec/hydra/pcdm/services/file/get_mime_type_spec.rb +24 -0
- data/spec/hydra/pcdm/services/object/add_object_spec.rb +186 -0
- data/spec/hydra/pcdm/services/object/add_related_object_spec.rb +94 -0
- data/spec/hydra/pcdm/services/object/get_objects_spec.rb +33 -0
- data/spec/hydra/pcdm/services/object/get_related_objects_spec.rb +39 -0
- data/spec/hydra/pcdm/services/object/remove_object_spec.rb +158 -0
- data/spec/hydra/pcdm/services/object/remove_related_object_spec.rb +126 -0
- data/spec/hydra/pcdm_spec.rb +56 -0
- data/spec/spec_helper.rb +34 -0
- 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
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
data/hydra-pcdm.gemspec
ADDED
@@ -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,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,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
|