ddr-core 0.3.0 → 1.2.0.rc1
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 +4 -4
- data/README.md +1 -1
- data/app/models/concerns/ddr/#search_builder_behavior.rb# +10 -0
- data/app/models/concerns/ddr/describable.rb +8 -12
- data/app/models/concerns/ddr/has_admin_metadata.rb +13 -65
- data/app/models/concerns/ddr/has_children.rb +8 -0
- data/app/models/concerns/ddr/has_content.rb +1 -0
- data/app/models/concerns/ddr/has_parent.rb +14 -2
- data/app/models/concerns/ddr/search_builder_behavior.rb~ +9 -0
- data/app/models/concerns/ddr/solr_document_behavior.rb +11 -90
- data/app/models/ddr/#admin_set.rb# +26 -0
- data/app/models/ddr/#auxiliary_resource_cache.rb# +34 -0
- data/app/models/ddr/admin_set.rb +3 -7
- data/app/models/ddr/alert.rb +16 -0
- data/app/models/ddr/auxiliary_resource.rb +24 -0
- data/app/models/ddr/auxiliary_resource.rb~ +13 -0
- data/app/models/ddr/cacheable_auxiliary_resource.rb~ +20 -0
- data/app/models/ddr/collection.rb +5 -4
- data/app/models/ddr/component.rb +8 -0
- data/app/models/ddr/contact.rb +1 -5
- data/app/models/ddr/finding_aid.rb +61 -0
- data/app/models/ddr/item.rb +0 -14
- data/app/models/ddr/language.rb +1 -6
- data/app/models/ddr/resource.rb +14 -0
- data/app/models/ddr/rights_statement.rb +2 -6
- data/config/locales/ddr-core.en.yml +4 -1
- data/db/migrate/20200207194453_add_default_to_lock_version.rb +6 -0
- data/lib/ddr/auth/#duke_person.rb# +9 -0
- data/lib/ddr/auth/ability_definitions/publication_ability_definitions.rb +7 -0
- data/lib/ddr/auth/ability_definitions/role_based_ability_definitions.rb +2 -2
- data/lib/ddr/auth/ability_definitions/superuser_ability_definitions.rb +3 -0
- data/lib/ddr/auth/duke_directory.rb~ +7 -0
- data/lib/ddr/auth/effective_permissions.rb +2 -1
- data/lib/ddr/auth/effective_roles.rb +6 -2
- data/lib/ddr/auth/failure_app.rb +1 -1
- data/lib/ddr/auth/grouper_gateway.rb +2 -2
- data/lib/ddr/auth/permissions.rb +14 -11
- data/lib/ddr/auth/role_based_access_controls_enforcement.rb +1 -37
- data/lib/ddr/auth/roles.rb +15 -3
- data/lib/ddr/auth/roles/role.rb +27 -69
- data/lib/ddr/auth/roles/role_types.rb +13 -6
- data/lib/ddr/core.rb +9 -0
- data/lib/ddr/core/version.rb +1 -1
- data/lib/ddr/fits.rb +0 -91
- data/lib/ddr/index.rb +2 -2
- data/lib/ddr/index/csv_query_result.rb +27 -20
- data/lib/ddr/index/fields.rb +5 -0
- data/lib/ddr/managers/technical_metadata_manager.rb +9 -4
- data/lib/ddr/structure.rb +2 -1
- data/lib/ddr/vocab/asset.rb +4 -0
- data/lib/ddr/workflow.rb +1 -0
- metadata +35 -9
@@ -1,7 +1,8 @@
|
|
1
1
|
module Ddr::Auth
|
2
2
|
class EffectivePermissions
|
3
3
|
|
4
|
-
# @param obj [Object] an object that receives :roles and returns
|
4
|
+
# @param obj [Object] an object that receives :roles and returns an Array
|
5
|
+
# of Ddr::Auth::Roles::Role.
|
5
6
|
# @param agents [String, Array<String>] agent(s) to match roles
|
6
7
|
# @return [Array<Symbol>]
|
7
8
|
def self.call(obj, agents)
|
@@ -1,8 +1,12 @@
|
|
1
1
|
module Ddr::Auth
|
2
2
|
class EffectiveRoles
|
3
3
|
|
4
|
-
def self.call(obj, agents)
|
5
|
-
( obj.
|
4
|
+
def self.call(obj, agents = nil)
|
5
|
+
( obj.roles | obj.inherited_roles ).tap do |roles|
|
6
|
+
if agents
|
7
|
+
roles.select! { |r| agents.include?(r.agent) }
|
8
|
+
end
|
9
|
+
end
|
6
10
|
end
|
7
11
|
|
8
12
|
end
|
data/lib/ddr/auth/failure_app.rb
CHANGED
@@ -25,7 +25,7 @@ module Ddr
|
|
25
25
|
|
26
26
|
# List of all grouper groups for the repository
|
27
27
|
def repository_groups(raw = false)
|
28
|
-
repo_groups = groups(
|
28
|
+
repo_groups = groups(Ddr::Auth.repository_group_filter)
|
29
29
|
if ok?
|
30
30
|
return repo_groups if raw
|
31
31
|
repo_groups.map do |g|
|
@@ -52,7 +52,7 @@ module Ddr
|
|
52
52
|
result = response["WsGetGroupsResults"]["results"].first
|
53
53
|
# Have to manually filter results b/c Grouper WS version 1.5 does not support filter parameter
|
54
54
|
if result && result["wsGroups"]
|
55
|
-
groups = result["wsGroups"].select { |g| g["name"] =~ /^#{
|
55
|
+
groups = result["wsGroups"].select { |g| g["name"] =~ /^#{Ddr::Auth.repository_group_filter}/ }
|
56
56
|
end
|
57
57
|
end
|
58
58
|
rescue StandardError => e
|
data/lib/ddr/auth/permissions.rb
CHANGED
@@ -1,18 +1,21 @@
|
|
1
1
|
module Ddr::Auth
|
2
2
|
class Permissions
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
4
|
+
DISCOVER = :discover
|
5
|
+
READ = :read
|
6
|
+
DOWNLOAD = :download
|
7
|
+
ADD_CHILDREN = :add_children
|
8
|
+
UPDATE = :update
|
9
|
+
REPLACE = :replace
|
10
|
+
ARRANGE = :arrange
|
11
|
+
PUBLISH = :publish
|
12
|
+
UNPUBLISH = :unpublish
|
13
|
+
MAKE_NONPUBLISHABLE = :make_nonpublishable
|
14
|
+
AUDIT = :audit
|
15
|
+
GRANT = :grant
|
14
16
|
|
15
|
-
ALL = [ READ, DOWNLOAD, ADD_CHILDREN, UPDATE,
|
17
|
+
ALL = [ DISCOVER, READ, DOWNLOAD, ADD_CHILDREN, UPDATE,
|
18
|
+
REPLACE, ARRANGE, PUBLISH, UNPUBLISH, MAKE_NONPUBLISHABLE, AUDIT, GRANT ]
|
16
19
|
|
17
20
|
end
|
18
21
|
end
|
@@ -1,11 +1,5 @@
|
|
1
1
|
module Ddr
|
2
2
|
module Auth
|
3
|
-
#
|
4
|
-
# Hydra controller mixin for role-based access control
|
5
|
-
#
|
6
|
-
# Overrides Hydra::AccessControlsEnforcement#gated_discovery_filters
|
7
|
-
# to apply role filters instead of permissions filters.
|
8
|
-
#
|
9
3
|
module RoleBasedAccessControlsEnforcement
|
10
4
|
|
11
5
|
def self.included(controller)
|
@@ -17,38 +11,8 @@ module Ddr
|
|
17
11
|
@current_ability ||= AbilityFactory.call(current_user, request.env)
|
18
12
|
end
|
19
13
|
|
20
|
-
# List of URIs for policies on which any of the current user's agent has a role in policy scope
|
21
|
-
def policy_role_policies
|
22
|
-
@policy_role_policies ||= Array.new.tap do |uris|
|
23
|
-
filters = current_ability.agents.map do |agent|
|
24
|
-
"#{Ddr::Index::Fields::POLICY_ROLE}:\"#{agent}\""
|
25
|
-
end.join(" OR ")
|
26
|
-
query = "#{Ddr::Index::Fields::ACTIVE_FEDORA_MODEL}:Collection AND (#{filters})"
|
27
|
-
results = ActiveFedora::SolrService.query(query, rows: Collection.count, fl: Ddr::Index::Fields::INTERNAL_URI)
|
28
|
-
results.each_with_object(uris) { |r, memo| memo << r[Ddr::Index::Fields::INTERNAL_URI] }
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def policy_role_filters
|
33
|
-
if policy_role_policies.present?
|
34
|
-
rels = policy_role_policies.map { |pid| [:is_governed_by, pid] }
|
35
|
-
ActiveFedora::SolrService.construct_query_for_rel(rels, "OR")
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def resource_role_filters
|
40
|
-
current_ability.agents.map do |agent|
|
41
|
-
ActiveFedora::SolrService.raw_query(Ddr::Index::Fields::RESOURCE_ROLE, agent)
|
42
|
-
end.join(" OR ")
|
43
|
-
end
|
44
|
-
|
45
|
-
def gated_discovery_filters
|
46
|
-
[resource_role_filters, policy_role_filters].compact
|
47
|
-
end
|
48
|
-
|
49
|
-
# Overrides Hydra::AccessControlsEnforcement
|
50
14
|
def enforce_show_permissions
|
51
|
-
authorize!
|
15
|
+
authorize! Permissions::DISCOVER, params[:id]
|
52
16
|
end
|
53
17
|
|
54
18
|
end
|
data/lib/ddr/auth/roles.rb
CHANGED
@@ -10,18 +10,30 @@ module Ddr::Auth
|
|
10
10
|
|
11
11
|
RESOURCE_SCOPE = "resource".freeze
|
12
12
|
POLICY_SCOPE = "policy".freeze
|
13
|
-
SCOPES = [RESOURCE_SCOPE, POLICY_SCOPE].freeze
|
13
|
+
SCOPES = [ RESOURCE_SCOPE, POLICY_SCOPE ].freeze
|
14
|
+
|
15
|
+
ORDERED_ROLE_TYPES = [
|
16
|
+
CURATOR,
|
17
|
+
EDITOR,
|
18
|
+
METADATA_EDITOR,
|
19
|
+
CONTRIBUTOR,
|
20
|
+
DOWNLOADER,
|
21
|
+
VIEWER,
|
22
|
+
METADATA_VIEWER
|
23
|
+
]
|
14
24
|
|
15
25
|
class << self
|
16
|
-
|
17
26
|
def type_map
|
18
27
|
@type_map ||= role_types.map { |role_type| [role_type.to_s, role_type] }.to_h
|
19
28
|
end
|
20
29
|
|
21
30
|
def role_types
|
22
|
-
|
31
|
+
ORDERED_ROLE_TYPES
|
23
32
|
end
|
24
33
|
|
34
|
+
def titles
|
35
|
+
@titles ||= role_types.map(&:title)
|
36
|
+
end
|
25
37
|
end
|
26
38
|
|
27
39
|
end
|
data/lib/ddr/auth/roles/role.rb
CHANGED
@@ -8,67 +8,38 @@ module Ddr
|
|
8
8
|
|
9
9
|
DEFAULT_SCOPE = Roles::RESOURCE_SCOPE
|
10
10
|
|
11
|
-
ValidScope = Valkyrie::Types::
|
12
|
-
ValidRoleType = Valkyrie::Types::Strict::String.enum(*(Roles
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
# @return [Role] the role
|
23
|
-
# @example
|
24
|
-
# Role.build type: "Curator", agent: "bob", scope: "resource"
|
25
|
-
def build(args={})
|
26
|
-
new.tap do |role|
|
27
|
-
args[:role_type] ||= args.delete(:type)
|
28
|
-
args[:agent] ||= nil # Triggers a constraint error
|
29
|
-
args[:agent] = args[:agent].to_s # Coerce Ddr::Auth:Group to string
|
30
|
-
|
31
|
-
args.each do |attr, val|
|
32
|
-
role.set_value(attr, val)
|
33
|
-
end
|
11
|
+
ValidScope = Valkyrie::Types::Coercible::String.default(DEFAULT_SCOPE).enum(*(Roles::SCOPES))
|
12
|
+
ValidRoleType = Valkyrie::Types::Strict::String.enum(*(Roles.titles))
|
13
|
+
ValidAgent = Valkyrie::Types::Coercible::String.constrained(min_size: 1)
|
14
|
+
|
15
|
+
# Symbolize input keys
|
16
|
+
# https://dry-rb.org/gems/dry-struct/1.0/recipes/#symbolize-input-keys
|
17
|
+
transform_keys do |key|
|
18
|
+
_k = key.to_sym
|
19
|
+
# For backwards compat allow :type as an alias for :role_type
|
20
|
+
_k == :type ? :role_type : _k
|
21
|
+
end
|
34
22
|
|
35
|
-
|
23
|
+
# Make nils use default values
|
24
|
+
# https://dry-rb.org/gems/dry-struct/1.0/recipes/#resolving-default-values-on-code-nil-code
|
25
|
+
transform_types do |type|
|
26
|
+
if type.default?
|
27
|
+
type.constructor do |value|
|
28
|
+
value.nil? ? Dry::Types::Undefined : value
|
36
29
|
end
|
30
|
+
else
|
31
|
+
type
|
37
32
|
end
|
33
|
+
end
|
38
34
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
#
|
43
|
-
# # Deserialize a Role from JSON
|
44
|
-
# # @param json [String] the JSON string
|
45
|
-
# # @return [Role] the role
|
46
|
-
# def from_json(json)
|
47
|
-
# build JSON.parse(json)
|
48
|
-
# end
|
49
|
-
|
50
|
-
# alias_method :deserialize, :from_json
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
#
|
55
|
-
# DELETEME
|
56
|
-
#
|
57
|
-
# def build_attributes(args={})
|
58
|
-
# # symbolize keys and stringify values
|
59
|
-
# attrs = args.each_with_object({}) do |(k, v), memo|
|
60
|
-
# memo[k.to_sym] = Array(v).first.to_s
|
61
|
-
# end
|
62
|
-
# # set default scope if necessary
|
63
|
-
# attrs[:scope] ||= DEFAULT_SCOPE
|
64
|
-
# # accept :type key for role_type attribute
|
65
|
-
# if attrs.key?(:type)
|
66
|
-
# attrs[:role_type] = attrs.delete(:type)
|
67
|
-
# end
|
68
|
-
# attrs
|
69
|
-
# end
|
35
|
+
attribute :agent, ValidAgent
|
36
|
+
attribute :role_type, ValidRoleType
|
37
|
+
attribute :scope, ValidScope
|
70
38
|
|
71
|
-
|
39
|
+
# DEPRECATED: Use constructor
|
40
|
+
def self.build(args={})
|
41
|
+
new(args)
|
42
|
+
end
|
72
43
|
|
73
44
|
# Roles are considered equal (==) if they
|
74
45
|
# are of the same type and have the same agent and scope.
|
@@ -96,19 +67,6 @@ module Ddr
|
|
96
67
|
"agent=#{agent.inspect}, scope=#{scope.inspect}>"
|
97
68
|
end
|
98
69
|
|
99
|
-
# TODO refactor up?
|
100
|
-
def proper_attributes
|
101
|
-
attributes.slice(self.class.fields - self.class.reserved_attributes)
|
102
|
-
end
|
103
|
-
|
104
|
-
###############
|
105
|
-
# FIXME or remove serialization/deserialization
|
106
|
-
###############
|
107
|
-
#
|
108
|
-
# delegate :to_json, to: :proper_attributes
|
109
|
-
#
|
110
|
-
# alias_method :serialize, :to_json
|
111
|
-
|
112
70
|
# Returns the permissions associated with the role
|
113
71
|
# @return [Array<Symbol>] the permissions
|
114
72
|
def permissions
|
@@ -14,36 +14,43 @@ module Ddr
|
|
14
14
|
"Editor",
|
15
15
|
"The Editor role conveys reponsibility for managing the content, " \
|
16
16
|
"description and structural arrangement of a resource.",
|
17
|
-
[ Permissions::
|
18
|
-
Permissions::
|
17
|
+
[ Permissions::DISCOVER, Permissions::READ, Permissions::DOWNLOAD,
|
18
|
+
Permissions::ADD_CHILDREN, Permissions::UPDATE,
|
19
|
+
Permissions::REPLACE, Permissions::ARRANGE ]
|
19
20
|
)
|
20
21
|
|
21
22
|
METADATA_EDITOR = RoleType.new(
|
22
23
|
"MetadataEditor",
|
23
24
|
"The Metadata Editor role conveys responsibility for " \
|
24
25
|
"managing the description of a resource.",
|
25
|
-
[ Permissions::READ, Permissions::DOWNLOAD, Permissions::UPDATE ]
|
26
|
+
[ Permissions::DISCOVER, Permissions::READ, Permissions::DOWNLOAD, Permissions::UPDATE ]
|
26
27
|
)
|
27
28
|
|
28
29
|
CONTRIBUTOR = RoleType.new(
|
29
30
|
"Contributor",
|
30
31
|
"The Contributor role conveys responsibility for adding related " \
|
31
32
|
"resources to a resource, such as works to a collection.",
|
32
|
-
[ Permissions::READ, Permissions::ADD_CHILDREN ]
|
33
|
+
[ Permissions::DISCOVER, Permissions::READ, Permissions::ADD_CHILDREN ]
|
33
34
|
)
|
34
35
|
|
35
36
|
DOWNLOADER = RoleType.new(
|
36
37
|
"Downloader",
|
37
38
|
"The Downloader role conveys access to the \"master\" file " \
|
38
39
|
"(original content bitstream) of a resource.",
|
39
|
-
[ Permissions::READ, Permissions::DOWNLOAD ]
|
40
|
+
[ Permissions::DISCOVER, Permissions::READ, Permissions::DOWNLOAD ]
|
40
41
|
)
|
41
42
|
|
42
43
|
VIEWER = RoleType.new(
|
43
44
|
"Viewer",
|
44
45
|
"The Viewer role conveys access to the description and \"access\" " \
|
45
46
|
"files (e.g., derivative bitstreams) of a resource.",
|
46
|
-
[ Permissions::READ ]
|
47
|
+
[ Permissions::DISCOVER, Permissions::READ ]
|
48
|
+
)
|
49
|
+
|
50
|
+
METADATA_VIEWER = RoleType.new(
|
51
|
+
"MetadataViewer",
|
52
|
+
"The MetadataViewer role coveys access to the description of a resource.",
|
53
|
+
[ Permissions::DISCOVER ]
|
47
54
|
)
|
48
55
|
|
49
56
|
end
|
data/lib/ddr/core.rb
CHANGED
@@ -9,6 +9,7 @@ module Ddr
|
|
9
9
|
autoload :Files
|
10
10
|
autoload :NotFoundError, 'ddr/error'
|
11
11
|
autoload :Fits
|
12
|
+
autoload :FindingAid
|
12
13
|
autoload :Index
|
13
14
|
autoload :Managers
|
14
15
|
autoload :Utils
|
@@ -103,6 +104,14 @@ module Ddr
|
|
103
104
|
false
|
104
105
|
end
|
105
106
|
|
107
|
+
mattr_accessor :ddr_aux_api_url do
|
108
|
+
ENV["DDR_AUX_API_URL"]
|
109
|
+
end
|
110
|
+
|
111
|
+
mattr_accessor :ead_xml_base_url do
|
112
|
+
ENV["EAD_XML_BASE_URL"]
|
113
|
+
end
|
114
|
+
|
106
115
|
module Core
|
107
116
|
|
108
117
|
end
|
data/lib/ddr/core/version.rb
CHANGED
data/lib/ddr/fits.rb
CHANGED
@@ -94,96 +94,5 @@ module Ddr
|
|
94
94
|
xpath('//fits:fits', fits: FITS_XMLNS).first
|
95
95
|
end
|
96
96
|
|
97
|
-
### DDRevo ##########################################
|
98
|
-
# From Ddr::Datastreams::FitsDatastream. Code above accounts for proxy terms from below and has a private 'root'
|
99
|
-
# method but does not (yet) provide methods for all the terms in the terminology. Thought it was better to wait
|
100
|
-
# and see which ones are actually needed.
|
101
|
-
### DDRevo ##########################################
|
102
|
-
# set_terminology do |t|
|
103
|
-
# t.root(path: "fits",
|
104
|
-
# xmlns: FITS_XMLNS,
|
105
|
-
# schema: FITS_SCHEMA)
|
106
|
-
# t.version(path: {attribute: "version"})
|
107
|
-
# t.timestamp(path: {attribute: "timestamp"})
|
108
|
-
# t.identification {
|
109
|
-
# t.identity {
|
110
|
-
# t.mimetype(path: {attribute: "mimetype"})
|
111
|
-
# t.format_label(path: {attribute: "format"})
|
112
|
-
# t.version
|
113
|
-
# t.externalIdentifier
|
114
|
-
# t.pronom_identifier(path: "externalIdentifier", attributes: {type: "puid"})
|
115
|
-
# }
|
116
|
-
# }
|
117
|
-
# t.fileinfo {
|
118
|
-
# t.created
|
119
|
-
# t.creatingApplicationName
|
120
|
-
# t.creatingos
|
121
|
-
# t.filename
|
122
|
-
# t.filepath
|
123
|
-
# t.fslastmodified
|
124
|
-
# t.lastmodified
|
125
|
-
# t.md5checksum
|
126
|
-
# t.size
|
127
|
-
# }
|
128
|
-
# t.filestatus {
|
129
|
-
# t.valid
|
130
|
-
# t.well_formed(path: "well-formed")
|
131
|
-
# }
|
132
|
-
# t.metadata {
|
133
|
-
# t.image {
|
134
|
-
# t.imageWidth
|
135
|
-
# t.imageHeight
|
136
|
-
# t.colorSpace
|
137
|
-
# t.iccProfileName
|
138
|
-
# t.iccProfileVersion
|
139
|
-
# }
|
140
|
-
# t.document {
|
141
|
-
# # TODO - configure to get from Tika?
|
142
|
-
# # t.encoding
|
143
|
-
# }
|
144
|
-
# t.text
|
145
|
-
# t.audio
|
146
|
-
# t.video
|
147
|
-
# }
|
148
|
-
#
|
149
|
-
# ## proxy terms
|
150
|
-
#
|
151
|
-
# # identification / identity
|
152
|
-
# t.format_label proxy: [:identification, :identity, :format_label]
|
153
|
-
# t.format_version proxy: [:identification, :identity, :version]
|
154
|
-
# t.media_type proxy: [:identification, :identity, :mimetype]
|
155
|
-
# t.pronom_identifier proxy: [:identification, :identity, :pronom_identifier]
|
156
|
-
#
|
157
|
-
# # filestatus
|
158
|
-
# t.valid proxy: [:filestatus, :valid]
|
159
|
-
# t.well_formed proxy: [:filestatus, :well_formed]
|
160
|
-
#
|
161
|
-
# # fileinfo
|
162
|
-
# t.created proxy: [:fileinfo, :created]
|
163
|
-
# t.creating_application proxy: [:fileinfo, :creatingApplicationName]
|
164
|
-
# t.extent proxy: [:fileinfo, :size]
|
165
|
-
# t.md5 proxy: [:fileinfo, :md5checksum]
|
166
|
-
#
|
167
|
-
# # image metadata
|
168
|
-
# t.color_space proxy: [:metadata, :image, :colorSpace]
|
169
|
-
# t.icc_profile_name proxy: [:metadata, :image, :iccProfileName]
|
170
|
-
# t.icc_profile_version proxy: [:metadata, :image, :iccProfileVersion]
|
171
|
-
# t.image_height proxy: [:metadata, :image, :imageHeight]
|
172
|
-
# t.image_width proxy: [:metadata, :image, :imageWidth]
|
173
|
-
# end
|
174
|
-
#
|
175
|
-
# def self.xml_template
|
176
|
-
# builder = Nokogiri::XML::Builder.new do |xml|
|
177
|
-
# xml.fits("xmlns"=>FITS_XMLNS,
|
178
|
-
# "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
|
179
|
-
# "xsi:schemaLocation"=>"http://hul.harvard.edu/ois/xml/ns/fits/fits_output http://hul.harvard.edu/ois/xml/xsd/fits/fits_output.xsd")
|
180
|
-
# end
|
181
|
-
# builder.doc
|
182
|
-
# end
|
183
|
-
#
|
184
|
-
# def prefix
|
185
|
-
# "fits__"
|
186
|
-
# end
|
187
|
-
|
188
97
|
end
|
189
98
|
end
|