cocina-models 0.31.0 → 0.34.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +51 -0
- data/.github/pull_request_template.md +8 -1
- data/.rubocop.yml +53 -2
- data/README.md +8 -13
- data/cocina-models.gemspec +3 -3
- data/docs/index.html +20 -0
- data/docs/maps/DRO.json +1 -1
- data/exe/generator +1 -1
- data/lib/cocina/generator.rb +0 -11
- data/lib/cocina/generator/generator.rb +3 -0
- data/lib/cocina/generator/schema_value.rb +2 -2
- data/lib/cocina/models.rb +5 -3
- data/lib/cocina/models/access.rb +4 -0
- data/lib/cocina/models/admin_policy_administrative.rb +1 -1
- data/lib/cocina/models/administrative.rb +1 -1
- data/lib/cocina/models/dro.rb +1 -1
- data/lib/cocina/models/dro_access.rb +7 -1
- data/lib/cocina/models/event.rb +1 -1
- data/lib/cocina/models/file.rb +1 -1
- data/lib/cocina/models/identification.rb +2 -0
- data/lib/cocina/models/request_collection.rb +1 -1
- data/lib/cocina/models/request_dro.rb +2 -2
- data/lib/cocina/models/request_identification.rb +13 -0
- data/lib/cocina/models/sequence.rb +1 -0
- data/lib/cocina/models/version.rb +1 -1
- data/openapi.yml +160 -32
- metadata +14 -17
- data/.travis.yml +0 -23
- data/docs/README.md +0 -9
- data/docs/_config.yml +0 -1
- data/docs/meta.json +0 -9
- data/docs/schema.json +0 -1654
- data/docs/schema.md +0 -268
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47e0e5c391575050da0d7ec099da98ced48dc06f5d7ba2a2df5f53f3e687e04d
|
4
|
+
data.tar.gz: cc63b9adc18d069b325ddedf8c019529fa10655168a34e12aa0114220793d372
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2f94eb4be540092d833435fec055b48a43d8c3d8b67ffa746dca94607810b23bce102cb0d20fe6eb6097ba721f83be403b2498c881b2dbf448f2c0f2341a5f4
|
7
|
+
data.tar.gz: cbae9dff9f1f89bfc9e7557086f63a3dae4941eb4785ba29e2f006fde18a6bdc51a4d747ea74af7d0211e19e20c1f53f2d949d1b233e9f394b6abb6aaf1fae7f
|
@@ -0,0 +1,51 @@
|
|
1
|
+
version: 2.1
|
2
|
+
executors:
|
3
|
+
docker-publisher:
|
4
|
+
docker:
|
5
|
+
- image: circleci/buildpack-deps:stretch
|
6
|
+
jobs:
|
7
|
+
test:
|
8
|
+
docker:
|
9
|
+
- image: circleci/ruby:2.7.0-node
|
10
|
+
steps:
|
11
|
+
- checkout
|
12
|
+
- run:
|
13
|
+
name: install bundler
|
14
|
+
command: gem install bundler -v 2.1.4
|
15
|
+
- run:
|
16
|
+
name: Install gem dependencies
|
17
|
+
command: bundle check || bundle install
|
18
|
+
- run:
|
19
|
+
name: Lint using rubocop
|
20
|
+
command: bundle exec rubocop
|
21
|
+
- run:
|
22
|
+
name: Setup Code Climate test-reporter
|
23
|
+
command: |
|
24
|
+
curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
25
|
+
chmod +x ./cc-test-reporter
|
26
|
+
./cc-test-reporter before-build
|
27
|
+
- run:
|
28
|
+
name: Run RSpec test suite
|
29
|
+
command: bundle exec rspec
|
30
|
+
- run:
|
31
|
+
name: upload test coverage report to Code Climate
|
32
|
+
command: ./cc-test-reporter after-build --coverage-input-type simplecov --exit-code $?
|
33
|
+
- run:
|
34
|
+
name: Validate API specification
|
35
|
+
command: |
|
36
|
+
sudo npm install -g openapi-enforcer-cli
|
37
|
+
result=$(openapi-enforcer validate openapi.yml)
|
38
|
+
[[ $result =~ "Document is valid" ]] && {
|
39
|
+
echo "Validation good"
|
40
|
+
exit 0
|
41
|
+
} || {
|
42
|
+
echo $result
|
43
|
+
exit 1
|
44
|
+
}
|
45
|
+
|
46
|
+
workflows:
|
47
|
+
version: 2
|
48
|
+
|
49
|
+
test:
|
50
|
+
jobs:
|
51
|
+
- test
|
data/.rubocop.yml
CHANGED
@@ -4,7 +4,7 @@ inherit_from: .rubocop_todo.yml
|
|
4
4
|
require:
|
5
5
|
- rubocop-rspec
|
6
6
|
|
7
|
-
|
7
|
+
Layout/LineLength:
|
8
8
|
Max: 114
|
9
9
|
Exclude:
|
10
10
|
- lib/cocina/models/*
|
@@ -26,7 +26,58 @@ RSpec/ExampleLength:
|
|
26
26
|
- spec/cocina/models/description_spec.rb
|
27
27
|
- spec/cocina/models/dro_shared_examples.rb
|
28
28
|
|
29
|
-
|
30
29
|
Style/Documentation:
|
31
30
|
Exclude:
|
32
31
|
- lib/cocina/models/*
|
32
|
+
|
33
|
+
Layout/EmptyLinesAroundAttributeAccessor:
|
34
|
+
Enabled: true
|
35
|
+
|
36
|
+
Layout/SpaceAroundMethodCallOperator:
|
37
|
+
Enabled: true
|
38
|
+
|
39
|
+
Lint/DeprecatedOpenSSLConstant:
|
40
|
+
Enabled: true
|
41
|
+
|
42
|
+
Lint/MixedRegexpCaptureTypes:
|
43
|
+
Enabled: true
|
44
|
+
|
45
|
+
Lint/RaiseException:
|
46
|
+
Enabled: true
|
47
|
+
|
48
|
+
Lint/StructNewOverride:
|
49
|
+
Enabled: true
|
50
|
+
|
51
|
+
Style/AccessorGrouping:
|
52
|
+
Enabled: true
|
53
|
+
|
54
|
+
Style/BisectedAttrAccessor:
|
55
|
+
Enabled: true
|
56
|
+
|
57
|
+
Style/ExponentialNotation:
|
58
|
+
Enabled: true
|
59
|
+
|
60
|
+
Style/HashEachMethods:
|
61
|
+
Enabled: true
|
62
|
+
|
63
|
+
Style/HashTransformKeys:
|
64
|
+
Enabled: true
|
65
|
+
|
66
|
+
Style/HashTransformValues:
|
67
|
+
Enabled: true
|
68
|
+
|
69
|
+
Style/RedundantAssignment:
|
70
|
+
Enabled: true
|
71
|
+
|
72
|
+
Style/RedundantFetchBlock:
|
73
|
+
Enabled: true
|
74
|
+
|
75
|
+
Style/RedundantRegexpCharacterClass:
|
76
|
+
Enabled: true
|
77
|
+
|
78
|
+
Style/RedundantRegexpEscape:
|
79
|
+
Enabled: true
|
80
|
+
|
81
|
+
Style/SlicingWithRange:
|
82
|
+
Enabled: true
|
83
|
+
|
data/README.md
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
[![
|
1
|
+
[![CircleCI](https://circleci.com/gh/sul-dlss/cocina-models.svg?style=svg)](https://circleci.com/gh/sul-dlss/cocina-models)
|
2
2
|
[![Test Coverage](https://api.codeclimate.com/v1/badges/472273351516ac01dce1/test_coverage)](https://codeclimate.com/github/sul-dlss/cocina-models/test_coverage)
|
3
3
|
[![Maintainability](https://api.codeclimate.com/v1/badges/472273351516ac01dce1/maintainability)](https://codeclimate.com/github/sul-dlss/cocina-models/maintainability)
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/cocina-models.svg)](https://badge.fury.io/rb/cocina-models)
|
5
|
+
[![OpenAPI Validator](http://validator.swagger.io/validator?url=https://raw.githubusercontent.com/sul-dlss/cocina-models/master/openapi.yml)](http://validator.swagger.io/validator/debug?url=https://raw.githubusercontent.com/sul-dlss/cocina-models/master/openapi.yml)
|
5
6
|
|
6
7
|
# Cocina::Models
|
7
8
|
|
@@ -25,20 +26,14 @@ exe/generator generate
|
|
25
26
|
exe/generator generate_schema DRO
|
26
27
|
```
|
27
28
|
|
28
|
-
##
|
29
|
+
## Testing
|
29
30
|
|
30
|
-
|
31
|
-
gem install prmd
|
32
|
-
cd docs
|
31
|
+
The generator is tested via its output when run against `openapi.yml`, viz., the Cocina model classes. Thus, `generate` should be run after any changes to `openapi.yml`.
|
33
32
|
|
34
|
-
|
35
|
-
prmd combine --meta meta.json maps/ > schema.json
|
33
|
+
Beyond what is necessary to test the generator, the Cocina model classes are not tested, i.e., they are assumed to be as specified in `openapi.yml`.
|
36
34
|
|
37
|
-
|
38
|
-
prmd verify schema.json
|
35
|
+
## Using this gem
|
39
36
|
|
40
|
-
|
41
|
-
prmd doc schema.json > schema.md
|
42
|
-
```
|
37
|
+
If you are using this gem in an application that has an API that accepts Cocina models (e.g., SDR API, Dor-Services-App), make sure that the `openapi.yml` for the application includes the schemas that match the schemas in this `openapi.yml`.
|
43
38
|
|
44
|
-
|
39
|
+
This can be accomplished by cutting and pasting these schemas. By convention, these schemas are listed first in the `openapi.yml` of the associated projects, followed by the application-specific schemas.
|
data/cocina-models.gemspec
CHANGED
@@ -33,9 +33,9 @@ Gem::Specification.new do |spec|
|
|
33
33
|
|
34
34
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
35
35
|
spec.add_development_dependency 'committee'
|
36
|
-
spec.add_development_dependency 'rake', '~>
|
36
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
37
37
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
38
|
-
spec.add_development_dependency 'rubocop', '~> 0.
|
38
|
+
spec.add_development_dependency 'rubocop', '~> 0.87'
|
39
39
|
spec.add_development_dependency 'rubocop-rspec'
|
40
|
-
spec.add_development_dependency 'simplecov'
|
40
|
+
spec.add_development_dependency 'simplecov', '~> 0.17.0'
|
41
41
|
end
|
data/docs/index.html
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>API documentation</title>
|
5
|
+
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
7
|
+
|
8
|
+
|
9
|
+
<style>
|
10
|
+
body {
|
11
|
+
margin: 0;
|
12
|
+
padding: 0;
|
13
|
+
}
|
14
|
+
</style>
|
15
|
+
</head>
|
16
|
+
<body>
|
17
|
+
<redoc spec-url='https://raw.githubusercontent.com/sul-dlss/cocina-models/master/openapi.yml'></redoc>
|
18
|
+
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
|
19
|
+
</body>
|
20
|
+
</html>
|
data/docs/maps/DRO.json
CHANGED
@@ -84,7 +84,7 @@
|
|
84
84
|
"download": {
|
85
85
|
"description": "Download level for the DRO metadata.",
|
86
86
|
"type": "string",
|
87
|
-
"enum": ["world", "stanford", "location-based", "
|
87
|
+
"enum": ["world", "stanford", "location-based", "none"]
|
88
88
|
},
|
89
89
|
"embargo": {
|
90
90
|
"description": "Embargo metadata",
|
data/exe/generator
CHANGED
data/lib/cocina/generator.rb
CHANGED
@@ -1,16 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'zeitwerk'
|
4
|
-
require 'yaml'
|
5
|
-
require 'active_support/core_ext/string'
|
6
|
-
require 'thor'
|
7
|
-
require 'openapi3_parser'
|
8
|
-
require 'byebug'
|
9
|
-
|
10
|
-
loader = Zeitwerk::Loader.new
|
11
|
-
loader.push_dir(File.absolute_path("#{__FILE__}/../.."))
|
12
|
-
loader.setup
|
13
|
-
|
14
3
|
module Cocina
|
15
4
|
# Module for generating Cocina models from openapi.
|
16
5
|
module Generator
|
@@ -17,10 +17,13 @@ module Cocina
|
|
17
17
|
def generate
|
18
18
|
clean_output
|
19
19
|
|
20
|
+
# rubocop:disable Style/HashEachMethods
|
21
|
+
# This is not a Hash
|
20
22
|
schemas.keys.each do |schema_name|
|
21
23
|
schema = schema_for(schema_name)
|
22
24
|
generate_for(schema) if schema
|
23
25
|
end
|
26
|
+
# rubocop:enable Style/HashEachMethods
|
24
27
|
|
25
28
|
generate_vocab
|
26
29
|
end
|
@@ -4,11 +4,11 @@ module Cocina
|
|
4
4
|
module Generator
|
5
5
|
# Class for generating from an openapi value
|
6
6
|
class SchemaValue < SchemaBase
|
7
|
-
# rubocop:disable
|
7
|
+
# rubocop:disable Layout/LineLength
|
8
8
|
def generate
|
9
9
|
"#{description}#{example}attribute :#{name.camelize(:lower)}, Types::#{dry_datatype(schema_doc)}#{default}#{enum}#{omittable}"
|
10
10
|
end
|
11
|
-
# rubocop:enable
|
11
|
+
# rubocop:enable Layout/LineLength
|
12
12
|
|
13
13
|
private
|
14
14
|
|
data/lib/cocina/models.rb
CHANGED
@@ -5,13 +5,15 @@ require 'zeitwerk'
|
|
5
5
|
require 'dry-struct'
|
6
6
|
require 'dry-types'
|
7
7
|
require 'json'
|
8
|
+
require 'yaml'
|
8
9
|
require 'openapi_parser'
|
10
|
+
require 'openapi3_parser'
|
9
11
|
require 'active_support/core_ext/hash/indifferent_access'
|
10
|
-
require '
|
12
|
+
require 'active_support/core_ext/string'
|
13
|
+
require 'thor'
|
11
14
|
|
12
15
|
# Help Zeitwerk find some of our classes
|
13
16
|
class CocinaModelsInflector < Zeitwerk::Inflector
|
14
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
15
17
|
# rubocop:disable Metrics/MethodLength
|
16
18
|
def camelize(basename, _abspath)
|
17
19
|
case basename
|
@@ -31,7 +33,7 @@ class CocinaModelsInflector < Zeitwerk::Inflector
|
|
31
33
|
super
|
32
34
|
end
|
33
35
|
end
|
34
|
-
|
36
|
+
|
35
37
|
# rubocop:enable Metrics/MethodLength
|
36
38
|
end
|
37
39
|
|
data/lib/cocina/models/access.rb
CHANGED
@@ -5,6 +5,10 @@ module Cocina
|
|
5
5
|
class Access < Struct
|
6
6
|
# Access level
|
7
7
|
attribute :access, Types::Strict::String.default('dark').enum('world', 'stanford', 'location-based', 'citation-only', 'dark').meta(omittable: true)
|
8
|
+
# Download access level for a file
|
9
|
+
attribute :download, Types::Strict::String.default('none').enum('world', 'stanford', 'location-based', 'none').meta(omittable: true)
|
10
|
+
# If access is "location-based", which location should have access.
|
11
|
+
attribute :readLocation, Types::Strict::String.enum('spec', 'music', 'ars', 'art', 'hoover', 'm&m').meta(omittable: true)
|
8
12
|
end
|
9
13
|
end
|
10
14
|
end
|
@@ -5,7 +5,7 @@ module Cocina
|
|
5
5
|
class AdminPolicyAdministrative < Struct
|
6
6
|
attribute :defaultObjectRights, Types::Strict::String.default('<?xml version="1.0" encoding="UTF-8"?><rightsMetadata><access type="discover"><machine><world/></machine></access><access type="read"><machine><world/></machine></access><use><human type="useAndReproduction"/><human type="creativeCommons"/><machine type="creativeCommons" uri=""/><human type="openDataCommons"/><machine type="openDataCommons" uri=""/></use><copyright><human/></copyright></rightsMetadata>').meta(omittable: true)
|
7
7
|
attribute :registrationWorkflow, Types::Strict::String.meta(omittable: true)
|
8
|
-
attribute :hasAdminPolicy, Types::Strict::String
|
8
|
+
attribute :hasAdminPolicy, Types::Strict::String
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -4,7 +4,7 @@ module Cocina
|
|
4
4
|
module Models
|
5
5
|
class Administrative < Struct
|
6
6
|
# example: druid:bc123df4567
|
7
|
-
attribute :hasAdminPolicy, Types::Strict::String
|
7
|
+
attribute :hasAdminPolicy, Types::Strict::String
|
8
8
|
attribute :releaseTags, Types::Strict::Array.of(ReleaseTag).meta(omittable: true)
|
9
9
|
# Administrative or Internal project this resource is a part of
|
10
10
|
# example: Google Books
|
data/lib/cocina/models/dro.rb
CHANGED
@@ -31,7 +31,7 @@ module Cocina
|
|
31
31
|
# Version for the DRO within SDR.
|
32
32
|
attribute :version, Types::Strict::Integer
|
33
33
|
attribute(:access, DROAccess.default { DROAccess.new })
|
34
|
-
attribute
|
34
|
+
attribute(:administrative, Administrative.default { Administrative.new })
|
35
35
|
attribute :description, Description.optional.meta(omittable: true)
|
36
36
|
attribute :identification, Identification.optional.meta(omittable: true)
|
37
37
|
attribute :structural, DROStructural.optional.meta(omittable: true)
|
@@ -7,10 +7,16 @@ module Cocina
|
|
7
7
|
# The human readable copyright statement that applies
|
8
8
|
# example: Copyright World Trade Organization
|
9
9
|
attribute :copyright, Types::Strict::String.meta(omittable: true)
|
10
|
+
attribute :embargo, Embargo.optional.meta(omittable: true)
|
11
|
+
# Download access level. This is used in the transition from Fedora as a way to set a default download level at registration that is copied down to all the files.
|
12
|
+
|
13
|
+
attribute :download, Types::Strict::String.default('none').enum('world', 'stanford', 'location-based', 'none').meta(omittable: true)
|
14
|
+
# If access is "location-based", which location should have access. This is used in the transition from Fedora as a way to set a default readLocation at registration that is copied down to all the files.
|
15
|
+
|
16
|
+
attribute :readLocation, Types::Strict::String.enum('spec', 'music', 'ars', 'art', 'hoover', 'm&m').meta(omittable: true)
|
10
17
|
# The human readable use and reproduction statement that applies
|
11
18
|
# example: Property rights reside with the repository. Literary rights reside with the creators of the documents or their heirs. To obtain permission to publish or reproduce, please contact the Public Services Librarian of the Dept. of Special Collections (http://library.stanford.edu/spc).
|
12
19
|
attribute :useAndReproductionStatement, Types::Strict::String.meta(omittable: true)
|
13
|
-
attribute :embargo, Embargo.optional.meta(omittable: true)
|
14
20
|
end
|
15
21
|
end
|
16
22
|
end
|
data/lib/cocina/models/event.rb
CHANGED
@@ -3,13 +3,13 @@
|
|
3
3
|
module Cocina
|
4
4
|
module Models
|
5
5
|
class Event < Struct
|
6
|
+
attribute :structuredValue, Types::Strict::Array.of(DescriptiveBasicValue).meta(omittable: true)
|
6
7
|
# Description of the event (creation, publication, etc.).
|
7
8
|
attribute :type, Types::Strict::String.meta(omittable: true)
|
8
9
|
attribute :date, Types::Strict::Array.of(DescriptiveValue).meta(omittable: true)
|
9
10
|
attribute :contributor, Types::Strict::Array.of(Contributor).meta(omittable: true)
|
10
11
|
attribute :location, Types::Strict::Array.of(DescriptiveValue).meta(omittable: true)
|
11
12
|
attribute :note, Types::Strict::Array.of(DescriptiveValue).meta(omittable: true)
|
12
|
-
attribute :structuredValue, Types::Strict::Array.of(DescriptiveBasicValue).meta(omittable: true)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
data/lib/cocina/models/file.rb
CHANGED
@@ -14,7 +14,7 @@ module Cocina
|
|
14
14
|
# Primary processing label (can be same as title) for a File.
|
15
15
|
attribute :label, Types::Strict::String
|
16
16
|
# Filename for a file. Can be same as label.
|
17
|
-
attribute :filename, Types::Strict::String
|
17
|
+
attribute :filename, Types::Strict::String
|
18
18
|
# Size of the File (binary) in bytes.
|
19
19
|
attribute :size, Types::Strict::Integer.meta(omittable: true)
|
20
20
|
# Version for the File within SDR.
|
@@ -3,6 +3,8 @@
|
|
3
3
|
module Cocina
|
4
4
|
module Models
|
5
5
|
class Identification < Struct
|
6
|
+
# Unique identifier in some other system. This is because a large proportion of what is deposited in SDR, historically and currently, are representations of objects that are also represented in other systems. For example, digitized paper and A/V collections have physical manifestations, and those physical objects are managed in systems that have their own identifiers. Similarly, books have barcodes, archival materials have collection numbers and physical locations, etc. The sourceId allows determining if an item has been deposited before and where to look for the original item if you're looking at its SDR representation.
|
7
|
+
|
6
8
|
# example: sul:PC0170_s3_Fiesta_Bowl_2012-01-02_210609_2026
|
7
9
|
attribute :sourceId, Types::Strict::String.meta(omittable: true)
|
8
10
|
attribute :catalogLinks, Types::Strict::Array.of(CatalogLink).meta(omittable: true)
|
@@ -16,7 +16,7 @@ module Cocina
|
|
16
16
|
attribute :label, Types::Strict::String
|
17
17
|
attribute :version, Types::Strict::Integer
|
18
18
|
attribute(:access, Access.default { Access.new })
|
19
|
-
attribute
|
19
|
+
attribute(:administrative, Administrative.default { Administrative.new })
|
20
20
|
attribute :description, Description.optional.meta(omittable: true)
|
21
21
|
attribute :identification, CollectionIdentification.optional.meta(omittable: true)
|
22
22
|
|
@@ -26,9 +26,9 @@ module Cocina
|
|
26
26
|
attribute :label, Types::Strict::String
|
27
27
|
attribute :version, Types::Strict::Integer
|
28
28
|
attribute :access, DROAccess.optional.meta(omittable: true)
|
29
|
-
attribute
|
29
|
+
attribute(:administrative, Administrative.default { Administrative.new })
|
30
30
|
attribute :description, Description.optional.meta(omittable: true)
|
31
|
-
attribute
|
31
|
+
attribute(:identification, RequestIdentification.default { RequestIdentification.new })
|
32
32
|
attribute :structural, RequestDROStructural.optional.meta(omittable: true)
|
33
33
|
attribute :geographic, Geographic.optional.meta(omittable: true)
|
34
34
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cocina
|
4
|
+
module Models
|
5
|
+
class RequestIdentification < Struct
|
6
|
+
# Unique identifier in some other system. This is because a large proportion of what is deposited in SDR, historically and currently, are representations of objects that are also represented in other systems. For example, digitized paper and A/V collections have physical manifestations, and those physical objects are managed in systems that have their own identifiers. Similarly, books have barcodes, archival materials have collection numbers and physical locations, etc. The sourceId allows determining if an item has been deposited before and where to look for the original item if you're looking at its SDR representation.
|
7
|
+
|
8
|
+
# example: sul:PC0170_s3_Fiesta_Bowl_2012-01-02_210609_2026
|
9
|
+
attribute :sourceId, Types::Strict::String
|
10
|
+
attribute :catalogLinks, Types::Strict::Array.of(CatalogLink).meta(omittable: true)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|