dor-services 4.6.6.3 → 4.6.7
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.
- data/config/dev_console_env.rb +1 -0
- data/lib/dor/config.rb +1 -1
- data/lib/dor/datastreams/content_metadata_ds.rb +0 -1
- data/lib/dor/datastreams/geo2mods.xsl +59 -34
- data/lib/dor/models/describable.rb +1 -3
- data/lib/dor/models/processable.rb +56 -47
- data/lib/dor/models/publishable.rb +1 -3
- data/lib/dor/models/shelvable.rb +12 -49
- data/lib/dor/services/digital_stacks_service.rb +25 -111
- data/lib/dor/version.rb +1 -1
- metadata +8 -14
data/config/dev_console_env.rb
CHANGED
data/lib/dor/config.rb
CHANGED
@@ -88,7 +88,7 @@ module Dor
|
|
88
88
|
config[:stomp][:host] ||= URI.parse(config.fedora.url).host rescue nil
|
89
89
|
|
90
90
|
[:cert_file, :key_file, :key_pass].each do |key|
|
91
|
-
stack = caller.dup
|
91
|
+
stack = Kernel.caller.dup
|
92
92
|
stack.shift while stack[0] =~ %r{(active_support/callbacks|dor/config|dor-services)\.rb}
|
93
93
|
if config.fedora[key].present?
|
94
94
|
ActiveSupport::Deprecation.warn "Dor::Config -- fedora.#{key.to_s} is deprecated. Please use ssl.#{key.to_s} instead.", stack
|
@@ -6,7 +6,6 @@ module Dor
|
|
6
6
|
set_terminology do |t|
|
7
7
|
t.root :path => 'contentMetadata', :index_as => [:not_searchable]
|
8
8
|
t.contentType :path => '/contentMetadata/@type', :index_as => [:not_searchable]
|
9
|
-
t.stacks :path=> '/contentMetadata/@stacks', :index_as => [:not_searchable]
|
10
9
|
t.resource(:index_as => [:not_searchable]) do
|
11
10
|
t.id_ :path => { :attribute => 'id' }
|
12
11
|
t.sequence :path => { :attribute => 'sequence' }#, :data_type => :integer
|
@@ -3,7 +3,7 @@
|
|
3
3
|
geo2mods.xsl - Transformation from ISO 19139 XML into MODS v3
|
4
4
|
|
5
5
|
|
6
|
-
Copyright 2013, The Board of Trustees of the Leland Stanford Junior University
|
6
|
+
Copyright 2013-2014, The Board of Trustees of the Leland Stanford Junior University
|
7
7
|
|
8
8
|
Licensed under the Apache License, Version 2.0 (the "License");
|
9
9
|
you may not use this file except in compliance with the License.
|
@@ -26,7 +26,6 @@
|
|
26
26
|
http://www.schemacentral.com/sc/niem21/t-gml32_GeometryPropertyType.html
|
27
27
|
* purl - e.g., http://purl.stanford.edu/aa111bb2222
|
28
28
|
* zipName - e.g., data.zip
|
29
|
-
* format - e.g., MIME type application/x-esri-shapefile
|
30
29
|
|
31
30
|
TODO:
|
32
31
|
* Series statements may need work?
|
@@ -41,7 +40,6 @@
|
|
41
40
|
version="1.0" exclude-result-prefixes="gml gmd gco gmi xsl">
|
42
41
|
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
|
43
42
|
<xsl:strip-space elements="*"/>
|
44
|
-
<xsl:param name="format" select="'application/x-esri-shapefile'"/>
|
45
43
|
<xsl:param name="geometryType"/>
|
46
44
|
<xsl:param name="purl"/>
|
47
45
|
<xsl:param name="zipName" select="'data.zip'"/>
|
@@ -51,15 +49,27 @@
|
|
51
49
|
-->
|
52
50
|
<xsl:param name="geoformat" select="'MARC255'"/>
|
53
51
|
<xsl:param name="fileIdentifier" select="''"/>
|
52
|
+
<xsl:variable name="format">
|
53
|
+
<xsl:choose>
|
54
|
+
<xsl:when test="contains(gmd:MD_Metadata/gmd:distributionInfo/gmd:MD_Distribution/gmd:distributionFormat/gmd:MD_Format/gmd:name, 'Raster Dataset')">
|
55
|
+
<xsl:text>image/tiff</xsl:text>
|
56
|
+
</xsl:when>
|
57
|
+
<xsl:when test="contains(gmd:MD_Metadata/gmd:distributionInfo/gmd:MD_Distribution/gmd:distributionFormat/gmd:MD_Format/gmd:name, 'GeoTIFF')">
|
58
|
+
<xsl:text>image/tiff</xsl:text>
|
59
|
+
</xsl:when>
|
60
|
+
<xsl:when test="contains(gmd:MD_Metadata/gmd:distributionInfo/gmd:MD_Distribution/gmd:distributionFormat/gmd:MD_Format/gmd:name, 'Shapefile')">
|
61
|
+
<xsl:text>application/x-esri-shapefile</xsl:text>
|
62
|
+
</xsl:when>
|
63
|
+
</xsl:choose>
|
64
|
+
</xsl:variable>
|
54
65
|
<xsl:template match="/">
|
55
66
|
<mods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.loc.gov/mods/v3" xmlns:xlink="http://www.w3.org/1999/xlink" version="3.4" xsi:schemaLocation="http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-4.xsd">
|
56
67
|
<xsl:for-each select="/gmi:MI_Metadata|/gmd:MD_Metadata|//gmd:MD_Metadata">
|
57
68
|
<xsl:if test="gmd:fileIdentifier/gco:CharacterString/text()">
|
58
69
|
<xsl:variable name="fileIdentifier" select="."/>
|
59
70
|
</xsl:if>
|
60
|
-
|
61
|
-
|
62
|
-
</xsl:if>
|
71
|
+
<xsl:variable name="purl" select="gmd:dataSetURI"/>
|
72
|
+
|
63
73
|
<titleInfo>
|
64
74
|
<title>
|
65
75
|
<xsl:apply-templates select="gmd:identificationInfo/gmd:MD_DataIdentification/gmd:citation/gmd:CI_Citation/gmd:title"/>
|
@@ -153,21 +163,8 @@
|
|
153
163
|
</xsl:choose>
|
154
164
|
</dateIssued>
|
155
165
|
|
156
|
-
|
157
|
-
|
158
|
-
<xsl:if test="gmd:identificationInfo/gmd:MD_DataIdentification/gmd:extent/gmd:EX_Extent/gmd:temporalElement/gmd:EX_TemporalExtent/gmd:extent/gml:TimePeriod">
|
159
|
-
<dateValid>
|
160
|
-
<xsl:attribute name="point">start</xsl:attribute>
|
161
|
-
|
162
|
-
<xsl:value-of select="substring-before(gmd:identificationInfo/gmd:MD_DataIdentification/gmd:extent/gmd:EX_Extent/gmd:temporalElement/gmd:EX_TemporalExtent/gmd:extent/gml:TimePeriod/gml:beginPosition, 'T')"/>
|
163
|
-
</dateValid>
|
164
|
-
<dateValid>
|
165
|
-
<xsl:attribute name="point">end</xsl:attribute>
|
166
|
-
<xsl:value-of select="substring-before(gmd:identificationInfo/gmd:MD_DataIdentification/gmd:extent/gmd:EX_Extent/gmd:temporalElement/gmd:EX_TemporalExtent/gmd:extent/gml:TimePeriod/gml:endPosition, 'T')"/>
|
167
|
-
</dateValid>
|
168
|
-
</xsl:if> -->
|
169
|
-
|
170
|
-
<xsl:for-each select="gmd:identificationInfo/gmd:MD_DataIdentification/gmd:descriptiveKeywords/gmd:MD_Keywords">
|
166
|
+
|
167
|
+
<xsl:for-each select="gmd:identificationInfo/gmd:MD_DataIdentification/gmd:descriptiveKeywords/gmd:MD_Keywords">
|
171
168
|
<xsl:if test="gmd:type/gmd:MD_KeywordTypeCode[@codeListValue='temporal']">
|
172
169
|
<xsl:for-each select="gmd:keyword">
|
173
170
|
|
@@ -226,15 +223,10 @@
|
|
226
223
|
<xsl:for-each select="gmd:distributionInfo/gmd:MD_Distribution/gmd:transferOptions/gmd:MD_DigitalTransferOptions/gmd:transferSize">
|
227
224
|
<extent>
|
228
225
|
<xsl:value-of select="gco:Real"/>
|
229
|
-
|
230
|
-
<xsl:when test="ancestor-or-self::*/gmd:MD_DigitalTransferOptions/gmd:unitsOfDistribution">
|
226
|
+
<xsl:if test="ancestor-or-self::*/gmd:MD_DigitalTransferOptions/gmd:unitsOfDistribution">
|
231
227
|
<xsl:text> </xsl:text>
|
232
228
|
<xsl:value-of select="ancestor-or-self::*/gmd:MD_DigitalTransferOptions/gmd:unitsOfDistribution"/>
|
233
|
-
</xsl:
|
234
|
-
<xsl:otherwise>
|
235
|
-
<xsl:text> MB</xsl:text>
|
236
|
-
</xsl:otherwise>
|
237
|
-
</xsl:choose>
|
229
|
+
</xsl:if>
|
238
230
|
</extent>
|
239
231
|
|
240
232
|
<!-- The digitalOrigin is coded here:
|
@@ -506,6 +498,13 @@
|
|
506
498
|
</title>
|
507
499
|
</titleInfo>
|
508
500
|
<typeOfResource collection="yes"/>
|
501
|
+
<xsl:if test="gmd:aggregateDataSetName/gmd:CI_Citation/gmd:identifier/gmd:MD_Identifier/gmd:code">
|
502
|
+
<location>
|
503
|
+
<url>
|
504
|
+
<xsl:value-of select="gmd:aggregateDataSetName/gmd:CI_Citation/gmd:identifier/gmd:MD_Identifier/gmd:code"/>
|
505
|
+
</url>
|
506
|
+
</location>
|
507
|
+
</xsl:if>
|
509
508
|
<xsl:for-each select="gmd:aggregateDataSetName/gmd:CI_Citation/gmd:citedResponsibleParty/gmd:CI_ResponsibleParty/gmd:organisationName">
|
510
509
|
<xsl:if test="ancestor-or-self::gmd:CI_ResponsibleParty/gmd:role/gmd:CI_RoleCode[@codeListValue='originator']">
|
511
510
|
<name type="corporate">
|
@@ -547,7 +546,9 @@
|
|
547
546
|
</edition>
|
548
547
|
</xsl:for-each>
|
549
548
|
</originInfo>
|
550
|
-
|
549
|
+
|
550
|
+
<!-- series titles / not in use -->
|
551
|
+
<!-- <xsl:for-each select="gmd:aggregateDataSetName/gmd:CI_Citation/gmd:series/gmd:CI_Series">
|
551
552
|
<relatedItem>
|
552
553
|
<xsl:attribute name="type">host</xsl:attribute>
|
553
554
|
<titleInfo>
|
@@ -562,7 +563,7 @@
|
|
562
563
|
<issuance>continuing</issuance>
|
563
564
|
</originInfo>
|
564
565
|
</relatedItem>
|
565
|
-
</xsl:for-each>
|
566
|
+
</xsl:for-each> -->
|
566
567
|
</relatedItem>
|
567
568
|
</xsl:if>
|
568
569
|
</xsl:for-each>
|
@@ -749,9 +750,9 @@
|
|
749
750
|
<xsl:attribute name="valueURI"><xsl:value-of select="."/></xsl:attribute>
|
750
751
|
<xsl:text>Planning and Cadastral</xsl:text>
|
751
752
|
</xsl:when>
|
752
|
-
<xsl:when test="contains(.,'
|
753
|
+
<xsl:when test="contains(.,'structure')">
|
753
754
|
<xsl:attribute name="valueURI"><xsl:value-of select="."/></xsl:attribute>
|
754
|
-
<xsl:text>
|
755
|
+
<xsl:text>Structure</xsl:text>
|
755
756
|
</xsl:when>
|
756
757
|
<xsl:when test="contains(.,'transportation')">
|
757
758
|
<xsl:attribute name="valueURI"><xsl:value-of select="."/></xsl:attribute>
|
@@ -769,13 +770,37 @@
|
|
769
770
|
</topic>
|
770
771
|
</subject>
|
771
772
|
</xsl:for-each>
|
772
|
-
|
773
|
+
|
774
|
+
|
775
|
+
<location>
|
776
|
+
<url>
|
777
|
+
<xsl:value-of select="$purl"/>
|
778
|
+
</url>
|
779
|
+
</location>
|
780
|
+
|
773
781
|
<!-- access rights to be mapped from restrictionCode/otherRestrictions/APO -->
|
774
782
|
<xsl:for-each select="gmd:identificationInfo/gmd:MD_DataIdentification/gmd:resourceConstraints/gmd:MD_LegalConstraints/gmd:otherConstraints">
|
775
783
|
<accessCondition type="useAndReproduction">
|
776
784
|
<xsl:value-of select=". "/>
|
777
785
|
</accessCondition>
|
778
786
|
</xsl:for-each>
|
787
|
+
|
788
|
+
<!-- recordInfo -->
|
789
|
+
|
790
|
+
|
791
|
+
<recordInfo>
|
792
|
+
<recordContentSource>
|
793
|
+
<xsl:text>Stanford</xsl:text>
|
794
|
+
</recordContentSource>
|
795
|
+
<recordIdentifier>
|
796
|
+
<xsl:value-of select="gmd:fileIdentifier"/>
|
797
|
+
</recordIdentifier>
|
798
|
+
<recordOrigin>This record was translated from ISO 19139 to MODS v.3 using an xsl transformation.</recordOrigin>
|
799
|
+
<languageOfCataloging>
|
800
|
+
<languageTerm authority="iso639-2b" type="code">eng</languageTerm>
|
801
|
+
</languageOfCataloging>
|
802
|
+
</recordInfo>
|
803
|
+
|
779
804
|
|
780
805
|
<!-- Output geo extension to MODS -->
|
781
806
|
<xsl:if test="gmd:identificationInfo/gmd:MD_DataIdentification/gmd:extent/gmd:EX_Extent/gmd:geographicElement/gmd:EX_GeographicBoundingBox">
|
@@ -823,7 +848,7 @@
|
|
823
848
|
<xsl:value-of select="../../@xlink:href"/>
|
824
849
|
</xsl:attribute>
|
825
850
|
<xsl:attribute name="dc:language">
|
826
|
-
<xsl:value-of select="../../../../../gmd:language/gmd:LanguageCode"/>
|
851
|
+
<xsl:value-of select="../../../../../gmd:language/gmd:LanguageCode"/>
|
827
852
|
</xsl:attribute>
|
828
853
|
<xsl:attribute name="dc:title">
|
829
854
|
<xsl:value-of select="."/>
|
@@ -56,9 +56,7 @@ module Dor
|
|
56
56
|
doc = self.descMetadata.ng_xml.dup(1)
|
57
57
|
add_collection_reference(doc)
|
58
58
|
add_access_conditions(doc)
|
59
|
-
|
60
|
-
new_doc.encoding = 'UTF-8'
|
61
|
-
new_doc.to_xml
|
59
|
+
Nokogiri::XML(doc.to_xml) { |x| x.noblanks }.to_xml { |config| config.no_declaration }
|
62
60
|
end
|
63
61
|
|
64
62
|
# Create MODS accessCondition statements from rightsMetadata
|
@@ -11,6 +11,33 @@ module Dor
|
|
11
11
|
after_initialize :set_workflows_datastream_location
|
12
12
|
end
|
13
13
|
|
14
|
+
#verbiage we want to use to describe an item when it has completed a particular step
|
15
|
+
STATUS_CODE_DISP_TXT = {
|
16
|
+
0 => 'Unknown Status', #if there are no milestones for the current version, someone likely messed up the versioning process.
|
17
|
+
1 => 'Registered',
|
18
|
+
2 => 'In accessioning',
|
19
|
+
3 => 'In accessioning (described)',
|
20
|
+
4 => 'In accessioning (described, published)',
|
21
|
+
5 => 'In accessioning (described, published, deposited)',
|
22
|
+
6 => 'Accessioned',
|
23
|
+
7 => 'Accessioned (indexed)',
|
24
|
+
8 => 'Accessioned (indexed, ingested)',
|
25
|
+
9 => 'Opened'
|
26
|
+
}
|
27
|
+
|
28
|
+
#milestones from accessioning and the order they happen in
|
29
|
+
STEPS = {
|
30
|
+
'registered' => 1,
|
31
|
+
'submitted' => 2,
|
32
|
+
'described' => 3,
|
33
|
+
'published' => 4,
|
34
|
+
'deposited' => 5,
|
35
|
+
'accessioned' => 6,
|
36
|
+
'indexed' => 7,
|
37
|
+
'shelved' => 8,
|
38
|
+
'opened' => 1
|
39
|
+
}
|
40
|
+
|
14
41
|
def set_workflows_datastream_location
|
15
42
|
# This is a work-around for some strange logic in ActiveFedora that
|
16
43
|
# don't allow self.workflows.new? to work if we load the object using
|
@@ -78,69 +105,49 @@ module Dor
|
|
78
105
|
def milestones
|
79
106
|
Dor::WorkflowService.get_milestones('dor',self.pid)
|
80
107
|
end
|
81
|
-
|
82
|
-
|
108
|
+
|
109
|
+
def status_info()
|
110
|
+
current_version = '1'
|
83
111
|
begin
|
84
112
|
current_version = self.versionMetadata.current_version_id
|
85
113
|
rescue
|
86
114
|
end
|
87
|
-
|
88
|
-
version = ''
|
89
|
-
#verbage we want to use to describe an item when it has completed a particular step
|
90
|
-
status_hash={
|
91
|
-
0 => 'Unknown Status', #if there are no milestones for the current version, someone likely messed up the versioning process.
|
92
|
-
1 => 'Registered',
|
93
|
-
2 => 'In accessioning',
|
94
|
-
3 => 'In accessioning (described)',
|
95
|
-
4 => 'In accessioning (described, published)',
|
96
|
-
5 => 'In accessioning (described, published, deposited)',
|
97
|
-
6 => 'Accessioned',
|
98
|
-
7 => 'Accessioned (indexed)',
|
99
|
-
8 => 'Accessioned (indexed, ingested)',
|
100
|
-
9 => 'Opened'
|
101
|
-
}
|
102
|
-
#milestones from accesioning and the order they happen in
|
103
|
-
steps={
|
104
|
-
'registered' => 1,
|
105
|
-
'submitted' => 2,
|
106
|
-
'described' => 3,
|
107
|
-
'published' => 4,
|
108
|
-
'deposited' => 5,
|
109
|
-
'accessioned' => 6,
|
110
|
-
'indexed' => 7,
|
111
|
-
'shelved' => 8,
|
112
|
-
'opened' => 1
|
113
|
-
}
|
114
|
-
status_time=nil
|
115
|
-
|
116
|
-
current=false
|
117
|
-
versions=[]
|
118
|
-
result=""
|
115
|
+
|
119
116
|
current_milestones = []
|
120
|
-
#only get steps that are part of accessioning and part of the current version. That can mean they were archived with the current version
|
117
|
+
#only get steps that are part of accessioning and part of the current version. That can mean they were archived with the current version
|
118
|
+
#number, or they might be active (no version number).
|
121
119
|
milestones.each do |m|
|
122
|
-
if
|
120
|
+
if STEPS.keys.include?(m[:milestone]) and (m[:version].nil? or m[:version] == current_version)
|
123
121
|
current_milestones << m unless m[:milestone] == 'registered' and current_version.to_i > 1
|
124
122
|
end
|
125
123
|
end
|
126
|
-
|
124
|
+
|
125
|
+
status_code = 0
|
127
126
|
status_time = ''
|
128
127
|
#for each milestone in the current version, see if it comes after the current 'last' step, if so, make it the last and record the date/time
|
129
128
|
current_milestones.each do |m|
|
130
|
-
name=m[:milestone]
|
131
|
-
time=m[:at].utc.xmlschema
|
132
|
-
if
|
133
|
-
if
|
134
|
-
|
135
|
-
status_time=time
|
129
|
+
name = m[:milestone]
|
130
|
+
time = m[:at].utc.xmlschema
|
131
|
+
if STEPS.keys.include? name
|
132
|
+
if STEPS[name] > status_code
|
133
|
+
status_code = STEPS[name]
|
134
|
+
status_time = time
|
136
135
|
end
|
137
136
|
end
|
138
137
|
end
|
138
|
+
|
139
|
+
return {:current_version => current_version, :status_code => status_code, :status_time => status_time}
|
140
|
+
end
|
141
|
+
|
142
|
+
def status(include_time=false)
|
143
|
+
status_info_hash = status_info
|
144
|
+
current_version, status_code, status_time = status_info_hash[:current_version], status_info_hash[:status_code], status_info_hash[:status_time]
|
145
|
+
|
139
146
|
#use the translation table to get the appropriate verbage for the latest step
|
140
|
-
result=
|
141
|
-
result +=" #{format_date(status_time)}" if include_time
|
142
|
-
result
|
143
|
-
|
147
|
+
result = "v#{current_version} #{STATUS_CODE_DISP_TXT[status_code]}"
|
148
|
+
result += " #{format_date(status_time)}" if include_time
|
149
|
+
return result
|
150
|
+
end
|
144
151
|
|
145
152
|
def to_solr(solr_doc=Hash.new, *args)
|
146
153
|
super(solr_doc, *args)
|
@@ -210,6 +217,8 @@ module Dor
|
|
210
217
|
opts[:priority] = priority if(priority > 0)
|
211
218
|
Dor::WorkflowService.create_workflow(repo, self.pid, name, Dor::WorkflowObject.initial_workflow(name), opts)
|
212
219
|
end
|
220
|
+
|
221
|
+
|
213
222
|
private
|
214
223
|
#handles formating utc date/time to human readable
|
215
224
|
def format_date datetime
|
@@ -41,9 +41,7 @@ module Dor
|
|
41
41
|
rels = public_relationships.root
|
42
42
|
pub.add_child(rels.clone) unless rels.nil? # TODO: Should never be nil in practice; working around an ActiveFedora quirk for testing
|
43
43
|
pub.add_child(self.generate_dublin_core.root.clone)
|
44
|
-
|
45
|
-
new_pub.encoding = 'UTF-8'
|
46
|
-
new_pub.to_xml
|
44
|
+
Nokogiri::XML(pub.to_xml) { |x| x.noblanks }.to_xml { |config| config.no_declaration }
|
47
45
|
end
|
48
46
|
|
49
47
|
# Copies this object's public_xml to the Purl document cache if it is world discoverable
|
data/lib/dor/models/shelvable.rb
CHANGED
@@ -7,58 +7,21 @@ module Dor
|
|
7
7
|
|
8
8
|
# Push file changes for shelve-able files into the stacks
|
9
9
|
def shelve
|
10
|
-
# retrieve the differences between the current contentMetadata and the previously ingested version
|
11
|
-
shelve_diff = get_shelve_diff
|
12
|
-
stacks_object_pathname = get_stacks_location
|
13
|
-
# determine the location of the object's files in the stacks area
|
14
|
-
stacks_druid = DruidTools::StacksDruid.new id, stacks_object_pathname
|
15
|
-
stacks_object_pathname = Pathname(stacks_druid.path)
|
16
|
-
# determine the location of the object's content files in the workspace area
|
17
|
-
workspace_druid = DruidTools::Druid.new(id,Config.stacks.local_workspace_root)
|
18
|
-
workspace_content_pathname = workspace_content_dir(shelve_diff, workspace_druid)
|
19
|
-
# delete, rename, or copy files to the stacks area
|
20
|
-
DigitalStacksService.remove_from_stacks(stacks_object_pathname, shelve_diff)
|
21
|
-
DigitalStacksService.rename_in_stacks(stacks_object_pathname, shelve_diff)
|
22
|
-
DigitalStacksService.shelve_to_stacks(workspace_content_pathname, stacks_object_pathname, shelve_diff)
|
23
|
-
end
|
24
|
-
|
25
|
-
# retrieve the differences between the current contentMetadata and the previously ingested version
|
26
|
-
# (filtering to select only the files that should be shelved to stacks)
|
27
|
-
def get_shelve_diff
|
28
10
|
inventory_diff_xml = self.get_content_diff(:shelve)
|
29
11
|
inventory_diff = Moab::FileInventoryDifference.parse(inventory_diff_xml)
|
30
|
-
|
31
|
-
|
32
|
-
end
|
12
|
+
content_group_diff = inventory_diff.group_difference("content")
|
13
|
+
deltas = content_group_diff.file_deltas
|
33
14
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
content_pathname
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
# get the stack location based on the contentMetadata stacks attribute
|
48
|
-
# or using the default value from the config file if it doesn't exist
|
49
|
-
def get_stacks_location
|
50
|
-
|
51
|
-
contentMetadataDS = self.datastreams['contentMetadata']
|
52
|
-
unless contentMetadataDS.nil? or contentMetadataDS.stacks.length == 0
|
53
|
-
stacks_location = contentMetadataDS.stacks[0]
|
54
|
-
if stacks_location.start_with?"/" #Absolute stacks path
|
55
|
-
return stacks_location
|
56
|
-
else
|
57
|
-
raise "stacks attribute for item: "+self.id+ " contentMetadata should start with /. The current value is "+stacks_location
|
58
|
-
end
|
59
|
-
end
|
60
|
-
return Config.stacks.local_stacks_root #Default stacks
|
61
|
-
|
15
|
+
if content_group_diff.rename_require_temp_files(deltas[:renamed])
|
16
|
+
triplets = content_group_diff.rename_tempfile_triplets(deltas[:renamed])
|
17
|
+
DigitalStacksService.rename_in_stacks self.pid, triplets.collect{|old,new,temp| [old,temp]}
|
18
|
+
DigitalStacksService.rename_in_stacks self.pid, triplets.collect{|old,new,temp| [temp,new]}
|
19
|
+
else
|
20
|
+
DigitalStacksService.rename_in_stacks self.pid, deltas[:renamed]
|
21
|
+
end
|
22
|
+
DigitalStacksService.shelve_to_stacks self.pid, deltas[:modified] + deltas[:added] + deltas[:copyadded].collect{|old,new| new}
|
23
|
+
DigitalStacksService.remove_from_stacks self.pid, deltas[:deleted] + deltas[:copydeleted]
|
62
24
|
end
|
25
|
+
|
63
26
|
end
|
64
27
|
end
|
@@ -2,128 +2,42 @@ require 'net/ssh'
|
|
2
2
|
require 'net/sftp'
|
3
3
|
|
4
4
|
module Dor
|
5
|
-
|
6
5
|
class DigitalStacksService
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
[:deleted, :copydeleted, :modified].each do |change_type|
|
13
|
-
subset = content_diff.subset(change_type) # {Moab::FileGroupDifferenceSubset}
|
14
|
-
subset.files.each do |moab_file| # {Moab::FileInstanceDifference}
|
15
|
-
moab_signature = moab_file.signatures.first # {Moab::FileSignature}
|
16
|
-
file_pathname = stacks_object_pathname.join(moab_file.basis_path)
|
17
|
-
self.delete_file(file_pathname, moab_signature)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Delete a file, but only if it exists and matches the expected signature
|
23
|
-
# @param [Pathname] file_pathname The location of the file to be deleted
|
24
|
-
# @param [Moab::FileSignature] moab_signature The fixity values of the file
|
25
|
-
# @return [Boolean] true if file deleted, false otherwise
|
26
|
-
def self.delete_file(file_pathname, moab_signature)
|
27
|
-
if file_pathname.exist? and (file_pathname.size == moab_signature.size)
|
28
|
-
file_signature = Moab::FileSignature.new.signature_from_file(file_pathname)
|
29
|
-
if (file_signature == moab_signature)
|
30
|
-
file_pathname.delete
|
31
|
-
return true
|
32
|
-
end
|
33
|
-
end
|
34
|
-
return false
|
35
|
-
end
|
36
|
-
|
37
|
-
# Rename files from stacks that have change type 'renamed' using an intermediate temp filename.
|
38
|
-
# The 2-step renaming allows chained or cyclic renames to occur without file collisions.
|
39
|
-
# @param [Pathname] stacks_object_pathname the stacks location of the digital object
|
40
|
-
# @param [Moab::FileGroupDifference] content_diff the content file version differences report
|
41
|
-
def self.rename_in_stacks(stacks_object_pathname, content_diff)
|
42
|
-
subset = content_diff.subset(:renamed) # {Moab::FileGroupDifferenceSubset
|
43
|
-
|
44
|
-
# 1st Pass - rename files from original name to checksum-based name
|
45
|
-
subset.files.each do |moab_file| # {Moab::FileInstanceDifference}
|
46
|
-
moab_signature = moab_file.signatures.first # {Moab::FileSignature}
|
47
|
-
original_pathname = stacks_object_pathname.join(moab_file.basis_path)
|
48
|
-
temp_pathname = stacks_object_pathname.join(moab_signature.checksums.values.last)
|
49
|
-
self.rename_file(original_pathname, temp_pathname, moab_signature)
|
50
|
-
end
|
51
|
-
|
52
|
-
# 2nd Pass - rename files from checksum-based name to new name
|
53
|
-
subset.files.each do |moab_file| # {Moab::FileInstanceDifference}
|
54
|
-
moab_signature = moab_file.signatures.first # {Moab::FileSignature}
|
55
|
-
temp_pathname = stacks_object_pathname.join(moab_signature.checksums.values.last)
|
56
|
-
new_pathname = stacks_object_pathname.join(moab_file.other_path)
|
57
|
-
self.rename_file(temp_pathname, new_pathname, moab_signature)
|
58
|
-
end
|
59
|
-
|
7
|
+
def self.transfer_to_document_store(id, content, filename)
|
8
|
+
druid = DruidTools::PurlDruid.new id, Config.stacks.local_document_cache_root
|
9
|
+
druid.content_dir # create the druid tree if it doesn't exist yet
|
10
|
+
File.open(File.join(druid.content_dir, filename), 'w') {|f| f.write content }
|
60
11
|
end
|
61
12
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
def self.rename_file(old_pathname, new_pathname, moab_signature)
|
68
|
-
if old_pathname.exist? and (old_pathname.size == moab_signature.size)
|
69
|
-
file_signature = Moab::FileSignature.new.signature_from_file(old_pathname)
|
70
|
-
if (file_signature == moab_signature)
|
71
|
-
new_pathname.parent.mkpath
|
72
|
-
old_pathname.rename(new_pathname)
|
73
|
-
return true
|
74
|
-
end
|
13
|
+
def self.remove_from_stacks(id, files)
|
14
|
+
files.each do |file|
|
15
|
+
dr = DruidTools::StacksDruid.new id, Config.stacks.local_stacks_root
|
16
|
+
content = dr.find_content file
|
17
|
+
FileUtils.rm content if content
|
75
18
|
end
|
76
|
-
return false
|
77
19
|
end
|
78
20
|
|
79
|
-
#
|
80
|
-
# @param [
|
81
|
-
#
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
moab_signature = moab_file.signatures.last # {Moab::FileSignature}
|
89
|
-
filename = (change_type == :modified) ? moab_file.basis_path : moab_file.other_path
|
90
|
-
workspace_pathname = workspace_content_pathname.join(filename)
|
91
|
-
stacks_pathname = stacks_object_pathname.join(filename)
|
92
|
-
self.copy_file(workspace_pathname, stacks_pathname, moab_signature)
|
93
|
-
end
|
21
|
+
# @param [String] id object pid
|
22
|
+
# @param [Array<Array<String>>] file_map an array of two string arrays. Each inner array represents old-file/new-file mappings. First string is the old file name, second string is the new file name. e.g:
|
23
|
+
# [ ['src1.file', 'dest1.file'], ['src2.file', 'dest2.file'] ]
|
24
|
+
def self.rename_in_stacks(id, file_map)
|
25
|
+
return if file_map.nil? or file_map.empty?
|
26
|
+
dr = DruidTools::StacksDruid.new id, Config.stacks.local_stacks_root
|
27
|
+
content_dir = dr.find_filelist_parent('content', file_map.first.first)
|
28
|
+
file_map.each do |src, dest|
|
29
|
+
File.rename(File.join(content_dir, src), File.join(content_dir, dest))
|
94
30
|
end
|
95
|
-
true
|
96
31
|
end
|
97
32
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
file_signature = Moab::FileSignature.new.signature_from_file(stacks_pathname)
|
106
|
-
stacks_pathname.delete if (file_signature != moab_signature)
|
107
|
-
end
|
108
|
-
unless stacks_pathname.exist?
|
109
|
-
stacks_pathname.parent.mkpath
|
110
|
-
FileUtils.cp workspace_pathname.to_s, stacks_pathname.to_s
|
111
|
-
return true
|
33
|
+
def self.shelve_to_stacks(id, files)
|
34
|
+
workspace_druid = DruidTools::Druid.new(id,Config.stacks.local_workspace_root)
|
35
|
+
stacks_druid = DruidTools::StacksDruid.new(id,Config.stacks.local_stacks_root)
|
36
|
+
files.each do |file|
|
37
|
+
stacks_druid.content_dir
|
38
|
+
workspace_file = workspace_druid.find_content(file)
|
39
|
+
FileUtils.cp workspace_file, stacks_druid.content_dir
|
112
40
|
end
|
113
|
-
return false
|
114
|
-
end
|
115
|
-
|
116
|
-
### depricated ???
|
117
|
-
|
118
|
-
# Create a file inside the content directory under the stacks.local_document_cache_root
|
119
|
-
# @param [String] id The druid identifier for the object
|
120
|
-
# @param [String] content The contents of the file to be created
|
121
|
-
# @param [String] filename The name of the file to be created
|
122
|
-
# @return [void]
|
123
|
-
def self.transfer_to_document_store(id, content, filename)
|
124
|
-
druid = DruidTools::PurlDruid.new id, Config.stacks.local_document_cache_root
|
125
|
-
druid.content_dir # create the druid tree if it doesn't exist yet
|
126
|
-
File.open(File.join(druid.content_dir, filename), 'w') { |f| f.write content }
|
127
41
|
end
|
128
42
|
|
129
43
|
# Assumes the digital stacks storage root is mounted to the local file system
|
data/lib/dor/version.rb
CHANGED
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.6.
|
4
|
+
version: 4.6.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2014-
|
16
|
+
date: 2014-06-02 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: active-fedora
|
@@ -36,7 +36,7 @@ dependencies:
|
|
36
36
|
requirement: !ruby/object:Gem::Requirement
|
37
37
|
none: false
|
38
38
|
requirements:
|
39
|
-
- -
|
39
|
+
- - ! '>='
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: 3.2.16
|
42
42
|
type: :runtime
|
@@ -44,7 +44,7 @@ dependencies:
|
|
44
44
|
version_requirements: !ruby/object:Gem::Requirement
|
45
45
|
none: false
|
46
46
|
requirements:
|
47
|
-
- -
|
47
|
+
- - ! '>='
|
48
48
|
- !ruby/object:Gem::Version
|
49
49
|
version: 3.2.16
|
50
50
|
- !ruby/object:Gem::Dependency
|
@@ -134,7 +134,7 @@ dependencies:
|
|
134
134
|
requirements:
|
135
135
|
- - ~>
|
136
136
|
- !ruby/object:Gem::Version
|
137
|
-
version:
|
137
|
+
version: 1.6.0
|
138
138
|
type: :runtime
|
139
139
|
prerelease: false
|
140
140
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -142,7 +142,7 @@ dependencies:
|
|
142
142
|
requirements:
|
143
143
|
- - ~>
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
145
|
+
version: 1.6.0
|
146
146
|
- !ruby/object:Gem::Dependency
|
147
147
|
name: om
|
148
148
|
requirement: !ruby/object:Gem::Requirement
|
@@ -342,10 +342,7 @@ dependencies:
|
|
342
342
|
requirements:
|
343
343
|
- - ~>
|
344
344
|
- !ruby/object:Gem::Version
|
345
|
-
version: 1.5
|
346
|
-
- - ! '>='
|
347
|
-
- !ruby/object:Gem::Version
|
348
|
-
version: 1.5.1
|
345
|
+
version: '1.5'
|
349
346
|
type: :runtime
|
350
347
|
prerelease: false
|
351
348
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -353,10 +350,7 @@ dependencies:
|
|
353
350
|
requirements:
|
354
351
|
- - ~>
|
355
352
|
- !ruby/object:Gem::Version
|
356
|
-
version: 1.5
|
357
|
-
- - ! '>='
|
358
|
-
- !ruby/object:Gem::Version
|
359
|
-
version: 1.5.1
|
353
|
+
version: '1.5'
|
360
354
|
- !ruby/object:Gem::Dependency
|
361
355
|
name: druid-tools
|
362
356
|
requirement: !ruby/object:Gem::Requirement
|