dor-services 5.32.1 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/dor-services.rb +11 -1
- data/lib/dor/datastreams/workflow_definition_ds.rb +0 -4
- data/lib/dor/datastreams/workflow_ds.rb +0 -11
- data/lib/dor/indexers/composite_indexer.rb +27 -0
- data/lib/dor/indexers/data_indexer.rb +14 -0
- data/lib/dor/indexers/describable_indexer.rb +58 -0
- data/lib/dor/indexers/editable_indexer.rb +23 -0
- data/lib/dor/indexers/identifiable_indexer.rb +84 -0
- data/lib/dor/indexers/processable_indexer.rb +70 -0
- data/lib/dor/indexers/releasable_indexer.rb +26 -0
- data/lib/dor/models/abstract.rb +5 -1
- data/lib/dor/models/admin_policy_object.rb +8 -0
- data/lib/dor/models/agreement.rb +4 -2
- data/lib/dor/models/collection.rb +7 -0
- data/lib/dor/models/concerns/describable.rb +0 -51
- data/lib/dor/models/concerns/editable.rb +0 -13
- data/lib/dor/models/concerns/identifiable.rb +5 -79
- data/lib/dor/models/concerns/processable.rb +0 -60
- data/lib/dor/models/concerns/publishable.rb +7 -38
- data/lib/dor/models/concerns/releaseable.rb +0 -15
- data/lib/dor/models/item.rb +9 -0
- data/lib/dor/models/set.rb +7 -0
- data/lib/dor/models/workflow_object.rb +7 -4
- data/lib/dor/services/public_xml_service.rb +5 -3
- data/lib/dor/services/thumbnail_service.rb +55 -0
- data/lib/dor/version.rb +1 -1
- data/lib/dor/workflow/document.rb +0 -7
- data/lib/dor/workflow/process.rb +1 -0
- metadata +24 -17
- data/lib/dor/workflow/graph.rb +0 -163
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: cddc117f7297f0e5610b46e5ef181dba30fb0fcd57d7a4f21309cd68a5d5eee8
         | 
| 4 | 
            +
              data.tar.gz: 203483f92135bffbb04b40be6e4673153863eb305518f87922b8a7027797abe8
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 14cdd9ea0fa92d23c000de0f992209d9ceff820e143716b0c479ffde26c26c822c73f51f8d799e0ce6820f50beced8e2f0c69f0aca3266227a0341782f1a50ca
         | 
| 7 | 
            +
              data.tar.gz: 4056a91b565637a56a126c35998ddbf1f1a8653821587d1a4ddba823a33df82b3a626a6747b0bc6bd6b8bd0cd6efb4e42c82178a698fbca300b33e9782198d37
         | 
    
        data/lib/dor-services.rb
    CHANGED
    
    | @@ -81,6 +81,16 @@ module Dor | |
| 81 81 |  | 
| 82 82 | 
             
              require 'druid-tools'
         | 
| 83 83 |  | 
| 84 | 
            +
              autoload_under 'indexers' do
         | 
| 85 | 
            +
                autoload :CompositeIndexer
         | 
| 86 | 
            +
                autoload :DataIndexer
         | 
| 87 | 
            +
                autoload :DescribableIndexer
         | 
| 88 | 
            +
                autoload :EditableIndexer
         | 
| 89 | 
            +
                autoload :IdentifiableIndexer
         | 
| 90 | 
            +
                autoload :ProcessableIndexer
         | 
| 91 | 
            +
                autoload :ReleasableIndexer
         | 
| 92 | 
            +
              end
         | 
| 93 | 
            +
             | 
| 84 94 | 
             
              # datastreams
         | 
| 85 95 | 
             
              autoload_under 'datastreams' do
         | 
| 86 96 | 
             
                autoload :AdministrativeMetadataDS
         | 
| @@ -154,12 +164,12 @@ module Dor | |
| 154 164 | 
             
                autoload :CleanupResetService
         | 
| 155 165 | 
             
                autoload :PublicDescMetadataService
         | 
| 156 166 | 
             
                autoload :PublicXmlService
         | 
| 167 | 
            +
                autoload :ThumbnailService
         | 
| 157 168 | 
             
              end
         | 
| 158 169 |  | 
| 159 170 | 
             
              # Workflow Classes
         | 
| 160 171 | 
             
              module Workflow
         | 
| 161 172 | 
             
                extend ActiveSupport::Autoload
         | 
| 162 | 
            -
                autoload :Graph
         | 
| 163 173 | 
             
                autoload :Process
         | 
| 164 174 | 
             
                autoload :Document
         | 
| 165 175 | 
             
              end
         | 
| @@ -37,10 +37,6 @@ class WorkflowDefinitionDs < ActiveFedora::OmDatastream | |
| 37 37 | 
             
                add_child_node(ng_xml.at_xpath('/workflow-def'), :process, self, attributes)
         | 
| 38 38 | 
             
              end
         | 
| 39 39 |  | 
| 40 | 
            -
              def graph(parent = nil)
         | 
| 41 | 
            -
                Workflow::Graph.from_processes(repo, name, processes, parent)
         | 
| 42 | 
            -
              end
         | 
| 43 | 
            -
             | 
| 44 40 | 
             
              def processes
         | 
| 45 41 | 
             
                ng_xml.xpath('/workflow-def/process').collect do |node|
         | 
| 46 42 | 
             
                  Workflow::Process.new(repo, name, node)
         | 
| @@ -49,17 +49,6 @@ module Dor | |
| 49 49 | 
             
                  @workflows ||= workflow.nodeset.collect { |wf_node| Workflow::Document.new wf_node.to_xml }
         | 
| 50 50 | 
             
                end
         | 
| 51 51 |  | 
| 52 | 
            -
                def graph(dir = nil)
         | 
| 53 | 
            -
                  result = GraphViz.digraph(pid)
         | 
| 54 | 
            -
                  sg = result.add_graph('rank') { |g| g[:rank => 'same'] }
         | 
| 55 | 
            -
                  workflows.reject(&:nil?).each do |wf|
         | 
| 56 | 
            -
                    g = wf.graph(result)
         | 
| 57 | 
            -
                    sg.add_node(g.root.id) unless g.nil?
         | 
| 58 | 
            -
                  end
         | 
| 59 | 
            -
                  result['rankdir'] = dir || 'TB'
         | 
| 60 | 
            -
                  result
         | 
| 61 | 
            -
                end
         | 
| 62 | 
            -
             | 
| 63 52 | 
             
                # Finds the first workflow that is expedited, then returns the value of its priority
         | 
| 64 53 | 
             
                #
         | 
| 65 54 | 
             
                # @return [Integer] value of the priority.  Defaults to 0 if none of the workflows are expedited
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Dor
         | 
| 4 | 
            +
              class CompositeIndexer
         | 
| 5 | 
            +
                attr_reader :indexers
         | 
| 6 | 
            +
                def initialize(*indexers)
         | 
| 7 | 
            +
                  @indexers = indexers
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def new(resource:)
         | 
| 11 | 
            +
                  Instance.new(indexers, resource: resource)
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                class Instance
         | 
| 15 | 
            +
                  attr_reader :indexers, :resource
         | 
| 16 | 
            +
                  def initialize(indexers, resource:)
         | 
| 17 | 
            +
                    @resource = resource
         | 
| 18 | 
            +
                    @indexers = indexers.map { |i| i.new(resource: resource) }
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  # @return [Hash] the merged solr document for all the sub-indexers
         | 
| 22 | 
            +
                  def to_solr
         | 
| 23 | 
            +
                    indexers.map(&:to_solr).inject({}, &:merge)
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            module Dor
         | 
| 2 | 
            +
              # Indexing provided by ActiveFedora
         | 
| 3 | 
            +
              class DataIndexer
         | 
| 4 | 
            +
                include ActiveFedora::Indexing
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                attr_reader :resource
         | 
| 7 | 
            +
                def initialize(resource:)
         | 
| 8 | 
            +
                  @resource = resource
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                delegate :create_date, :modified_date, :state, :pid, :inner_object,
         | 
| 12 | 
            +
                         :datastreams, :relationships, to: :resource
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| @@ -0,0 +1,58 @@ | |
| 1 | 
            +
            module Dor
         | 
| 2 | 
            +
              class DescribableIndexer
         | 
| 3 | 
            +
                attr_reader :resource
         | 
| 4 | 
            +
                def initialize(resource:)
         | 
| 5 | 
            +
                  @resource = resource
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                # @return [Hash] the partial solr document for describable concerns
         | 
| 9 | 
            +
                def to_solr
         | 
| 10 | 
            +
                  add_metadata_format_to_solr_doc.merge(add_mods_to_solr_doc)
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def add_metadata_format_to_solr_doc
         | 
| 14 | 
            +
                  { 'metadata_format_ssim' => 'mods' }
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def add_mods_to_solr_doc
         | 
| 18 | 
            +
                  solr_doc = {}
         | 
| 19 | 
            +
                  mods_sources = {
         | 
| 20 | 
            +
                    sw_title_display: %w(sw_display_title_tesim),
         | 
| 21 | 
            +
                    main_author_w_date: %w(sw_author_ssim sw_author_tesim),
         | 
| 22 | 
            +
                    sw_sort_author: %w(sw_author_sort_ssi),
         | 
| 23 | 
            +
                    sw_language_facet: %w(sw_language_ssim sw_language_tesim),
         | 
| 24 | 
            +
                    sw_genre: %w(sw_genre_ssim sw_genre_tesim),
         | 
| 25 | 
            +
                    format_main: %w(sw_format_ssim sw_format_tesim),
         | 
| 26 | 
            +
                    topic_facet: %w(sw_topic_ssim sw_topic_tesim),
         | 
| 27 | 
            +
                    era_facet: %w(sw_subject_temporal_ssim sw_subject_temporal_tesim),
         | 
| 28 | 
            +
                    geographic_facet: %w(sw_subject_geographic_ssim sw_subject_geographic_tesim),
         | 
| 29 | 
            +
                    [:term_values, :typeOfResource] => %w(mods_typeOfResource_ssim mods_typeOfResource_tesim),
         | 
| 30 | 
            +
                    pub_year_sort_str: %w(sw_pub_date_sort_ssi),
         | 
| 31 | 
            +
                    pub_year_int: %w(sw_pub_date_sort_isi),
         | 
| 32 | 
            +
                    pub_year_display_str: %w(sw_pub_date_facet_ssi)
         | 
| 33 | 
            +
                  }
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  mods_sources.each_pair do |meth, solr_keys|
         | 
| 36 | 
            +
                    vals = meth.is_a?(Array) ? resource.stanford_mods.send(meth.shift, *meth) : resource.stanford_mods.send(meth)
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    next if vals.nil? || (vals.respond_to?(:empty?) && vals.empty?)
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    solr_keys.each do |key|
         | 
| 41 | 
            +
                      solr_doc[key] ||= []
         | 
| 42 | 
            +
                      solr_doc[key].push(*vals)
         | 
| 43 | 
            +
                    end
         | 
| 44 | 
            +
                    # asterisk to avoid multi-dimensional array: push values, not the array
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  # convert multivalued fields to single value
         | 
| 48 | 
            +
                  %w(sw_pub_date_sort_ssi sw_pub_date_sort_isi sw_pub_date_facet_ssi).each do |key|
         | 
| 49 | 
            +
                    solr_doc[key] = solr_doc[key].first unless solr_doc[key].nil?
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
                  # some fields get explicit "(none)" placeholder values, mostly for faceting
         | 
| 52 | 
            +
                  %w(sw_language_tesim sw_genre_tesim sw_format_tesim).each do |key|
         | 
| 53 | 
            +
                    solr_doc[key] = ['(none)'] if solr_doc[key].nil? || solr_doc[key].empty?
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
                  solr_doc
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
            end
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            module Dor
         | 
| 2 | 
            +
              class EditableIndexer
         | 
| 3 | 
            +
                include SolrDocHelper
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                attr_reader :resource
         | 
| 6 | 
            +
                def initialize(resource:)
         | 
| 7 | 
            +
                  @resource = resource
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def to_solr
         | 
| 11 | 
            +
                  {}.tap do |solr_doc|
         | 
| 12 | 
            +
                    add_solr_value(solr_doc, 'default_rights', default_rights_for_indexing, :string, [:symbol])
         | 
| 13 | 
            +
                    add_solr_value(solr_doc, 'agreement', resource.agreement, :string, [:symbol]) if resource.agreement_object
         | 
| 14 | 
            +
                    add_solr_value(solr_doc, 'default_use_license_machine', resource.use_license, :string, [:stored_sortable])
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                # @return [String] A description of the rights defined in the default object rights datastream. Can be 'Stanford', 'World', 'Dark' or 'None'
         | 
| 19 | 
            +
                def default_rights_for_indexing
         | 
| 20 | 
            +
                  RightsMetadataDS::RIGHTS_TYPE_CODES.fetch(resource.default_rights, 'Unrecognized default rights value')
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
| @@ -0,0 +1,84 @@ | |
| 1 | 
            +
            module Dor
         | 
| 2 | 
            +
              class IdentifiableIndexer
         | 
| 3 | 
            +
                include SolrDocHelper
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                attr_reader :resource
         | 
| 6 | 
            +
                def initialize(resource:)
         | 
| 7 | 
            +
                  @resource = resource
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                ## Module-level variables, shared between ALL mixin includers (and ALL *their* includers/extenders)!
         | 
| 11 | 
            +
                ## used for caching found values
         | 
| 12 | 
            +
                @@collection_hash = {}
         | 
| 13 | 
            +
                @@apo_hash = {}
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                # @return [Hash] the partial solr document for identifiable concerns
         | 
| 16 | 
            +
                def to_solr
         | 
| 17 | 
            +
                  solr_doc = {}
         | 
| 18 | 
            +
                  resource.assert_content_model
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  solr_doc[Dor::INDEX_VERSION_FIELD] = Dor::VERSION
         | 
| 21 | 
            +
                  solr_doc['indexed_at_dtsi'] = Time.now.utc.xmlschema
         | 
| 22 | 
            +
                  resource.datastreams.values.each do |ds|
         | 
| 23 | 
            +
                    add_solr_value(solr_doc, 'ds_specs', ds.datastream_spec_string, :string, [:symbol]) unless ds.new?
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  add_solr_value(solr_doc, 'title_sort', resource.label, :string, [:stored_sortable])
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  rels_doc = Nokogiri::XML(resource.datastreams['RELS-EXT'].content)
         | 
| 29 | 
            +
                  ns_hash = {'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#'}
         | 
| 30 | 
            +
                  apos = rels_doc.search('//rdf:RDF/rdf:Description/hydra:isGovernedBy', ns_hash)
         | 
| 31 | 
            +
                  collections = rels_doc.search('//rdf:RDF/rdf:Description/fedora:isMemberOfCollection', ns_hash)
         | 
| 32 | 
            +
                  solrize_related_obj_titles(solr_doc, apos, @@apo_hash, 'apo_title', 'nonhydrus_apo_title', 'hydrus_apo_title')
         | 
| 33 | 
            +
                  solrize_related_obj_titles(solr_doc, collections, @@collection_hash, 'collection_title', 'nonhydrus_collection_title', 'hydrus_collection_title')
         | 
| 34 | 
            +
                  solr_doc['public_dc_relation_tesim'] ||= solr_doc['collection_title_tesim'] if solr_doc['collection_title_tesim']
         | 
| 35 | 
            +
                  solr_doc['metadata_source_ssi'] = identity_metadata_source
         | 
| 36 | 
            +
                  solr_doc
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                # @return [String] calculated value for Solr index
         | 
| 40 | 
            +
                def identity_metadata_source
         | 
| 41 | 
            +
                  if resource.identityMetadata.otherId('catkey').first ||
         | 
| 42 | 
            +
                     resource.identityMetadata.otherId('barcode').first
         | 
| 43 | 
            +
                    'Symphony'
         | 
| 44 | 
            +
                  else
         | 
| 45 | 
            +
                    'DOR'
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                private
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                def solrize_related_obj_titles(solr_doc, relationships, title_hash, union_field_name, nonhydrus_field_name, hydrus_field_name)
         | 
| 52 | 
            +
                  # TODO: if you wanted to get a little fancier, you could also solrize a 2 level hierarchy and display using hierarchial facets, like
         | 
| 53 | 
            +
                  # ["SOURCE", "SOURCE : TITLE"] (e.g. ["Hydrus", "Hydrus : Special Collections"], see (exploded) tags in IdentityMetadataDS#to_solr).
         | 
| 54 | 
            +
                  title_type = :symbol  # we'll get an _ssim because of the type
         | 
| 55 | 
            +
                  title_attrs = [:stored_searchable]  # we'll also get a _tesim from this attr
         | 
| 56 | 
            +
                  relationships.each do |rel_node|
         | 
| 57 | 
            +
                    rel_druid = rel_node['rdf:resource']
         | 
| 58 | 
            +
                    next unless rel_druid   # TODO: warning here would also be useful
         | 
| 59 | 
            +
                    rel_druid = rel_druid.gsub('info:fedora/', '')
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    # populate cache if necessary
         | 
| 62 | 
            +
                    unless title_hash.key?(rel_druid)
         | 
| 63 | 
            +
                      begin
         | 
| 64 | 
            +
                        related_obj = Dor.find(rel_druid)
         | 
| 65 | 
            +
                        related_obj_title = get_related_obj_display_title(related_obj, rel_druid)
         | 
| 66 | 
            +
                        is_from_hydrus = (related_obj && related_obj.tags.include?('Project : Hydrus'))
         | 
| 67 | 
            +
                        title_hash[rel_druid] = {'related_obj_title' => related_obj_title, 'is_from_hydrus' => is_from_hydrus}
         | 
| 68 | 
            +
                      rescue ActiveFedora::ObjectNotFoundError
         | 
| 69 | 
            +
                        # This may happen if the given APO or Collection does not exist (bad data)
         | 
| 70 | 
            +
                        title_hash[rel_druid] = {'related_obj_title' => rel_druid, 'is_from_hydrus' => false}
         | 
| 71 | 
            +
                      end
         | 
| 72 | 
            +
                    end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                    # cache should definitely be populated, so just use that to write solr field
         | 
| 75 | 
            +
                    if title_hash[rel_druid]['is_from_hydrus']
         | 
| 76 | 
            +
                      add_solr_value(solr_doc, hydrus_field_name, title_hash[rel_druid]['related_obj_title'], title_type, title_attrs)
         | 
| 77 | 
            +
                    else
         | 
| 78 | 
            +
                      add_solr_value(solr_doc, nonhydrus_field_name, title_hash[rel_druid]['related_obj_title'], title_type, title_attrs)
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
                    add_solr_value(solr_doc, union_field_name, title_hash[rel_druid]['related_obj_title'], title_type, title_attrs)
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
                end
         | 
| 83 | 
            +
              end
         | 
| 84 | 
            +
            end
         | 
| @@ -0,0 +1,70 @@ | |
| 1 | 
            +
            module Dor
         | 
| 2 | 
            +
              class ProcessableIndexer
         | 
| 3 | 
            +
                include SolrDocHelper
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                attr_reader :resource
         | 
| 6 | 
            +
                def initialize(resource:)
         | 
| 7 | 
            +
                  @resource = resource
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                # @return [Hash] the partial solr document for processable concerns
         | 
| 11 | 
            +
                def to_solr
         | 
| 12 | 
            +
                  solr_doc = {}
         | 
| 13 | 
            +
                  sortable_milestones = {}
         | 
| 14 | 
            +
                  current_version = '1'
         | 
| 15 | 
            +
                  begin
         | 
| 16 | 
            +
                    current_version = resource.versionMetadata.current_version_id
         | 
| 17 | 
            +
                  rescue StandardError
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                  current_version_num = current_version.to_i
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  if resource.respond_to?('versionMetadata')
         | 
| 22 | 
            +
                    # add an entry with version id, tag and description for each version
         | 
| 23 | 
            +
                    while current_version_num > 0
         | 
| 24 | 
            +
                      new_val = "#{current_version_num};#{resource.versionMetadata.tag_for_version(current_version_num.to_s)};#{resource.versionMetadata.description_for_version(current_version_num.to_s)}"
         | 
| 25 | 
            +
                      add_solr_value(solr_doc, 'versions', new_val, :string, [:displayable])
         | 
| 26 | 
            +
                      current_version_num -= 1
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  resource.milestones.each do |milestone|
         | 
| 31 | 
            +
                    timestamp = milestone[:at].utc.xmlschema
         | 
| 32 | 
            +
                    sortable_milestones[milestone[:milestone]] ||= []
         | 
| 33 | 
            +
                    sortable_milestones[milestone[:milestone]] << timestamp
         | 
| 34 | 
            +
                    milestone[:version] ||= current_version
         | 
| 35 | 
            +
                    solr_doc['lifecycle_ssim'] ||= []
         | 
| 36 | 
            +
                    solr_doc['lifecycle_ssim'] << milestone[:milestone]
         | 
| 37 | 
            +
                    add_solr_value(solr_doc, 'lifecycle', "#{milestone[:milestone]}:#{timestamp};#{milestone[:version]}", :symbol)
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  sortable_milestones.each do |milestone, unordered_dates|
         | 
| 41 | 
            +
                    dates = unordered_dates.sort
         | 
| 42 | 
            +
                    # create the published_dttsi and published_day fields and the like
         | 
| 43 | 
            +
                    dates.each do |date|
         | 
| 44 | 
            +
                      solr_doc["#{milestone}_dttsim"] ||= []
         | 
| 45 | 
            +
                      solr_doc["#{milestone}_dttsim"] << date unless solr_doc["#{milestone}_dttsim"].include?(date)
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
                    # fields for OAI havester to sort on: _dttsi is trie date +stored +indexed (single valued, i.e. sortable)
         | 
| 48 | 
            +
                    solr_doc["#{milestone}_earliest_dttsi"] = dates.first
         | 
| 49 | 
            +
                    solr_doc["#{milestone}_latest_dttsi"] = dates.last
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
                  solr_doc['status_ssi'] = resource.status # status is singular (i.e. the current one)
         | 
| 52 | 
            +
                  solr_doc['current_version_isi'] = current_version.to_i
         | 
| 53 | 
            +
                  solr_doc['modified_latest_dttsi'] = resource.modified_date.to_datetime.utc.strftime('%FT%TZ')
         | 
| 54 | 
            +
                  add_solr_value(solr_doc, 'rights', resource.rights, :string, [:symbol]) if resource.respond_to? :rights
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  status_info_hash = resource.status_info
         | 
| 57 | 
            +
                  status_code = status_info_hash[:status_code]
         | 
| 58 | 
            +
                  add_solr_value(solr_doc, 'processing_status_text', simplified_status_code_disp_txt(status_code), :string, [:stored_sortable])
         | 
| 59 | 
            +
                  solr_doc['processing_status_code_isi'] = status_code # no _isi in Solrizer's default descriptors
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  solr_doc
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                # @return [String] text translation of the status code, minus any trailing parenthetical explanation
         | 
| 65 | 
            +
                # e.g. 'In accessioning (described)' and 'In accessioning (described, published)' both return 'In accessioning'
         | 
| 66 | 
            +
                def simplified_status_code_disp_txt(status_code)
         | 
| 67 | 
            +
                  Processable::STATUS_CODE_DISP_TXT[status_code].gsub(/\(.*\)$/, '').strip
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
            end
         | 
| @@ -0,0 +1,26 @@ | |
| 1 | 
            +
            module Dor
         | 
| 2 | 
            +
              class ReleasableIndexer
         | 
| 3 | 
            +
                include SolrDocHelper
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                attr_reader :resource
         | 
| 6 | 
            +
                def initialize(resource:)
         | 
| 7 | 
            +
                  @resource = resource
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                # @return [Hash] the partial solr document for releasable concerns
         | 
| 11 | 
            +
                def to_solr
         | 
| 12 | 
            +
                  solr_doc = {}
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  # TODO: sort of worried about the performance impact in bulk reindex
         | 
| 15 | 
            +
                  # situations, since released_for recurses all parent collections.  jmartin 2015-07-14
         | 
| 16 | 
            +
                  resource.released_for(true).each { |release_target, release_info|
         | 
| 17 | 
            +
                    add_solr_value(solr_doc, 'released_to', release_target, :symbol, []) if release_info['release']
         | 
| 18 | 
            +
                  }
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  # TODO: need to solrize whether item is released to purl?  does released_for return that?
         | 
| 21 | 
            +
                  # logic is: "True when there is a published lifecycle and Access Rights is anything but Dark"
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  solr_doc
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
            end
         | 
    
        data/lib/dor/models/abstract.rb
    CHANGED
    
    
| @@ -7,5 +7,13 @@ module Dor | |
| 7 7 | 
             
                has_metadata :name => 'administrativeMetadata', :type => Dor::AdministrativeMetadataDS, :label => 'Administrative Metadata'
         | 
| 8 8 | 
             
                has_metadata :name => 'roleMetadata',           :type => Dor::RoleMetadataDS,           :label => 'Role Metadata'
         | 
| 9 9 | 
             
                has_metadata :name => 'defaultObjectRights',    :type => Dor::DefaultObjectRightsDS,    :label => 'Default Object Rights'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                self.resource_indexer = CompositeIndexer.new(
         | 
| 12 | 
            +
                  DataIndexer,
         | 
| 13 | 
            +
                  DescribableIndexer,
         | 
| 14 | 
            +
                  EditableIndexer,
         | 
| 15 | 
            +
                  IdentifiableIndexer,
         | 
| 16 | 
            +
                  ProcessableIndexer
         | 
| 17 | 
            +
                )
         | 
| 10 18 | 
             
              end
         | 
| 11 19 | 
             
            end
         | 
    
        data/lib/dor/models/agreement.rb
    CHANGED
    
    
| @@ -64,57 +64,6 @@ module Dor | |
| 64 64 | 
             
                  PublicDescMetadataService.new(self).to_xml(**options)
         | 
| 65 65 | 
             
                end
         | 
| 66 66 |  | 
| 67 | 
            -
                def to_solr(solr_doc = {}, *args)
         | 
| 68 | 
            -
                  solr_doc = super solr_doc, *args
         | 
| 69 | 
            -
                  add_metadata_format_to_solr_doc(solr_doc)
         | 
| 70 | 
            -
                  add_mods_to_solr_doc(solr_doc)
         | 
| 71 | 
            -
                end
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                def add_metadata_format_to_solr_doc(solr_doc)
         | 
| 74 | 
            -
                  solr_doc['metadata_format_ssim'] ||= []
         | 
| 75 | 
            -
                  solr_doc['metadata_format_ssim'] += ['mods']
         | 
| 76 | 
            -
                end
         | 
| 77 | 
            -
             | 
| 78 | 
            -
                def add_mods_to_solr_doc(solr_doc)
         | 
| 79 | 
            -
                  mods_sources = {
         | 
| 80 | 
            -
                    sw_title_display: %w(sw_display_title_tesim),
         | 
| 81 | 
            -
                    main_author_w_date: %w(sw_author_ssim sw_author_tesim),
         | 
| 82 | 
            -
                    sw_sort_author: %w(sw_author_sort_ssi),
         | 
| 83 | 
            -
                    sw_language_facet: %w(sw_language_ssim sw_language_tesim),
         | 
| 84 | 
            -
                    sw_genre: %w(sw_genre_ssim sw_genre_tesim),
         | 
| 85 | 
            -
                    format_main: %w(sw_format_ssim sw_format_tesim),
         | 
| 86 | 
            -
                    topic_facet: %w(sw_topic_ssim sw_topic_tesim),
         | 
| 87 | 
            -
                    era_facet: %w(sw_subject_temporal_ssim sw_subject_temporal_tesim),
         | 
| 88 | 
            -
                    geographic_facet: %w(sw_subject_geographic_ssim sw_subject_geographic_tesim),
         | 
| 89 | 
            -
                    [:term_values, :typeOfResource] => %w(mods_typeOfResource_ssim mods_typeOfResource_tesim),
         | 
| 90 | 
            -
                    pub_year_sort_str: %w(sw_pub_date_sort_ssi),
         | 
| 91 | 
            -
                    pub_year_int: %w(sw_pub_date_sort_isi),
         | 
| 92 | 
            -
                    pub_year_display_str: %w(sw_pub_date_facet_ssi)
         | 
| 93 | 
            -
                  }
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                  mods_sources.each_pair do |meth, solr_keys|
         | 
| 96 | 
            -
                    vals = meth.is_a?(Array) ? stanford_mods.send(meth.shift, *meth) : stanford_mods.send(meth)
         | 
| 97 | 
            -
             | 
| 98 | 
            -
                    next if vals.nil? || (vals.respond_to?(:empty?) && vals.empty?)
         | 
| 99 | 
            -
             | 
| 100 | 
            -
                    solr_keys.each do |key|
         | 
| 101 | 
            -
                      solr_doc[key] ||= []
         | 
| 102 | 
            -
                      solr_doc[key].push *vals
         | 
| 103 | 
            -
                    end
         | 
| 104 | 
            -
                    # asterisk to avoid multi-dimensional array: push values, not the array
         | 
| 105 | 
            -
                  end
         | 
| 106 | 
            -
             | 
| 107 | 
            -
                  # convert multivalued fields to single value
         | 
| 108 | 
            -
                  %w(sw_pub_date_sort_ssi sw_pub_date_sort_isi sw_pub_date_facet_ssi).each do |key|
         | 
| 109 | 
            -
                    solr_doc[key] = solr_doc[key].first unless solr_doc[key].nil?
         | 
| 110 | 
            -
                  end
         | 
| 111 | 
            -
                  # some fields get explicit "(none)" placeholder values, mostly for faceting
         | 
| 112 | 
            -
                  %w(sw_language_tesim sw_genre_tesim sw_format_tesim).each do |key|
         | 
| 113 | 
            -
                    solr_doc[key] = ['(none)'] if solr_doc[key].nil? || solr_doc[key].empty?
         | 
| 114 | 
            -
                  end
         | 
| 115 | 
            -
                  solr_doc
         | 
| 116 | 
            -
                end
         | 
| 117 | 
            -
             | 
| 118 67 | 
             
                # @param [Boolean] force Overwrite existing XML
         | 
| 119 68 | 
             
                # @return [String] descMetadata.content XML
         | 
| 120 69 | 
             
                def set_desc_metadata_using_label(force = false)
         | 
| @@ -45,14 +45,6 @@ module Dor | |
| 45 45 | 
             
                                  :uri => 'http://opendatacommons.org/licenses/odbl/1.0/' }
         | 
| 46 46 | 
             
                }.freeze
         | 
| 47 47 |  | 
| 48 | 
            -
                def to_solr(solr_doc = {}, *args)
         | 
| 49 | 
            -
                  solr_doc = super(solr_doc, *args)
         | 
| 50 | 
            -
                  add_solr_value(solr_doc, 'default_rights', default_rights_for_indexing, :string, [:symbol])
         | 
| 51 | 
            -
                  add_solr_value(solr_doc, 'agreement', agreement, :string, [:symbol]) if agreement_object
         | 
| 52 | 
            -
                  add_solr_value(solr_doc, 'default_use_license_machine', use_license, :string, [:stored_sortable])
         | 
| 53 | 
            -
                  solr_doc
         | 
| 54 | 
            -
                end
         | 
| 55 | 
            -
             | 
| 56 48 | 
             
                # Adds a person or group to a role in the APO role metadata datastream
         | 
| 57 49 | 
             
                #
         | 
| 58 50 | 
             
                # @param role   [String] the role the group or person will be filed under, ex. dor-apo-manager
         | 
| @@ -280,11 +272,6 @@ module Dor | |
| 280 272 | 
             
                  end
         | 
| 281 273 | 
             
                end
         | 
| 282 274 |  | 
| 283 | 
            -
                # @return [String] A description of the rights defined in the default object rights datastream. Can be 'Stanford', 'World', 'Dark' or 'None'
         | 
| 284 | 
            -
                def default_rights_for_indexing
         | 
| 285 | 
            -
                  RightsMetadataDS::RIGHTS_TYPE_CODES.fetch(default_rights, 'Unrecognized default rights value')
         | 
| 286 | 
            -
                end
         | 
| 287 | 
            -
             | 
| 288 275 | 
             
                # Set the rights in default object rights
         | 
| 289 276 | 
             
                # @param rights [String] Stanford, World, Dark, or None
         | 
| 290 277 | 
             
                def default_rights=(rights)
         | 
| @@ -1,7 +1,6 @@ | |
| 1 1 | 
             
            module Dor
         | 
| 2 2 | 
             
              module Identifiable
         | 
| 3 3 | 
             
                extend ActiveSupport::Concern
         | 
| 4 | 
            -
                include SolrDocHelper
         | 
| 5 4 |  | 
| 6 5 | 
             
                # ids for previous and current catkeys
         | 
| 7 6 | 
             
                CATKEY_TYPE_ID = 'catkey'.freeze
         | 
| @@ -18,13 +17,13 @@ module Dor | |
| 18 17 | 
             
                    @object_type = str
         | 
| 19 18 | 
             
                    Dor.registered_classes[str] = self
         | 
| 20 19 | 
             
                  end
         | 
| 21 | 
            -
                end
         | 
| 22 20 |  | 
| 23 | 
            -
             | 
| 24 | 
            -
                   | 
| 25 | 
            -
             | 
| 21 | 
            +
                  # Overrides the method in ActiveFedora to mint a pid using SURI rather
         | 
| 22 | 
            +
                  # than the default Fedora sequence
         | 
| 23 | 
            +
                  def assign_pid(_obj)
         | 
| 24 | 
            +
                    return Dor::SuriService.mint_id if Dor::Config.suri.mint_ids
         | 
| 25 | 
            +
                    super
         | 
| 26 26 | 
             
                  end
         | 
| 27 | 
            -
                  super
         | 
| 28 27 | 
             
                end
         | 
| 29 28 |  | 
| 30 29 | 
             
                # helper method to get the tags as an array
         | 
| @@ -38,44 +37,6 @@ module Dor | |
| 38 37 | 
             
                  content_tag.size == 1 ? content_tag[0].split(':').last.strip : ''
         | 
| 39 38 | 
             
                end
         | 
| 40 39 |  | 
| 41 | 
            -
                ## Module-level variables, shared between ALL mixin includers (and ALL *their* includers/extenders)!
         | 
| 42 | 
            -
                ## used for caching found values
         | 
| 43 | 
            -
                @@collection_hash = {}
         | 
| 44 | 
            -
                @@apo_hash = {}
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                def to_solr(solr_doc = {}, *args)
         | 
| 47 | 
            -
                  assert_content_model
         | 
| 48 | 
            -
                  solr_doc = super(solr_doc, *args)
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                  solr_doc[Dor::INDEX_VERSION_FIELD] = Dor::VERSION
         | 
| 51 | 
            -
                  solr_doc['indexed_at_dtsi'] = Time.now.utc.xmlschema
         | 
| 52 | 
            -
                  datastreams.values.each do |ds|
         | 
| 53 | 
            -
                    add_solr_value(solr_doc, 'ds_specs', ds.datastream_spec_string, :string, [:symbol]) unless ds.new?
         | 
| 54 | 
            -
                  end
         | 
| 55 | 
            -
             | 
| 56 | 
            -
                  add_solr_value(solr_doc, 'title_sort', label, :string, [:stored_sortable])
         | 
| 57 | 
            -
             | 
| 58 | 
            -
                  rels_doc = Nokogiri::XML(datastreams['RELS-EXT'].content)
         | 
| 59 | 
            -
                  ns_hash = {'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#'}
         | 
| 60 | 
            -
                  apos = rels_doc.search('//rdf:RDF/rdf:Description/hydra:isGovernedBy', ns_hash)
         | 
| 61 | 
            -
                  collections = rels_doc.search('//rdf:RDF/rdf:Description/fedora:isMemberOfCollection', ns_hash)
         | 
| 62 | 
            -
                  solrize_related_obj_titles(solr_doc, apos, @@apo_hash, 'apo_title', 'nonhydrus_apo_title', 'hydrus_apo_title')
         | 
| 63 | 
            -
                  solrize_related_obj_titles(solr_doc, collections, @@collection_hash, 'collection_title', 'nonhydrus_collection_title', 'hydrus_collection_title')
         | 
| 64 | 
            -
                  solr_doc['public_dc_relation_tesim'] ||= solr_doc['collection_title_tesim'] if solr_doc['collection_title_tesim']
         | 
| 65 | 
            -
                  solr_doc['metadata_source_ssi'] = identity_metadata_source
         | 
| 66 | 
            -
                  solr_doc
         | 
| 67 | 
            -
                end
         | 
| 68 | 
            -
             | 
| 69 | 
            -
                # @return [String] calculated value for Solr index
         | 
| 70 | 
            -
                def identity_metadata_source
         | 
| 71 | 
            -
                  if identityMetadata.otherId('catkey').first ||
         | 
| 72 | 
            -
                     identityMetadata.otherId('barcode').first
         | 
| 73 | 
            -
                    'Symphony'
         | 
| 74 | 
            -
                  else
         | 
| 75 | 
            -
                    'DOR'
         | 
| 76 | 
            -
                  end
         | 
| 77 | 
            -
                end
         | 
| 78 | 
            -
             | 
| 79 40 | 
             
                # Convenience method
         | 
| 80 41 | 
             
                def source_id
         | 
| 81 42 | 
             
                  identityMetadata.sourceId
         | 
| @@ -268,40 +229,5 @@ module Dor | |
| 268 229 | 
             
                    end
         | 
| 269 230 | 
             
                  end
         | 
| 270 231 | 
             
                end
         | 
| 271 | 
            -
             | 
| 272 | 
            -
                private
         | 
| 273 | 
            -
             | 
| 274 | 
            -
                def solrize_related_obj_titles(solr_doc, relationships, title_hash, union_field_name, nonhydrus_field_name, hydrus_field_name)
         | 
| 275 | 
            -
                  # TODO: if you wanted to get a little fancier, you could also solrize a 2 level hierarchy and display using hierarchial facets, like
         | 
| 276 | 
            -
                  # ["SOURCE", "SOURCE : TITLE"] (e.g. ["Hydrus", "Hydrus : Special Collections"], see (exploded) tags in IdentityMetadataDS#to_solr).
         | 
| 277 | 
            -
                  title_type = :symbol  # we'll get an _ssim because of the type
         | 
| 278 | 
            -
                  title_attrs = [:stored_searchable]  # we'll also get a _tesim from this attr
         | 
| 279 | 
            -
                  relationships.each do |rel_node|
         | 
| 280 | 
            -
                    rel_druid = rel_node['rdf:resource']
         | 
| 281 | 
            -
                    next unless rel_druid   # TODO: warning here would also be useful
         | 
| 282 | 
            -
                    rel_druid = rel_druid.gsub('info:fedora/', '')
         | 
| 283 | 
            -
             | 
| 284 | 
            -
                    # populate cache if necessary
         | 
| 285 | 
            -
                    unless title_hash.key?(rel_druid)
         | 
| 286 | 
            -
                      begin
         | 
| 287 | 
            -
                        related_obj = Dor.find(rel_druid)
         | 
| 288 | 
            -
                        related_obj_title = get_related_obj_display_title(related_obj, rel_druid)
         | 
| 289 | 
            -
                        is_from_hydrus = (related_obj && related_obj.tags.include?('Project : Hydrus'))
         | 
| 290 | 
            -
                        title_hash[rel_druid] = {'related_obj_title' => related_obj_title, 'is_from_hydrus' => is_from_hydrus}
         | 
| 291 | 
            -
                      rescue ActiveFedora::ObjectNotFoundError
         | 
| 292 | 
            -
                        # This may happen if the given APO or Collection does not exist (bad data)
         | 
| 293 | 
            -
                        title_hash[rel_druid] = {'related_obj_title' => rel_druid, 'is_from_hydrus' => false}
         | 
| 294 | 
            -
                      end
         | 
| 295 | 
            -
                    end
         | 
| 296 | 
            -
             | 
| 297 | 
            -
                    # cache should definitely be populated, so just use that to write solr field
         | 
| 298 | 
            -
                    if title_hash[rel_druid]['is_from_hydrus']
         | 
| 299 | 
            -
                      add_solr_value(solr_doc, hydrus_field_name, title_hash[rel_druid]['related_obj_title'], title_type, title_attrs)
         | 
| 300 | 
            -
                    else
         | 
| 301 | 
            -
                      add_solr_value(solr_doc, nonhydrus_field_name, title_hash[rel_druid]['related_obj_title'], title_type, title_attrs)
         | 
| 302 | 
            -
                    end
         | 
| 303 | 
            -
                    add_solr_value(solr_doc, union_field_name, title_hash[rel_druid]['related_obj_title'], title_type, title_attrs)
         | 
| 304 | 
            -
                  end
         | 
| 305 | 
            -
                end
         | 
| 306 232 | 
             
              end
         | 
| 307 233 | 
             
            end
         | 
| @@ -3,7 +3,6 @@ require 'equivalent-xml' | |
| 3 3 | 
             
            module Dor
         | 
| 4 4 | 
             
              module Processable
         | 
| 5 5 | 
             
                extend ActiveSupport::Concern
         | 
| 6 | 
            -
                include SolrDocHelper
         | 
| 7 6 |  | 
| 8 7 | 
             
                included do
         | 
| 9 8 | 
             
                  has_metadata :name => 'workflows', :type => Dor::WorkflowDs, :label => 'Workflows', :control_group => 'E'
         | 
| @@ -147,65 +146,6 @@ module Dor | |
| 147 146 | 
             
                  result
         | 
| 148 147 | 
             
                end
         | 
| 149 148 |  | 
| 150 | 
            -
                # @return [String] text translation of the status code, minus any trailing parenthetical explanation
         | 
| 151 | 
            -
                # e.g. 'In accessioning (described)' and 'In accessioning (described, published)' both return 'In accessioning'
         | 
| 152 | 
            -
                def simplified_status_code_disp_txt(status_code)
         | 
| 153 | 
            -
                  STATUS_CODE_DISP_TXT[status_code].gsub(/\(.*\)$/, '').strip
         | 
| 154 | 
            -
                end
         | 
| 155 | 
            -
             | 
| 156 | 
            -
                def to_solr(solr_doc = {}, *args)
         | 
| 157 | 
            -
                  solr_doc = super(solr_doc, *args)
         | 
| 158 | 
            -
                  sortable_milestones = {}
         | 
| 159 | 
            -
                  current_version = '1'
         | 
| 160 | 
            -
                  begin
         | 
| 161 | 
            -
                    current_version = versionMetadata.current_version_id
         | 
| 162 | 
            -
                  rescue
         | 
| 163 | 
            -
                  end
         | 
| 164 | 
            -
                  current_version_num = current_version.to_i
         | 
| 165 | 
            -
             | 
| 166 | 
            -
                  if self.respond_to?('versionMetadata')
         | 
| 167 | 
            -
                    # add an entry with version id, tag and description for each version
         | 
| 168 | 
            -
                    while current_version_num > 0
         | 
| 169 | 
            -
                      new_val = "#{current_version_num};#{versionMetadata.tag_for_version(current_version_num.to_s)};#{versionMetadata.description_for_version(current_version_num.to_s)}"
         | 
| 170 | 
            -
                      add_solr_value(solr_doc, 'versions', new_val, :string, [:displayable])
         | 
| 171 | 
            -
                      current_version_num -= 1
         | 
| 172 | 
            -
                    end
         | 
| 173 | 
            -
                  end
         | 
| 174 | 
            -
             | 
| 175 | 
            -
                  milestones.each do |milestone|
         | 
| 176 | 
            -
                    timestamp = milestone[:at].utc.xmlschema
         | 
| 177 | 
            -
                    sortable_milestones[milestone[:milestone]] ||= []
         | 
| 178 | 
            -
                    sortable_milestones[milestone[:milestone]] << timestamp
         | 
| 179 | 
            -
                    milestone[:version] ||= current_version
         | 
| 180 | 
            -
                    solr_doc['lifecycle_ssim'] ||= []
         | 
| 181 | 
            -
                    solr_doc['lifecycle_ssim'] << milestone[:milestone]
         | 
| 182 | 
            -
                    add_solr_value(solr_doc, 'lifecycle', "#{milestone[:milestone]}:#{timestamp};#{milestone[:version]}", :symbol)
         | 
| 183 | 
            -
                  end
         | 
| 184 | 
            -
             | 
| 185 | 
            -
                  sortable_milestones.each do |milestone, unordered_dates|
         | 
| 186 | 
            -
                    dates = unordered_dates.sort
         | 
| 187 | 
            -
                    # create the published_dttsi and published_day fields and the like
         | 
| 188 | 
            -
                    dates.each do |date|
         | 
| 189 | 
            -
                      solr_doc["#{milestone}_dttsim"] ||= []
         | 
| 190 | 
            -
                      solr_doc["#{milestone}_dttsim"] << date unless solr_doc["#{milestone}_dttsim"].include?(date)
         | 
| 191 | 
            -
                    end
         | 
| 192 | 
            -
                    # fields for OAI havester to sort on: _dttsi is trie date +stored +indexed (single valued, i.e. sortable)
         | 
| 193 | 
            -
                    solr_doc["#{milestone}_earliest_dttsi"] = dates.first
         | 
| 194 | 
            -
                    solr_doc["#{milestone}_latest_dttsi"  ] = dates.last
         | 
| 195 | 
            -
                  end
         | 
| 196 | 
            -
                  solr_doc['status_ssi'] = status # status is singular (i.e. the current one)
         | 
| 197 | 
            -
                  solr_doc['current_version_isi'] = current_version.to_i
         | 
| 198 | 
            -
                  solr_doc['modified_latest_dttsi'] = modified_date.to_datetime.utc.strftime('%FT%TZ')
         | 
| 199 | 
            -
                  add_solr_value(solr_doc, 'rights', rights, :string, [:symbol]) if self.respond_to? :rights
         | 
| 200 | 
            -
             | 
| 201 | 
            -
                  status_info_hash = status_info
         | 
| 202 | 
            -
                  status_code = status_info_hash[:status_code]
         | 
| 203 | 
            -
                  add_solr_value(solr_doc, 'processing_status_text', simplified_status_code_disp_txt(status_code), :string, [:stored_sortable])
         | 
| 204 | 
            -
                  solr_doc['processing_status_code_isi'] = status_code # no _isi in Solrizer's default descriptors
         | 
| 205 | 
            -
             | 
| 206 | 
            -
                  solr_doc
         | 
| 207 | 
            -
                end
         | 
| 208 | 
            -
             | 
| 209 149 | 
             
                # Initilizes workflow for the object in the workflow service
         | 
| 210 150 | 
             
                #  It will set the priorty of the new workflow to the current_priority if it is > 0
         | 
| 211 151 | 
             
                #  It will set lane_id from the item's APO default workflow lane
         | 
| @@ -3,50 +3,17 @@ require 'fileutils' | |
| 3 3 |  | 
| 4 4 | 
             
            module Dor
         | 
| 5 5 | 
             
              module Publishable
         | 
| 6 | 
            +
                extend Deprecation
         | 
| 6 7 | 
             
                extend ActiveSupport::Concern
         | 
| 8 | 
            +
                self.deprecation_horizon = 'dor-services version 7.0.0'
         | 
| 7 9 |  | 
| 8 10 | 
             
                # Compute the thumbnail for this object following the rules at https://consul.stanford.edu/display/chimera/The+Rules+of+Thumb
         | 
| 11 | 
            +
                # Used by PublicXmlService
         | 
| 9 12 | 
             
                # @return [String] the computed thumb filename, with the druid prefix and a slash in front of it, e.g. oo000oo0001/filenamewith space.jp2
         | 
| 10 13 | 
             
                def thumb
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                   cm = contentMetadata.ng_xml
         | 
| 13 | 
            -
                   mime_type_finder = "@mimetype='image/jp2' or @mimeType='image/jp2'" # allow the mimetype attribute to be lower or camelcase when searching to make it more robust
         | 
| 14 | 
            -
                   thumb_image=nil
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                   # these are the finders we will use to search for a thumb resource in contentMetadata, they will be searched in the order provided, stopping when one is reached
         | 
| 17 | 
            -
                   thumb_xpath_finders = [
         | 
| 18 | 
            -
                       # first find a file of mimetype jp2 explicitly marked as a thumb in the resource type and with a thumb=yes attribute
         | 
| 19 | 
            -
                       {image_type: 'local', finder: "/contentMetadata/resource[@type='thumb' and @thumb='yes']/file[#{mime_type_finder}]"},
         | 
| 20 | 
            -
                       # same thing for external files
         | 
| 21 | 
            -
                       {image_type: 'external', finder: "/contentMetadata/resource[@type='thumb' and @thumb='yes']/externalFile[#{mime_type_finder}]"},
         | 
| 22 | 
            -
                       # next find any image or page resource types with the thumb=yes attribute of mimetype jp2
         | 
| 23 | 
            -
                       {image_type: 'local', finder: "/contentMetadata/resource[(@type='page' or @type='image') and @thumb='yes']/file[#{mime_type_finder}]"},
         | 
| 24 | 
            -
                       # same thing for external file
         | 
| 25 | 
            -
                       {image_type: 'external', finder: "/contentMetadata/resource[(@type='page' or @type='image') and @thumb='yes']/externalFile[#{mime_type_finder}]"},
         | 
| 26 | 
            -
                       # next find a file of mimetype jp2 and resource type=thumb but not marked with the thumb directive
         | 
| 27 | 
            -
                       {image_type: 'local', finder: "/contentMetadata/resource[@type='thumb']/file[#{mime_type_finder}]"},
         | 
| 28 | 
            -
                       # same thing for external file
         | 
| 29 | 
            -
                       {image_type: 'external', finder: "/contentMetadata/resource[@type='thumb']/externalFile[#{mime_type_finder}]"},
         | 
| 30 | 
            -
                       # finally find the first page or image resource of mimetype jp2
         | 
| 31 | 
            -
                       {image_type: 'local', finder: "/contentMetadata/resource[@type='page' or @type='image']/file[#{mime_type_finder}]"},
         | 
| 32 | 
            -
                       # same thing for external file
         | 
| 33 | 
            -
                       {image_type: 'external', finder: "/contentMetadata/resource[@type='page' or @type='image']/externalFile[#{mime_type_finder}]"}
         | 
| 34 | 
            -
                     ]
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                   thumb_xpath_finders.each do |search_path|
         | 
| 37 | 
            -
                     thumb_files = cm.xpath(search_path[:finder]) # look for a thumb
         | 
| 38 | 
            -
                     if thumb_files.size > 0   # if we find one, return the filename based on whether it is a local file or external file
         | 
| 39 | 
            -
                       if search_path[:image_type] == 'local'
         | 
| 40 | 
            -
                         thumb_image="#{remove_druid_prefix}/#{thumb_files[0]['id']}"
         | 
| 41 | 
            -
                       else
         | 
| 42 | 
            -
                         thumb_image="#{remove_druid_prefix(thumb_files[0]['objectId'])}/#{thumb_files[0]['fileId']}"
         | 
| 43 | 
            -
                       end
         | 
| 44 | 
            -
                       break  # break out of the loop so we stop searching
         | 
| 45 | 
            -
                     end
         | 
| 46 | 
            -
                   end
         | 
| 47 | 
            -
             | 
| 48 | 
            -
                   thumb_image
         | 
| 14 | 
            +
                  ThumbnailService.new(self).thumb
         | 
| 49 15 | 
             
                end
         | 
| 16 | 
            +
                deprecation_deprecate :thumb
         | 
| 50 17 |  | 
| 51 18 | 
             
                # Return a URI encoded version of the thumb image for use by indexers (leaving the extension of the filename)
         | 
| 52 19 | 
             
                # @return [String] URI encoded version of the thumb with the druid prefix, e.g. oo000oo0001%2Ffilenamewith%20space.jp2
         | 
| @@ -57,6 +24,7 @@ module Dor | |
| 57 24 | 
             
                  thumb_filename=thumb_image.split(/#{pid_regex}[\/]/).last # everything after the druid
         | 
| 58 25 | 
             
                  "#{thumb_druid}%2F#{ERB::Util.url_encode(thumb_filename)}"
         | 
| 59 26 | 
             
                end
         | 
| 27 | 
            +
                deprecation_deprecate :encoded_thumb
         | 
| 60 28 |  | 
| 61 29 | 
             
                # Return a full qualified thumbnail image URL if the thumb is computable
         | 
| 62 30 | 
             
                # @return [String] fully qualified image URL for the computed thumbnail, e.g. https://stacks.stanford.edu/image/iiif/oo000oo0001%2Ffilenamewith%20space/full
         | 
| @@ -65,6 +33,7 @@ module Dor | |
| 65 33 | 
             
                  thumb_basename=File.basename(encoded_thumb, File.extname(encoded_thumb)) # strip the extension for URL generation
         | 
| 66 34 | 
             
                  "https://#{Dor::Config.stacks.host}/image/iiif/#{thumb_basename}/full/!400,400/0/default.jpg"
         | 
| 67 35 | 
             
                end
         | 
| 36 | 
            +
                deprecation_deprecate :thumb_url
         | 
| 68 37 |  | 
| 69 38 | 
             
                # strips away the relationships that should not be shown in public desc metadata
         | 
| 70 39 | 
             
                # @return [Nokogiri::XML]
         | 
| @@ -304,20 +304,5 @@ module Dor | |
| 304 304 | 
             
                  end
         | 
| 305 305 | 
             
                  new_tags
         | 
| 306 306 | 
             
                end
         | 
| 307 | 
            -
             | 
| 308 | 
            -
                def to_solr(solr_doc = {}, *args)
         | 
| 309 | 
            -
                  solr_doc = super(solr_doc, *args)
         | 
| 310 | 
            -
             | 
| 311 | 
            -
                  # TODO: sort of worried about the performance impact in bulk reindex
         | 
| 312 | 
            -
                  # situations, since released_for recurses all parent collections.  jmartin 2015-07-14
         | 
| 313 | 
            -
                  released_for(true).each { |release_target, release_info|
         | 
| 314 | 
            -
                    add_solr_value(solr_doc, 'released_to', release_target, :symbol, []) if release_info['release']
         | 
| 315 | 
            -
                  }
         | 
| 316 | 
            -
             | 
| 317 | 
            -
                  # TODO: need to solrize whether item is released to purl?  does released_for return that?
         | 
| 318 | 
            -
                  # logic is: "True when there is a published lifecycle and Access Rights is anything but Dark"
         | 
| 319 | 
            -
             | 
| 320 | 
            -
                  solr_doc
         | 
| 321 | 
            -
                end
         | 
| 322 307 | 
             
              end
         | 
| 323 308 | 
             
            end
         | 
    
        data/lib/dor/models/item.rb
    CHANGED
    
    | @@ -4,12 +4,21 @@ module Dor | |
| 4 4 | 
             
                include Embargoable
         | 
| 5 5 | 
             
                include Publishable
         | 
| 6 6 | 
             
                include Itemizable
         | 
| 7 | 
            +
                include Preservable
         | 
| 7 8 | 
             
                include Assembleable
         | 
| 8 9 | 
             
                include Contentable
         | 
| 9 10 | 
             
                include Geoable
         | 
| 10 11 | 
             
                include Releaseable
         | 
| 11 12 |  | 
| 12 13 | 
             
                has_object_type 'item'
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                self.resource_indexer = CompositeIndexer.new(
         | 
| 16 | 
            +
                  DataIndexer,
         | 
| 17 | 
            +
                  DescribableIndexer,
         | 
| 18 | 
            +
                  IdentifiableIndexer,
         | 
| 19 | 
            +
                  ProcessableIndexer,
         | 
| 20 | 
            +
                  ReleasableIndexer
         | 
| 21 | 
            +
                )
         | 
| 13 22 | 
             
              end
         | 
| 14 23 | 
             
            end
         | 
| 15 24 |  | 
    
        data/lib/dor/models/set.rb
    CHANGED
    
    | @@ -4,5 +4,12 @@ module Dor | |
| 4 4 |  | 
| 5 5 | 
             
                has_many :members, :property => :is_member_of_collection, :class_name => 'ActiveFedora::Base'
         | 
| 6 6 | 
             
                has_object_type 'set'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                self.resource_indexer = CompositeIndexer.new(
         | 
| 9 | 
            +
                  DataIndexer,
         | 
| 10 | 
            +
                  DescribableIndexer,
         | 
| 11 | 
            +
                  IdentifiableIndexer,
         | 
| 12 | 
            +
                  ProcessableIndexer
         | 
| 13 | 
            +
                )
         | 
| 7 14 | 
             
              end
         | 
| 8 15 | 
             
            end
         | 
| @@ -8,6 +8,13 @@ module Dor | |
| 8 8 | 
             
                has_object_type 'workflow'
         | 
| 9 9 | 
             
                has_metadata :name => 'workflowDefinition', :type => Dor::WorkflowDefinitionDs, :label => 'Workflow Definition'
         | 
| 10 10 |  | 
| 11 | 
            +
                self.resource_indexer = CompositeIndexer.new(
         | 
| 12 | 
            +
                  DataIndexer,
         | 
| 13 | 
            +
                  DescribableIndexer,
         | 
| 14 | 
            +
                  IdentifiableIndexer,
         | 
| 15 | 
            +
                  ProcessableIndexer
         | 
| 16 | 
            +
                )
         | 
| 17 | 
            +
             | 
| 11 18 | 
             
                def self.find_by_name(name)
         | 
| 12 19 | 
             
                  Dor::WorkflowObject.where(Solrizer.solr_name('workflow_name', :symbol) => name).first
         | 
| 13 20 | 
             
                end
         | 
| @@ -38,10 +45,6 @@ module Dor | |
| 38 45 | 
             
                  datastreams['workflowDefinition']
         | 
| 39 46 | 
             
                end
         | 
| 40 47 |  | 
| 41 | 
            -
                def graph(*args)
         | 
| 42 | 
            -
                  definition.graph *args
         | 
| 43 | 
            -
                end
         | 
| 44 | 
            -
             | 
| 45 48 | 
             
                def generate_initial_workflow
         | 
| 46 49 | 
             
                  datastreams['workflowDefinition'].initial_workflow
         | 
| 47 50 | 
             
                end
         | 
| @@ -5,7 +5,7 @@ module Dor | |
| 5 5 | 
             
                def initialize(object)
         | 
| 6 6 | 
             
                  @object = object
         | 
| 7 7 | 
             
                end
         | 
| 8 | 
            -
             | 
| 8 | 
            +
             | 
| 9 9 | 
             
                def to_xml
         | 
| 10 10 | 
             
                  pub = Nokogiri::XML('<publicObject/>').root
         | 
| 11 11 | 
             
                  pub['id'] = object.pid
         | 
| @@ -21,8 +21,10 @@ module Dor | |
| 21 21 | 
             
                  pub.add_child(Nokogiri::XML(object.generate_public_desc_md).root)
         | 
| 22 22 | 
             
                  pub.add_child(release_xml.root) unless release_xml.xpath('//release').children.size == 0 # If there are no release_tags, this prevents an empty <releaseData/> from being added
         | 
| 23 23 | 
             
                  # Note we cannot base this on if an individual object has release tags or not, because the collection may cause one to be generated for an item,
         | 
| 24 | 
            -
                  # so we need to calculate it and then look at the final result. | 
| 25 | 
            -
             | 
| 24 | 
            +
                  # so we need to calculate it and then look at the final result.
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  thumb = ThumbnailService.new(object).thumb
         | 
| 27 | 
            +
                  pub.add_child(Nokogiri("<thumb>#{thumb}</thumb>").root) unless thumb.nil?
         | 
| 26 28 |  | 
| 27 29 | 
             
                  new_pub = Nokogiri::XML(pub.to_xml) { |x| x.noblanks }
         | 
| 28 30 | 
             
                  new_pub.encoding = 'UTF-8'
         | 
| @@ -0,0 +1,55 @@ | |
| 1 | 
            +
            module Dor
         | 
| 2 | 
            +
              # Responsible for finding a path to a thumbnail based on the contentMetadata of an object
         | 
| 3 | 
            +
              class ThumbnailService
         | 
| 4 | 
            +
                # allow the mimetype attribute to be lower or camelcase when searching to make it more robust
         | 
| 5 | 
            +
                MIME_TYPE_FINDER = "@mimetype='image/jp2' or @mimeType='image/jp2'".freeze
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                # these are the finders we will use to search for a thumb resource in contentMetadata, they will be searched in the order provided, stopping when one is reached
         | 
| 8 | 
            +
                THUMB_XPATH_FINDERS = [
         | 
| 9 | 
            +
                  # first find a file of mimetype jp2 explicitly marked as a thumb in the resource type and with a thumb=yes attribute
         | 
| 10 | 
            +
                  { image_type: 'local', finder: "/contentMetadata/resource[@type='thumb' and @thumb='yes']/file[#{MIME_TYPE_FINDER}]"},
         | 
| 11 | 
            +
                  # same thing for external files
         | 
| 12 | 
            +
                  { image_type: 'external', finder: "/contentMetadata/resource[@type='thumb' and @thumb='yes']/externalFile[#{MIME_TYPE_FINDER}]"},
         | 
| 13 | 
            +
                  # next find any image or page resource types with the thumb=yes attribute of mimetype jp2
         | 
| 14 | 
            +
                  { image_type: 'local', finder: "/contentMetadata/resource[(@type='page' or @type='image') and @thumb='yes']/file[#{MIME_TYPE_FINDER}]"},
         | 
| 15 | 
            +
                  # same thing for external file
         | 
| 16 | 
            +
                  { image_type: 'external', finder: "/contentMetadata/resource[(@type='page' or @type='image') and @thumb='yes']/externalFile[#{MIME_TYPE_FINDER}]"},
         | 
| 17 | 
            +
                  # next find a file of mimetype jp2 and resource type=thumb but not marked with the thumb directive
         | 
| 18 | 
            +
                  { image_type: 'local', finder: "/contentMetadata/resource[@type='thumb']/file[#{MIME_TYPE_FINDER}]"},
         | 
| 19 | 
            +
                  # same thing for external file
         | 
| 20 | 
            +
                  { image_type: 'external', finder: "/contentMetadata/resource[@type='thumb']/externalFile[#{MIME_TYPE_FINDER}]"},
         | 
| 21 | 
            +
                  # finally find the first page or image resource of mimetype jp2
         | 
| 22 | 
            +
                  { image_type: 'local', finder: "/contentMetadata/resource[@type='page' or @type='image']/file[#{MIME_TYPE_FINDER}]"},
         | 
| 23 | 
            +
                  # same thing for external file
         | 
| 24 | 
            +
                  { image_type: 'external', finder: "/contentMetadata/resource[@type='page' or @type='image']/externalFile[#{MIME_TYPE_FINDER}]"}
         | 
| 25 | 
            +
                ].freeze
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                # @params [Dor::Item] object
         | 
| 28 | 
            +
                def initialize(object)
         | 
| 29 | 
            +
                  @object = object
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                attr_reader :object
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                # @return [String] the computed thumb filename, with the druid prefix and a slash in front of it, e.g. oo000oo0001/filenamewith space.jp2
         | 
| 35 | 
            +
                def thumb
         | 
| 36 | 
            +
                  return unless object.respond_to?(:contentMetadata) && object.contentMetadata.present?
         | 
| 37 | 
            +
                  cm = object.contentMetadata.ng_xml
         | 
| 38 | 
            +
                  thumb_image = nil
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  THUMB_XPATH_FINDERS.each do |search_path|
         | 
| 41 | 
            +
                    thumb_files = cm.xpath(search_path[:finder]) # look for a thumb
         | 
| 42 | 
            +
                    next if thumb_files.empty?
         | 
| 43 | 
            +
                    # if we find one, return the filename based on whether it is a local file or external file
         | 
| 44 | 
            +
                    thumb_image = if search_path[:image_type] == 'local'
         | 
| 45 | 
            +
                                    "#{object.remove_druid_prefix}/#{thumb_files[0]['id']}"
         | 
| 46 | 
            +
                                  else
         | 
| 47 | 
            +
                                    "#{object.remove_druid_prefix(thumb_files[0]['objectId'])}/#{thumb_files[0]['fileId']}"
         | 
| 48 | 
            +
                                  end
         | 
| 49 | 
            +
                    break  # break out of the loop so we stop searching
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  thumb_image
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
            end
         | 
    
        data/lib/dor/version.rb
    CHANGED
    
    
| @@ -54,13 +54,6 @@ module Workflow | |
| 54 54 | 
             
                  end
         | 
| 55 55 | 
             
                end
         | 
| 56 56 |  | 
| 57 | 
            -
                def graph(parent = nil, dir = nil)
         | 
| 58 | 
            -
                  wf_definition = definition
         | 
| 59 | 
            -
                  result = wf_definition ? Workflow::Graph.from_processes(wf_definition.repo, wf_definition.name, processes, parent) : nil
         | 
| 60 | 
            -
                  result['rankdir'] = dir || 'TB' unless result.nil?
         | 
| 61 | 
            -
                  result
         | 
| 62 | 
            -
                end
         | 
| 63 | 
            -
             | 
| 64 57 | 
             
                def [](value)
         | 
| 65 58 | 
             
                  processes.find { |p| p.name == value }
         | 
| 66 59 | 
             
                end
         | 
    
        data/lib/dor/workflow/process.rb
    CHANGED
    
    | @@ -89,6 +89,7 @@ module Workflow | |
| 89 89 | 
             
                # @param info [Hash,Nokogiri::XML::Element,NilClass]
         | 
| 90 90 | 
             
                # @param new_owner [Dor::Workflow::Document]
         | 
| 91 91 | 
             
                def update!(info, new_owner)
         | 
| 92 | 
            +
                  raise ArgumentError, 'Owner can not be nil. It must be an instance of Dor::Workflow::Document' unless new_owner
         | 
| 92 93 | 
             
                  @owner = new_owner
         | 
| 93 94 | 
             
                  return self if info.nil?
         | 
| 94 95 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: dor-services
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version:  | 
| 4 | 
            +
              version: 6.0.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Michael Klein
         | 
| @@ -14,7 +14,7 @@ authors: | |
| 14 14 | 
             
            autorequire: 
         | 
| 15 15 | 
             
            bindir: bin
         | 
| 16 16 | 
             
            cert_chain: []
         | 
| 17 | 
            -
            date: 2018-11- | 
| 17 | 
            +
            date: 2018-11-28 00:00:00.000000000 Z
         | 
| 18 18 | 
             
            dependencies:
         | 
| 19 19 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 20 20 | 
             
              name: active-fedora
         | 
| @@ -70,6 +70,20 @@ dependencies: | |
| 70 70 | 
             
                - - "~>"
         | 
| 71 71 | 
             
                  - !ruby/object:Gem::Version
         | 
| 72 72 | 
             
                    version: 0.2.7
         | 
| 73 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 74 | 
            +
              name: deprecation
         | 
| 75 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 76 | 
            +
                requirements:
         | 
| 77 | 
            +
                - - "~>"
         | 
| 78 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 79 | 
            +
                    version: '0'
         | 
| 80 | 
            +
              type: :runtime
         | 
| 81 | 
            +
              prerelease: false
         | 
| 82 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 83 | 
            +
                requirements:
         | 
| 84 | 
            +
                - - "~>"
         | 
| 85 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 86 | 
            +
                    version: '0'
         | 
| 73 87 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 74 88 | 
             
              name: equivalent-xml
         | 
| 75 89 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -220,20 +234,6 @@ dependencies: | |
| 220 234 | 
             
                - - "~>"
         | 
| 221 235 | 
             
                  - !ruby/object:Gem::Version
         | 
| 222 236 | 
             
                    version: 0.3.0
         | 
| 223 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 224 | 
            -
              name: ruby-graphviz
         | 
| 225 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 226 | 
            -
                requirements:
         | 
| 227 | 
            -
                - - ">="
         | 
| 228 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 229 | 
            -
                    version: '0'
         | 
| 230 | 
            -
              type: :runtime
         | 
| 231 | 
            -
              prerelease: false
         | 
| 232 | 
            -
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 233 | 
            -
                requirements:
         | 
| 234 | 
            -
                - - ">="
         | 
| 235 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 236 | 
            -
                    version: '0'
         | 
| 237 237 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 238 238 | 
             
              name: rubydora
         | 
| 239 239 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -588,6 +588,13 @@ files: | |
| 588 588 | 
             
            - lib/dor/datastreams/workflow_definition_ds.rb
         | 
| 589 589 | 
             
            - lib/dor/datastreams/workflow_ds.rb
         | 
| 590 590 | 
             
            - lib/dor/exceptions.rb
         | 
| 591 | 
            +
            - lib/dor/indexers/composite_indexer.rb
         | 
| 592 | 
            +
            - lib/dor/indexers/data_indexer.rb
         | 
| 593 | 
            +
            - lib/dor/indexers/describable_indexer.rb
         | 
| 594 | 
            +
            - lib/dor/indexers/editable_indexer.rb
         | 
| 595 | 
            +
            - lib/dor/indexers/identifiable_indexer.rb
         | 
| 596 | 
            +
            - lib/dor/indexers/processable_indexer.rb
         | 
| 597 | 
            +
            - lib/dor/indexers/releasable_indexer.rb
         | 
| 591 598 | 
             
            - lib/dor/models/abstract.rb
         | 
| 592 599 | 
             
            - lib/dor/models/admin_policy_object.rb
         | 
| 593 600 | 
             
            - lib/dor/models/agreement.rb
         | 
| @@ -629,6 +636,7 @@ files: | |
| 629 636 | 
             
            - lib/dor/services/search_service.rb
         | 
| 630 637 | 
             
            - lib/dor/services/suri_service.rb
         | 
| 631 638 | 
             
            - lib/dor/services/technical_metadata_service.rb
         | 
| 639 | 
            +
            - lib/dor/services/thumbnail_service.rb
         | 
| 632 640 | 
             
            - lib/dor/utils/hydrus_shims.rb
         | 
| 633 641 | 
             
            - lib/dor/utils/ng_tidy.rb
         | 
| 634 642 | 
             
            - lib/dor/utils/predicate_patch.rb
         | 
| @@ -636,7 +644,6 @@ files: | |
| 636 644 | 
             
            - lib/dor/utils/solr_doc_helper.rb
         | 
| 637 645 | 
             
            - lib/dor/version.rb
         | 
| 638 646 | 
             
            - lib/dor/workflow/document.rb
         | 
| 639 | 
            -
            - lib/dor/workflow/graph.rb
         | 
| 640 647 | 
             
            - lib/dor/workflow/process.rb
         | 
| 641 648 | 
             
            - lib/tasks/rdoc.rake
         | 
| 642 649 | 
             
            homepage: 
         | 
    
        data/lib/dor/workflow/graph.rb
    DELETED
    
    | @@ -1,163 +0,0 @@ | |
| 1 | 
            -
            require 'graphviz'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module Dor
         | 
| 4 | 
            -
            module Workflow
         | 
| 5 | 
            -
            class Graph
         | 
| 6 | 
            -
             | 
| 7 | 
            -
              FILL_COLORS = { 'waiting' => 'white', 'ready' => 'white', 'error' => '#8B0000', 'blocked' => 'white', 'completed' => 'darkgreen', 'unknown' => '#CFCFCF' }.freeze
         | 
| 8 | 
            -
              TEXT_COLORS = { 'waiting' => 'black', 'ready' => 'black', 'error' => 'white', 'blocked' => '#8B0000', 'completed' => 'white', 'unknown' => 'black' }.freeze
         | 
| 9 | 
            -
              PATTERNS    = { 'waiting' => 'diagonals', 'ready' => 'filled', 'error' => 'filled', 'blocked' => 'diagonals', 'completed' => 'filled', 'unknown' => 'filled' }.freeze
         | 
| 10 | 
            -
              RESERVED_KEYS = %w(repository name).freeze
         | 
| 11 | 
            -
             | 
| 12 | 
            -
              attr_reader :repo, :name, :processes, :graph, :root
         | 
| 13 | 
            -
             | 
| 14 | 
            -
              def self.from_config(name, config, parent = nil)
         | 
| 15 | 
            -
                wf = new(config['repository'], name, parent)
         | 
| 16 | 
            -
                config.keys.each { |p| wf.add_process(p.to_s) unless RESERVED_KEYS.include?(p) }
         | 
| 17 | 
            -
                config.keys.each { |p|
         | 
| 18 | 
            -
                  next unless wf.processes[p]
         | 
| 19 | 
            -
                  Array(config[p]['prerequisite']).each { |prereq|
         | 
| 20 | 
            -
                    prereq.sub!(/^#{config['repository']}:#{name}:/e, '')
         | 
| 21 | 
            -
                    if wf.processes[prereq]
         | 
| 22 | 
            -
                      wf.processes[p].depends_on(wf.processes[prereq])
         | 
| 23 | 
            -
                    else
         | 
| 24 | 
            -
                      wf.processes[p].depends_on(wf.add_process(prereq).set_status('external'))
         | 
| 25 | 
            -
                    end
         | 
| 26 | 
            -
                  }
         | 
| 27 | 
            -
                }
         | 
| 28 | 
            -
                wf.finish
         | 
| 29 | 
            -
                wf
         | 
| 30 | 
            -
              end
         | 
| 31 | 
            -
             | 
| 32 | 
            -
              def self.from_processes(repo, name, processes, parent = nil)
         | 
| 33 | 
            -
                wf = new(repo, name, parent)
         | 
| 34 | 
            -
                processes.each { |p|
         | 
| 35 | 
            -
                  wf.add_process(p.name).status = p.state || 'unknown'
         | 
| 36 | 
            -
                }
         | 
| 37 | 
            -
                processes.each { |p|
         | 
| 38 | 
            -
                  p.prerequisite.each { |prereq|
         | 
| 39 | 
            -
                    prereq.sub!(/^#{repo}:#{name}:/e, '')
         | 
| 40 | 
            -
                    if wf.processes[prereq]
         | 
| 41 | 
            -
                      wf.processes[p.name].depends_on(wf.processes[prereq])
         | 
| 42 | 
            -
                    else
         | 
| 43 | 
            -
                      wf.processes[p.name].depends_on(wf.add_process(prereq).set_status('external'))
         | 
| 44 | 
            -
                    end
         | 
| 45 | 
            -
                  }
         | 
| 46 | 
            -
                }
         | 
| 47 | 
            -
                wf.finish
         | 
| 48 | 
            -
                wf
         | 
| 49 | 
            -
              end
         | 
| 50 | 
            -
             | 
| 51 | 
            -
              def initialize(repo, name, parent = nil)
         | 
| 52 | 
            -
                @repo = repo
         | 
| 53 | 
            -
                @name = name
         | 
| 54 | 
            -
                if parent.nil?
         | 
| 55 | 
            -
                  @graph = GraphViz.new(qname)
         | 
| 56 | 
            -
                  @root = add_nodes(name)
         | 
| 57 | 
            -
                else
         | 
| 58 | 
            -
                  @graph = parent.subgraph(qname)
         | 
| 59 | 
            -
                  @root = parent.add_nodes(name)
         | 
| 60 | 
            -
                end
         | 
| 61 | 
            -
                @graph[:truecolor => true]
         | 
| 62 | 
            -
                @root.shape = 'plaintext'
         | 
| 63 | 
            -
                @processes = {}
         | 
| 64 | 
            -
              end
         | 
| 65 | 
            -
             | 
| 66 | 
            -
              def qname
         | 
| 67 | 
            -
                [@repo, @name].join(':')
         | 
| 68 | 
            -
              end
         | 
| 69 | 
            -
             | 
| 70 | 
            -
              def add_process(name, external = false)
         | 
| 71 | 
            -
                pqname = name.split(/:/).length == 3 ? name : [qname, name].join(':')
         | 
| 72 | 
            -
                p = Process.new(self, pqname, name)
         | 
| 73 | 
            -
                @processes[name] = p
         | 
| 74 | 
            -
                p
         | 
| 75 | 
            -
              end
         | 
| 76 | 
            -
             | 
| 77 | 
            -
              def finish
         | 
| 78 | 
            -
                @processes.values.each do |process|
         | 
| 79 | 
            -
                  process.node.fontname = 'Helvetica'
         | 
| 80 | 
            -
                  if process.id =~ %r{^#{qname}} && process.prerequisites.length == 0
         | 
| 81 | 
            -
                    (@root << process.node)[:arrowhead => 'none', :arrowtail => 'none', :dir => 'both', :style => 'invisible']
         | 
| 82 | 
            -
                  end
         | 
| 83 | 
            -
                end
         | 
| 84 | 
            -
             | 
| 85 | 
            -
                @root.fontname = 'Helvetica'
         | 
| 86 | 
            -
                self
         | 
| 87 | 
            -
              end
         | 
| 88 | 
            -
             | 
| 89 | 
            -
              def inspect
         | 
| 90 | 
            -
                "#{to_s[0..-2]} #{repo}:#{name} (#{processes.keys.join(', ')})>"
         | 
| 91 | 
            -
              end
         | 
| 92 | 
            -
             | 
| 93 | 
            -
              def method_missing(sym, *args)
         | 
| 94 | 
            -
                if @graph.respond_to?(sym)
         | 
| 95 | 
            -
                  @graph.send(sym, *args)
         | 
| 96 | 
            -
                else
         | 
| 97 | 
            -
                  super
         | 
| 98 | 
            -
                end
         | 
| 99 | 
            -
              end
         | 
| 100 | 
            -
             | 
| 101 | 
            -
              class Process
         | 
| 102 | 
            -
             | 
| 103 | 
            -
                attr_reader :name, :status, :node, :prerequisites
         | 
| 104 | 
            -
             | 
| 105 | 
            -
                def initialize(graph, id, name)
         | 
| 106 | 
            -
                  @name = name
         | 
| 107 | 
            -
                  @graph = graph
         | 
| 108 | 
            -
                  @node = @graph.add_nodes(id)
         | 
| 109 | 
            -
                  @node.shape = 'box'
         | 
| 110 | 
            -
                  @node.label = name
         | 
| 111 | 
            -
                  @prerequisites = []
         | 
| 112 | 
            -
                  set_status('unknown')
         | 
| 113 | 
            -
                end
         | 
| 114 | 
            -
             | 
| 115 | 
            -
                def id
         | 
| 116 | 
            -
                  @node.id
         | 
| 117 | 
            -
                end
         | 
| 118 | 
            -
             | 
| 119 | 
            -
                def status=(s)
         | 
| 120 | 
            -
                  @status = s
         | 
| 121 | 
            -
                  if s == 'external'
         | 
| 122 | 
            -
                    @node.fillcolor = 'gray'
         | 
| 123 | 
            -
                    @node.fontcolor = 'black'
         | 
| 124 | 
            -
                    @node.style = 'dashed'
         | 
| 125 | 
            -
                  else
         | 
| 126 | 
            -
                    @node.fillcolor = FILL_COLORS[s] || 'yellow'
         | 
| 127 | 
            -
                    @node.fontcolor = TEXT_COLORS[s]
         | 
| 128 | 
            -
                    @node.style = PATTERNS[s]
         | 
| 129 | 
            -
                  end
         | 
| 130 | 
            -
                end
         | 
| 131 | 
            -
             | 
| 132 | 
            -
                def set_status(s)
         | 
| 133 | 
            -
                  self.status = s
         | 
| 134 | 
            -
                  self
         | 
| 135 | 
            -
                end
         | 
| 136 | 
            -
             | 
| 137 | 
            -
                def depends_on(*processes)
         | 
| 138 | 
            -
                  wf1 = id.split(/:/)[0..1].join(':')
         | 
| 139 | 
            -
                  processes.each { |process|
         | 
| 140 | 
            -
                    wf2 = process.id.split(/:/)[0..1].join(':')
         | 
| 141 | 
            -
                    edge = (process.node << @node)
         | 
| 142 | 
            -
                    edge.dir = 'both'
         | 
| 143 | 
            -
                    edge.arrowhead = 'none'
         | 
| 144 | 
            -
                    edge.arrowtail = 'none'
         | 
| 145 | 
            -
                    edge.style = 'dashed' if wf1 != wf2
         | 
| 146 | 
            -
                    prerequisites << process
         | 
| 147 | 
            -
                  }
         | 
| 148 | 
            -
                  self
         | 
| 149 | 
            -
                end
         | 
| 150 | 
            -
             | 
| 151 | 
            -
                def same_as(process)
         | 
| 152 | 
            -
                  @node = process.node
         | 
| 153 | 
            -
                end
         | 
| 154 | 
            -
             | 
| 155 | 
            -
                def all_prerequisites
         | 
| 156 | 
            -
                  prerequisites.collect { |p| p.all_prerequisites + [p.name] }.flatten.uniq
         | 
| 157 | 
            -
                end
         | 
| 158 | 
            -
             | 
| 159 | 
            -
              end
         | 
| 160 | 
            -
             | 
| 161 | 
            -
            end
         | 
| 162 | 
            -
            end
         | 
| 163 | 
            -
            end
         |