ddr-core 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +12 -0
  3. data/README.md +27 -0
  4. data/Rakefile +30 -0
  5. data/app/assets/config/ddr_core_manifest.js +0 -0
  6. data/app/controllers/users/omniauth_callbacks_controller.rb +11 -0
  7. data/app/controllers/users/sessions_controller.rb +15 -0
  8. data/app/models/concerns/ddr/captionable.rb +25 -0
  9. data/app/models/concerns/ddr/describable.rb +108 -0
  10. data/app/models/concerns/ddr/governable.rb +25 -0
  11. data/app/models/concerns/ddr/has_admin_metadata.rb +141 -0
  12. data/app/models/concerns/ddr/has_attachments.rb +10 -0
  13. data/app/models/concerns/ddr/has_children.rb +10 -0
  14. data/app/models/concerns/ddr/has_content.rb +132 -0
  15. data/app/models/concerns/ddr/has_extracted_text.rb +10 -0
  16. data/app/models/concerns/ddr/has_intermediate_file.rb +25 -0
  17. data/app/models/concerns/ddr/has_multires_image.rb +14 -0
  18. data/app/models/concerns/ddr/has_parent.rb +18 -0
  19. data/app/models/concerns/ddr/has_struct_metadata.rb +21 -0
  20. data/app/models/concerns/ddr/has_thumbnail.rb +33 -0
  21. data/app/models/concerns/ddr/solr_document_behavior.rb +429 -0
  22. data/app/models/concerns/ddr/streamable.rb +25 -0
  23. data/app/models/ddr/admin_set.rb +28 -0
  24. data/app/models/ddr/attachment.rb +14 -0
  25. data/app/models/ddr/collection.rb +28 -0
  26. data/app/models/ddr/component.rb +31 -0
  27. data/app/models/ddr/contact.rb +23 -0
  28. data/app/models/ddr/digest.rb +8 -0
  29. data/app/models/ddr/file.rb +40 -0
  30. data/app/models/ddr/item.rb +36 -0
  31. data/app/models/ddr/language.rb +31 -0
  32. data/app/models/ddr/media_type.rb +22 -0
  33. data/app/models/ddr/resource.rb +94 -0
  34. data/app/models/ddr/rights_statement.rb +25 -0
  35. data/app/models/ddr/target.rb +17 -0
  36. data/config/initializers/devise.rb +262 -0
  37. data/config/locales/ddr-core.en.yml +85 -0
  38. data/config/routes.rb +3 -0
  39. data/db/migrate/20141104181418_create_users.rb +34 -0
  40. data/db/migrate/20141107124012_add_columns_to_user.rb +46 -0
  41. data/lib/ddr-core.rb +1 -0
  42. data/lib/ddr/auth.rb +80 -0
  43. data/lib/ddr/auth/ability.rb +18 -0
  44. data/lib/ddr/auth/ability_definitions.rb +26 -0
  45. data/lib/ddr/auth/ability_definitions/admin_set_ability_definitions.rb +9 -0
  46. data/lib/ddr/auth/ability_definitions/alias_ability_definitions.rb +23 -0
  47. data/lib/ddr/auth/ability_definitions/attachment_ability_definitions.rb +13 -0
  48. data/lib/ddr/auth/ability_definitions/collection_ability_definitions.rb +28 -0
  49. data/lib/ddr/auth/ability_definitions/component_ability_definitions.rb +13 -0
  50. data/lib/ddr/auth/ability_definitions/item_ability_definitions.rb +13 -0
  51. data/lib/ddr/auth/ability_definitions/lock_ability_definitions.rb +13 -0
  52. data/lib/ddr/auth/ability_definitions/publication_ability_definitions.rb +16 -0
  53. data/lib/ddr/auth/ability_definitions/role_based_ability_definitions.rb +39 -0
  54. data/lib/ddr/auth/ability_definitions/superuser_ability_definitions.rb +9 -0
  55. data/lib/ddr/auth/ability_factory.rb +10 -0
  56. data/lib/ddr/auth/abstract_ability.rb +48 -0
  57. data/lib/ddr/auth/affiliation.rb +14 -0
  58. data/lib/ddr/auth/affiliation_groups.rb +20 -0
  59. data/lib/ddr/auth/anonymous_ability.rb +7 -0
  60. data/lib/ddr/auth/auth_context.rb +109 -0
  61. data/lib/ddr/auth/auth_context_factory.rb +13 -0
  62. data/lib/ddr/auth/detached_auth_context.rb +19 -0
  63. data/lib/ddr/auth/dynamic_groups.rb +13 -0
  64. data/lib/ddr/auth/effective_permissions.rb +12 -0
  65. data/lib/ddr/auth/effective_roles.rb +9 -0
  66. data/lib/ddr/auth/failure_app.rb +16 -0
  67. data/lib/ddr/auth/group.rb +40 -0
  68. data/lib/ddr/auth/grouper_gateway.rb +70 -0
  69. data/lib/ddr/auth/groups.rb +32 -0
  70. data/lib/ddr/auth/ldap_gateway.rb +74 -0
  71. data/lib/ddr/auth/permissions.rb +18 -0
  72. data/lib/ddr/auth/remote_groups.rb +14 -0
  73. data/lib/ddr/auth/role_based_access_controls_enforcement.rb +56 -0
  74. data/lib/ddr/auth/roles.rb +28 -0
  75. data/lib/ddr/auth/roles/role.rb +121 -0
  76. data/lib/ddr/auth/roles/role_type.rb +23 -0
  77. data/lib/ddr/auth/roles/role_types.rb +52 -0
  78. data/lib/ddr/auth/superuser_ability.rb +7 -0
  79. data/lib/ddr/auth/test_helpers.rb +22 -0
  80. data/lib/ddr/auth/user.rb +54 -0
  81. data/lib/ddr/auth/web_auth_context.rb +29 -0
  82. data/lib/ddr/core.rb +110 -0
  83. data/lib/ddr/core/engine.rb +8 -0
  84. data/lib/ddr/core/version.rb +5 -0
  85. data/lib/ddr/error.rb +16 -0
  86. data/lib/ddr/files.rb +13 -0
  87. data/lib/ddr/fits.rb +189 -0
  88. data/lib/ddr/index.rb +29 -0
  89. data/lib/ddr/index/abstract_query_result.rb +22 -0
  90. data/lib/ddr/index/connection.rb +38 -0
  91. data/lib/ddr/index/csv_query_result.rb +84 -0
  92. data/lib/ddr/index/document_builder.rb +9 -0
  93. data/lib/ddr/index/field.rb +35 -0
  94. data/lib/ddr/index/field_attribute.rb +22 -0
  95. data/lib/ddr/index/fields.rb +154 -0
  96. data/lib/ddr/index/filter.rb +139 -0
  97. data/lib/ddr/index/query.rb +82 -0
  98. data/lib/ddr/index/query_builder.rb +185 -0
  99. data/lib/ddr/index/query_clause.rb +112 -0
  100. data/lib/ddr/index/query_params.rb +40 -0
  101. data/lib/ddr/index/query_result.rb +102 -0
  102. data/lib/ddr/index/response.rb +30 -0
  103. data/lib/ddr/index/sort_order.rb +28 -0
  104. data/lib/ddr/index/unique_key_field.rb +12 -0
  105. data/lib/ddr/managers.rb +9 -0
  106. data/lib/ddr/managers/manager.rb +13 -0
  107. data/lib/ddr/managers/technical_metadata_manager.rb +141 -0
  108. data/lib/ddr/structure.rb +188 -0
  109. data/lib/ddr/structures/agent.rb +49 -0
  110. data/lib/ddr/structures/component_type_term.rb +29 -0
  111. data/lib/ddr/structures/div.rb +64 -0
  112. data/lib/ddr/structures/f_locat.rb +54 -0
  113. data/lib/ddr/structures/file.rb +52 -0
  114. data/lib/ddr/structures/file_grp.rb +35 -0
  115. data/lib/ddr/structures/file_sec.rb +22 -0
  116. data/lib/ddr/structures/fptr.rb +31 -0
  117. data/lib/ddr/structures/mets_hdr.rb +37 -0
  118. data/lib/ddr/structures/mptr.rb +49 -0
  119. data/lib/ddr/structures/struct_map.rb +40 -0
  120. data/lib/ddr/utils.rb +185 -0
  121. data/lib/ddr/vocab.rb +22 -0
  122. data/lib/ddr/vocab/asset.rb +51 -0
  123. data/lib/ddr/vocab/contact.rb +9 -0
  124. data/lib/ddr/vocab/display.rb +9 -0
  125. data/lib/ddr/vocab/duke_terms.rb +13 -0
  126. data/lib/ddr/vocab/rdf_vocabulary_parser.rb +43 -0
  127. data/lib/ddr/vocab/roles.rb +25 -0
  128. data/lib/ddr/vocab/sources/duketerms.rdf +870 -0
  129. data/lib/ddr/vocab/vocabulary.rb +37 -0
  130. data/lib/ddr/workflow.rb +8 -0
  131. data/lib/tasks/ddr/core_tasks.rake +4 -0
  132. metadata +428 -0
@@ -0,0 +1,30 @@
1
+ require "delegate"
2
+
3
+ module Ddr::Index
4
+ #
5
+ # Wraps an index query response
6
+ #
7
+ class Response < SimpleDelegator
8
+
9
+ def docs
10
+ response["docs"]
11
+ end
12
+
13
+ def num_found
14
+ response["numFound"].to_i
15
+ end
16
+
17
+ def facet_counts
18
+ self["facet_counts"] || {}
19
+ end
20
+
21
+ def facet_fields
22
+ facet_counts["facet_fields"] || {}
23
+ end
24
+
25
+ def response
26
+ self["response"]
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ require "virtus"
2
+
3
+ module Ddr::Index
4
+ class SortOrder
5
+ include Virtus.value_object
6
+
7
+ ASC = "asc"
8
+ DESC = "desc"
9
+
10
+ values do
11
+ attribute :field, FieldAttribute
12
+ attribute :order, String
13
+ end
14
+
15
+ def to_s
16
+ [ field, order ].join(" ")
17
+ end
18
+
19
+ def self.asc(field)
20
+ new(field: field, order: ASC)
21
+ end
22
+
23
+ def self.desc(field)
24
+ new(field: field, order: DESC)
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+ require 'singleton'
2
+
3
+ module Ddr::Index
4
+ class UniqueKeyField < Field
5
+ include Singleton
6
+
7
+ def initialize
8
+ super Ddr::SOLR_DOCUMENT_ID
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ module Ddr
2
+ module Managers
3
+ extend ActiveSupport::Autoload
4
+
5
+ autoload :Manager
6
+ autoload :TechnicalMetadataManager
7
+
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ module Ddr
2
+ module Managers
3
+ # @abstract
4
+ class Manager
5
+ attr_reader :object
6
+
7
+ def initialize(object)
8
+ @object = object
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,141 @@
1
+ module Ddr
2
+ module Managers
3
+ class TechnicalMetadataManager < Manager
4
+
5
+ FITS_TIMESTAMP_FORMAT = "%D %l:%M %p" # Ex. 7/3/15 8:29 PM
6
+
7
+ delegate :content, to: :object
8
+
9
+ delegate :color_space,
10
+ :created,
11
+ :creating_application,
12
+ :extent,
13
+ :format_label,
14
+ :format_version,
15
+ :icc_profile_name,
16
+ :icc_profile_version,
17
+ :image_height,
18
+ :image_width,
19
+ :media_type,
20
+ :modified,
21
+ :pronom_identifier,
22
+ :valid,
23
+ :well_formed,
24
+ to: :fits
25
+
26
+ alias_method :last_modified, :modified
27
+
28
+ def fits
29
+ if object.fits_file.present?
30
+ Ddr::Fits.new(Nokogiri::XML(object.fits_file.file))
31
+ else
32
+ Ddr::Fits.new(Ddr::Fits.xml_template)
33
+ end
34
+ end
35
+
36
+ def fits?
37
+ !fits_version.nil?
38
+ end
39
+
40
+ def fits_version
41
+ fits.version.first
42
+ end
43
+
44
+ def fits_datetime
45
+ if fits_timestamp = fits.timestamp.first
46
+ # no_zone = DateTime.strptime(fits_timestamp, FITS_TIMESTAMP_FORMAT)
47
+ # no_zone.change(offset: no_zone.to_time.zone)
48
+ Time.zone.strptime(fits_timestamp, FITS_TIMESTAMP_FORMAT)
49
+ end
50
+ end
51
+
52
+ def file_size
53
+ extent.map(&:to_i)
54
+ end
55
+
56
+ def file_human_size
57
+ file_size.map do |fs|
58
+ "%s (%s bytes)" % [ ActiveSupport::NumberHelper.number_to_human_size(fs),
59
+ ActiveSupport::NumberHelper.number_to_delimited(fs) ]
60
+ end
61
+ end
62
+
63
+ def md5
64
+ fits.md5.first
65
+ end
66
+
67
+ # Ddr::File currently implements the 'digest' attribute as a set (array) of
68
+ # Ddr::Digest objects. This method (and the 'checksum_value' method that
69
+ # follows) assumes there is only one checksum associated with a file (as was
70
+ # the case in ddr-models). The current implementation simply picks the first
71
+ # checksum, unless/until we decide on a different approach.
72
+ def checksum_digest
73
+ content&.digest&.first&.type
74
+ end
75
+
76
+ def checksum_value
77
+ content&.digest&.first&.value
78
+ end
79
+
80
+ def invalid?
81
+ valid.any? { |v| v == "false" }
82
+ end
83
+
84
+ def valid?
85
+ !invalid?
86
+ end
87
+
88
+ def ill_formed?
89
+ well_formed.any? { |v| v == "false" }
90
+ end
91
+
92
+ def well_formed?
93
+ !ill_formed?
94
+ end
95
+
96
+ def creation_time
97
+ created.map { |datestr| coerce_to_time(datestr) }.compact
98
+ end
99
+
100
+ def modification_time
101
+ modified.map { |datestr| coerce_to_time(datestr) }.compact
102
+ end
103
+
104
+ ### DDRevo #######################################################
105
+ # Holding off on this until we address indexing more generally,
106
+ # perhaps in the context of the ddr-admin staff app.
107
+ ### DDRevo #######################################################
108
+ # def index_fields
109
+ # { Ddr::Index::Fields::TECHMD_FITS_VERSION => fits_version,
110
+ # Ddr::Index::Fields::TECHMD_FITS_DATETIME => Ddr::Utils.solr_date(fits_datetime),
111
+ # Ddr::Index::Fields::TECHMD_CREATION_TIME => Ddr::Utils.solr_dates(creation_time),
112
+ # Ddr::Index::Fields::TECHMD_MODIFICATION_TIME => Ddr::Utils.solr_dates(modification_time),
113
+ # Ddr::Index::Fields::TECHMD_COLOR_SPACE => color_space,
114
+ # Ddr::Index::Fields::TECHMD_CREATING_APPLICATION => creating_application,
115
+ # Ddr::Index::Fields::TECHMD_FILE_SIZE => file_size,
116
+ # Ddr::Index::Fields::TECHMD_FORMAT_LABEL => format_label,
117
+ # Ddr::Index::Fields::TECHMD_FORMAT_VERSION => format_version,
118
+ # Ddr::Index::Fields::TECHMD_ICC_PROFILE_NAME => icc_profile_name,
119
+ # Ddr::Index::Fields::TECHMD_ICC_PROFILE_VERSION => icc_profile_version,
120
+ # Ddr::Index::Fields::TECHMD_IMAGE_HEIGHT => image_height,
121
+ # Ddr::Index::Fields::TECHMD_IMAGE_WIDTH => image_width,
122
+ # Ddr::Index::Fields::TECHMD_MD5 => md5,
123
+ # Ddr::Index::Fields::TECHMD_MEDIA_TYPE => media_type,
124
+ # Ddr::Index::Fields::TECHMD_PRONOM_IDENTIFIER => pronom_identifier,
125
+ # Ddr::Index::Fields::TECHMD_VALID => valid,
126
+ # Ddr::Index::Fields::TECHMD_WELL_FORMED => well_formed,
127
+ # }
128
+ # end
129
+
130
+ private
131
+
132
+ def coerce_to_time(datestr)
133
+ datestr.sub! /\A(\d+):(\d+):(\d+)/, '\1-\2-\3'
134
+ DateTime.parse(datestr).to_time
135
+ rescue ArgumentError
136
+ nil
137
+ end
138
+
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,188 @@
1
+ module Ddr
2
+ #
3
+ # Wraps a Nokogiri (XML) 'mets' Document
4
+ #
5
+ class Structure < SimpleDelegator
6
+
7
+ # Indicates whether the structure is externally provided or maintained by the repository itself (i.e., is the
8
+ # default structure for the object).
9
+ EXTERNALLY_PROVIDED = 'provided'.freeze
10
+ REPOSITORY_MAINTAINED = 'repository'.freeze
11
+
12
+ TYPE_DEFAULT = 'default'.freeze
13
+
14
+ # Based on the PCDM Extension 'Use' ontology -- https://github.com/duraspace/pcdm/blob/master/pcdm-ext/use.rdf
15
+ USE_EXTRACTED_TEXT = 'ExtractedText'.freeze
16
+ USE_INTERMEDIATE_FILE = 'IntermediateFile'.freeze
17
+ USE_ORIGINAL_FILE = 'OriginalFile'.freeze
18
+ USE_PRESERVATION_MASTER_FILE = 'PreservationMasterFile'.freeze
19
+ USE_SERVICE_FILE = 'ServiceFile'.freeze
20
+ USE_THUMBNAIL_IMAGE = 'ThumbnailImage'.freeze
21
+ USE_TRANSCRIPT = 'Transcript'.freeze
22
+
23
+ def filesec
24
+ @filesec ||= Ddr::Structures::FileSec.new(fileSec_node)
25
+ end
26
+
27
+ def files
28
+ @files ||= collect_files
29
+ end
30
+
31
+ def uses
32
+ @uses ||= collect_uses
33
+ end
34
+
35
+ def structmap(type=nil)
36
+ sm = type ? structMap_node(type) : structMap_nodes.first
37
+ @structmap ||= Ddr::Structures::StructMap.new(sm)
38
+ end
39
+
40
+ def structmaps
41
+ @structmaps ||= structMap_nodes.map { |sm| Ddr::Structures::StructMap.new(sm) }
42
+ end
43
+
44
+ def metshdr
45
+ @metshdr ||= Ddr::Structures::MetsHdr.new(metsHdr_node)
46
+ end
47
+
48
+ def creator
49
+ @creator ||= metshdr.empty? ? nil
50
+ : Ddr::Structures::MetsHdr.new(metsHdr_node).agents.first.name
51
+ end
52
+
53
+ def repository_maintained?
54
+ creator == Ddr::Structures::Agent::NAME_REPOSITORY_DEFAULT
55
+ end
56
+
57
+ def dereferenced_structure
58
+ deref_struct = {}
59
+ structmaps.each do |sm|
60
+ deref_struct[sm.type] = sm.dereferenced_hash
61
+ end
62
+ deref_struct
63
+ end
64
+
65
+ def as_xml_document
66
+ __getobj__
67
+ end
68
+
69
+ def add_metshdr(id:nil, createdate:nil, lastmoddate:nil, recordstatus:nil)
70
+ metshdr = Ddr::Structures::MetsHdr.build(id: id, createdate: createdate, lastmoddate: lastmoddate,
71
+ recordstatus: recordstatus, document: as_xml_document)
72
+ root.add_child(metshdr)
73
+ metshdr
74
+ end
75
+
76
+ def add_agent(parent:, id:nil, role:, otherrole:nil, type:nil, othertype:nil, name:nil)
77
+ agent = Ddr::Structures::Agent.build(id: id, role: role, otherrole: otherrole, type: type,
78
+ othertype: othertype, name: name, document: as_xml_document)
79
+ parent.add_child(agent)
80
+ agent
81
+ end
82
+
83
+ def add_filesec(id:nil)
84
+ filesec = Ddr::Structures::FileSec.build(id: id, document: as_xml_document)
85
+ root.add_child(filesec)
86
+ filesec
87
+ end
88
+
89
+ def add_filegrp(parent:, id:nil, use:nil)
90
+ filegrp = Ddr::Structures::FileGrp.build(id: id, use: use, document: as_xml_document)
91
+ parent.add_child(filegrp)
92
+ filegrp
93
+ end
94
+
95
+ def add_file(parent:, id:SecureRandom.uuid, use:nil)
96
+ file = Ddr::Structures::File.build(id: id, use: use, document: as_xml_document)
97
+ parent.add_child(file)
98
+ file
99
+ end
100
+
101
+ def add_flocat(parent:, id:nil, loctype:'ARK', otherloctype: nil, use:nil, href:)
102
+ flocat = Ddr::Structures::FLocat.build(id: id, loctype: loctype, otherloctype: otherloctype, use: use,
103
+ href: href, document: as_xml_document)
104
+ parent.add_child(flocat)
105
+ flocat
106
+ end
107
+
108
+ def add_structmap(id:nil, label:nil, type:)
109
+ structmap = Ddr::Structures::StructMap.build(id: id, label: label, type: type, document: as_xml_document)
110
+ root.add_child(structmap)
111
+ structmap
112
+ end
113
+
114
+ def add_div(parent:, id:nil, label:nil, order:nil, orderlabel: nil, type:nil)
115
+ div = Ddr::Structures::Div.build(id: id, label: label, order:order, orderlabel: orderlabel, type: type,
116
+ document: as_xml_document)
117
+ parent.add_child(div)
118
+ div
119
+ end
120
+
121
+ def add_fptr(parent:, id: nil, fileid:)
122
+ fptr = Ddr::Structures::Fptr.build(id: id, fileid: fileid, document: as_xml_document)
123
+ parent.add_child(fptr)
124
+ fptr
125
+ end
126
+
127
+ def add_mptr(parent:, id: nil, loctype:'ARK', otherloctype: nil, href:)
128
+ mptr = Ddr::Structures::Mptr.build(id: id, loctype: loctype, otherloctype: otherloctype, href: href,
129
+ document: as_xml_document)
130
+ parent.add_child(mptr)
131
+ mptr
132
+ end
133
+
134
+ private
135
+
136
+ def fileSec_node
137
+ xpath("//xmlns:fileSec").first
138
+ end
139
+
140
+ def structMap_nodes
141
+ xpath("//xmlns:structMap")
142
+ end
143
+
144
+ def structMap_node(type)
145
+ xpath("//xmlns:structMap[@TYPE='#{type}']").first
146
+ end
147
+
148
+ def metsHdr_node
149
+ xpath("//xmlns:metsHdr")
150
+ end
151
+
152
+ def file_nodes
153
+ xpath("//xmlns:file")
154
+ end
155
+
156
+ def flocat_nodes
157
+ xpath("//xmlns:FLocat")
158
+ end
159
+
160
+ def collect_files
161
+ files = {}
162
+ file_nodes.each do |file_node|
163
+ file = Ddr::Structures::File.new(file_node)
164
+ files[file.id] = file
165
+ end
166
+ files
167
+ end
168
+
169
+ def collect_uses
170
+ uses = {}
171
+ flocat_nodes.each do |flocat_node|
172
+ flocat = Ddr::Structures::FLocat.new(flocat_node)
173
+ uses[flocat.effective_use] ||= []
174
+ uses[flocat.effective_use] << flocat
175
+ end
176
+ uses
177
+ end
178
+
179
+ def self.xml_template
180
+ Nokogiri::XML(
181
+ '<mets xmlns="http://www.loc.gov/METS/" xmlns:xlink="http://www.w3.org/1999/xlink" />'
182
+ ) do |config|
183
+ config.noblanks
184
+ end
185
+ end
186
+
187
+ end
188
+ end
@@ -0,0 +1,49 @@
1
+ module Ddr::Structures
2
+ #
3
+ # Wraps a Nokogiri (XML) 'agent' node
4
+ #
5
+ class Agent < SimpleDelegator
6
+
7
+ ROLE_CREATOR = 'CREATOR'.freeze
8
+
9
+ NAME_REPOSITORY_DEFAULT = 'REPOSITORY DEFAULT'.freeze
10
+
11
+ def id
12
+ self['ID']
13
+ end
14
+
15
+ def role
16
+ self['ROLE']
17
+ end
18
+
19
+ def otherrole
20
+ self['OTHERROLE']
21
+ end
22
+
23
+ def type
24
+ self['TYPE']
25
+ end
26
+
27
+ def othertype
28
+ self['OTHERTYPE']
29
+ end
30
+
31
+ def name
32
+ xpath('xmlns:name').first.content
33
+ end
34
+
35
+ def self.build(args)
36
+ node = Nokogiri::XML::Node.new('agent', args[:document])
37
+ node['ID'] = args[:id] if args[:id]
38
+ node['ROLE'] = args[:role] if args[:role]
39
+ node['OTHERROLE'] = args[:otherrole] if args[:otherrole]
40
+ node['TYPE'] = args[:type] if args[:type]
41
+ node['OTHERTYPE'] = args[:othertype] if args[:othertype]
42
+ name_node = Nokogiri::XML::Node.new('name', args[:document])
43
+ name_node.content = args[:name]
44
+ node.add_child(name_node)
45
+ node
46
+ end
47
+
48
+ end
49
+ end