dor-services 4.6.6.3 → 4.6.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|