diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 9bccabaa..f5d6081d 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2018-05-18 08:42:26 -0500 using RuboCop version 0.56.0. +# on 2018-11-28 16:13:16 -0600 using RuboCop version 0.60.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -8,7 +8,7 @@ # Offense count: 3 # Cop supports --auto-correct. -# Configuration parameters: Include, TreatCommentsAsGroupSeparators. +# Configuration parameters: TreatCommentsAsGroupSeparators, Include. # Include: **/*.gemfile, **/Gemfile, **/gems.rb Bundler/OrderedGems: Exclude: @@ -16,7 +16,7 @@ Bundler/OrderedGems: # Offense count: 4 # Cop supports --auto-correct. -# Configuration parameters: Include, TreatCommentsAsGroupSeparators. +# Configuration parameters: TreatCommentsAsGroupSeparators, Include. # Include: **/*.gemspec Gemspec/OrderedDependencies: Exclude: @@ -27,14 +27,12 @@ Lint/AmbiguousBlockAssociation: Exclude: - 'spec/models/concerns/processable_spec.rb' -# Offense count: 5 +# Offense count: 3 Lint/AmbiguousOperator: Exclude: - 'lib/dor-services.rb' - 'lib/dor/config.rb' - - 'lib/dor/models/concerns/describable.rb' - 'lib/dor/models/concerns/eventable.rb' - - 'lib/dor/models/workflow_object.rb' # Offense count: 2 # Configuration parameters: AllowSafeAssignment. @@ -52,9 +50,9 @@ Lint/DeprecatedClassMethods: # Offense count: 6 Lint/HandleExceptions: Exclude: + - 'lib/dor/indexers/processable_indexer.rb' - 'lib/dor/models/concerns/contentable.rb' - 'lib/dor/models/concerns/processable.rb' - - 'lib/dor/indexers/processable_indexer.rb' - 'script/console' - 'script/manual_integration.rb' - 'spec/support/foxml_helper.rb' @@ -87,12 +85,7 @@ Lint/ShadowedArgument: Exclude: - 'lib/dor/datastreams/embargo_metadata_ds.rb' -# Offense count: 1 -Lint/SplatKeywordArguments: - Exclude: - - 'lib/dor/models/concerns/describable.rb' - -# Offense count: 22 +# Offense count: 23 # Cop supports --auto-correct. # Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. Lint/UnusedBlockArgument: @@ -108,7 +101,7 @@ Lint/UnusedBlockArgument: - 'spec/services/digital_stacks_service_spec.rb' - 'spec/support/foxml_helper.rb' -# Offense count: 10 +# Offense count: 9 # Cop supports --auto-correct. # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods. Lint/UnusedMethodArgument: @@ -121,7 +114,6 @@ Lint/UnusedMethodArgument: - 'lib/dor/services/sdr_ingest_service.rb' - 'lib/dor/services/search_service.rb' - 'lib/dor/workflow/document.rb' - - 'lib/dor/workflow/graph.rb' - 'spec/services/metadata_service_spec.rb' # Offense count: 2 @@ -142,35 +134,34 @@ Lint/Void: Exclude: - 'lib/dor/models/concerns/identifiable.rb' -# Offense count: 87 +# Offense count: 85 Metrics/AbcSize: - Max: 131 + Max: 129 -# Offense count: 168 +# Offense count: 179 # Configuration parameters: CountComments, ExcludedMethods. +# ExcludedMethods: refine Metrics/BlockLength: - Exclude: - - 'spec/**/*' - Max: 50 + Max: 542 # Offense count: 11 # Configuration parameters: CountComments. Metrics/ClassLength: - Max: 254 + Max: 253 # Offense count: 19 Metrics/CyclomaticComplexity: Max: 25 -# Offense count: 87 -# Configuration parameters: CountComments. +# Offense count: 84 +# Configuration parameters: CountComments, ExcludedMethods. Metrics/MethodLength: Max: 75 -# Offense count: 8 +# Offense count: 7 # Configuration parameters: CountComments. Metrics/ModuleLength: - Max: 275 + Max: 265 # Offense count: 2 # Configuration parameters: CountKeywordArgs. @@ -181,7 +172,7 @@ Metrics/ParameterLists: Metrics/PerceivedComplexity: Max: 25 -# Offense count: 9 +# Offense count: 8 Naming/AccessorMethodName: Exclude: - 'lib/dor/datastreams/rights_metadata_ds.rb' @@ -189,9 +180,8 @@ Naming/AccessorMethodName: - 'lib/dor/models/concerns/governable.rb' - 'lib/dor/models/concerns/releaseable.rb' - 'lib/dor/models/concerns/shelvable.rb' - - 'lib/dor/workflow/graph.rb' -# Offense count: 12 +# Offense count: 14 # Configuration parameters: EnforcedStyle. # SupportedStyles: lowercase, uppercase Naming/HeredocDelimiterCase: @@ -245,9 +235,9 @@ Naming/UncommunicativeBlockParamName: Exclude: - 'lib/dor/services/public_xml_service.rb' -# Offense count: 15 +# Offense count: 13 # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. -# AllowedNames: io, id, to, by, on, in, at +# AllowedNames: io, id, to, by, on, in, at, ip, db Naming/UncommunicativeMethodParamName: Exclude: - 'lib/dor/datastreams/content_metadata_ds.rb' @@ -258,7 +248,6 @@ Naming/UncommunicativeMethodParamName: - 'lib/dor/models/concerns/editable.rb' - 'lib/dor/models/concerns/preservable.rb' - 'lib/dor/models/concerns/rightsable.rb' - - 'lib/dor/workflow/graph.rb' # Offense count: 19 # Configuration parameters: EnforcedStyle. @@ -324,7 +313,7 @@ Style/Alias: - 'lib/dor/models/workflow_object.rb' - 'lib/dor/services/merge_service.rb' -# Offense count: 115 +# Offense count: 106 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, IgnoredMethods. # SupportedStyles: line_count_based, semantic, braces_for_chaining @@ -334,25 +323,38 @@ Style/Alias: Style/BlockDelimiters: Enabled: false -# Offense count: 38 +# Offense count: 34 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: braces, no_braces, context_dependent Style/BracesAroundHashParameters: - Enabled: false + Exclude: + - 'lib/dor/config.rb' + - 'lib/dor/datastreams/default_object_rights_ds.rb' + - 'lib/dor/models/concerns/editable.rb' + - 'lib/dor/models/concerns/publishable.rb' + - 'lib/dor/models/concerns/versionable.rb' + - 'lib/dor/services/registration_service.rb' + - 'lib/dor/services/search_service.rb' + - 'spec/datastreams/identity_metadata_spec.rb' + - 'spec/models/concerns/editable_spec.rb' + - 'spec/models/concerns/processable_spec.rb' + - 'spec/models/concerns/releaseable_spec.rb' + - 'spec/models/concerns/versionable_spec.rb' + - 'spec/models/workflow_document_spec.rb' + - 'spec/services/sdr_ingest_service_spec.rb' -# Offense count: 6 +# Offense count: 5 # Cop supports --auto-correct. # Configuration parameters: AutoCorrect, EnforcedStyle. # SupportedStyles: nested, compact Style/ClassAndModuleChildren: Exclude: - 'lib/dor/datastreams/datastream_spec_solrizer.rb' - - 'lib/dor/models/agreement.rb' - 'lib/dor/utils/ng_tidy.rb' - 'spec/spec_helper.rb' -# Offense count: 11 +# Offense count: 13 Style/ClassVars: Exclude: - 'lib/dor-services.rb' @@ -371,23 +373,24 @@ Style/CommentedKeyword: - 'lib/dor/services/reset_workspace_service.rb' - 'spec/services/registration_service_spec.rb' -# Offense count: 4 +# Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions. # SupportedStyles: assign_to_condition, assign_inside_condition Style/ConditionalAssignment: Exclude: - 'lib/dor/models/concerns/contentable.rb' - - 'lib/dor/models/concerns/publishable.rb' - 'lib/dor/services/merge_service.rb' - 'spec/support/foxml_helper.rb' -# Offense count: 1 +# Offense count: 2 +# Configuration parameters: AllowCoercion. Style/DateTime: Exclude: + - 'lib/dor/indexers/processable_indexer.rb' - 'lib/dor/models/concerns/processable.rb' -# Offense count: 68 +# Offense count: 73 Style/Documentation: Enabled: false @@ -436,7 +439,7 @@ Style/GuardClause: - 'lib/dor/services/technical_metadata_service.rb' - 'lib/dor/utils/predicate_patch.rb' -# Offense count: 661 +# Offense count: 648 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys @@ -448,7 +451,7 @@ Style/IfInsideElse: Exclude: - 'lib/dor/models/concerns/identifiable.rb' -# Offense count: 28 +# Offense count: 26 # Cop supports --auto-correct. Style/IfUnlessModifier: Enabled: false @@ -461,11 +464,6 @@ Style/MethodDefParentheses: Exclude: - 'lib/dor/services/public_desc_metadata_service.rb' -# Offense count: 1 -Style/MissingRespondToMissing: - Exclude: - - 'lib/dor/workflow/graph.rb' - # Offense count: 1 Style/MultilineBlockChain: Exclude: @@ -484,23 +482,15 @@ Style/NestedTernaryOperator: Exclude: - 'lib/dor/workflow/document.rb' -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, MinBodyLength. -# SupportedStyles: skip_modifier_ifs, always -Style/Next: - Exclude: - - 'lib/dor/models/concerns/publishable.rb' - # Offense count: 6 # Cop supports --auto-correct. # Configuration parameters: Strict. Style/NumericLiterals: MinDigits: 11 -# Offense count: 20 +# Offense count: 37 # Cop supports --auto-correct. -# Configuration parameters: AutoCorrect, EnforcedStyle. +# Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods. # SupportedStyles: predicate, comparison Style/NumericPredicate: Enabled: false @@ -511,7 +501,7 @@ Style/OrAssignment: Exclude: - 'lib/dor/models/concerns/releaseable.rb' -# Offense count: 36 +# Offense count: 34 # Cop supports --auto-correct. # Configuration parameters: PreferredDelimiters. Style/PercentLiteralDelimiters: @@ -542,7 +532,7 @@ Style/RedundantReturn: - 'lib/dor/datastreams/simple_dublin_core_ds.rb' - 'lib/dor/utils/sdr_client.rb' -# Offense count: 27 +# Offense count: 25 # Cop supports --auto-correct. Style/RedundantSelf: Exclude: @@ -555,7 +545,7 @@ Style/RedundantSelf: - 'lib/dor/services/metadata_service.rb' - 'lib/dor/workflow/process.rb' -# Offense count: 12 +# Offense count: 11 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, AllowInnerSlashes. # SupportedStyles: slashes, percent_r, mixed @@ -566,7 +556,6 @@ Style/RegexpLiteral: - 'lib/dor/services/registration_service.rb' - 'lib/dor/services/search_service.rb' - 'lib/dor/services/technical_metadata_service.rb' - - 'lib/dor/workflow/graph.rb' - 'script/manual_integration.rb' - 'spec/models/concerns/publishable_spec.rb' - 'spec/services/digital_stacks_service_spec.rb' @@ -578,7 +567,7 @@ Style/RescueModifier: Exclude: - 'lib/dor/services/indexing_service.rb' -# Offense count: 14 +# Offense count: 13 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: implicit, explicit @@ -645,7 +634,7 @@ Style/StringLiterals: Style/SymbolArray: EnforcedStyle: brackets -# Offense count: 20 +# Offense count: 19 # Cop supports --auto-correct. # Configuration parameters: IgnoredMethods. # IgnoredMethods: respond_to, define_method @@ -665,7 +654,6 @@ Style/SymbolProc: - 'lib/dor/services/public_xml_service.rb' - 'lib/dor/services/suri_service.rb' - 'lib/dor/utils/ng_tidy.rb' - - 'spec/models/concerns/describable_spec.rb' # Offense count: 7 # Cop supports --auto-correct. @@ -698,7 +686,7 @@ Style/UnneededInterpolation: - 'spec/services/cleanup_reset_service_spec.rb' - 'spec/services/reset_workspace_service_spec.rb' -# Offense count: 6 +# Offense count: 4 # Cop supports --auto-correct. # Configuration parameters: WordRegex. # SupportedStyles: percent, brackets @@ -706,7 +694,7 @@ Style/WordArray: EnforcedStyle: percent MinSize: 4 -# Offense count: 29 +# Offense count: 27 # Cop supports --auto-correct. Style/ZeroLengthPredicate: Enabled: false diff --git a/dor-services.gemspec b/dor-services.gemspec index 28138649..c30ae4d5 100644 --- a/dor-services.gemspec +++ b/dor-services.gemspec @@ -57,7 +57,7 @@ Gem::Specification.new do |s| s.add_development_dependency 'rdoc' s.add_development_dependency 'vcr' s.add_development_dependency 'webmock' - s.add_development_dependency 'rubocop', '~> 0.56.0' + s.add_development_dependency 'rubocop', '~> 0.60.0' s.add_development_dependency 'yard' s.files = Dir.glob('lib/**/*') + Dir.glob('config/**/*') + Dir.glob('bin/*') diff --git a/lib/dor/datastreams/content_metadata_ds.rb b/lib/dor/datastreams/content_metadata_ds.rb index 55c2bf4e..7bb326fc 100644 --- a/lib/dor/datastreams/content_metadata_ds.rb +++ b/lib/dor/datastreams/content_metadata_ds.rb @@ -46,6 +46,7 @@ def singular_node(xpath) len = node.length raise "#{xpath} not found" if len < 1 raise "#{xpath} duplicated: #{len} found" if len != 1 + node.first end @@ -132,18 +133,20 @@ def to_solr(solr_doc = {}, *args) def add_file(file, resource_name) resource_nodes = ng_xml.search('//resource[@id=\'' + resource_name + '\']') raise 'resource doesnt exist.' if resource_nodes.length == 0 + self.ng_xml_will_change! node = resource_nodes.first file_node = Nokogiri::XML::Node.new('file', ng_xml) file_node['id'] = file[:name] - file_node['shelve'] = file[:shelve] ? file[:shelve] : '' - file_node['publish'] = file[:publish] ? file[:publish] : '' - file_node['preserve'] = file[:preserve] ? file[:preserve] : '' + file_node['shelve'] = file[:shelve] || '' + file_node['publish'] = file[:publish] || '' + file_node['preserve'] = file[:preserve] || '' node.add_child(file_node) [:md5, :sha1].each do |algo| next unless file[algo] + checksum_node = Nokogiri::XML::Node.new('checksum', ng_xml) checksum_node['type'] = algo.to_s checksum_node.content = file[algo] @@ -187,6 +190,7 @@ def add_virtual_resource(child_druid, child_resource) # @return [Nokogiri::XML::Node] the new resource that was added to the contentMetadata def add_resource(files, resource_name, position, type = 'file') raise "resource #{resource_name} already exists" if ng_xml.search('//resource[@id=\'' + resource_name + '\']').length > 0 + self.ng_xml_will_change! max = ng_xml.search('//resource').map { |node| node['sequence'].to_i }.max # renumber all of the resources that will come after the newly added one @@ -201,12 +205,13 @@ def add_resource(files, resource_name, position, type = 'file') node['type'] = type files.each do |file| file_node = Nokogiri::XML::Node.new('file', ng_xml) - %w(shelve publish preserve).each { |x| file_node[x] = file[x.to_sym] ? file[x.to_sym] : '' } + %w(shelve publish preserve).each { |x| file_node[x] = file[x.to_sym] || '' } file_node['id'] = file[:name] node.add_child(file_node) [:md5, :sha1].each { |algo| next if file[algo].nil? + checksum_node = Nokogiri::XML::Node.new('checksum', ng_xml) checksum_node['type'] = algo.to_s checksum_node.content = file[algo] @@ -228,6 +233,7 @@ def remove_resource(resource_name) loop do res = ng_xml.search('//resource[@sequence=\'' + position.to_s + '\']') break if res.length == 0 + res['sequence'] = position.to_s position += 1 end @@ -262,6 +268,7 @@ def update_file(file, old_file_id) file_node['id'] = file[:name] [:md5, :sha1].each { |algo| next if file[algo].nil? + checksum_node = ng_xml.search('//file[@id=\'' + old_file_id + '\']/checksum[@type=\'' + algo.to_s + '\']').first if checksum_node.nil? checksum_node = Nokogiri::XML::Node.new('checksum', ng_xml) @@ -322,6 +329,7 @@ def move_resource(resource_name, new_position) position = node['sequence'].to_i new_position = new_position.to_i # tolerate strings as a Legacy behavior return node if position == new_position + # otherwise, is the resource being moved earlier in the sequence or later? up = new_position > position others = new_position..(up ? position - 1 : position + 1) # a range diff --git a/lib/dor/datastreams/datastream_spec_solrizer.rb b/lib/dor/datastreams/datastream_spec_solrizer.rb index a9fa78f7..f5376e82 100644 --- a/lib/dor/datastreams/datastream_spec_solrizer.rb +++ b/lib/dor/datastreams/datastream_spec_solrizer.rb @@ -7,8 +7,8 @@ module DatastreamSpecSolrizer def datastream_spec_string s = begin controlGroup == 'E' ? content.to_s.length : size - rescue - 0 + rescue + 0 end v = versionID.nil? ? '0' : versionID.to_s.split(/\./).last [dsid, controlGroup, mimeType, v, s, label].join('|') diff --git a/lib/dor/datastreams/default_object_rights_ds.rb b/lib/dor/datastreams/default_object_rights_ds.rb index c0daaf8a..ed83d825 100644 --- a/lib/dor/datastreams/default_object_rights_ds.rb +++ b/lib/dor/datastreams/default_object_rights_ds.rb @@ -84,6 +84,7 @@ def self.xml_template # Ensures that the template is present for the given term def initialize_term!(term) return unless find_by_terms(term).length < 1 + ng_xml_will_change! add_child_node(ng_xml.root, term) end diff --git a/lib/dor/datastreams/geo_metadata_ds.rb b/lib/dor/datastreams/geo_metadata_ds.rb index a6f10773..e821bf99 100644 --- a/lib/dor/datastreams/geo_metadata_ds.rb +++ b/lib/dor/datastreams/geo_metadata_ds.rb @@ -41,6 +41,7 @@ def metadata def feature_catalogue root = ng_xml.xpath('/rdf:RDF/rdf:Description/gfc:FC_FeatureCatalogue', XMLNS) return nil if root.nil? || root.empty? # Feature catalog is optional + Nokogiri::XML(root.first.to_xml) end diff --git a/lib/dor/datastreams/identity_metadata_ds.rb b/lib/dor/datastreams/identity_metadata_ds.rb index 81db3549..b7a34d4e 100644 --- a/lib/dor/datastreams/identity_metadata_ds.rb +++ b/lib/dor/datastreams/identity_metadata_ds.rb @@ -56,6 +56,7 @@ def sourceId=(value) parts = value.split(':', 2).map(&:strip) raise ArgumentError, "Source ID must follow the format 'namespace:value', not '#{value}'" unless parts.length == 2 && parts[0].present? && parts[1].present? + node ||= ng_xml.root.add_child('').first node['source'] = parts[0] node.content = parts[1] diff --git a/lib/dor/datastreams/version_metadata_ds.rb b/lib/dor/datastreams/version_metadata_ds.rb index 11f9bb70..ac5ab61c 100644 --- a/lib/dor/datastreams/version_metadata_ds.rb +++ b/lib/dor/datastreams/version_metadata_ds.rb @@ -9,14 +9,17 @@ class VersionTag def <=>(other) diff = @major <=> other.major return diff if diff != 0 + diff = @minor <=> other.minor return diff if diff != 0 + @admin <=> other.admin end # @param [String] raw_tag the value of the tag attribute from a Version node def self.parse(raw_tag) return nil unless raw_tag =~ /(\d+)\.(\d+)\.(\d+)/ + VersionTag.new $1, $2, $3 end @@ -125,6 +128,7 @@ def update_current_version(opts = {}) ng_xml.root['objectId'] = pid return if find_by_terms(:version).size == 1 return if opts.empty? + ng_xml_will_change! current = current_version_node if opts.include? :description @@ -189,6 +193,7 @@ def description_for_version(versionId) def current_description desc_node = current_version_node.at_xpath('description') return desc_node.content if desc_node + '' end diff --git a/lib/dor/datastreams/workflow_ds.rb b/lib/dor/datastreams/workflow_ds.rb index 43728ad3..13af66b2 100644 --- a/lib/dor/datastreams/workflow_ds.rb +++ b/lib/dor/datastreams/workflow_ds.rb @@ -22,6 +22,7 @@ def get_workflow(wf, repo = 'dor') xml = Dor::Config.workflow.client.get_workflow_xml(repo, pid, wf) xml = Nokogiri::XML(xml) return nil if xml.xpath('workflow').length == 0 + Workflow::Document.new(xml.to_s) end @@ -41,6 +42,7 @@ def content(refresh = false) xml = Nokogiri::XML(%(\n)) digital_object.datastreams.keys.each do |dsid| next unless dsid =~ /WF$/ + ds_content = Nokogiri::XML(Dor::Config.workflow.client.get_workflow_xml('dor', pid, dsid)) xml.root.add_child(ds_content.root) end @@ -57,6 +59,7 @@ def workflows def current_priority cp = workflows.detect(&:expedited?) return 0 if cp.nil? + cp.priority.to_i end diff --git a/lib/dor/indexers/identifiable_indexer.rb b/lib/dor/indexers/identifiable_indexer.rb index 923f32ac..2f05ab56 100644 --- a/lib/dor/indexers/identifiable_indexer.rb +++ b/lib/dor/indexers/identifiable_indexer.rb @@ -64,6 +64,7 @@ def solrize_related_obj_titles(solr_doc, relationships, title_hash, union_field_ relationships.each do |rel_node| rel_druid = rel_node['rdf:resource'] next unless rel_druid # TODO: warning here would also be useful + rel_druid = rel_druid.gsub('info:fedora/', '') # populate cache if necessary diff --git a/lib/dor/models/concerns/contentable.rb b/lib/dor/models/concerns/contentable.rb index d2312f8a..290d0217 100644 --- a/lib/dor/models/concerns/contentable.rb +++ b/lib/dor/models/concerns/contentable.rb @@ -9,6 +9,7 @@ def add_file(file, resource, file_name, mime_type = nil, publish = 'no', shelve xml = datastreams['contentMetadata'].ng_xml # make sure the resource exists raise 'resource doesnt exist.' if xml.search('//resource[@id=\'' + resource + '\']').length == 0 + sftp = Net::SFTP.start(Config.content.content_server, Config.content.content_user, :auth_methods => ['publickey']) druid_tools = DruidTools::Druid.new(pid, Config.content.content_base_dir) location = druid_tools.path(file_name) diff --git a/lib/dor/models/concerns/describable.rb b/lib/dor/models/concerns/describable.rb index 314724fd..456e5a38 100644 --- a/lib/dor/models/concerns/describable.rb +++ b/lib/dor/models/concerns/describable.rb @@ -37,6 +37,7 @@ def fetch_descMetadata_datastream def build_descMetadata_datastream(ds) content = fetch_descMetadata_datastream return nil if content.nil? + ds.dsLabel = 'Descriptive Metadata' ds.ng_xml = Nokogiri::XML(content) ds.ng_xml.normalize_text! @@ -58,6 +59,7 @@ def generate_dublin_core(include_collection_as_related_item: true) dc_doc.xpath('/oai_dc:dc/*[count(text()) = 0]', oai_dc: XMLNS_OAI_DC).remove # Remove empty nodes raise CrosswalkError, "Dor::Item#generate_dublin_core produced incorrect xml (no root):\n#{dc_doc.to_xml}" if dc_doc.root.nil? raise CrosswalkError, "Dor::Item#generate_dublin_core produced incorrect xml (no children):\n#{dc_doc.to_xml}" if dc_doc.root.children.size == 0 + dc_doc end @@ -72,6 +74,7 @@ def set_desc_metadata_using_label(force = false) unless force || descMetadata.new? raise 'Cannot proceed, there is already content in the descriptive metadata datastream: ' + descMetadata.content.to_s end + label = self.label builder = Nokogiri::XML::Builder.new { |xml| xml.mods(Dor::DescMetadataDS::MODS_HEADER_CONFIG) { diff --git a/lib/dor/models/concerns/editable.rb b/lib/dor/models/concerns/editable.rb index 1657e689..72366ec2 100644 --- a/lib/dor/models/concerns/editable.rb +++ b/lib/dor/models/concerns/editable.rb @@ -20,29 +20,29 @@ module Editable # TODO: need some way to do versioning. for instance, what happens when a new version of an existing license comes # out, since it will presumably use the same license code, but a different title and URI? CREATIVE_COMMONS_USE_LICENSES = { - 'by' => { :human_readable => 'Attribution 3.0 Unported', - :uri => 'https://creativecommons.org/licenses/by/3.0/' }, - 'by-sa' => { :human_readable => 'Attribution Share Alike 3.0 Unported', - :uri => 'https://creativecommons.org/licenses/by-sa/3.0/' }, - 'by_sa' => { :human_readable => 'Attribution Share Alike 3.0 Unported', - :uri => 'https://creativecommons.org/licenses/by-sa/3.0/', - :deprecation_warning => 'license code "by_sa" was a typo in argo, prefer "by-sa"' }, - 'by-nd' => { :human_readable => 'Attribution No Derivatives 3.0 Unported', - :uri => 'https://creativecommons.org/licenses/by-nd/3.0/' }, - 'by-nc' => { :human_readable => 'Attribution Non-Commercial 3.0 Unported', - :uri => 'https://creativecommons.org/licenses/by-nc/3.0/' }, + 'by' => { :human_readable => 'Attribution 3.0 Unported', + :uri => 'https://creativecommons.org/licenses/by/3.0/' }, + 'by-sa' => { :human_readable => 'Attribution Share Alike 3.0 Unported', + :uri => 'https://creativecommons.org/licenses/by-sa/3.0/' }, + 'by_sa' => { :human_readable => 'Attribution Share Alike 3.0 Unported', + :uri => 'https://creativecommons.org/licenses/by-sa/3.0/', + :deprecation_warning => 'license code "by_sa" was a typo in argo, prefer "by-sa"' }, + 'by-nd' => { :human_readable => 'Attribution No Derivatives 3.0 Unported', + :uri => 'https://creativecommons.org/licenses/by-nd/3.0/' }, + 'by-nc' => { :human_readable => 'Attribution Non-Commercial 3.0 Unported', + :uri => 'https://creativecommons.org/licenses/by-nc/3.0/' }, 'by-nc-sa' => { :human_readable => 'Attribution Non-Commercial Share Alike 3.0 Unported', :uri => 'https://creativecommons.org/licenses/by-nc-sa/3.0/' }, 'by-nc-nd' => { :human_readable => 'Attribution Non-Commercial, No Derivatives 3.0 Unported', :uri => 'https://creativecommons.org/licenses/by-nc-nd/3.0/' }, - 'pdm' => { :human_readable => 'Public Domain Mark 1.0', - :uri => 'https://creativecommons.org/publicdomain/mark/1.0/' } + 'pdm' => { :human_readable => 'Public Domain Mark 1.0', + :uri => 'https://creativecommons.org/publicdomain/mark/1.0/' } }.freeze OPEN_DATA_COMMONS_USE_LICENSES = { - 'pddl' => { :human_readable => 'Open Data Commons Public Domain Dedication and License 1.0', - :uri => 'http://opendatacommons.org/licenses/pddl/1.0/' }, - 'odc-by' => { :human_readable => 'Open Data Commons Attribution License 1.0', - :uri => 'http://opendatacommons.org/licenses/by/1.0/' }, + 'pddl' => { :human_readable => 'Open Data Commons Public Domain Dedication and License 1.0', + :uri => 'http://opendatacommons.org/licenses/pddl/1.0/' }, + 'odc-by' => { :human_readable => 'Open Data Commons Attribution License 1.0', + :uri => 'http://opendatacommons.org/licenses/by/1.0/' }, 'odc-odbl' => { :human_readable => 'Open Data Commons Open Database License 1.0', :uri => 'http://opendatacommons.org/licenses/odbl/1.0/' } }.freeze @@ -179,18 +179,21 @@ def open_data_commons_license_human def use_license return creative_commons_license unless creative_commons_license.blank? return open_data_commons_license unless open_data_commons_license.blank? + nil end def use_license_uri return defaultObjectRights.creative_commons.uri.first unless defaultObjectRights.creative_commons.uri.blank? return defaultObjectRights.open_data_commons.uri.first unless defaultObjectRights.open_data_commons.uri.blank? + nil end def use_license_human return creative_commons_license_human unless creative_commons_license_human.blank? return open_data_commons_license_human unless open_data_commons_license_human.blank? + nil end @@ -321,6 +324,7 @@ def default_workflows # @param wf [String] the name of the workflow, ex. 'digitizationWF' def default_workflow=(wf) fail ArgumentError, 'Must have a valid workflow for default' if wf.blank? + xml = administrativeMetadata.ng_xml administrativeMetadata.ng_xml_will_change! nodes = xml.search('//registration/workflow') @@ -345,6 +349,7 @@ def agreement def agreement=(val) fail ArgumentError, 'agreement must have a valid druid' if val.blank? + self.agreement_object = Dor.find val.to_s, :cast => true end end diff --git a/lib/dor/models/concerns/embargoable.rb b/lib/dor/models/concerns/embargoable.rb index d6546ee3..9aff61fa 100644 --- a/lib/dor/models/concerns/embargoable.rb +++ b/lib/dor/models/concerns/embargoable.rb @@ -70,6 +70,7 @@ def update_embargo(new_date) if new_date.past? raise ArgumentError, 'You cannot set the embargo date to a past date.' end + updated = false rightsMetadata.ng_xml.search('//embargoReleaseDate').each do |node| node.content = new_date.beginning_of_day.utc.xmlschema @@ -78,6 +79,7 @@ def update_embargo(new_date) rightsMetadata.ng_xml_will_change! rightsMetadata.save raise 'No release date in rights metadata, cannot proceed!' unless updated + embargoMetadata.ng_xml.xpath('//releaseDate').each do |node| node.content = new_date.beginning_of_day.utc.xmlschema end diff --git a/lib/dor/models/concerns/governable.rb b/lib/dor/models/concerns/governable.rb index bca48b17..6d45b919 100644 --- a/lib/dor/models/concerns/governable.rb +++ b/lib/dor/models/concerns/governable.rb @@ -25,6 +25,7 @@ def default_workflow_lane lane = admin_md.default_workflow_lane return 'default' if lane.blank? + lane end @@ -83,8 +84,10 @@ def reapplyAdminPolicyObjectDefaults def rights return nil unless self.respond_to? :rightsMetadata return nil if rightsMetadata.nil? + xml = rightsMetadata.ng_xml return nil if xml.search('//rightsMetadata').length != 1 # ORLY? + if xml.search('//rightsMetadata/access[@type=\'read\']/machine/group').length == 1 'Stanford' elsif xml.search('//rightsMetadata/access[@type=\'read\']/machine/world').length == 1 diff --git a/lib/dor/models/concerns/identifiable.rb b/lib/dor/models/concerns/identifiable.rb index 19e09f19..e56b7644 100644 --- a/lib/dor/models/concerns/identifiable.rb +++ b/lib/dor/models/concerns/identifiable.rb @@ -24,6 +24,7 @@ def has_object_type(str) # than the default Fedora sequence def assign_pid(_obj) return Dor::SuriService.mint_id if Dor::Config.suri.mint_ids + super end end @@ -89,6 +90,7 @@ def add_other_Id(type, val) if identityMetadata.otherId(type).length > 0 raise 'There is an existing entry for ' + type + ', consider using update_other_Id().' end + identityMetadata.add_otherId(type + ':' + val) end @@ -137,6 +139,7 @@ def validate_and_normalize_tag(tag_str, existing_tag_list) if dupe_existing_tag raise "An existing tag (#{dupe_existing_tag}) is the same, consider using update_tag?" end + normalized_tag end @@ -151,6 +154,7 @@ def validate_tag_format(tag_str) if tag_arr.detect { |str| str.empty? } raise ArgumentError, "Invalid tag structure: tag '#{tag_str}' contains empty elements" end + tag_arr end diff --git a/lib/dor/models/concerns/itemizable.rb b/lib/dor/models/concerns/itemizable.rb index 617f0ad8..5b83ebe6 100644 --- a/lib/dor/models/concerns/itemizable.rb +++ b/lib/dor/models/concerns/itemizable.rb @@ -18,6 +18,7 @@ def clear_diff_cache if Dor::Config.stacks.local_workspace_root.nil? raise ArgumentError, 'Missing Dor::Config.stacks.local_workspace_root' end + druid = DruidTools::Druid.new(pid, Dor::Config.stacks.local_workspace_root) diff_pattern = File.join(druid.temp_dir, DIFF_FILENAME + '.*') FileUtils.rm_f Dir.glob(diff_pattern) diff --git a/lib/dor/models/concerns/processable.rb b/lib/dor/models/concerns/processable.rb index 2d42b259..78d65e8b 100644 --- a/lib/dor/models/concerns/processable.rb +++ b/lib/dor/models/concerns/processable.rb @@ -27,15 +27,15 @@ module Processable # milestones from accessioning and the order they happen in STEPS = { - 'registered' => 1, - 'submitted' => 2, - 'described' => 3, - 'published' => 4, - 'deposited' => 5, + 'registered' => 1, + 'submitted' => 2, + 'described' => 3, + 'published' => 4, + 'deposited' => 5, 'accessioned' => 6, - 'indexed' => 7, - 'shelved' => 8, - 'opened' => 9 + 'indexed' => 7, + 'shelved' => 8, + 'opened' => 9 }.freeze # This is a work-around for some strange logic in ActiveFedora that @@ -44,12 +44,14 @@ module Processable def set_workflows_datastream_location return if self.respond_to?(:inner_object) && inner_object.is_a?(ActiveFedora::SolrDigitalObject) return unless workflows.new? + workflows.mimeType = 'application/xml' workflows.dsLocation = File.join(Dor::Config.workflow.url, "dor/objects/#{pid}/workflows") end def empty_datastream?(datastream) return true if datastream.new? + if datastream.class.respond_to?(:xml_template) datastream.content.to_s.empty? || EquivalentXml.equivalent?(datastream.content, datastream.class.xml_template) else @@ -92,6 +94,7 @@ def build_datastream(datastream, force = false, is_required = false) end # Check for success. raise "Required datastream #{datastream} could not be populated!" if is_required && empty_datastream?(ds) + ds end @@ -127,6 +130,7 @@ def status_info m_name = m[:milestone] m_time = m[:at].utc.xmlschema next unless STEPS.keys.include?(m_name) && (!status_time || m_time > status_time) + status_code = STEPS[m_name] status_time = m_time end diff --git a/lib/dor/models/concerns/publishable.rb b/lib/dor/models/concerns/publishable.rb index 681aca9e..08e2c51e 100644 --- a/lib/dor/models/concerns/publishable.rb +++ b/lib/dor/models/concerns/publishable.rb @@ -22,6 +22,7 @@ def thumb def encoded_thumb thumb_image = thumb # store the result locally, so we don't have to compute each time we use it below return unless thumb_image + thumb_druid = thumb_image.split('/').first # the druid (before the first slash) thumb_filename = thumb_image.split(/#{pid_regex}[\/]/).last # everything after the druid "#{thumb_druid}%2F#{ERB::Util.url_encode(thumb_filename)}" @@ -32,6 +33,7 @@ def encoded_thumb # @return [String] fully qualified image URL for the computed thumbnail, e.g. https://stacks.stanford.edu/image/iiif/oo000oo0001%2Ffilenamewith%20space/full def thumb_url return unless encoded_thumb + thumb_basename = File.basename(encoded_thumb, File.extname(encoded_thumb)) # strip the extension for URL generation "https://#{Dor::Config.stacks.host}/image/iiif/#{thumb_basename}/full/!400,400/0/default.jpg" end @@ -113,6 +115,7 @@ def publish_notify_on_success # When publishing a PURL, we notify purl-fetcher of changes. def publish_delete_on_success return unless Dor::Config.purl_services.url + id = pid.gsub(/^druid:/, '') purl_services = Dor::Config.purl_services.rest_client diff --git a/lib/dor/models/concerns/releaseable.rb b/lib/dor/models/concerns/releaseable.rb index ac5a7052..49a0d53a 100644 --- a/lib/dor/models/concerns/releaseable.rb +++ b/lib/dor/models/concerns/releaseable.rb @@ -47,6 +47,7 @@ def released_for(skip_live_purl = false) (potential_applicable_release_tags.keys - released_hash.keys).each do |key| # don't bother checking if already added to the release hash, they were added due to a self tag so that has won latest_tag = latest_applicable_release_tag_in_array(potential_applicable_release_tags[key], administrative_tags) next if latest_tag.nil? # Otherwise, we have a valid tag, record it + released_hash[key] = { 'release' => latest_tag['release'] } end @@ -68,6 +69,7 @@ def get_release_tags_for_item_and_all_governing_sets return_tags = release_nodes || {} collections.each do |collection| next if collection.id == id # recursive, so parents of parents are found, but we need to avoid an infinite loop if the collection references itself (i.e. bad data) + return_tags = combine_two_release_tag_hashes(return_tags, collection.get_release_tags_for_item_and_all_governing_sets) end return_tags @@ -123,6 +125,7 @@ def newest_release_tag_in_an_array(array_of_tags) def does_release_tag_apply(release_tag, admin_tags = false) # Is the tag global or restricted return true if release_tag['tag'].nil? # no specific tag specificied means this tag is global to all members of the collection + admin_tags = tags unless admin_tags # We use false instead of [], since an item can have no admin_tags at which point we'd be passing this var as [] and would not attempt to retrieve it admin_tags.include?(release_tag['tag']) end @@ -140,6 +143,7 @@ def latest_applicable_release_tag_in_array(release_tags, admin_tags) release_tags.slice!(release_tags.index(newest_tag)) return latest_applicable_release_tag_in_array(release_tags, admin_tags) if release_tags.size > 0 # Try again after dropping the inapplicable + nil # We're out of tags, no applicable ones end @@ -188,6 +192,7 @@ def release_tag_node_to_hash(rtag) # @return [Boolean] Returns true if no errors found def valid_release_attributes_and_tag(tag, attrs = {}) raise ArgumentError, ':when is not iso8601' if attrs[:when].match('\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z').nil? + [:who, :to, :what].each do |check_attr| raise ArgumentError, "#{check_attr} not supplied as a String" if attrs[check_attr].class != String end @@ -198,6 +203,7 @@ def valid_release_attributes_and_tag(tag, attrs = {}) end raise ArgumentError, ':what must be self or collection' unless what_correct raise ArgumentError, 'the value set for this tag is not a boolean' if !!tag != tag # rubocop:disable Style/DoubleNegation + true end @@ -229,11 +235,13 @@ def add_release_node(release, attrs = {}) # @return [Boolean] Returns true if no errors found def valid_release_attributes(tag, attrs = {}) raise ArgumentError, ':when is not iso8601' if attrs[:when].match('\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z').nil? + [:who, :to, :what].each do |check_attr| raise ArgumentError, "#{check_attr} not supplied as a String" if attrs[check_attr].class != String end raise ArgumentError, ':what must be self or collection' unless %w(self collection).include? attrs[:what] raise ArgumentError, 'the value set for this tag is not a boolean' unless [true, false].include? tag + true end diff --git a/lib/dor/models/concerns/shelvable.rb b/lib/dor/models/concerns/shelvable.rb index fe305bd5..27a44839 100644 --- a/lib/dor/models/concerns/shelvable.rb +++ b/lib/dor/models/concerns/shelvable.rb @@ -39,6 +39,7 @@ def workspace_content_dir(content_diff, workspace_druid) deltas = content_diff.file_deltas filelist = deltas[:modified] + deltas[:added] + deltas[:copyadded].collect { |old, new| new } return nil if filelist.empty? + content_pathname = Pathname(workspace_druid.find_filelist_parent('content', filelist)) content_pathname end @@ -50,6 +51,7 @@ def get_stacks_location unless contentMetadataDS.nil? || contentMetadataDS.stacks.length == 0 stacks_location = contentMetadataDS.stacks[0] return stacks_location if stacks_location.start_with? '/' # Absolute stacks path + raise 'stacks attribute for item: ' + id + ' contentMetadata should start with /. The current value is ' + stacks_location end Config.stacks.local_stacks_root # Default stacks diff --git a/lib/dor/models/concerns/versionable.rb b/lib/dor/models/concerns/versionable.rb index 3037ba73..ed1fe58e 100644 --- a/lib/dor/models/concerns/versionable.rb +++ b/lib/dor/models/concerns/versionable.rb @@ -37,6 +37,7 @@ def open_new_version(opts = {}) vmd_upd_info = opts[:vers_md_upd_info] return unless vmd_upd_info + add_event('open', vmd_upd_info[:opening_user_name], "Version #{vmd_ds.current_version_id} opened") vmd_ds.update_current_version({ :description => vmd_upd_info[:description], :significance => vmd_upd_info[:significance].to_sym }) save @@ -71,6 +72,7 @@ def close_version(opts = {}) # @return [Boolean] true if 'opened' lifecycle is active, false otherwise def new_version_open? return true if Dor::Config.workflow.client.get_active_lifecycle('dor', pid, 'opened') + false end diff --git a/lib/dor/models/workflow_object.rb b/lib/dor/models/workflow_object.rb index e189d7d3..bec1d3d8 100644 --- a/lib/dor/models/workflow_object.rb +++ b/lib/dor/models/workflow_object.rb @@ -28,6 +28,7 @@ def self.find_by_name(name) # @return [String] the initial workflow xml def self.initial_workflow(name) return @@xml_cache[name] if @@xml_cache.include?(name) + find_and_cache_workflow_xml_and_repo name @@xml_cache[name] end @@ -38,6 +39,7 @@ def self.initial_workflow(name) # @return [String] the initial workflow xml def self.initial_repo(name) return @@repo_cache[name] if @@repo_cache.include?(name) + find_and_cache_workflow_xml_and_repo name @@repo_cache[name] end @@ -59,6 +61,7 @@ def generate_initial_workflow def self.find_and_cache_workflow_xml_and_repo(name) wobj = find_by_name(name) raise "Failed to find workflow via find_by_name('#{name}')" if wobj.nil? + @@repo_cache[name] = wobj.definition.repo @@xml_cache[name] = wobj.generate_initial_workflow wobj diff --git a/lib/dor/services/digital_stacks_service.rb b/lib/dor/services/digital_stacks_service.rb index 157a8ce8..6bce9715 100644 --- a/lib/dor/services/digital_stacks_service.rb +++ b/lib/dor/services/digital_stacks_service.rb @@ -81,6 +81,7 @@ def self.rename_file(old_pathname, new_pathname, moab_signature) # @param [Moab::FileGroupDifference] content_diff the content file version differences report def self.shelve_to_stacks(workspace_content_pathname, stacks_object_pathname, content_diff) return false if workspace_content_pathname.nil? + [:added, :copyadded, :modified].each do |change_type| subset = content_diff.subset(change_type) # {Moab::FileGroupDifferenceSubset subset.files.each do |moab_file| # {Moab::FileInstanceDifference} diff --git a/lib/dor/services/merge_service.rb b/lib/dor/services/merge_service.rb index 9db614d0..c9ae7ae5 100644 --- a/lib/dor/services/merge_service.rb +++ b/lib/dor/services/merge_service.rb @@ -25,6 +25,7 @@ def initialize(primary_druid, secondary_pids, tag, logger = nil) def check_objects_editable raise Dor::Exception, "Primary object is not editable: #{@primary.pid}" unless @primary.allows_modification? + non_editable = @secondary_objs.detect { |obj| !obj.allows_modification? } raise Dor::Exception, "Secondary object is not editable: #{non_editable.pid}" if non_editable end diff --git a/lib/dor/services/metadata_service.rb b/lib/dor/services/metadata_service.rb index 43bda7a4..4b93f1c2 100644 --- a/lib/dor/services/metadata_service.rb +++ b/lib/dor/services/metadata_service.rb @@ -65,6 +65,7 @@ def label_for(identifier) def handler_for(prefix) handler = handlers[prefix.to_sym] raise MetadataError, "Unkown metadata prefix: #{prefix}" if handler.nil? + handler end diff --git a/lib/dor/services/public_desc_metadata_service.rb b/lib/dor/services/public_desc_metadata_service.rb index 9ec6c662..cdf2f85a 100644 --- a/lib/dor/services/public_desc_metadata_service.rb +++ b/lib/dor/services/public_desc_metadata_service.rb @@ -43,24 +43,30 @@ def add_access_conditions! rights.xpath('//use/human[@type="useAndReproduction"]').each do |use| txt = use.text.strip next if txt.empty? + doc.root.element_children.last.add_next_sibling doc.create_element('accessCondition', txt, :type => 'useAndReproduction') end rights.xpath('//copyright/human[@type="copyright"]').each do |cr| txt = cr.text.strip next if txt.empty? + doc.root.element_children.last.add_next_sibling doc.create_element('accessCondition', txt, :type => 'copyright') end rights.xpath("//use/machine[#{ci_compare('type', 'creativecommons')}]").each do |lic_type| next if lic_type.text =~ /none/i + lic_text = rights.at_xpath("//use/human[#{ci_compare('type', 'creativecommons')}]").text.strip next if lic_text.empty? + new_text = "CC #{lic_type.text}: #{lic_text}" doc.root.element_children.last.add_next_sibling doc.create_element('accessCondition', new_text, :type => 'license') end rights.xpath("//use/machine[#{ci_compare('type', 'opendatacommons')}]").each do |lic_type| next if lic_type.text =~ /none/i + lic_text = rights.at_xpath("//use/human[#{ci_compare('type', 'opendatacommons')}]").text.strip next if lic_text.empty? + new_text = "ODC #{lic_type.text}: #{lic_text}" doc.root.element_children.last.add_next_sibling doc.create_element('accessCondition', new_text, :type => 'license') end diff --git a/lib/dor/services/public_xml_service.rb b/lib/dor/services/public_xml_service.rb index c6fda80f..3f292369 100644 --- a/lib/dor/services/public_xml_service.rb +++ b/lib/dor/services/public_xml_service.rb @@ -67,6 +67,7 @@ def public_identity_metadata # @return [Nokogiri::XML::Document] sanitized for public consumption def public_content_metadata return Nokogiri::XML::Document.new unless object.datastreams['contentMetadata'] + @public_content_metadata ||= begin result = object.datastreams['contentMetadata'].ng_xml.clone diff --git a/lib/dor/services/registration_service.rb b/lib/dor/services/registration_service.rb index d200f58c..6be7d3ee 100644 --- a/lib/dor/services/registration_service.rb +++ b/lib/dor/services/registration_service.rb @@ -13,10 +13,12 @@ class << self # @raise [Dor::DuplicateIdError] def unduplicated_pid(pid = nil) return Dor::SuriService.mint_id unless pid + existing_pid = SearchService.query_by_id(pid).first unless existing_pid.nil? raise Dor::DuplicateIdError.new(existing_pid), "An object with the PID #{pid} has already been registered." end + pid end @@ -28,6 +30,7 @@ def check_source_id(source_id_string) unless SearchService.query_by_id("#{source_id_string}").first.nil? raise Dor::DuplicateIdError.new(source_id_string), "An object with the source ID '#{source_id_string}' has already been registered." end + source_id_string end @@ -50,9 +53,10 @@ def register_object(params = {}) raise Dor::ParameterError, "#{required_param.inspect} must be specified in call to #{name}.register_object" unless params[required_param] end metadata_source = params[:metadata_source] - if params[:label].length < 1 && (metadata_source == 'label' || metadata_source == 'none') + if params[:label].length < 1 && %w[label none].include?(metadata_source) raise Dor::ParameterError, "label cannot be empty to call #{name}.register_object" end + object_type = params[:object_type] item_class = Dor.registered_classes[object_type] raise Dor::ParameterError, "Unknown item type: '#{object_type}'" if item_class.nil? @@ -157,21 +161,21 @@ def create_from_request(params) end dor_params = { - :pid => params[:pid], - :admin_policy => params[:admin_policy], - :content_model => params[:model], - :label => params[:label], - :object_type => params[:object_type], - :other_ids => ids_to_hash(other_ids), - :parent => params[:parent], - :source_id => ids_to_hash(params[:source_id]), - :tags => params[:tag] || [], - :seed_datastream => params[:seed_datastream], - :initiate_workflow => Array(params[:initiate_workflow]) + Array(params[:workflow_id]), - :rights => params[:rights], - :metadata_source => params[:metadata_source], - :collection => params[:collection], - :workflow_priority => params[:workflow_priority] + :pid => params[:pid], + :admin_policy => params[:admin_policy], + :content_model => params[:model], + :label => params[:label], + :object_type => params[:object_type], + :other_ids => ids_to_hash(other_ids), + :parent => params[:parent], + :source_id => ids_to_hash(params[:source_id]), + :tags => params[:tag] || [], + :seed_datastream => params[:seed_datastream], + :initiate_workflow => Array(params[:initiate_workflow]) + Array(params[:workflow_id]), + :rights => params[:rights], + :metadata_source => params[:metadata_source], + :collection => params[:collection], + :workflow_priority => params[:workflow_priority] } dor_params.delete_if { |k, v| v.nil? } @@ -185,6 +189,7 @@ def create_from_request(params) def ids_to_hash(ids) return nil if ids.nil? + Hash[Array(ids).map { |id| id.split(':', 2) }] end end diff --git a/lib/dor/services/sdr_ingest_service.rb b/lib/dor/services/sdr_ingest_service.rb index cc3f3eed..cc8705a9 100644 --- a/lib/dor/services/sdr_ingest_service.rb +++ b/lib/dor/services/sdr_ingest_service.rb @@ -96,6 +96,7 @@ def self.verify_version_metadata(metadata_dir, expected) # @param [Integer] found The version number that is actually in the file def self.verify_version_id(pathname, expected, found) raise "Version mismatch in #{pathname}, expected #{expected}, found #{found}" unless expected == found + true end @@ -166,6 +167,7 @@ def self.verify_bag_structure(bag_dir) # @return [Boolean] true if file exists, raises exception if not def self.verify_pathname(pathname) raise "#{pathname.basename} not found at #{pathname}" unless pathname.exist? + true end end diff --git a/lib/dor/services/search_service.rb b/lib/dor/services/search_service.rb index 13b40475..e2dda142 100644 --- a/lib/dor/services/search_service.rb +++ b/lib/dor/services/search_service.rb @@ -17,12 +17,12 @@ def risearch(query, opts = {}) client = Config.fedora.client['risearch'] client.options[:timeout] = opts.delete(:timeout) query_params = { - :type => 'tuples', - :lang => 'itql', + :type => 'tuples', + :lang => 'itql', :format => 'CSV', - :limit => '1000', + :limit => '1000', :stream => 'on', - :query => query + :query => query }.merge(opts) result = client.post(query_params) result.split(/\n/)[1..-1].collect { |pid| pid.chomp.sub(/^info:fedora\//, '') } @@ -50,6 +50,7 @@ def query(query, args = {}) params[:start] ||= 0 resp = solr.get 'select', params: params return resp unless block_given? + cont = true while cont && resp['response']['docs'].length > 0 cont = yield(resp) diff --git a/lib/dor/services/technical_metadata_service.rb b/lib/dor/services/technical_metadata_service.rb index 3a612bd4..438a19fb 100644 --- a/lib/dor/services/technical_metadata_service.rb +++ b/lib/dor/services/technical_metadata_service.rb @@ -72,6 +72,7 @@ def self.get_new_files(deltas) def self.get_old_technical_metadata(dor_item) sdr_techmd = get_sdr_technical_metadata(dor_item.pid) return sdr_techmd unless sdr_techmd.nil? + get_dor_technical_metadata(dor_item) end @@ -82,6 +83,7 @@ def self.get_sdr_technical_metadata(druid) sdr_techmd = get_sdr_metadata(druid, 'technicalMetadata') return sdr_techmd if sdr_techmd =~ / - EOC + EOC def prettify PRETTIFY_XSLT.transform(self).to_xml diff --git a/lib/dor/utils/sdr_client.rb b/lib/dor/utils/sdr_client.rb index 912a7827..7e889c91 100644 --- a/lib/dor/utils/sdr_client.rb +++ b/lib/dor/utils/sdr_client.rb @@ -12,6 +12,7 @@ def current_version(druid) begin doc = Nokogiri::XML xml raise if doc.root.name != 'currentVersion' + return Integer(doc.text) rescue raise "Unable to parse XML from SDR current_version API call: #{xml}" diff --git a/lib/dor/workflow/document.rb b/lib/dor/workflow/document.rb index 110c874f..29ab995e 100644 --- a/lib/dor/workflow/document.rb +++ b/lib/dor/workflow/document.rb @@ -63,6 +63,7 @@ def [](value) def processes # if the workflow service didnt return any processes, dont return any processes from the reified wf return [] if ng_xml.search('/workflow/process').length == 0 + @processes ||= if definition definition.processes.collect do |process| @@ -95,6 +96,7 @@ def to_solr(solr_doc = {}, *args) processes.each do |process| next unless process.status.present? + # add a record of the robot having operated on this item, so we can track robot activity if !process.date_time.blank? && process.status && (process.status == 'completed' || process.status == 'error') solr_doc["wf_#{wf_name}_#{process.name}_dttsi"] = Time.parse(process.date_time).utc.iso8601 @@ -109,6 +111,7 @@ def to_solr(solr_doc = {}, *args) add_solr_value(solr_doc, 'wf_swp', "#{process.status}:#{wf_name}", wf_solr_type, wf_solr_attrs) add_solr_value(solr_doc, 'wf_swp', "#{process.status}:#{wf_name}:#{process.name}", wf_solr_type, wf_solr_attrs) next unless process.state != process.status + add_solr_value(solr_doc, 'wf_wsp', "#{wf_name}:#{process.state}:#{process.name}", wf_solr_type, wf_solr_attrs) add_solr_value(solr_doc, 'wf_wps', "#{wf_name}:#{process.name}:#{process.state}", wf_solr_type, wf_solr_attrs) add_solr_value(solr_doc, 'wf_swp', "#{process.state}", wf_solr_type, wf_solr_attrs) diff --git a/lib/dor/workflow/process.rb b/lib/dor/workflow/process.rb index 55d970e6..b4fb5618 100644 --- a/lib/dor/workflow/process.rb +++ b/lib/dor/workflow/process.rb @@ -20,14 +20,14 @@ def initialize(repo, workflow, attrs) def init_from_node(node) @attrs = { - 'name' => node['name'], - 'sequence' => node['sequence'] ? node['sequence'].to_i : nil, - 'status' => node['status'], # TODO: see how this affects argo - 'lifecycle' => node['lifecycle'], - 'label' => node.at_xpath('label/text()').to_s, - 'batch_limit' => node['batch-limit'] ? node['batch-limit'].to_i : nil, - 'error_limit' => node['error-limit'] ? node['error-limit'].to_i : nil, - 'priority' => node['priority'] ? node['priority'].to_i : 0, + 'name' => node['name'], + 'sequence' => node['sequence'] ? node['sequence'].to_i : nil, + 'status' => node['status'], # TODO: see how this affects argo + 'lifecycle' => node['lifecycle'], + 'label' => node.at_xpath('label/text()').to_s, + 'batch_limit' => node['batch-limit'] ? node['batch-limit'].to_i : nil, + 'error_limit' => node['error-limit'] ? node['error-limit'].to_i : nil, + 'priority' => node['priority'] ? node['priority'].to_i : 0, 'prerequisite' => node.xpath('prereq').collect { |p| repo = (p['repository'].nil? || p['repository'] == @repo) ? nil : p['repository'] wf = (p['workflow'].nil? || p['workflow'] == @workflow) ? nil : p['workflow'] @@ -92,6 +92,7 @@ def elapsed # @param new_owner [Dor::Workflow::Document] def update!(info, new_owner) raise ArgumentError, 'Owner can not be nil. It must be an instance of Dor::Workflow::Document' unless new_owner + @owner = new_owner return self if info.nil? diff --git a/spec/datastreams/content_metadata_ds_spec.rb b/spec/datastreams/content_metadata_ds_spec.rb index cebd964d..c0d6318a 100644 --- a/spec/datastreams/content_metadata_ds_spec.rb +++ b/spec/datastreams/content_metadata_ds_spec.rb @@ -30,11 +30,11 @@ ' allow(Dor).to receive(:find).and_return(@item) @file = { - :name => 'new_file.jp2', - :shelve => 'no', - :publish => 'no', + :name => 'new_file.jp2', + :shelve => 'no', + :publish => 'no', :preserve => 'no', - :size => '12345' + :size => '12345' } @files = [@file] @cm = @item.contentMetadata @@ -215,16 +215,16 @@ end it 'should generate required fields' do expected = { - 'content_type_ssim' => 'map', - 'content_file_mimetypes_ssim' => ['image/jp2', 'image/gif', 'image/tiff'], - 'content_file_roles_ssim' => ['derivative'], + 'content_type_ssim' => 'map', + 'content_file_mimetypes_ssim' => ['image/jp2', 'image/gif', 'image/tiff'], + 'content_file_roles_ssim' => ['derivative'], 'shelved_content_file_count_itsi' => 1, - 'resource_count_itsi' => 1, - 'content_file_count_itsi' => 3, - 'image_resource_count_itsi' => 1, - 'first_shelved_image_ss' => 'gw177fc7976_05_0001.jp2', - 'preserved_size_dbtsi' => 86774303, - 'shelved_size_dbtsi' => 5143883 + 'resource_count_itsi' => 1, + 'content_file_count_itsi' => 3, + 'image_resource_count_itsi' => 1, + 'first_shelved_image_ss' => 'gw177fc7976_05_0001.jp2', + 'preserved_size_dbtsi' => 86774303, + 'shelved_size_dbtsi' => 5143883 } expect(@doc).to include expected diff --git a/spec/datastreams/default_object_rights_ds_spec.rb b/spec/datastreams/default_object_rights_ds_spec.rb index 24960450..f6922418 100644 --- a/spec/datastreams/default_object_rights_ds_spec.rb +++ b/spec/datastreams/default_object_rights_ds_spec.rb @@ -26,7 +26,7 @@ -XML + XML end it 'understands terms of a rightsMetadata and will normalize the text' do diff --git a/spec/datastreams/embargo_metadata_spec.rb b/spec/datastreams/embargo_metadata_spec.rb index 53f1dbff..39bd4361 100644 --- a/spec/datastreams/embargo_metadata_spec.rb +++ b/spec/datastreams/embargo_metadata_spec.rb @@ -29,7 +29,7 @@ - EOF + EOF } it 'creates itself from xml' do diff --git a/spec/datastreams/rights_metadata_spec.rb b/spec/datastreams/rights_metadata_spec.rb index c6b7e546..7fc9db47 100644 --- a/spec/datastreams/rights_metadata_spec.rb +++ b/spec/datastreams/rights_metadata_spec.rb @@ -341,12 +341,12 @@ doc = @item.to_solr expect(doc).to match a_hash_including( - 'rights_primary_ssi' => 'world_qualified', - 'rights_descriptions_ssim' => include( + 'rights_primary_ssi' => 'world_qualified', + 'rights_descriptions_ssim' => include( 'location: reading_room (no-download)', 'stanford', 'world (no-download)', 'dark (file)' ), - 'metadata_source_ssi' => 'DOR', - 'title_tesim' => ['Indianapolis 500'], + 'metadata_source_ssi' => 'DOR', + 'title_tesim' => ['Indianapolis 500'], 'rights_characteristics_ssim' => include( 'world_discover', 'has_group_rights', 'has_rule', 'group|stanford', 'location', 'location_with_rule', 'world_read', 'world|no-download', 'profile:group1|location1|world1', 'none_read_file' @@ -365,16 +365,16 @@ mock_dra_obj = double(Dor::RightsAuth) expect(mock_dra_obj).to receive(:index_elements).with(no_args).at_least(:once).and_return( :primary => 'access_restricted', - :errors => [], - :terms => [], + :errors => [], + :terms => [], :obj_locations_qualified => [{ :location => 'someplace', :rule => 'somerule' }], - :file_groups_qualified => [{ :group => 'somegroup', :rule => 'someotherrule' }] + :file_groups_qualified => [{ :group => 'somegroup', :rule => 'someotherrule' }] ) expect(rights_md_ds).to receive(:dra_object).and_return(mock_dra_obj) doc = rights_md_ds.to_solr expect(doc).to match a_hash_including( - 'rights_primary_ssi' => 'access_restricted', + 'rights_primary_ssi' => 'access_restricted', 'rights_descriptions_ssim' => include('location: someplace (somerule)', 'somegroup (file) (someotherrule)'), ) expect(doc).not_to match a_hash_including( @@ -387,15 +387,15 @@ mock_dra_obj = double(Dor::RightsAuth) expect(mock_dra_obj).to receive(:index_elements).with(no_args).at_least(:once).and_return( :primary => 'world_qualified', - :errors => [], - :terms => [], + :errors => [], + :terms => [], :obj_world_qualified => [{ :rule => 'somerule' }] ) expect(rights_md_ds).to receive(:dra_object).and_return(mock_dra_obj) doc = rights_md_ds.to_solr expect(doc).to match a_hash_including( - 'rights_primary_ssi' => 'world_qualified', + 'rights_primary_ssi' => 'world_qualified', 'rights_descriptions_ssim' => include('world (somerule)'), ) expect(doc).not_to match a_hash_including( @@ -408,21 +408,21 @@ mock_dra_obj = double(Dor::RightsAuth) expect(mock_dra_obj).to receive(:index_elements).with(no_args).at_least(:once).and_return( :primary => 'access_restricted', - :errors => [], - :terms => [], - :obj_locations => ['location'], + :errors => [], + :terms => [], + :obj_locations => ['location'], :file_locations => ['file_specific_location'], - :obj_agents => ['agent'], - :file_agents => ['file_specific_agent'] + :obj_agents => ['agent'], + :file_agents => ['file_specific_agent'] ) expect(rights_md_ds).to receive(:dra_object).and_return(mock_dra_obj) doc = rights_md_ds.to_solr expect(doc).to match a_hash_including( - 'obj_rights_locations_ssim' => ['location'], + 'obj_rights_locations_ssim' => ['location'], 'file_rights_locations_ssim' => ['file_specific_location'], - 'obj_rights_agents_ssim' => ['agent'], - 'file_rights_agents_ssim' => ['file_specific_agent'] + 'obj_rights_agents_ssim' => ['agent'], + 'file_rights_agents_ssim' => ['file_specific_agent'] ) end end diff --git a/spec/indexers/describable_indexer_spec.rb b/spec/indexers/describable_indexer_spec.rb index 605d615d..994a0ca1 100644 --- a/spec/indexers/describable_indexer_spec.rb +++ b/spec/indexers/describable_indexer_spec.rb @@ -33,15 +33,15 @@ it 'includes values from stanford_mods' do # require 'pp'; pp doc expect(doc).to match a_hash_including( - 'sw_language_ssim' => ['English'], - 'sw_language_tesim' => ['English'], - 'sw_format_ssim' => ['Book'], - 'sw_format_tesim' => ['Book'], - 'sw_subject_temporal_ssim' => ['1800-1900'], - 'sw_subject_temporal_tesim' => ['1800-1900'], - 'sw_pub_date_sort_ssi' => '1911', - 'sw_pub_date_sort_isi' => 1911, - 'sw_pub_date_facet_ssi' => '1911' + 'sw_language_ssim' => ['English'], + 'sw_language_tesim' => ['English'], + 'sw_format_ssim' => ['Book'], + 'sw_format_tesim' => ['Book'], + 'sw_subject_temporal_ssim' => ['1800-1900'], + 'sw_subject_temporal_tesim' => ['1800-1900'], + 'sw_pub_date_sort_ssi' => '1911', + 'sw_pub_date_sort_isi' => 1911, + 'sw_pub_date_facet_ssi' => '1911' ) end diff --git a/spec/indexers/indexer_spec.rb b/spec/indexers/indexer_spec.rb index d4116ddf..6f44dc9c 100644 --- a/spec/indexers/indexer_spec.rb +++ b/spec/indexers/indexer_spec.rb @@ -27,24 +27,24 @@ it 'searchworks date-fu: temporal periods and pub_dates' do expect(doc).to match a_hash_including( - 'sw_subject_temporal_ssim' => a_collection_containing_exactly('18th century', '17th century'), + 'sw_subject_temporal_ssim' => a_collection_containing_exactly('18th century', '17th century'), 'sw_subject_temporal_tesim' => a_collection_containing_exactly('18th century', '17th century'), - 'sw_pub_date_sort_ssi' => '1600', - 'sw_pub_date_sort_isi' => 1600, - 'sw_pub_date_facet_ssi' => '1600' + 'sw_pub_date_sort_ssi' => '1600', + 'sw_pub_date_sort_isi' => 1600, + 'sw_pub_date_facet_ssi' => '1600' ) end it 'subject geographic fields' do expect(doc).to match a_hash_including( - 'sw_subject_geographic_ssim' => %w(Europe Europe), + 'sw_subject_geographic_ssim' => %w(Europe Europe), 'sw_subject_geographic_tesim' => %w(Europe Europe) ) end it 'genre fields' do genre_list = obj.stanford_mods.sw_genre expect(doc).to match a_hash_including( - 'sw_genre_ssim' => genre_list, - 'sw_genre_tesim' => genre_list + 'sw_genre_ssim' => genre_list, + 'sw_genre_tesim' => genre_list ) end end diff --git a/spec/models/concerns/publishable_spec.rb b/spec/models/concerns/publishable_spec.rb index a7a2af5c..fc5e511e 100644 --- a/spec/models/concerns/publishable_spec.rb +++ b/spec/models/concerns/publishable_spec.rb @@ -286,9 +286,9 @@ class ItemizableItem < ActiveFedora::Base it 'relationships' do ns = { - 'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', - 'hydra' => 'http://projecthydra.org/ns/relations#', - 'fedora' => 'info:fedora/fedora-system:def/relations-external#', + 'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', + 'hydra' => 'http://projecthydra.org/ns/relations#', + 'fedora' => 'info:fedora/fedora-system:def/relations-external#', 'fedora-model' => 'info:fedora/fedora-system:def/model#' } expect(public_xml.at_xpath('/publicObject/rdf:RDF', ns)).to be diff --git a/spec/models/concerns/releaseable_no_vcr_spec.rb b/spec/models/concerns/releaseable_no_vcr_spec.rb index f4e9e5cd..b7fe1e3e 100644 --- a/spec/models/concerns/releaseable_no_vcr_spec.rb +++ b/spec/models/concerns/releaseable_no_vcr_spec.rb @@ -104,9 +104,9 @@ end it 'released_for pulls from identityMetadata for authoritative values (not PURL)' do expect(@item.released_for).to match a_hash_including( - 'Searchworks' => { 'release' => true }, + 'Searchworks' => { 'release' => true }, 'Some_special_place' => { 'release' => true }, # hey, free annoying capitalization! - 'Former_place' => { 'release' => false } # because it isn't in identityMetadata! + 'Former_place' => { 'release' => false } # because it isn't in identityMetadata! ) expect(@item.released_for).not_to match a_hash_including('other_place') end diff --git a/spec/services/public_desc_metadata_service_spec.rb b/spec/services/public_desc_metadata_service_spec.rb index be2b85db..c9bb8c46 100644 --- a/spec/services/public_desc_metadata_service_spec.rb +++ b/spec/services/public_desc_metadata_service_spec.rb @@ -192,7 +192,7 @@ - XML + XML obj.datastreams['rightsMetadata'].content = rxml expect(public_mods.xpath('//mods:accessCondition[@type="license"]').size).to eq(1) expect(public_mods.xpath('//mods:accessCondition[@type="license"]').text).to match(/by-nc: Open Data hoo ha/) @@ -205,7 +205,7 @@ none - XML + XML obj.datastreams['rightsMetadata'].content = rxml expect(public_mods.xpath('//mods:accessCondition[@type="license"]').size).to eq 0 end diff --git a/spec/services/registration_service_spec.rb b/spec/services/registration_service_spec.rb index 8d1afbfd..ea578d97 100644 --- a/spec/services/registration_service_spec.rb +++ b/spec/services/registration_service_spec.rb @@ -24,13 +24,13 @@ allow_any_instance_of(Dor::Item).to receive(:create).and_return(true) @params = { - :object_type => 'item', + :object_type => 'item', :content_model => 'googleScannedBook', - :admin_policy => 'druid:fg890hi1234', - :label => 'Google : Scanned Book 12345', - :source_id => { :barcode => 9191919191 }, - :other_ids => { :catkey => '000', :uuid => '111' }, - :tags => ['Google : Google Tag!', 'Google : Other Google Tag!'] + :admin_policy => 'druid:fg890hi1234', + :label => 'Google : Scanned Book 12345', + :source_id => { :barcode => 9191919191 }, + :other_ids => { :catkey => '000', :uuid => '111' }, + :tags => ['Google : Google Tag!', 'Google : Other Google Tag!'] } end @@ -327,10 +327,10 @@ allow_any_instance_of(Dor::Item).to receive(:create).and_return(true) @params = { - :object_type => 'item', - :admin_policy => 'druid:fg890hi1234', - :label => 'web-archived-crawl for http://www.example.org', - :source_id => 'sul:SOMETHING-www.example.org' + :object_type => 'item', + :admin_policy => 'druid:fg890hi1234', + :label => 'web-archived-crawl for http://www.example.org', + :source_id => 'sul:SOMETHING-www.example.org' } end diff --git a/spec/services/technical_metadata_service_spec.rb b/spec/services/technical_metadata_service_spec.rb index 9915d22a..41c244a9 100644 --- a/spec/services/technical_metadata_service_spec.rb +++ b/spec/services/technical_metadata_service_spec.rb @@ -290,7 +290,7 @@ - EOF + EOF ) end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index faaa20a3..ea901879 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -58,6 +58,7 @@ def instantiate_fixture(druid, klass = ActiveFedora::Base) mask = File.join(@fixture_dir, "*_#{druid.sub(/:/, '_')}.xml") fname = Dir[mask].first return nil if fname.nil? + item_from_foxml(File.read(fname), klass) end