dor-services 5.1.0 → 5.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +13 -5
  2. data/config/dev_console_env.rb +45 -32
  3. data/lib/dor-services.rb +52 -49
  4. data/lib/dor/datastreams/administrative_metadata_ds.rb +2 -2
  5. data/lib/dor/datastreams/content_metadata_ds.rb +114 -144
  6. data/lib/dor/datastreams/default_object_rights_ds.rb +10 -12
  7. data/lib/dor/datastreams/desc_metadata_ds.rb +4 -4
  8. data/lib/dor/datastreams/events_ds.rb +8 -8
  9. data/lib/dor/datastreams/identity_metadata_ds.rb +40 -23
  10. data/lib/dor/datastreams/rights_metadata_ds.rb +109 -0
  11. data/lib/dor/datastreams/role_metadata_ds.rb +4 -4
  12. data/lib/dor/datastreams/simple_dublin_core_ds.rb +6 -6
  13. data/lib/dor/datastreams/version_metadata_ds.rb +29 -10
  14. data/lib/dor/models/admin_policy_object.rb +3 -3
  15. data/lib/dor/models/describable.rb +5 -4
  16. data/lib/dor/models/editable.rb +29 -33
  17. data/lib/dor/models/embargoable.rb +1 -12
  18. data/lib/dor/models/governable.rb +4 -27
  19. data/lib/dor/models/identifiable.rb +60 -58
  20. data/lib/dor/models/item.rb +5 -9
  21. data/lib/dor/models/presentable.rb +15 -2
  22. data/lib/dor/models/processable.rb +34 -30
  23. data/lib/dor/models/publishable.rb +5 -14
  24. data/lib/dor/models/{releasable.rb → releaseable.rb} +59 -15
  25. data/lib/dor/models/rightsable.rb +25 -0
  26. data/lib/dor/models/versionable.rb +6 -3
  27. data/lib/dor/models/workflow_object.rb +4 -4
  28. data/lib/dor/services/cleanup_reset_service.rb +1 -2
  29. data/lib/dor/services/cleanup_service.rb +1 -1
  30. data/lib/dor/services/registration_service.rb +0 -3
  31. data/lib/dor/services/sdr_ingest_service.rb +1 -1
  32. data/lib/dor/services/search_service.rb +1 -1
  33. data/lib/dor/utils/sdr_client.rb +23 -0
  34. data/lib/dor/version.rb +1 -1
  35. data/lib/dor/workflow/document.rb +23 -22
  36. data/lib/tasks/rdoc.rake +4 -4
  37. metadata +113 -96
  38. data/config/environments/development.rb +0 -84
  39. data/config/environments/development.rb.old +0 -84
  40. data/config/environments/test.rb +0 -84
  41. data/lib/tasks/dor.rake +0 -39
@@ -1,20 +1,18 @@
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
- t.copyright :path => 'copyright/human', :index_as => [:facetable]
7
- t.use_statement :path => '/use/human[@type=\'useAndReproduction\']', :index_as => [:facetable]
8
-
6
+ t.copyright :path => 'copyright/human', :index_as => [:symbol]
7
+ t.use_statement :path => '/use/human[@type=\'useAndReproduction\']', :index_as => [:symbol]
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
-
18
16
  end
19
17
 
20
18
  define_template :creative_commons do |xml|
@@ -23,6 +21,7 @@ module Dor
23
21
  xml.machine(:type => "creativeCommons")
24
22
  }
25
23
  end
24
+
26
25
  def self.xml_template
27
26
  Nokogiri::XML::Builder.new do |xml|
28
27
  xml.rightsMetadata{
@@ -30,7 +29,7 @@ module Dor
30
29
  xml.machine{
31
30
  xml.world
32
31
  }
33
- }
32
+ }
34
33
  xml.access(:type => 'read'){
35
34
  xml.machine{
36
35
  xml.world
@@ -44,9 +43,8 @@ module Dor
44
43
  xml.copyright{
45
44
  xml.human
46
45
  }
47
-
48
- }
49
- end.doc
46
+ }
47
+ end.doc
48
+ end
50
49
  end
51
50
  end
52
- end
@@ -4,7 +4,7 @@ class DescMetadataDS < ActiveFedora::OmDatastream
4
4
  MODS_NS = 'http://www.loc.gov/mods/v3'
5
5
  set_terminology do |t|
6
6
  t.root :path => 'mods', :xmlns => MODS_NS, :index_as => [:not_searchable]
7
- t.originInfo :index_as => [:not_searchable] do
7
+ t.originInfo :index_as => [:not_searchable] do
8
8
  t.publisher :index_as => [:stored_searchable]
9
9
  t.date_created :path => 'dateCreated', :index_as => [:stored_searchable]
10
10
  t.place :index_as => [:not_searchable] do
@@ -31,9 +31,9 @@ class DescMetadataDS < ActiveFedora::OmDatastream
31
31
  def self.xml_template
32
32
  Nokogiri::XML::Builder.new do |xml|
33
33
  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'){
34
- xml.titleInfo{
35
- xml.title
36
- }
34
+ xml.titleInfo{
35
+ xml.title
36
+ }
37
37
  }
38
38
  end.doc
39
39
  end
@@ -3,12 +3,12 @@ class EventsDS < ActiveFedora::OmDatastream
3
3
  before_create :ensure_non_versionable
4
4
 
5
5
  set_terminology do |t|
6
- t.root(:path => "events")
6
+ t.root(:path => 'events')
7
7
  t.event do
8
- t.who :path => { :attribute => "who" }, :index_as => [:displayable, :not_searchable]
9
- t.type_ :path => { :attribute => "type" }, :index_as => [:displayable, :not_searchable]
10
- t.when :path => { :attribute => "when" }, :index_as => [:displayable, :not_searchable], :data_type => :date
11
- t.message :path => "text()", :index_as => [:displayable, :not_searchable]
8
+ t.who :path => { :attribute => 'who' }, :index_as => [:displayable, :not_searchable]
9
+ t.type_ :path => { :attribute => 'type' }, :index_as => [:displayable, :not_searchable]
10
+ t.when :path => { :attribute => 'when' }, :index_as => [:displayable, :not_searchable], :data_type => :date
11
+ t.message :path => 'text()', :index_as => [:displayable, :not_searchable]
12
12
  end
13
13
  end
14
14
 
@@ -21,7 +21,7 @@ class EventsDS < ActiveFedora::OmDatastream
21
21
  end
22
22
 
23
23
  def ensure_non_versionable
24
- self.versionable = "false"
24
+ self.versionable = 'false'
25
25
  end
26
26
 
27
27
  # Adds an event to the datastream
@@ -29,7 +29,7 @@ class EventsDS < ActiveFedora::OmDatastream
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
35
  ng_xml_will_change!
@@ -60,4 +60,4 @@ class EventsDS < ActiveFedora::OmDatastream
60
60
  end
61
61
 
62
62
  end
63
- end
63
+ end
@@ -4,18 +4,18 @@ class IdentityMetadataDS < ActiveFedora::OmDatastream
4
4
 
5
5
  set_terminology do |t|
6
6
  t.root(:path=>"identityMetadata")
7
- t.objectId :index_as => [:symbol, :searchable]
8
- t.objectType :index_as => [:symbol, :searchable, :facetable]
7
+ t.objectId :index_as => [:symbol]
8
+ t.objectType :index_as => [:symbol]
9
9
  t.objectLabel
10
10
  t.citationCreator
11
11
  t.sourceId
12
12
  t.otherId(:path => 'otherId') do
13
13
  t.name_(:path => { :attribute => 'name' })
14
14
  end
15
- t.agreementId :index_as => [:searchable, :facetable]
16
- t.tag :index_as => [:symbol, :searchable, :facetable]
15
+ t.agreementId :index_as => [:stored_searchable, :symbol]
16
+ t.tag :index_as => [:symbol]
17
17
  t.citationTitle
18
- t.objectCreator :index_as => [:searchable, :facetable]
18
+ t.objectCreator :index_as => [:stored_searchable, :symbol]
19
19
  t.adminPolicy :index_as => [:not_searchable]
20
20
  end
21
21
 
@@ -82,35 +82,52 @@ class IdentityMetadataDS < ActiveFedora::OmDatastream
82
82
 
83
83
  def to_solr(solr_doc=Hash.new, *args)
84
84
  super(solr_doc, *args)
85
+
85
86
  if digital_object.respond_to?(:profile)
86
- digital_object.profile.each_pair do |property,value|
87
- if property =~ /Date/
88
- add_solr_value(solr_doc, property.underscore, Time.parse(value).utc.xmlschema, :date, [:stored_searchable])
89
- else
90
- add_solr_value(solr_doc, property.underscore, value, :string, [:stored_searchable])
91
- end
87
+ digital_object.profile.each_pair do |property, value|
88
+ add_solr_value(solr_doc, property.underscore, value, (property =~ /Date/ ? :date : :symbol), [:stored_searchable])
92
89
  end
93
90
  end
91
+
94
92
  if sourceId.present?
95
- (name,id) = sourceId.split(/:/,2)
96
- add_solr_value(solr_doc, "dor_id", id, :string, [:searchable, :facetable])
97
- add_solr_value(solr_doc, "identifier", sourceId, :string, [:searchable, :facetable, :symbol])
98
- add_solr_value(solr_doc, "source_id", sourceId, :string, [:symbol, :searchable, :facetable])
93
+ (name, id) = sourceId.split(/:/, 2)
94
+ add_solr_value(solr_doc, "dor_id", id, :symbol, [:stored_searchable])
95
+ add_solr_value(solr_doc, "identifier", sourceId, :symbol, [:stored_searchable])
96
+ add_solr_value(solr_doc, "source_id", sourceId, :symbol, [])
99
97
  end
100
98
  otherId.compact.each { |qid|
101
- (name,id) = qid.split(/:/,2)
102
- add_solr_value(solr_doc, "dor_id", id, :string, [:searchable, :facetable])
103
- add_solr_value(solr_doc, "identifier", qid, :string, [:searchable, :facetable, :symbol])
104
- add_solr_value(solr_doc, "#{name}_id", id, :string, [:symbol, :searchable, :facetable])
99
+ # this section will solrize barcode and catkey, which live in otherId
100
+ (name, id) = qid.split(/:/, 2)
101
+ add_solr_value(solr_doc, "dor_id", id, :symbol, [:stored_searchable])
102
+ add_solr_value(solr_doc, "identifier", qid, :symbol, [:stored_searchable])
103
+ add_solr_value(solr_doc, "#{name}_id", id, :symbol, [])
105
104
  }
106
-
105
+
106
+ # do some stuff to make tags in general and project tags specifically more easily searchable and facetable
107
107
  self.find_by_terms(:tag).each { |tag|
108
- (top,rest) = tag.text.split(/:/,2)
108
+ (prefix, rest) = tag.text.split(/:/, 2)
109
+ prefix = prefix.downcase.strip.gsub(/\s/,'_')
109
110
  unless rest.nil?
110
- add_solr_value(solr_doc, "#{top.downcase.strip.gsub(/\s/,'_')}_tag", rest.strip, :string, [:symbol, :searchable, :facetable])
111
+ # this part will index a value in a field specific to the tag, e.g. registered_by_tag_*,
112
+ # book_tag_*, project_tag_*, remediated_by_tag_*, etc. project_tag_* and registered_by_tag_*
113
+ # definitley get used, but most don't. we can limit the prefixes that get solrized if things
114
+ # get out of hand.
115
+ add_solr_value(solr_doc, "#{prefix}_tag", rest.strip, :symbol, [])
116
+ end
117
+
118
+ # solrize each possible prefix for the tag, inclusive of the full tag.
119
+ # e.g., for a tag such as "A : B : C", this will solrize to an _ssim field
120
+ # that contains ["A", "A : B", "A : B : C"].
121
+ tag_parts = tag.text.split(/:/)
122
+ progressive_tag_prefix = ''
123
+ tag_parts.each_with_index do |part, index|
124
+ progressive_tag_prefix += " : " if index > 0
125
+ progressive_tag_prefix += part.strip
126
+ add_solr_value(solr_doc, "exploded_tag", progressive_tag_prefix, :symbol, [])
111
127
  end
112
128
  }
113
- solr_doc
129
+
130
+ return solr_doc
114
131
  end
115
132
  end #class
116
133
  end
@@ -0,0 +1,109 @@
1
+ module Dor
2
+ class RightsMetadataDS < ActiveFedora::OmDatastream
3
+ require 'dor/rights_auth'
4
+
5
+ attr_writer :dra_object
6
+
7
+ # This is separate from default_object_rights because
8
+ # (1) we cannot default to such a permissive state
9
+ # (2) this is real, not default
10
+ #
11
+ # Ultimately, default_object_rights should go away and APOs also use an instantation of this class
12
+
13
+ set_terminology do |t|
14
+ t.root :path => 'rightsMetadata', :index_as => [:not_searchable]
15
+ t.copyright :path => 'copyright/human', :index_as => [:symbol]
16
+ t.use_statement :path => '/use/human[@type=\'useAndReproduction\']', :index_as => [:symbol]
17
+
18
+ t.use do
19
+ t.machine
20
+ t.human
21
+ end
22
+
23
+ t.creative_commons :path => '/use/machine', :type => 'creativeCommons'
24
+ t.creative_commons_human :path => '/use/human[@type=\'creativeCommons\']'
25
+ end
26
+
27
+ define_template :creative_commons do |xml|
28
+ xml.use {
29
+ xml.human(:type => "creativeCommons")
30
+ xml.machine(:type => "creativeCommons")
31
+ }
32
+ end
33
+
34
+ def self.xml_template
35
+ Nokogiri::XML::Builder.new do |xml|
36
+ xml.rightsMetadata{
37
+ xml.access(:type => 'discover'){
38
+ xml.machine{ xml.none }
39
+ }
40
+ xml.access(:type => 'read'){
41
+ xml.machine{ xml.none } # dark default
42
+ }
43
+ xml.use{
44
+ xml.human(:type => 'useAndReproduction')
45
+ xml.human(:type => "creativeCommons")
46
+ xml.machine(:type => "creativeCommons")
47
+ }
48
+ xml.copyright{ xml.human }
49
+ }
50
+ end.doc
51
+ end
52
+
53
+ # just a wrapper to invalidate @dra_object
54
+ def content=(xml)
55
+ @dra_object = nil
56
+ super
57
+ end
58
+
59
+ def dra_object
60
+ @dra_object ||= Dor::RightsAuth.parse(self.ng_xml, true)
61
+ end
62
+
63
+ # @param rights [string] archetypical rights to assign: 'world', 'stanford', 'none' or 'dark'
64
+ # Moved from Governable
65
+ # slight misnomer: also sets discover rights!
66
+ # TODO: convert xpath reads to dra_object calls
67
+ def set_read_rights(rights)
68
+ raise(ArgumentError, "Argument '#{rights}' is not a recognized value") unless ['world','stanford','none','dark'].include? rights
69
+ rights_xml = self.ng_xml
70
+ if (rights_xml.search('//rightsMetadata/access[@type=\'read\']').length==0)
71
+ raise('The rights metadata stream doesnt contain an entry for machine read permissions. Consider populating it from the APO before trying to change it.')
72
+ end
73
+ label = rights=='dark' ? 'none' : 'world'
74
+ @dra_object = nil # until TODO complete, we'll expect to have to reparse after modification
75
+ rights_xml.search('//rightsMetadata/access[@type=\'discover\']/machine').each do |node|
76
+ node.children.remove
77
+ node.add_child Nokogiri::XML::Node.new(label,rights_xml)
78
+ end
79
+ rights_xml.search('//rightsMetadata/access[@type=\'read\']').each do |node|
80
+ node.children.remove
81
+ machine_node = Nokogiri::XML::Node.new('machine',rights_xml)
82
+ node.add_child(machine_node)
83
+ if rights == 'world'
84
+ machine_node.add_child Nokogiri::XML::Node.new(rights,rights_xml)
85
+ elsif rights == 'stanford'
86
+ group_node = Nokogiri::XML::Node.new('group',rights_xml)
87
+ group_node.content = "Stanford"
88
+ machine_node.add_child(group_node)
89
+ else # we know it is none or dark by the argument filter (first line)
90
+ machine_node.add_child Nokogiri::XML::Node.new('none',rights_xml)
91
+ end
92
+ end
93
+ end
94
+
95
+ def to_solr(solr_doc=Hash.new, *args)
96
+ super(solr_doc, *args)
97
+ dra = self.dra_object
98
+ solr_doc['rights_primary_ssi'] = dra.index_elements[:primary]
99
+ solr_doc['rights_errors_ssim'] = dra.index_elements[:errors] if dra.index_elements[:errors].size > 0
100
+ solr_doc['rights_characteristics_ssim'] = dra.index_elements[:terms] if dra.index_elements[:terms].size > 0
101
+ # suppress empties
102
+ %w[use_statement_ssim copyright_ssim].each do |key|
103
+ solr_doc[key] = solr_doc[key].reject{ |val| val.nil? || val == '' }.flatten unless solr_doc[key].nil?
104
+ end
105
+ solr_doc
106
+ end
107
+
108
+ end #class
109
+ end
@@ -37,11 +37,11 @@ class RoleMetadataDS < ActiveFedora::OmDatastream
37
37
  def to_solr(solr_doc=Hash.new, *args)
38
38
  self.find_by_xpath('/roleMetadata/role/*').each do |actor|
39
39
  role_type = actor.parent['type']
40
- val = [actor.at_xpath('identifier/@type'),actor.at_xpath('identifier/text()')].join ':'
41
- add_solr_value(solr_doc, "apo_role_#{actor.name}_#{role_type}", val, :string, [:searchable, :facetable, :symbol])
42
- add_solr_value(solr_doc, "apo_role_#{role_type}", val, :string, [:searchable, :facetable, :symbol])
40
+ val = [actor.at_xpath('identifier/@type'), actor.at_xpath('identifier/text()')].join ':'
41
+ add_solr_value(solr_doc, "apo_role_#{actor.name}_#{role_type}", val, :string, [:symbol])
42
+ add_solr_value(solr_doc, "apo_role_#{role_type}", val, :string, [:symbol])
43
43
  if ['dor-apo-manager','dor-apo-depositor'].include? role_type
44
- add_solr_value(solr_doc, "apo_register_permissions", val, :string, [:searchable, :facetable, :symbol])
44
+ add_solr_value(solr_doc, "apo_register_permissions", val, :string, [:symbol, :stored_searchable])
45
45
  end
46
46
  end
47
47
  solr_doc
@@ -3,9 +3,9 @@ class SimpleDublinCoreDs < ActiveFedora::OmDatastream
3
3
 
4
4
  set_terminology do |t|
5
5
  t.root(:path=>"dc", :xmlns=>"http://www.openarchives.org/OAI/2.0/oai_dc/", :schema=>"http://cosimo.stanford.edu/standards/oai_dc/v2/oai_dc.xsd", :namespace_prefix => 'oai_dc', :index_as => [:not_searchable])
6
- t.title( :index_as=>[:displayable, :facetable, :stored_searchable], :xmlns => "http://purl.org/dc/elements/1.1/", :namespace_prefix => 'dc')
7
- t.creator( :index_as=>[:displayable, :facetable, :stored_searchable], :xmlns => "http://purl.org/dc/elements/1.1/", :namespace_prefix => 'dc')
8
- t.identifier(:index_as=>[:displayable, :stored_searchable], :xmlns => "http://purl.org/dc/elements/1.1/", :namespace_prefix => 'dc')
6
+ t.title( :index_as=>[:stored_sortable, :stored_searchable], :xmlns => "http://purl.org/dc/elements/1.1/", :namespace_prefix => 'dc')
7
+ t.creator( :index_as=>[:stored_sortable, :stored_searchable], :xmlns => "http://purl.org/dc/elements/1.1/", :namespace_prefix => 'dc')
8
+ t.identifier(:index_as=>[:symbol, :stored_searchable], :xmlns => "http://purl.org/dc/elements/1.1/", :namespace_prefix => 'dc')
9
9
  end
10
10
 
11
11
  def self.xml_template
@@ -27,15 +27,15 @@ class SimpleDublinCoreDs < ActiveFedora::OmDatastream
27
27
  begin
28
28
  doc = super solr_doc, *args
29
29
 
30
- add_solr_value(doc, 'dc_title', self.title.first, :string, [:sortable])
31
- add_solr_value(doc, 'dc_creator', self.creator.first, :string, [:sortable])
30
+ add_solr_value(doc, 'dc_title', self.title.first, :string, [:stored_sortable, :stored_searchable])
31
+ add_solr_value(doc, 'dc_creator', self.creator.first, :string, [:stored_sortable, :stored_searchable])
32
32
 
33
33
  identifiers = {}
34
34
 
35
35
  self.identifier.each { |i| ns, val = i.split(":"); identifiers[ns] ||= val }
36
36
 
37
37
  identifiers.each do |ns, val|
38
- add_solr_value(doc, "dc_identifier_#{ns}", val, :string, [:sortable])
38
+ add_solr_value(doc, "dc_identifier_#{ns}", val, :string, [:stored_sortable, :stored_searchable])
39
39
  end
40
40
 
41
41
  return doc
@@ -107,7 +107,7 @@ module Dor
107
107
  end
108
108
  end
109
109
 
110
- # @return [Fixnum] value of the most current versionId
110
+ # @return [String] value of the most current versionId
111
111
  def current_version_id
112
112
  current_version=current_version_node
113
113
  if current_version.nil?
@@ -151,11 +151,6 @@ module Dor
151
151
  self.content = ng_xml.to_s
152
152
  end
153
153
 
154
- # @return [String] The value of the greatest versionId
155
- def current_version_id
156
- current_version_node[:versionId].to_s
157
- end
158
-
159
154
  # @return [Boolean] returns true if the current version has a tag and a description, false otherwise
160
155
  def current_version_closeable?
161
156
  current = current_version_node
@@ -168,9 +163,9 @@ module Dor
168
163
 
169
164
  # @return [String] The tag for the newest version
170
165
  def current_tag
171
- current_version_node[:tag].to_s
166
+ current_version_node[:tag].to_s
172
167
  end
173
-
168
+
174
169
  def tag_for_version(versionId)
175
170
  nodes=self.ng_xml.search('//version[@versionId=\''+versionId+'\']')
176
171
  if nodes.length == 1
@@ -179,6 +174,7 @@ module Dor
179
174
  ''
180
175
  end
181
176
  end
177
+
182
178
  # @return [String] The description for the specified version, or empty string if there is no description
183
179
  def description_for_version(versionId)
184
180
  nodes=self.ng_xml.search('//version[@versionId=\''+versionId+'\']')
@@ -188,7 +184,7 @@ module Dor
188
184
  ''
189
185
  end
190
186
  end
191
-
187
+
192
188
  # @return [String] The description for the current version
193
189
  def current_description
194
190
  desc_node=current_version_node.at_xpath('description')
@@ -197,7 +193,29 @@ module Dor
197
193
  end
198
194
  ''
199
195
  end
200
-
196
+
197
+ # Compares the current_version with the passed in known_version (usually SDRs version)
198
+ # If the known_version is greater than the current version, then all version nodes greater than the known_version are removed,
199
+ # then the current_version is incremented. This repairs the case where a previous call to open a new verison
200
+ # updates the versionMetadata datastream, but versioningWF is not initiated. Prevents the versions from getting
201
+ # out of synch with SDR
202
+ #
203
+ # @param [Integer] known_version object version you wish to synch to, usually SDR's version
204
+ # @param [Hash] opts optional parameters
205
+ # @option opts [String] :description describes the version change
206
+ # @option opts [Symbol] :significance which part of the version tag to increment
207
+ def sync_then_increment_version known_version, opts = {}
208
+ cv = current_version_id.to_i
209
+ raise Dor::Exception.new("Cannot sync to a version greater than current: #{cv}, requested #{known_version}") if cv < known_version
210
+
211
+ while cv != known_version &&
212
+ current_version_node.remove
213
+ cv = current_version_id.to_i
214
+ end
215
+
216
+ increment_version(opts[:description], opts[:significance])
217
+ end
218
+
201
219
  private
202
220
 
203
221
  # @return [Nokogiri::XML::Node] Node representing the current version
@@ -210,5 +228,6 @@ module Dor
210
228
  tags = find_by_terms(:version, :tag)
211
229
  tags.map{|t| VersionTag.parse(t.value)}.max
212
230
  end
231
+
213
232
  end
214
233
  end