pbcore 0.2.0
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.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +674 -0
- data/README.md +37 -0
- data/Rakefile +6 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/lib/pbcore.rb +28 -0
- data/lib/pbcore/annotation.rb +12 -0
- data/lib/pbcore/asset_date.rb +12 -0
- data/lib/pbcore/asset_type.rb +11 -0
- data/lib/pbcore/attributes.rb +6 -0
- data/lib/pbcore/attributes/common.rb +13 -0
- data/lib/pbcore/attributes/time_interval.rb +12 -0
- data/lib/pbcore/audience_level.rb +11 -0
- data/lib/pbcore/audience_rating.rb +11 -0
- data/lib/pbcore/contributor.rb +19 -0
- data/lib/pbcore/contributor/contributor.rb +12 -0
- data/lib/pbcore/contributor/role.rb +12 -0
- data/lib/pbcore/coverage.rb +20 -0
- data/lib/pbcore/coverage/coverage.rb +11 -0
- data/lib/pbcore/coverage/type.rb +11 -0
- data/lib/pbcore/creator.rb +19 -0
- data/lib/pbcore/creator/creator.rb +16 -0
- data/lib/pbcore/creator/role.rb +11 -0
- data/lib/pbcore/description.rb +13 -0
- data/lib/pbcore/description_document.rb +60 -0
- data/lib/pbcore/element.rb +199 -0
- data/lib/pbcore/errors.rb +55 -0
- data/lib/pbcore/extension.rb +19 -0
- data/lib/pbcore/extension/embedded.rb +15 -0
- data/lib/pbcore/extension/wrap.rb +26 -0
- data/lib/pbcore/extension/wrap/authority_used.rb +11 -0
- data/lib/pbcore/extension/wrap/element.rb +11 -0
- data/lib/pbcore/extension/wrap/value.rb +11 -0
- data/lib/pbcore/factories.rb +6 -0
- data/lib/pbcore/genre.rb +11 -0
- data/lib/pbcore/identifier.rb +11 -0
- data/lib/pbcore/instantiation.rb +87 -0
- data/lib/pbcore/instantiation/alternative_modes.rb +11 -0
- data/lib/pbcore/instantiation/annotation.rb +12 -0
- data/lib/pbcore/instantiation/channel_configuration.rb +11 -0
- data/lib/pbcore/instantiation/colors.rb +11 -0
- data/lib/pbcore/instantiation/data_rate.rb +13 -0
- data/lib/pbcore/instantiation/date.rb +13 -0
- data/lib/pbcore/instantiation/digital.rb +11 -0
- data/lib/pbcore/instantiation/dimensions.rb +13 -0
- data/lib/pbcore/instantiation/duration.rb +11 -0
- data/lib/pbcore/instantiation/essence_track.rb +59 -0
- data/lib/pbcore/instantiation/essence_track/annotation.rb +11 -0
- data/lib/pbcore/instantiation/essence_track/aspect_ratio.rb +11 -0
- data/lib/pbcore/instantiation/essence_track/bit_depth.rb +11 -0
- data/lib/pbcore/instantiation/essence_track/data_rate.rb +11 -0
- data/lib/pbcore/instantiation/essence_track/duration.rb +9 -0
- data/lib/pbcore/instantiation/essence_track/encoding.rb +9 -0
- data/lib/pbcore/instantiation/essence_track/frame_rate.rb +11 -0
- data/lib/pbcore/instantiation/essence_track/frame_size.rb +11 -0
- data/lib/pbcore/instantiation/essence_track/identifier.rb +9 -0
- data/lib/pbcore/instantiation/essence_track/language.rb +9 -0
- data/lib/pbcore/instantiation/essence_track/playback_speed.rb +11 -0
- data/lib/pbcore/instantiation/essence_track/sampling_rate.rb +11 -0
- data/lib/pbcore/instantiation/essence_track/standard.rb +9 -0
- data/lib/pbcore/instantiation/essence_track/time_start.rb +9 -0
- data/lib/pbcore/instantiation/essence_track/type.rb +9 -0
- data/lib/pbcore/instantiation/extension.rb +22 -0
- data/lib/pbcore/instantiation/file_size.rb +13 -0
- data/lib/pbcore/instantiation/generations.rb +11 -0
- data/lib/pbcore/instantiation/identifier.rb +11 -0
- data/lib/pbcore/instantiation/language.rb +11 -0
- data/lib/pbcore/instantiation/location.rb +11 -0
- data/lib/pbcore/instantiation/media_type.rb +11 -0
- data/lib/pbcore/instantiation/physical.rb +11 -0
- data/lib/pbcore/instantiation/relation.rb +19 -0
- data/lib/pbcore/instantiation/relation/identifier.rb +9 -0
- data/lib/pbcore/instantiation/relation/type.rb +9 -0
- data/lib/pbcore/instantiation/rights.rb +22 -0
- data/lib/pbcore/instantiation/rights/link.rb +11 -0
- data/lib/pbcore/instantiation/rights/summary.rb +11 -0
- data/lib/pbcore/instantiation/standard.rb +13 -0
- data/lib/pbcore/instantiation/time_start.rb +11 -0
- data/lib/pbcore/instantiation/tracks.rb +11 -0
- data/lib/pbcore/instantiation_document.rb +97 -0
- data/lib/pbcore/publisher.rb +19 -0
- data/lib/pbcore/publisher/publisher.rb +17 -0
- data/lib/pbcore/publisher/role.rb +11 -0
- data/lib/pbcore/relation.rb +19 -0
- data/lib/pbcore/relation/identifier.rb +11 -0
- data/lib/pbcore/relation/type.rb +11 -0
- data/lib/pbcore/rights_summary.rb +22 -0
- data/lib/pbcore/rights_summary/link.rb +11 -0
- data/lib/pbcore/rights_summary/summary.rb +11 -0
- data/lib/pbcore/subject.rb +15 -0
- data/lib/pbcore/title.rb +15 -0
- data/lib/pbcore/version.rb +3 -0
- data/lib/pbcore/vocab.rb +15 -0
- data/pbcore.gemspec +40 -0
- metadata +297 -0
data/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# PBCore
|
|
2
|
+
|
|
3
|
+
PBCore model for Ruby applications.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'pbcore'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
And then execute:
|
|
14
|
+
|
|
15
|
+
$ bundle
|
|
16
|
+
|
|
17
|
+
Or install it yourself as:
|
|
18
|
+
|
|
19
|
+
$ gem install pbcore
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
TODO: Write usage instructions here
|
|
24
|
+
|
|
25
|
+
## Development
|
|
26
|
+
|
|
27
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
28
|
+
|
|
29
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
30
|
+
|
|
31
|
+
## Contributing
|
|
32
|
+
|
|
33
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/pbcore.
|
|
34
|
+
|
|
35
|
+
## License
|
|
36
|
+
|
|
37
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require "pbcore"
|
|
5
|
+
|
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
+
|
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
+
require "pry"
|
|
11
|
+
Pry.start
|
data/bin/setup
ADDED
data/lib/pbcore.rb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require "pbcore/version"
|
|
2
|
+
require "pbcore/errors"
|
|
3
|
+
|
|
4
|
+
module PBCore
|
|
5
|
+
autoload :Element, 'pbcore/element'
|
|
6
|
+
autoload :Attributes, 'pbcore/attributes'
|
|
7
|
+
autoload :DescriptionDocument, 'pbcore/description_document'
|
|
8
|
+
autoload :AssetType, 'pbcore/asset_type'
|
|
9
|
+
autoload :AssetDate, 'pbcore/asset_date'
|
|
10
|
+
autoload :Identifier, 'pbcore/identifier'
|
|
11
|
+
autoload :Title, 'pbcore/title'
|
|
12
|
+
autoload :Subject, 'pbcore/subject'
|
|
13
|
+
autoload :Description, 'pbcore/description'
|
|
14
|
+
autoload :Genre, 'pbcore/genre'
|
|
15
|
+
autoload :Creator, 'pbcore/creator'
|
|
16
|
+
autoload :Coverage, 'pbcore/coverage'
|
|
17
|
+
autoload :Relation, 'pbcore/relation'
|
|
18
|
+
autoload :AudienceLevel, 'pbcore/audience_level'
|
|
19
|
+
autoload :AudienceRating, 'pbcore/audience_rating'
|
|
20
|
+
autoload :Contributor, 'pbcore/contributor'
|
|
21
|
+
autoload :Publisher, 'pbcore/publisher'
|
|
22
|
+
autoload :RightsSummary, 'pbcore/rights_summary'
|
|
23
|
+
autoload :Annotation, 'pbcore/annotation'
|
|
24
|
+
autoload :Extension, 'pbcore/extension'
|
|
25
|
+
autoload :Instantiation, 'pbcore/instantiation'
|
|
26
|
+
autoload :InstantiationDocument, 'pbcore/instantiation_document'
|
|
27
|
+
autoload :Vocab, 'pbcore/vocab'
|
|
28
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module PBCore
|
|
2
|
+
module Attributes
|
|
3
|
+
module Common
|
|
4
|
+
def self.included(base)
|
|
5
|
+
PBCore.fail_if_base_is_not_pbcore_element(included_module: self, base: base)
|
|
6
|
+
base.attribute :source
|
|
7
|
+
base.attribute :ref
|
|
8
|
+
base.attribute :annotation
|
|
9
|
+
base.attribute :version
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module PBCore
|
|
2
|
+
module Attributes
|
|
3
|
+
module TimeInterval
|
|
4
|
+
def self.included(base)
|
|
5
|
+
PBCore.fail_if_base_is_not_pbcore_element(included_module: self, base: base)
|
|
6
|
+
base.attribute :startTime, as: :start_time
|
|
7
|
+
base.attribute :endTime, as: :end_time
|
|
8
|
+
base.attribute :timeAnnotation, as: :time_annotation
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'pbcore/element'
|
|
2
|
+
|
|
3
|
+
module PBCore
|
|
4
|
+
class Contributor < Element
|
|
5
|
+
autoload :Contributor, 'pbcore/contributor/contributor'
|
|
6
|
+
autoload :Role, 'pbcore/contributor/role'
|
|
7
|
+
|
|
8
|
+
element :pbcoreContributor, as: :value
|
|
9
|
+
element :contributor, as: :contributor, class: PBCore::Contributor::Contributor
|
|
10
|
+
element :contributorRole, as: :role, class: PBCore::Contributor::Role
|
|
11
|
+
|
|
12
|
+
build_xml do |xml|
|
|
13
|
+
xml.pbcoreContributor(xml_attributes.compact) do |xml|
|
|
14
|
+
contributor.build(xml) if contributor
|
|
15
|
+
role.build(xml) if role
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'pbcore/element'
|
|
2
|
+
|
|
3
|
+
module PBCore
|
|
4
|
+
class Coverage < Element
|
|
5
|
+
|
|
6
|
+
autoload :Coverage, 'pbcore/coverage/coverage'
|
|
7
|
+
autoload :Type, 'pbcore/coverage/type'
|
|
8
|
+
|
|
9
|
+
element :pbcoreCoverage, as: :value
|
|
10
|
+
element :coverage, as: :coverage, class: PBCore::Coverage::Coverage
|
|
11
|
+
element :coverageType, as: :type, class: PBCore::Coverage::Type
|
|
12
|
+
|
|
13
|
+
build_xml do |xml|
|
|
14
|
+
xml.pbcoreCoverage(xml_attributes.compact) do |xml|
|
|
15
|
+
coverage.build(xml) if coverage
|
|
16
|
+
type.build(xml) if type
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'pbcore/element'
|
|
2
|
+
|
|
3
|
+
module PBCore
|
|
4
|
+
class Creator < Element
|
|
5
|
+
autoload :Creator, 'pbcore/creator/creator'
|
|
6
|
+
autoload :Role, 'pbcore/creator/role'
|
|
7
|
+
|
|
8
|
+
element :pbcoreCreator, as: :value
|
|
9
|
+
element :creator, as: :creator, class: PBCore::Creator::Creator
|
|
10
|
+
element :creatorRole, as: :role, class: PBCore::Creator::Role
|
|
11
|
+
|
|
12
|
+
build_xml do |xml|
|
|
13
|
+
xml.pbcoreCreator(xml_attributes.compact) do |xml|
|
|
14
|
+
creator.build(xml) if creator
|
|
15
|
+
role.build(xml) if role
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'pbcore/element'
|
|
2
|
+
|
|
3
|
+
module PBCore
|
|
4
|
+
class Creator::Creator < Element
|
|
5
|
+
element :creator, as: :value
|
|
6
|
+
attribute :affiliation, as: :affiliation
|
|
7
|
+
attribute :affiliationSource, as: :affiliation_source
|
|
8
|
+
attribute :affiliationRef, as: :affiliation_ref
|
|
9
|
+
attribute :affiliationVersion, as: :affiliation_version
|
|
10
|
+
attribute :affiliationAnnotation, as: :affiliation_annotation
|
|
11
|
+
|
|
12
|
+
build_xml do |xml|
|
|
13
|
+
xml.creator(value, xml_attributes.compact)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'pbcore/element'
|
|
2
|
+
|
|
3
|
+
module PBCore
|
|
4
|
+
class Description < Element
|
|
5
|
+
element :pbcoreDescription, as: :value
|
|
6
|
+
attribute :descriptionType, as: :type
|
|
7
|
+
attribute :descriptionTypeRef, as: :type_ref
|
|
8
|
+
|
|
9
|
+
build_xml do |xml|
|
|
10
|
+
xml.pbcoreDescription(value, xml_attributes.compact)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
require 'pbcore/element'
|
|
2
|
+
|
|
3
|
+
module PBCore
|
|
4
|
+
class DescriptionDocument < Element
|
|
5
|
+
elements :pbcoreIdentifier, as: :identifiers, class: PBCore::Identifier
|
|
6
|
+
elements :pbcoreTitle, as: :titles, class: PBCore::Title
|
|
7
|
+
elements :pbcoreDescription, as: :descriptions, class: PBCore::Description
|
|
8
|
+
elements :pbcoreAssetDate, as: :asset_dates, class: PBCore::AssetDate
|
|
9
|
+
elements :pbcoreAssetType, as: :asset_types, class: PBCore::AssetType
|
|
10
|
+
elements :pbcoreSubject, as: :subjects, class: PBCore::Subject
|
|
11
|
+
elements :pbcoreGenre, as: :genres, class: PBCore::Genre
|
|
12
|
+
elements :pbcoreRelation, as: :relations, class: PBCore::Relation
|
|
13
|
+
elements :pbcoreCoverage, as: :coverages, class: PBCore::Coverage
|
|
14
|
+
elements :pbcoreAudienceLevel, as: :audience_levels, class: PBCore::AudienceLevel
|
|
15
|
+
elements :pbcoreAudienceRating, as: :audience_ratings, class: PBCore::AudienceRating
|
|
16
|
+
elements :pbcoreCreator, as: :creators, class: PBCore::Creator
|
|
17
|
+
elements :pbcoreContributor, as: :contributors, class: PBCore::Contributor
|
|
18
|
+
elements :pbcorePublisher, as: :publishers, class: PBCore::Publisher
|
|
19
|
+
elements :pbcoreRightsSummary, as: :rights_summaries, class: PBCore::RightsSummary
|
|
20
|
+
elements :pbcoreAnnotation, as: :annotations, class: PBCore::Annotation
|
|
21
|
+
elements :pbcoreExtension, as: :extensions, class: PBCore::Extension
|
|
22
|
+
elements :pbcoreInstantiation, as: :instantiations, class: PBCore::Instantiation
|
|
23
|
+
|
|
24
|
+
build_xml do |xml|
|
|
25
|
+
xml.pbcoreDescriptionDocument(namespace_attributes) do |xml|
|
|
26
|
+
asset_types.each { |asset_type| asset_type.build(xml) }
|
|
27
|
+
asset_dates.each { |asset_date| asset_date.build(xml) }
|
|
28
|
+
identifiers.each { |identifier| identifier.build(xml) }
|
|
29
|
+
titles.each { |title| title.build(xml) }
|
|
30
|
+
subjects.each { |subject| subject.build(xml) }
|
|
31
|
+
descriptions.each { |description| description.build(xml) }
|
|
32
|
+
genres.each { |genre| genre.build(xml) }
|
|
33
|
+
relations.each { |relation| relation.build(xml) }
|
|
34
|
+
coverages.each { |coverage| coverage.build(xml) }
|
|
35
|
+
audience_levels.each { |audience_level| audience_level.build(xml) }
|
|
36
|
+
audience_ratings.each { |audience_rating| audience_rating.build(xml) }
|
|
37
|
+
creators.each { |creator| creator.build(xml) }
|
|
38
|
+
contributors.each { |contributor| contributor.build(xml) }
|
|
39
|
+
publishers.each { |publisher| publisher.build(xml) }
|
|
40
|
+
rights_summaries.each { |rights_summary| rights_summary.build(xml) }
|
|
41
|
+
instantiations.each { |instantiation| instantiation.build(xml) }
|
|
42
|
+
annotations.each { |annotation| annotation.build(xml) }
|
|
43
|
+
# TODO: no pbcore part?!
|
|
44
|
+
extensions.each { |extension| extension.build(xml) }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# NOTE: For some reason, these attributes will not parse with SAXMachine
|
|
49
|
+
# attributes.
|
|
50
|
+
# TODO: Is there a better way to set namespace attributes?
|
|
51
|
+
def namespace_attributes
|
|
52
|
+
{
|
|
53
|
+
# changed to www.pbcore because aapb doesnt like it without
|
|
54
|
+
'xmlns' => "http://www.pbcore.org/PBCore/PBCoreNamespace.html",
|
|
55
|
+
'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
|
|
56
|
+
'xsi:schemaLocation' => "http://www.pbcore.org/PBCore/PBCoreNamespace.html http://www.pbcore.org/xsd/pbcore-2.1.xsd"
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
require 'sax-machine'
|
|
2
|
+
|
|
3
|
+
module SAXMachine::SAXAbstractHandler
|
|
4
|
+
NO_BUFFER = ''
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
module PBCore
|
|
8
|
+
# TODO: decouple XML building behavior from schema-related declarations.
|
|
9
|
+
class Element
|
|
10
|
+
include SAXMachine
|
|
11
|
+
include PBCore::Attributes::Common
|
|
12
|
+
|
|
13
|
+
# Defines which accessor is used to get the value within an element.
|
|
14
|
+
# Here we defined it be simply :value.
|
|
15
|
+
value(:value, {}) do |val|
|
|
16
|
+
val == :no_buffer ? nil : val
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Defind attributes common to all PBCore elements.
|
|
20
|
+
# attribute :source
|
|
21
|
+
# attribute :ref
|
|
22
|
+
# attribute :annotation
|
|
23
|
+
# attribute :version
|
|
24
|
+
|
|
25
|
+
# Returns a hash of child element instances.
|
|
26
|
+
def elements(key_by_xml_name: false)
|
|
27
|
+
key_value_pairs_array = self.class.element_config_all.map do |name, element_configs|
|
|
28
|
+
# SAXMachine allows you to declare multiple elements with the same name
|
|
29
|
+
# but we don't do tha with PBCore, so just grab the first and only one.
|
|
30
|
+
element_config = element_configs.first
|
|
31
|
+
# get the accessor name by which to get the value
|
|
32
|
+
accessor = element_config.instance_variable_get(:@as)
|
|
33
|
+
|
|
34
|
+
# fetch the value by calling the accessor
|
|
35
|
+
value = send(accessor)
|
|
36
|
+
# create the key, value pair that will go into the Hash[] construct.
|
|
37
|
+
key = key_by_xml_name ? name : accessor
|
|
38
|
+
[ key, value ]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
Hash[ key_value_pairs_array ]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Shortcut for getting xml attributes.
|
|
45
|
+
def xml_attributes; attributes(key_by_xml_name: true); end
|
|
46
|
+
|
|
47
|
+
# Returns a hash of attrubutes as the should appear in the XML.
|
|
48
|
+
def attributes(key_by_xml_name: false)
|
|
49
|
+
xml_attrs = Hash[
|
|
50
|
+
self.class.sax_config.top_level_attributes.map do |attr|
|
|
51
|
+
accessor = attr.instance_variable_get(:@as)
|
|
52
|
+
key = key_by_xml_name ? attr.name : accessor
|
|
53
|
+
[ key, send(accessor) ]
|
|
54
|
+
end
|
|
55
|
+
]
|
|
56
|
+
xml_attrs
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Executes the block defined with the class method `build_xml`. Uses a
|
|
60
|
+
# Nokogiri::XML::Builder instance (either passed in or instantiated) to
|
|
61
|
+
# build the XML, and then returns the builder instance.
|
|
62
|
+
def build(builder=nil)
|
|
63
|
+
raise ArgumentError, "#{self.class}#build expects a Nokogiri::XML::Builder class, but #{builder.class} was given" unless builder.nil? || builder.is_a?(Nokogiri::XML::Builder)
|
|
64
|
+
PBCore.fail_if_missing_build_xml_block(element_class: self.class)
|
|
65
|
+
builder ||= Nokogiri::XML::Builder.new
|
|
66
|
+
instance_exec builder, &self.class.build_block
|
|
67
|
+
builder
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Builds the xml using #build with a new instance of Nokogiri::XML::Builder
|
|
71
|
+
# and immediately calls to_xml on it.
|
|
72
|
+
def to_xml
|
|
73
|
+
build.to_xml
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Define the class interfaces for all PBCore elements.
|
|
77
|
+
class << self
|
|
78
|
+
attr_reader :build_block
|
|
79
|
+
|
|
80
|
+
# Class method to allow extended classes to declaratively the logic used
|
|
81
|
+
# to build XML using Nokogiri::XML::Builder.
|
|
82
|
+
def build_xml(&block)
|
|
83
|
+
raise ArgumentError, "#{self.class}.build_xml requires a block with one parameter" unless block_given? && block.arity == 1
|
|
84
|
+
@build_block = block
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Returns true if the element is configured to contain a single instance
|
|
88
|
+
# of a child element that matches the name and opts parameters.
|
|
89
|
+
def has_one?(name, opts={})
|
|
90
|
+
element_config_has_one.any? do |element_config|
|
|
91
|
+
opts.all? do |key, val|
|
|
92
|
+
# In SAXMachine::SaxConfig::ElementConfig, the :class config option
|
|
93
|
+
# maps to instance variable @data_class.
|
|
94
|
+
key = :data_class if key == :class
|
|
95
|
+
val == element_config.instance_variable_get(:"@#{key}")
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Returns true if the element is configured to contain many instances of
|
|
101
|
+
# a child element that matches the name and opts parameters.
|
|
102
|
+
def has_many?(name, opts={})
|
|
103
|
+
element_config_has_many.any? do |element_config|
|
|
104
|
+
opts.all? do |key, val|
|
|
105
|
+
val == element_config.instance_variable_get(:"@#{key}")
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Returns true if the element is configured to contain a value.
|
|
111
|
+
def has_a_value?
|
|
112
|
+
!element_config_for_value.nil?
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def attribute_config
|
|
116
|
+
sax_config.top_level_attributes
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Returns the SAXMachine::SaxConfig::ElementConfig instances that allow
|
|
120
|
+
# for a single instance of another element.
|
|
121
|
+
# NOTE: We use the "has_one" and "has_many" terminoolgy for child elements
|
|
122
|
+
# because it seems to be the most readable option.
|
|
123
|
+
def element_config_has_one
|
|
124
|
+
sax_config.top_level_elements.reject do |_name, element_configs|
|
|
125
|
+
element_configs.detect do |element_config|
|
|
126
|
+
element_config.instance_variable_get(:@as) == :value
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Returns the SAXMachine::SaxConfig::ElementConfig instance for the
|
|
132
|
+
# element that represents the value (i.e. text that is one or more
|
|
133
|
+
# child elements). This is essentially the inverse of
|
|
134
|
+
# element_config_has_one.
|
|
135
|
+
def element_config_for_value
|
|
136
|
+
sax_config.top_level_elements.detect do |_name, element_configs|
|
|
137
|
+
element_configs.detect do |element_config|
|
|
138
|
+
element_config.instance_variable_get(:@as) == :value
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Returns the SAXMachine::SaxConfig::ElementConfig that allow for
|
|
144
|
+
# multiple instances of other elements.
|
|
145
|
+
# NOTE: SAXMachine uses the term "collection" elements, but that's very
|
|
146
|
+
# confusing since PBCoreCollection is a thing, so we change it to the
|
|
147
|
+
# has_many terminology (and has_one for the singular element config for
|
|
148
|
+
# consistency).
|
|
149
|
+
def element_config_has_many
|
|
150
|
+
sax_config.collection_elements.reject do |element_config|
|
|
151
|
+
element_config.instance_variable_get(:@as) == :value
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def element_config_all
|
|
156
|
+
element_config_has_one.merge(element_config_has_many) do |name, config_has_one, config_has_many|
|
|
157
|
+
config_has_many.present? ? config_has_many : config_has_one
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def has_sax_machine_attribute?(name, opts={})
|
|
162
|
+
sax_config.top_level_attributes.any? do |attr_config|
|
|
163
|
+
opts.all? do |key, val|
|
|
164
|
+
val == attr_config.instance_variable_get("@#{key}".to_sym)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def has_sax_machine_value_element?
|
|
170
|
+
!sax_config.top_level_element_value.empty?
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def has_sax_machine_top_level_element?(name, opts={})
|
|
174
|
+
Array(sax_config.top_level_elements.fetch(name.to_s, nil)).any? do |element_config|
|
|
175
|
+
opts.all? do |key, val|
|
|
176
|
+
key = :data_class if key == :class
|
|
177
|
+
val == element_config.instance_variable_get("@#{key}".to_sym)
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def has_sax_machine_collection_element?(name, opts={})
|
|
183
|
+
# NOTE: Accessing collection_element configs with squarey brackets has
|
|
184
|
+
# the unwanted side affect of creating an entry in the
|
|
185
|
+
# collection_elements, which we don't want. So we use #fetch here
|
|
186
|
+
Array(sax_config.collection_elements.fetch(name.to_s, nil)).any? do |element_config|
|
|
187
|
+
opts.all? do |key, val|
|
|
188
|
+
# This is a quirk of SAXMachine; for some reason it converts the
|
|
189
|
+
# config option :as to a string when assigning it to the
|
|
190
|
+
# ConfigElement instance, so we need to convert opts[:as] param to
|
|
191
|
+
# string in order to compare them accurately.
|
|
192
|
+
val = val.to_s if key == :as
|
|
193
|
+
val == element_config.instance_variable_get(:"@#{key}")
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|