dor-services 4.25.1 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/bin/dor-indexer +20 -19
  3. data/bin/dor-indexerd +3 -2
  4. data/config/certs/robots-dor-dev.crt +29 -0
  5. data/config/certs/robots-dor-dev.key +27 -0
  6. data/config/config_defaults.yml +0 -6
  7. data/config/dev_console_env.rb +65 -0
  8. data/config/environments/development.rb +84 -0
  9. data/config/environments/development.rb.old +84 -0
  10. data/config/environments/test.rb +84 -0
  11. data/lib/dor-services.rb +8 -18
  12. data/lib/dor/config.rb +18 -24
  13. data/lib/dor/datastreams/administrative_metadata_ds.rb +8 -7
  14. data/lib/dor/datastreams/content_metadata_ds.rb +200 -278
  15. data/lib/dor/datastreams/datastream_spec_solrizer.rb +1 -1
  16. data/lib/dor/datastreams/default_object_rights_ds.rb +10 -8
  17. data/lib/dor/datastreams/desc_metadata_ds.rb +30 -34
  18. data/lib/dor/datastreams/embargo_metadata_ds.rb +17 -13
  19. data/lib/dor/datastreams/events_ds.rb +12 -12
  20. data/lib/dor/datastreams/geo_metadata_ds.rb +3 -244
  21. data/lib/dor/datastreams/identity_metadata_ds.rb +34 -30
  22. data/lib/dor/datastreams/role_metadata_ds.rb +6 -6
  23. data/lib/dor/datastreams/simple_dublin_core_ds.rb +12 -9
  24. data/lib/dor/datastreams/version_metadata_ds.rb +14 -33
  25. data/lib/dor/datastreams/workflow_definition_ds.rb +18 -18
  26. data/lib/dor/datastreams/workflow_ds.rb +74 -65
  27. data/lib/dor/migrations/identifiable/assert_adminPolicy.rb +1 -1
  28. data/lib/dor/migrations/identifiable/fix_model_assertions.rb +1 -1
  29. data/lib/dor/migrations/identifiable/record_remediation.rb +2 -2
  30. data/lib/dor/migrations/identifiable/uriify_augmented_contentlocation_refs.rb +1 -1
  31. data/lib/dor/migrations/identifiable/uriify_contentlocation_refs.rb +1 -1
  32. data/lib/dor/migrations/processable/unify_workflows.rb +4 -4
  33. data/lib/dor/migrations/versionable/add_missing_version_md.rb +1 -1
  34. data/lib/dor/models/admin_policy_object.rb +1 -1
  35. data/lib/dor/models/assembleable.rb +3 -4
  36. data/lib/dor/models/collection.rb +0 -2
  37. data/lib/dor/models/contentable.rb +34 -35
  38. data/lib/dor/models/describable.rb +80 -122
  39. data/lib/dor/models/editable.rb +57 -73
  40. data/lib/dor/models/embargoable.rb +13 -15
  41. data/lib/dor/models/eventable.rb +3 -3
  42. data/lib/dor/models/geoable.rb +8 -9
  43. data/lib/dor/models/governable.rb +36 -54
  44. data/lib/dor/models/identifiable.rb +119 -115
  45. data/lib/dor/models/item.rb +4 -4
  46. data/lib/dor/models/itemizable.rb +9 -9
  47. data/lib/dor/models/presentable.rb +133 -0
  48. data/lib/dor/models/preservable.rb +4 -4
  49. data/lib/dor/models/processable.rb +29 -28
  50. data/lib/dor/models/publishable.rb +36 -30
  51. data/lib/dor/models/releasable.rb +310 -0
  52. data/lib/dor/models/shelvable.rb +14 -14
  53. data/lib/dor/models/upgradable.rb +13 -13
  54. data/lib/dor/models/versionable.rb +4 -7
  55. data/lib/dor/models/workflow_object.rb +16 -36
  56. data/lib/dor/services/cleanup_reset_service.rb +28 -34
  57. data/lib/dor/services/cleanup_service.rb +4 -4
  58. data/lib/dor/services/digital_stacks_service.rb +10 -10
  59. data/lib/dor/services/merge_service.rb +1 -1
  60. data/lib/dor/services/metadata_handlers/mdtoolkit_handler.rb +2 -2
  61. data/lib/dor/services/metadata_service.rb +20 -20
  62. data/lib/dor/services/registration_service.rb +26 -27
  63. data/lib/dor/services/reset_workspace_service.rb +15 -15
  64. data/lib/dor/services/sdr_ingest_service.rb +4 -4
  65. data/lib/dor/services/search_service.rb +4 -9
  66. data/lib/dor/services/suri_service.rb +5 -5
  67. data/lib/dor/services/technical_metadata_service.rb +3 -2
  68. data/lib/dor/utils/ng_tidy.rb +9 -9
  69. data/lib/dor/utils/predicate_patch.rb +1 -1
  70. data/lib/dor/utils/solr_doc_helper.rb +13 -5
  71. data/lib/dor/version.rb +1 -1
  72. data/lib/dor/workflow/document.rb +28 -30
  73. data/lib/dor/workflow/graph.rb +36 -36
  74. data/lib/dor/workflow/process.rb +12 -12
  75. data/lib/tasks/dor.rake +1 -1
  76. data/lib/tasks/rdoc.rake +3 -3
  77. metadata +67 -76
  78. data/lib/dor/datastreams/geo2mods.xsl +0 -867
  79. data/lib/dor/models/discoverable.rb +0 -64
  80. data/lib/dor/models/releaseable.rb +0 -357
  81. data/lib/dor/services/indexing_service.rb +0 -64
  82. data/lib/dor/utils/sdr_client.rb +0 -23
  83. data/lib/dor/utils/utc_date_field_mapper.rb +0 -7
@@ -1,7 +1,7 @@
1
1
  module DatastreamSpecSolrizer
2
2
  extend ActiveSupport::Concern
3
3
  include SolrDocHelper
4
-
4
+
5
5
  def datastream_spec_string
6
6
  s = begin
7
7
  controlGroup == 'E' ? content.to_s.length : size
@@ -1,18 +1,20 @@
1
1
  module Dor
2
- class DefaultObjectRightsDS < ActiveFedora::OmDatastream
2
+ class DefaultObjectRightsDS < ActiveFedora::OmDatastream
3
3
 
4
4
  set_terminology do |t|
5
5
  t.root :path => 'rightsMetadata', :index_as => [:not_searchable]
6
6
  t.copyright :path => 'copyright/human', :index_as => [:facetable]
7
7
  t.use_statement :path => '/use/human[@type=\'useAndReproduction\']', :index_as => [:facetable]
8
-
8
+
9
9
  t.use do
10
10
  t.machine
11
11
  t.human
12
12
  end
13
-
13
+
14
14
  t.creative_commons :path => '/use/machine', :type => 'creativeCommons'
15
15
  t.creative_commons_human :path => '/use/human[@type=\'creativeCommons\']'
16
+
17
+
16
18
  end
17
19
 
18
20
  define_template :creative_commons do |xml|
@@ -21,7 +23,6 @@ module Dor
21
23
  xml.machine(:type => "creativeCommons")
22
24
  }
23
25
  end
24
-
25
26
  def self.xml_template
26
27
  Nokogiri::XML::Builder.new do |xml|
27
28
  xml.rightsMetadata{
@@ -29,7 +30,7 @@ module Dor
29
30
  xml.machine{
30
31
  xml.world
31
32
  }
32
- }
33
+ }
33
34
  xml.access(:type => 'read'){
34
35
  xml.machine{
35
36
  xml.world
@@ -43,8 +44,9 @@ module Dor
43
44
  xml.copyright{
44
45
  xml.human
45
46
  }
46
- }
47
- end.doc
48
- end
47
+
48
+ }
49
+ end.doc
49
50
  end
50
51
  end
52
+ end
@@ -1,40 +1,36 @@
1
1
  module Dor
2
- class DescMetadataDS < ActiveFedora::OmDatastream
3
- include SolrDocHelper
4
-
5
- MODS_NS = 'http://www.loc.gov/mods/v3'
6
- set_terminology do |t|
7
- t.root :path => 'mods', :xmlns => MODS_NS, :index_as => [:not_searchable]
8
- t.originInfo :index_as => [:not_searchable] do
9
- t.publisher :index_as => [:searchable, :displayable]
10
- t.place :index_as => [:not_searchable] do
11
- t.placeTerm :attributes => {:type => 'text'}, :index_as => [:searchable, :displayable]
12
- end
2
+ class DescMetadataDS < ActiveFedora::OmDatastream
3
+
4
+ MODS_NS = 'http://www.loc.gov/mods/v3'
5
+ set_terminology do |t|
6
+ t.root :path => 'mods', :xmlns => MODS_NS, :index_as => [:not_searchable]
7
+ t.originInfo :index_as => [:not_searchable] do
8
+ t.publisher :index_as => [:searchable, :stored_searchable]
9
+ t.place :index_as => [:not_searchable] do
10
+ t.placeTerm :attributes => {:type => 'text'}, :index_as => [:searchable, :stored_searchable]
13
11
  end
14
- t.title_info(:path => 'titleInfo') {
15
- t.main_title(:index_as => [:facetable], :path => 'title', :label => 'title') {
16
- t.main_title_lang(:path => {:attribute => 'xml:lang'})
17
- }
18
- }
19
- t.language {
20
- t.languageTerm :attributes => {:type => 'code', :authority => 'iso639-2b'}, :index_as => [:not_searchable]
21
- }
22
- t.coordinates :index_as => [:searchable]
23
- t.extent :index_as => [:searchable]
24
- t.scale :index_as => [:searchable]
25
- t.topic :index_as => [:searchable]
26
- t.abstract :index_as => [:displayable]
27
12
  end
28
-
29
- def self.xml_template
30
- Nokogiri::XML::Builder.new do |xml|
31
- xml.mods( 'xmlns' => MODS_NS, 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', :version => '3.3', 'xsi:schemaLocation' => 'http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-3.xsd'){
32
- xml.titleInfo{
33
- xml.title
34
- }
13
+ t.title_info(:path=>"titleInfo") {
14
+ t.main_title(:index_as=>[:facetable],:path=>"title", :label=>"title") {
15
+ t.main_title_lang(:path=>{:attribute=> "xml:lang"})
16
+ }
17
+ }
18
+ t.coordinates :index_as => [:searchable]
19
+ t.extent :index_as => [:searchable]
20
+ t.scale :index_as => [:searchable]
21
+ t.topic :index_as => [:searchable]
22
+ t.abstract :index_as => [:displayable]
23
+ end
24
+
25
+ def self.xml_template
26
+ Nokogiri::XML::Builder.new do |xml|
27
+ xml.mods( 'xmlns' => 'http://www.loc.gov/mods/v3', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',:version => '3.3', "xsi:schemaLocation" => 'http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-3.xsd'){
28
+ xml.titleInfo{
29
+ xml.title
30
+ }
35
31
  }
36
- end.doc
37
- end
38
-
32
+ end.doc
39
33
  end
34
+
35
+ end
40
36
  end
@@ -1,15 +1,15 @@
1
1
  module Dor
2
2
  class EmbargoMetadataDS < ActiveFedora::OmDatastream
3
- include SolrDocHelper
4
3
 
5
4
  before_create :ensure_non_versionable
6
5
 
7
6
  set_terminology do |t|
8
7
  t.root(:path => "embargoMetadata")
9
- t.status(:index_as => [:searchable, :facetable])
10
- t.release_date(:path => "releaseDate")
8
+ t.status
9
+ t.embargo_status(:path => 'status', :index_as => [:symbol])
10
+ t.release_date(:path => "releaseDate", :index_as => [:dateable])
11
11
  t.release_access(:path => "releaseAccess")
12
- t.twenty_pct_status( :path => "twentyPctVisibilityStatus", :index_as => [:searchable, :facetable])
12
+ t.twenty_pct_status( :path => "twentyPctVisibilityStatus", :index_as => [:facetable])
13
13
  t.twenty_pct_release_date(:path => "twentyPctVisibilityReleaseDate")
14
14
  end
15
15
 
@@ -24,14 +24,16 @@ class EmbargoMetadataDS < ActiveFedora::OmDatastream
24
24
  xml.twentyPctVisibilityReleaseDate
25
25
  }
26
26
  end
27
- builder.doc
27
+ return builder.doc
28
28
  end
29
29
 
30
30
  def to_solr solr_doc = {}, *args
31
31
  super
32
- add_solr_value(solr_doc, 'embargo_release_date', release_date.utc.strftime('%FT%TZ') , :date, [:searchable]) rescue nil
33
- add_solr_value(solr_doc, 'twenty_pct_visibility_release_date', twenty_pct_release_date.utc.strftime('%FT%TZ') , :date, [:searchable]) rescue nil
34
-
32
+ #::Solrizer.insert_field(solr_doc, field_name, value, *index_types)
33
+ rd1 = self.release_date
34
+ rd20 = self.twenty_pct_release_date
35
+ ::Solrizer.insert_field(solr_doc, 'embargo_release', rd1.utc.strftime('%FT%TZ'), :dateable) unless rd1.nil?
36
+ ::Solrizer.insert_field(solr_doc, 'twenty_pct_visibility_release', rd20.utc.strftime('%FT%TZ'), :dateable) unless rd20.nil?
35
37
  solr_doc
36
38
  end
37
39
 
@@ -54,15 +56,16 @@ class EmbargoMetadataDS < ActiveFedora::OmDatastream
54
56
 
55
57
  # Sets the release date. Converts the date to beginning-of-day, UTC to help with Solr indexing
56
58
  # @param [Time] rd A Time object represeting the release date. By default, it is set to now
57
- def release_date=(rd = Time.now)
59
+ def release_date=(rd=Time.now)
58
60
  update_values([:release_date] => rd.beginning_of_day.utc.xmlschema)
59
- self.content=ng_xml.to_s
61
+ self.content=self.ng_xml.to_s
60
62
  end
61
63
 
62
64
  # Current releaseDate value
63
65
  # @return [Time]
64
66
  def release_date
65
- Time.parse(term_values(:release_date).first)
67
+ rd = term_values(:release_date).first
68
+ return (rd.nil? || rd.empty?) ? nil : Time.parse(rd)
66
69
  end
67
70
 
68
71
  def twenty_pct_status=(new_status)
@@ -76,7 +79,7 @@ class EmbargoMetadataDS < ActiveFedora::OmDatastream
76
79
 
77
80
  # Sets the 20% visibility release date. Converts the date to beginning-of-day, UTC to help with Solr indexing
78
81
  # @param [Time] rd A Time object represeting the release date. By default, it is set to now
79
- def twenty_pct_release_date=(rd = Time.now)
82
+ def twenty_pct_release_date=(rd=Time.now)
80
83
  update_values([:twenty_pct_release_date] => rd.beginning_of_day.utc.xmlschema)
81
84
  content_will_change!
82
85
  end
@@ -84,7 +87,8 @@ class EmbargoMetadataDS < ActiveFedora::OmDatastream
84
87
  # Current twentyPctVisibilityReleaseDate value
85
88
  # @return [Time]
86
89
  def twenty_pct_release_date
87
- Time.parse(term_values(:twenty_pct_release_date).first)
90
+ rd = term_values(:twenty_pct_release_date).first
91
+ return (rd.nil? || rd.empty?) ? nil : Time.parse(rd)
88
92
  end
89
93
 
90
94
  # @return [Nokogiri::XML::Element] The releaseAccess node
@@ -1,7 +1,7 @@
1
1
  module Dor
2
2
  class EventsDS < ActiveFedora::OmDatastream
3
3
  before_create :ensure_non_versionable
4
-
4
+
5
5
  set_terminology do |t|
6
6
  t.root(:path => "events")
7
7
  t.event do
@@ -11,30 +11,30 @@ class EventsDS < ActiveFedora::OmDatastream
11
11
  t.message :path => "text()", :index_as => [:displayable, :not_searchable]
12
12
  end
13
13
  end
14
-
15
- # Default EventsDS xml
14
+
15
+ # Default EventsDS xml
16
16
  def self.xml_template
17
17
  builder = Nokogiri::XML::Builder.new do |xml|
18
18
  xml.events
19
19
  end
20
- builder.doc
20
+ return builder.doc
21
21
  end
22
-
22
+
23
23
  def ensure_non_versionable
24
24
  self.versionable = "false"
25
25
  end
26
-
26
+
27
27
  # Adds an event to the datastream
28
28
  # @param [String] type a tag used to group events together. Sets the type attribute for the event
29
29
  # @param [String] who who is responsible for this event. Sets the who attribute for the event
30
30
  # @param [String] message what happened. Sets the content of the event with this message
31
31
  def add_event(type, who, message)
32
- ev = ng_xml.create_element "event", message,
32
+ ev = ng_xml.create_element "event", message,
33
33
  :type => type, :who => who, :when => Time.now.xmlschema
34
34
  ng_xml.root.add_child(ev)
35
- content_will_change!
35
+ ng_xml_will_change!
36
36
  end
37
-
37
+
38
38
  # Finds events with the desired type attribute
39
39
  # @param [String] tag events where type == tag will be returned
40
40
  # @yield [who, timestamp, message] The values of the current event
@@ -46,7 +46,7 @@ class EventsDS < ActiveFedora::OmDatastream
46
46
  block.call(node['who'], Time.parse(node['when']), node.content)
47
47
  end
48
48
  end
49
-
49
+
50
50
  # Returns all the events in the datastream
51
51
  # @yield [type, who, timestamp, message] The values of the current event
52
52
  # @yieldparam [String] type tag for this particular event. Value of the 'type' attribute
@@ -58,6 +58,6 @@ class EventsDS < ActiveFedora::OmDatastream
58
58
  block.call(node['type'], node['who'], Time.parse(node['when']), node.content)
59
59
  end
60
60
  end
61
-
62
- end
61
+
63
62
  end
63
+ end
@@ -9,10 +9,7 @@ module Dor
9
9
  # The datastream is packaged using RDF to identify the optional ISO 19139 feature catalog
10
10
  # @see http://www.isotc211.org
11
11
  # @author Darren Hardy
12
- class GeoMetadataDS < ActiveFedora::NokogiriDatastream
13
- include SolrDocHelper
14
-
15
- attr_accessor :geometryType, :zipName, :purl
12
+ class GeoMetadataDS < ActiveFedora::OmDatastream
16
13
 
17
14
  # namespaces
18
15
  NS = {
@@ -28,52 +25,6 @@ module Dor
28
25
  # schema locations
29
26
  NS_XSD = NS.keys.collect {|k| "#{NS[k]} #{NS[k]}/#{k}.xsd"}
30
27
 
31
- # [Nokogiri::XSLT::Stylesheet] for ISO 19139 to MODS
32
- XSLT_GEOMODS = Nokogiri::XSLT(File.read(
33
- File.join(
34
- File.dirname(__FILE__), 'geo2mods.xsl')))
35
-
36
- XSLT_DC = Nokogiri::XSLT(File.new(
37
- File.expand_path(
38
- File.dirname(__FILE__) + '/../models/mods2dc.xslt')))
39
-
40
- # @see http://ruby-doc.org/gems/docs/o/om-1.8.0/OM/XML/Document/ClassMethods.html#method-i-set_terminology
41
- set_terminology do |t|
42
- t.root :path => '/rdf:RDF/rdf:Description/gmd:MD_Metadata',
43
- 'xmlns:gmd' => NS[:gmd],
44
- 'xmlns:gco' => NS[:gco],
45
- 'xmlns:rdf' => NS[:rdf]
46
-
47
- t.id_ :path => '/rdf:RDF/rdf:Description[1]/@rdf:about'
48
-
49
- p = './'
50
- t.dataset_id :path => p + 'gmd:dataSetURI/gco:CharacterString'
51
- t.file_id :path => p + 'gmd:fileIdentifier/gco:CharacterString'
52
- t.metadata_dt :path => p + 'gmd:dateStamp/gco:Date/text()' # XXX: Allow DateTime
53
- t.metadata_language :path => p + 'gmd:MD_Metadata/gmd:language/gmd:LanguageCode[@codeSpace="ISO639-2"]/@codeListValue'
54
-
55
- p = 'gmd:identificationInfo/gmd:MD_DataIdentification/'
56
- t.abstract :path => p + 'gmd:abstract/gco:CharacterString/text()'
57
- t.purpose :path => p + 'gmd:purpose/gco:CharacterString/text()'
58
- t.publisher :path => p + 'gmd:pointOfContact/gmd:CI_ResponsibleParty[gmd:role/gmd:CI_RoleCode/@codeListValue="pointOfContact"]/gmd:organisationName/gco:CharacterString/text()'
59
-
60
- p = 'gmd:identificationInfo/gmd:MD_DataIdentification/gmd:citation/gmd:CI_Citation/'
61
- t.title :path => p + 'gmd:title/gco:CharacterString/text()'
62
- t.publish_dt :path => p + 'gmd:date/gmd:CI_Date/gmd:date/gco:Date/text()'
63
- t.originator :path => p + 'gmd:citedResponsibleParty/gmd:CI_ResponsibleParty[gmd:role/gmd:CI_RoleCode/@codeListValue="originator"]/gmd:organisationName/gco:CharacterString/text()'
64
-
65
- p = 'gmd:distributionInfo/gmd:MD_Distribution/gmd:distributionFormat/gmd:MD_Format/'
66
- t.format :path => p + 'gmd:name/gco:CharacterString/text()'#, :index_as => [:facetable]
67
-
68
- p = 'gmd:distributionInfo/gmd:MD_Distribution/gmd:transferOptions/gmd:MD_DigitalTransferOptions/gmd:onLine/gmd:CI_OnlineResource/'
69
- t.layername :path => p + 'gmd:name/gco:CharacterString/text()'
70
-
71
- # XXX should define projection as codeSpace + ':' + code in terminology
72
- p = 'gmd:referenceSystemInfo/gmd:MD_ReferenceSystem/gmd:referenceSystemIdentifier/gmd:RS_Identifier/'
73
- t.projection :path => p + 'gmd:code/gco:CharacterString/text()'
74
- t.projection_code_space :path => p + 'gmd:codeSpace/gco:CharacterString/text()'
75
- end
76
-
77
28
  # @return [Nokogiri::XML::Document] with gmd:MD_Metadata as root node
78
29
  # @raise [Dor::ParameterError] if MD_Metadata is missing
79
30
  def metadata
@@ -85,7 +36,8 @@ module Dor
85
36
  end
86
37
  end
87
38
 
88
- # @return [Nokogiri::XML::Document] with gfc:FC_FeatureCatalogue as root node or nil if not provided
39
+ # @return [Nokogiri::XML::Document] with gfc:FC_FeatureCatalogue as root node,
40
+ # or nil if not provided
89
41
  def feature_catalogue
90
42
  root = ng_xml.xpath('/rdf:RDF/rdf:Description/gfc:FC_FeatureCatalogue', XMLNS)
91
43
  if root.nil? || root.empty?
@@ -113,92 +65,6 @@ module Dor
113
65
  end.doc
114
66
  end
115
67
 
116
- # Generates MODS from ISO 19139
117
- #
118
- # @return [Nokogiri::XML::Document] Derived MODS metadata record
119
- # @raise [CrosswalkError] Raises if the generated MODS is empty or has no children
120
- #
121
- # Uses GML SimpleFeatures for the geometry type (e.g., Polygon, LineString, etc.)
122
- # @see http://portal.opengeospatial.org/files/?artifact_id=25355
123
- #
124
- def to_mods(params = {})
125
- params = params.merge({
126
- 'geometryType' => "'#{@geometryType.nil?? 'Polygon' : @geometryType}'",
127
- 'zipName' => "'#{@zipName.nil?? 'data.zip' : @zipName}'",
128
- 'purl' => "'#{@purl}'"
129
- })
130
- doc = XSLT_GEOMODS.transform(metadata.document, params.to_a.flatten)
131
- unless doc.root && doc.root.children.size > 0
132
- raise CrosswalkError, 'to_mods produced incorrect xml'
133
- end
134
- # ap doc
135
- doc.xpath('/mods:mods' +
136
- '/mods:subject' +
137
- '/mods:cartographics' +
138
- '/mods:projection',
139
- 'xmlns:mods' => Dor::DescMetadataDS::MODS_NS).each do |e|
140
- # Retrieve this mapping from config file
141
- case e.content.downcase
142
- when 'epsg:4326', 'epsg::4326', 'urn:ogc:def:crs:epsg::4326'
143
- e.content = 'World Geodetic System (WGS84)'
144
- when 'epsg:4269', 'epsg::4269', 'urn:ogc:def:crs:epsg::4269'
145
- e.content = 'North American Datum (NAD83)'
146
- end
147
- end
148
- doc.xpath('/mods:mods' +
149
- '/mods:subject' +
150
- '/mods:cartographics' +
151
- '/mods:coordinates',
152
- 'xmlns:mods' => Dor::DescMetadataDS::MODS_NS).each do |e|
153
- e.content = '(' + self.class.to_coordinates_ddmmss(e.content.to_s) + ')'
154
- end
155
- doc
156
- end
157
-
158
- def to_dublin_core
159
- XSLT_DC.transform(to_mods)
160
- end
161
-
162
- # @deprecated stub for GeoBlacklight (not Argo -- use to_solr as usual)
163
- def to_solr_spatial(solr_doc = {}, *args)
164
- # There are a whole bunch of namespace-related things that can go
165
- # wrong with this terminology. Until it's fixed in OM, ignore them all.
166
- begin
167
- doc = solr_doc # super solr_doc, *args
168
- bb = to_bbox
169
- ap({:doc => doc, :bb => bb, :self => self}) if $DEBUG
170
- # self is required once below, because format is a keyword
171
- {
172
- :id => id.first,
173
- :druid => URI(id.first).path.gsub(%r{^/}, ''),
174
- :file_id_s => file_id.first,
175
- :geo_bbox => to_solr_bbox,
176
- :geo_data_type_s => 'vector',
177
- :geo_format_s => self.format.first, # rubocop:disable Style/RedundantSelf
178
- :geo_geometry_type_s => 'Polygon',
179
- :geo_layername_s => File.basename(layername.first, '.shp'),
180
- :geo_ne_pt => Dor::GeoMetadataDS.to_wkt([bb.e, bb.n]),
181
- :geo_pt => to_solr_centroid,
182
- :geo_sw_pt => Dor::GeoMetadataDS.to_wkt([bb.w, bb.s]),
183
- :geo_proj => projection.first,
184
- :dc_coverage_t => to_dc_coverage,
185
- :dc_creator_t => originator.first,
186
- :dc_date_i => publish_dt.map {|i| i.to_s[0..3]},
187
- :dc_description_t => [abstract.first, purpose.first].join(";\n"),
188
- :dc_format_s => 'application/x-esri-shapefile',
189
- :dc_language_s => metadata_language.first,
190
- :dc_title_t => title.first,
191
- :text => [title.first, abstract.first, purpose.first].join(";\n")
192
- }.each do |id, v|
193
- ::Solrizer::Extractor.insert_solr_field_value(doc, id.to_s, v)
194
- end
195
-
196
- return doc
197
- rescue
198
- solr_doc
199
- end
200
- end
201
-
202
68
  # @return [Struct] in minX minY maxX maxY order
203
69
  # with .w, .e, .n., .s for west, east, north, south as floats
204
70
  def to_bbox
@@ -213,112 +79,5 @@ module Dor
213
79
  bb.xpath('gmd:southBoundLatitude/gco:Decimal', params).text.to_f
214
80
  )
215
81
  end
216
-
217
- # @return [Array<Numeric>] (x y) coordinates of center point - assumes #to_bbox
218
- # @see http://wiki.apache.org/solr/SolrAdaptersForLuceneSpatial4
219
- def to_centroid
220
- bb = to_bbox
221
- [ (bb.w + bb.e)/2, (bb.n + bb.s)/2 ]
222
- end
223
-
224
- # A lat-lon rectangle can be indexed with 4 numbers in minX minY maxX maxY order:
225
- #
226
- # <field name="geo">-74.093 41.042 -69.347 44.558</field>
227
- # <field name="geo">POLYGON((...))</field>
228
- #
229
- # @param [Symbol] either :solr3 or :solr4
230
- # @return [String] minX minY maxX maxY for :solr3 or POLYGON((...)) for :solr4
231
- # @see http://wiki.apache.org/solr/SolrAdaptersForLuceneSpatial4
232
- def to_solr_bbox format = :solr4
233
- bb = to_bbox
234
-
235
- case format
236
- when :solr3
237
- [bb.w, bb.s, bb.e, bb.n].join(' ')
238
- when :solr4
239
- Dor::GeoMetadataDS.to_wkt [bb.w, bb.s], [bb.e, bb.n]
240
- else
241
- raise ArgumentError, "Unsupported format #{format}"
242
- end
243
- end
244
-
245
- # @return [String] in Dublin Core Coverage format
246
- def to_dc_coverage
247
- bb = to_bbox
248
- "x.min=#{bb.w} x.max=#{bb.e} y.min=#{bb.s} y.max=#{bb.n}"
249
- end
250
-
251
- # A lat-lon point for the centroid of the bounding box:
252
- #
253
- # <field name="geo">69.4325,-78.085007</field>
254
- # <field name="geo">POINT(-78.085007 69.4325)</field>
255
- #
256
- # @param [Symbol] either :solr3 or :solr4
257
- # @return [String] minX minY maxX maxY for :solr3 or POLYGON((...)) for :solr4
258
- # @see http://wiki.apache.org/solr/SolrAdaptersForLuceneSpatial4
259
-
260
- # @return [String] (y,x) coordinates of center point matching the LatLonType Solr type
261
- # @see http://wiki.apache.org/solr/SolrAdaptersForLuceneSpatial4
262
- def to_solr_centroid format = :solr4
263
- x, y = to_centroid
264
-
265
- case format
266
- when :solr3
267
- [y, x].join(',') # for solr.LatLonType
268
- when :solr4
269
- Dor::GeoMetadataDS.to_wkt [x, y]
270
- else
271
- raise ArgumentError, "Unsupported format #{format}"
272
- end
273
- end
274
-
275
- # Class Methods
276
-
277
- # @param [Array<Numeric>] (x,y) coordinates for point or bounding box
278
- # @return [String] WKT for point or rectangle
279
- def self.to_wkt xy, xy2 = nil
280
- if xy2
281
- w = [xy[0], xy2[0]].min
282
- e = [xy[0], xy2[0]].max
283
- s = [xy[1], xy2[1]].min
284
- n = [xy[1], xy2[1]].max
285
- "POLYGON((#{w} #{s}, #{w} #{n}, #{e} #{n}, #{e} #{s}, #{w} #{s}))"
286
- else
287
- "POINT(#{xy[0]} #{xy[1]})"
288
- end
289
- end
290
-
291
- # Convert to MARC 255 DD into DDMMSS
292
- # westernmost longitude, easternmost longitude, northernmost latitude, and southernmost latitude
293
- # e.g., -109.758319 -- -88.990844/48.999336 -- 29.423028
294
- def self.to_coordinates_ddmmss s
295
- w, e, n, s = s.scanf('%f -- %f/%f -- %f')
296
- raise ArgumentError, "Out of bounds latitude: #{n} #{s}" unless n >= -90 && n <= 90 && s >= -90 && s <= 90
297
- raise ArgumentError, "Out of bounds longitude: #{w} #{e}" unless w >= -180 && w <= 180 && e >= -180 && e <= 180
298
- w = "#{w < 0 ? 'W' : 'E'} #{Dor::GeoMetadataDS::dd2ddmmss_abs w}"
299
- e = "#{e < 0 ? 'W' : 'E'} #{Dor::GeoMetadataDS::dd2ddmmss_abs e}"
300
- n = "#{n < 0 ? 'S' : 'N'} #{Dor::GeoMetadataDS::dd2ddmmss_abs n}"
301
- s = "#{s < 0 ? 'S' : 'N'} #{Dor::GeoMetadataDS::dd2ddmmss_abs s}"
302
- "#{w}--#{e}/#{n}--#{s}"
303
- end
304
-
305
- # Convert DD.DD to DD MM SS.SS
306
- # e.g.,
307
- # * -109.758319 => 109°45ʹ29.9484ʺ
308
- # * 48.999336 => 48°59ʹ57.609ʺ
309
- E = 1
310
- QSEC = 'ʺ'
311
- QMIN = 'ʹ'
312
- QDEG = "\u00B0"
313
- def self.dd2ddmmss_abs f
314
- dd = f.to_f.abs
315
- d = dd.floor
316
- mm = (dd - d) * 60
317
- m = mm.floor
318
- s = ((mm - mm.floor) * 60).round
319
- m, s = m + 1, 0 if s >= 60
320
- d, m = d + 1, 0 if m >= 60
321
- "#{d}#{QDEG}" + (m > 0 ? "#{m}#{QMIN}" : '') + (s > 0 ? "#{s}#{QSEC}" : '')
322
- end
323
82
  end
324
83
  end