pho 0.4.1 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +18 -1
- data/README +10 -0
- data/Rakefile +2 -1
- data/doc/rdoc/classes/Pho.html +33 -22
- data/doc/rdoc/classes/Pho/DatatypeProperty.html +12 -12
- data/doc/rdoc/classes/Pho/{RDF_JSON.html → Enrichment.html} +8 -7
- data/doc/rdoc/classes/Pho/Enrichment/ResourceEnricher.html +310 -0
- data/doc/rdoc/classes/Pho/Etags.html +42 -42
- data/doc/rdoc/classes/Pho/Facet/Results.html +19 -19
- data/doc/rdoc/classes/Pho/Facet/Term.html +6 -6
- data/doc/rdoc/classes/Pho/FieldPredicateMap.html +110 -105
- data/doc/rdoc/classes/Pho/FieldWeighting.html +12 -12
- data/doc/rdoc/classes/Pho/FileManagement.html +121 -0
- data/doc/rdoc/classes/Pho/FileManagement/AbstractFileManager.html +443 -0
- data/doc/rdoc/classes/Pho/FileManagement/FileManager.html +258 -0
- data/doc/rdoc/classes/Pho/FileManagement/RDFManager.html +271 -0
- data/doc/rdoc/classes/Pho/Job.html +64 -64
- data/doc/rdoc/classes/Pho/Jobs.html +60 -60
- data/doc/rdoc/classes/Pho/QueryProfile.html +60 -60
- data/doc/rdoc/classes/Pho/RDFCollection.html +4 -378
- data/doc/rdoc/classes/Pho/ResourceHash.html +123 -0
- data/doc/rdoc/classes/Pho/ResourceHash/Converter.html +323 -0
- data/doc/rdoc/classes/Pho/{RDF_JSON → ResourceHash}/SetAlgebra.html +18 -18
- data/doc/rdoc/classes/Pho/Snapshot.html +35 -35
- data/doc/rdoc/classes/Pho/Sparql.html +137 -0
- data/doc/rdoc/classes/Pho/Sparql/SparqlClient.html +515 -0
- data/doc/rdoc/classes/Pho/Sparql/SparqlHelper.html +575 -0
- data/doc/rdoc/classes/Pho/Status.html +26 -26
- data/doc/rdoc/classes/Pho/Store.html +271 -241
- data/doc/rdoc/classes/Pho/Update/Changeset.html +73 -73
- data/doc/rdoc/classes/Pho/Update/ChangesetBuilder.html +34 -34
- data/doc/rdoc/classes/Pho/Update/Changesets.html +14 -14
- data/doc/rdoc/classes/Pho/Update/LiteralStatement.html +31 -23
- data/doc/rdoc/classes/Pho/Update/ResourceStatement.html +45 -21
- data/doc/rdoc/classes/Pho/Update/Statement.html +29 -29
- data/doc/rdoc/classes/String.html +1 -1
- data/doc/rdoc/created.rid +1 -1
- data/doc/rdoc/files/CHANGES.html +49 -3
- data/doc/rdoc/files/README.html +15 -1
- data/doc/rdoc/files/lib/pho/changeset_builder_rb.html +1 -1
- data/doc/rdoc/files/lib/pho/changeset_rb.html +1 -1
- data/doc/rdoc/files/lib/pho/converter_rb.html +108 -0
- data/doc/rdoc/files/lib/pho/enrichment_rb.html +101 -0
- data/doc/rdoc/files/lib/pho/etags_rb.html +1 -1
- data/doc/rdoc/files/lib/pho/field_predicate_map_rb.html +1 -1
- data/doc/rdoc/files/lib/pho/file_management_rb.html +101 -0
- data/doc/rdoc/files/lib/pho/file_manager_rb.html +108 -0
- data/doc/rdoc/files/lib/pho/rdf_collection_rb.html +1 -1
- data/doc/rdoc/files/lib/pho/resource_hash_rb.html +101 -0
- data/doc/rdoc/files/lib/pho/{rdf_json_rb.html → sparql_rb.html} +4 -4
- data/doc/rdoc/files/lib/pho/store_rb.html +1 -1
- data/doc/rdoc/files/lib/pho_rb.html +7 -2
- data/doc/rdoc/fr_class_index.html +12 -2
- data/doc/rdoc/fr_file_index.html +6 -1
- data/doc/rdoc/fr_method_index.html +176 -139
- data/examples/sparql_construct_hash.rb +26 -0
- data/examples/sparql_select.rb +18 -0
- data/lib/pho.rb +6 -1
- data/lib/pho/changeset.rb +24 -9
- data/lib/pho/changeset_builder.rb +10 -10
- data/lib/pho/converter.rb +74 -0
- data/lib/pho/enrichment.rb +81 -0
- data/lib/pho/etags.rb +1 -0
- data/lib/pho/field_predicate_map.rb +6 -1
- data/lib/pho/file_management.rb +102 -0
- data/lib/pho/file_manager.rb +61 -0
- data/lib/pho/rdf_collection.rb +54 -120
- data/lib/pho/{rdf_json.rb → resource_hash.rb} +3 -4
- data/lib/pho/sparql.rb +332 -0
- data/lib/pho/store.rb +20 -14
- data/tests/tc_changeset.rb +46 -0
- data/tests/tc_changeset_builder.rb +122 -1
- data/tests/tc_converter.rb +95 -0
- data/tests/tc_enrichment.rb +83 -0
- data/tests/tc_file_manager.rb +88 -0
- data/tests/tc_rdf_collection.rb +3 -0
- data/tests/{tc_rdf_json.rb → tc_resource_hash.rb} +23 -23
- data/tests/tc_search.rb +1 -1
- data/tests/tc_sparql.rb +131 -6
- data/tests/tc_sparql_helper.rb +214 -0
- data/tests/ts_pho.rb +6 -2
- metadata +47 -8
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'pho'
|
3
|
+
|
4
|
+
query = <<-EOL
|
5
|
+
PREFIX space: <http://purl.org/net/schemas/space/>
|
6
|
+
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
7
|
+
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
|
8
|
+
CONSTRUCT {
|
9
|
+
?spacecraft foaf:name ?name;
|
10
|
+
space:agency ?agency;
|
11
|
+
space:mass ?mass.
|
12
|
+
}
|
13
|
+
WHERE {
|
14
|
+
?launch space:launched "1969-07-16"^^xsd:date.
|
15
|
+
?spacecraft space:launch ?launch;
|
16
|
+
foaf:name ?name;
|
17
|
+
space:agency ?agency;
|
18
|
+
space:mass ?mass.
|
19
|
+
}
|
20
|
+
EOL
|
21
|
+
|
22
|
+
sparql_client = Pho::Sparql::SparqlClient.new("http://api.talis.com/stores/space/services/sparql")
|
23
|
+
|
24
|
+
data = Pho::Sparql::SparqlHelper.constructToResourceHash(query, sparql_client)
|
25
|
+
|
26
|
+
puts data.inspect()
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'pho'
|
3
|
+
|
4
|
+
query = <<-EOL
|
5
|
+
PREFIX space: <http://purl.org/net/schemas/space/>
|
6
|
+
SELECT ?s WHERE {
|
7
|
+
?s a space:Spacecraft.
|
8
|
+
}
|
9
|
+
LIMIT 10
|
10
|
+
EOL
|
11
|
+
|
12
|
+
sparql_client = Pho::Sparql::SparqlClient.new("http://api.talis.com/stores/space/services/sparql")
|
13
|
+
|
14
|
+
uris = Pho::Sparql::SparqlHelper.selectValues(query, sparql_client)
|
15
|
+
|
16
|
+
uris.each do |uri|
|
17
|
+
puts uri
|
18
|
+
end
|
data/lib/pho.rb
CHANGED
@@ -12,10 +12,15 @@ require 'pho/query_profile'
|
|
12
12
|
require 'pho/status'
|
13
13
|
require 'pho/facet'
|
14
14
|
require 'pho/job'
|
15
|
+
require 'pho/file_management'
|
15
16
|
require 'pho/rdf_collection'
|
16
|
-
require 'pho/
|
17
|
+
require 'pho/file_manager'
|
18
|
+
require 'pho/resource_hash'
|
19
|
+
require 'pho/converter'
|
17
20
|
require 'pho/changeset_builder'
|
18
21
|
require 'pho/changeset'
|
22
|
+
require 'pho/sparql'
|
23
|
+
require 'pho/enrichment'
|
19
24
|
|
20
25
|
if RUBY_VERSION < "1.8.7"
|
21
26
|
class String
|
data/lib/pho/changeset.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
module Pho
|
2
2
|
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
# Convenience functions for adding/removing lists?
|
3
|
+
# TODO: assigning identifiers via changesets (Blank nodes on subject of change and subject)
|
4
|
+
# TODO: assigning identifiers to a changeset docs
|
5
|
+
# TODO: linking together changesets using either nodeID or an identifier
|
7
6
|
|
8
7
|
require 'uri'
|
9
8
|
|
@@ -43,15 +42,19 @@ module Pho
|
|
43
42
|
#Create an RDF/XML fragment describing this Statement
|
44
43
|
def to_rdf()
|
45
44
|
rdf = "<rdf:Statement>"
|
46
|
-
rdf <<
|
45
|
+
rdf << write_subject()
|
47
46
|
rdf << " <rdf:predicate rdf:resource=\"#{@predicate}\"/>"
|
48
47
|
rdf << write_object()
|
49
48
|
rdf << "</rdf:Statement>"
|
50
49
|
return rdf
|
51
50
|
end
|
52
|
-
|
51
|
+
|
53
52
|
private
|
54
|
-
|
53
|
+
|
54
|
+
def write_subject()
|
55
|
+
return " <rdf:subject rdf:resource=\"#{@subject}\"/>"
|
56
|
+
end
|
57
|
+
|
55
58
|
# subject:: URI of subject of triple
|
56
59
|
# predicate:: URI of predicate of triple
|
57
60
|
# object:: object value of triple (may be URI or literal)
|
@@ -102,8 +105,16 @@ module Pho
|
|
102
105
|
|
103
106
|
protected
|
104
107
|
def write_object()
|
105
|
-
|
106
|
-
|
108
|
+
tag = ""
|
109
|
+
if @datatype != nil
|
110
|
+
tag = "<rdf:object rdf:datatype=\"#{@datatype}\">"
|
111
|
+
elsif @language != nil
|
112
|
+
tag = "<rdf:object xml:lang=\"#{@language}\">"
|
113
|
+
else
|
114
|
+
tag = "<rdf:object>"
|
115
|
+
end
|
116
|
+
tag << "#{@object}</rdf:object>"
|
117
|
+
return tag
|
107
118
|
end
|
108
119
|
end
|
109
120
|
|
@@ -127,6 +138,10 @@ module Pho
|
|
127
138
|
end
|
128
139
|
|
129
140
|
protected
|
141
|
+
def write_subject()
|
142
|
+
return " <rdf:subject rdf:resource=\"#{@subject}\"/>"
|
143
|
+
end
|
144
|
+
|
130
145
|
def write_object()
|
131
146
|
"<rdf:object rdf:resource=\"#{@object}\"/>"
|
132
147
|
end
|
@@ -15,14 +15,14 @@ module Pho
|
|
15
15
|
#
|
16
16
|
#Returns an array of Changeset objects
|
17
17
|
#
|
18
|
-
# before::
|
19
|
-
# after::
|
18
|
+
# before:: resource hash describing current state of the resource
|
19
|
+
# after:: resource hash describing updated state of the resource
|
20
20
|
# creator_name:: name of the creator of the changes
|
21
21
|
# change_reason:: description of why the changes are being made
|
22
22
|
def ChangesetBuilder.build_batch(before, after, creator_name=nil, change_reason=nil)
|
23
23
|
|
24
|
-
removals = Pho::
|
25
|
-
additions = Pho::
|
24
|
+
removals = Pho::ResourceHash::SetAlgebra.minus(before, after)
|
25
|
+
additions = Pho::ResourceHash::SetAlgebra.minus(after, before)
|
26
26
|
|
27
27
|
batch = Array.new
|
28
28
|
|
@@ -58,13 +58,13 @@ module Pho
|
|
58
58
|
#The method will return a single Changeset object.
|
59
59
|
#
|
60
60
|
# subject_of_change:: uri of the resource being updated
|
61
|
-
# before::
|
62
|
-
# after::
|
61
|
+
# before:: resource hash describing current state of the resource
|
62
|
+
# after:: resource hash describing updated state of the resource
|
63
63
|
# creator_name:: name of the creator of the changes
|
64
64
|
# change_reason:: description of why the changes are being made
|
65
65
|
def ChangesetBuilder.build(subject_of_change, before, after, creator_name=nil, change_reason=nil)
|
66
|
-
removals = Pho::
|
67
|
-
additions = Pho::
|
66
|
+
removals = Pho::ResourceHash::SetAlgebra.minus(before, after)
|
67
|
+
additions = Pho::ResourceHash::SetAlgebra.minus(after, before)
|
68
68
|
|
69
69
|
cs = Pho::Update::Changeset.new(subject_of_change, creator_name, change_reason) do |cs|
|
70
70
|
cs.add_removals( create_statements(removals) )
|
@@ -75,9 +75,9 @@ module Pho
|
|
75
75
|
|
76
76
|
end
|
77
77
|
|
78
|
-
#Takes
|
78
|
+
#Takes a resource hash and serializes it as an array of Pho::Update::Statement objects
|
79
79
|
#
|
80
|
-
# triples:: a hash
|
80
|
+
# triples:: a resource hash, conforming to RDF-in-JSON structure
|
81
81
|
def ChangesetBuilder.create_statements(triples)
|
82
82
|
statements = Array.new
|
83
83
|
triples.each do |uri, properties|
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Pho
|
2
|
+
|
3
|
+
module ResourceHash
|
4
|
+
|
5
|
+
#TODO reading from streams
|
6
|
+
#TODO convert into other formats
|
7
|
+
#TODO wrap Redland exceptions. Parser/Serializer contruction as well as parsing errors
|
8
|
+
|
9
|
+
require 'rdf/redland'
|
10
|
+
|
11
|
+
#Class for converting to and from resource hashes
|
12
|
+
class Converter
|
13
|
+
|
14
|
+
#Parse JSON structured according to the RDF-in-JSON specification into
|
15
|
+
#a Ruby resource hash. Simply invokes the JSON parser.
|
16
|
+
#
|
17
|
+
# json:: valid RDF-in-JSON
|
18
|
+
def Converter.parse_json(json)
|
19
|
+
return JSON.parse(json)
|
20
|
+
end
|
21
|
+
|
22
|
+
#Parse a string containing RDF/XML into a resource hash
|
23
|
+
#
|
24
|
+
# rdfxml: a String containing RDF/XML
|
25
|
+
def Converter.parse_rdfxml(rdfxml, base_uri)
|
26
|
+
return Converter.parse(rdfxml, base_uri, "rdfxml")
|
27
|
+
end
|
28
|
+
|
29
|
+
#Parse a string containing N-Triples into a resource hash
|
30
|
+
#
|
31
|
+
# ntriples:: a String containing N-Triples
|
32
|
+
def Converter.parse_ntriples(ntriples, base_uri)
|
33
|
+
return Converter.parse(ntriples, base_uri, "ntriples")
|
34
|
+
end
|
35
|
+
|
36
|
+
#Parse a string containing Turtle into a resource hash
|
37
|
+
#
|
38
|
+
# ntriples:: a String containing Turtle
|
39
|
+
def Converter.parse_turtle(turtle, base_uri)
|
40
|
+
return Converter.parse(turtle, base_uri, "turtle")
|
41
|
+
end
|
42
|
+
|
43
|
+
#Convert specified format into a ResourceHash
|
44
|
+
#
|
45
|
+
# format:: one of rdfxml, ntriples, turtle
|
46
|
+
# data:: String containing the data to be parsed
|
47
|
+
# base_uri:: base uri of the data
|
48
|
+
def Converter.parse(data, base_uri, format="rdfxml")
|
49
|
+
model = Redland::Model.new()
|
50
|
+
case format
|
51
|
+
when "rdfxml" then mime="application/rdf+xml"
|
52
|
+
when "json" then mime="application/json"
|
53
|
+
else mime=""
|
54
|
+
end
|
55
|
+
|
56
|
+
parser = Redland::Parser.new(format, mime)
|
57
|
+
parser.parse_string_into_model(model, data, base_uri)
|
58
|
+
serializer = Redland::Serializer.new( "json", "application/json" )
|
59
|
+
json = serializer.model_to_string(Redland::Uri.new(base_uri), model)
|
60
|
+
return Converter.parse_json( json )
|
61
|
+
end
|
62
|
+
|
63
|
+
#Serialize a resource hash as RDF-in-JSON
|
64
|
+
#
|
65
|
+
# hash:: the resource hash to serialize
|
66
|
+
def Converter.serialize_json(hash)
|
67
|
+
return JSON.dump(hash)
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Pho
|
2
|
+
|
3
|
+
#Enrichment module. Provides classes and mixins for enriching data held in Platform stores using
|
4
|
+
#external SPARQL endpoints and services
|
5
|
+
module Enrichment
|
6
|
+
|
7
|
+
class ResourceEnricher
|
8
|
+
|
9
|
+
attr_reader :store
|
10
|
+
attr_reader :sparql_client
|
11
|
+
|
12
|
+
# Constructor
|
13
|
+
# store:: the store containing resource(s) to enrich
|
14
|
+
# sparql_client:: SparqlClient object to be used as client for retrieving enrichments
|
15
|
+
def initialize(store, sparql_client)
|
16
|
+
@store = store
|
17
|
+
@sparql_client = sparql_client
|
18
|
+
end
|
19
|
+
|
20
|
+
#Enrich a store against itself
|
21
|
+
#
|
22
|
+
#For the common case where a store needs to be enriched against itself by inferring new
|
23
|
+
#data from old using a CONSTRUCT query
|
24
|
+
#
|
25
|
+
# store:: the store to be updated
|
26
|
+
# query:: the SPARQL CONSTRUCT query to be used to infer the new data
|
27
|
+
def ResourceEnricher.infer(store, query)
|
28
|
+
enricher = ResourceEnricher.new( store, store.sparql_client() )
|
29
|
+
return enricher.merge( query )
|
30
|
+
end
|
31
|
+
|
32
|
+
#Execute the provided query against the configured SPARQL endpoint and store the results in
|
33
|
+
#the Platform Store
|
34
|
+
#
|
35
|
+
# query:: the SPARQL CONSTRUCT or DESCRIBE query to execute
|
36
|
+
def merge(query)
|
37
|
+
resp = @sparql_client.query( query, "application/rdf+xml" )
|
38
|
+
if resp.status != 200
|
39
|
+
raise "Unable to execute query. Response: #{resp.status} #{resp.reason} #{resp.content}"
|
40
|
+
end
|
41
|
+
resp = @store.store_data( resp.content )
|
42
|
+
return resp
|
43
|
+
end
|
44
|
+
|
45
|
+
#TODO: optimize POSTs back to the Platform, to deal with large number of resources, e.g. batching
|
46
|
+
|
47
|
+
# Enrich a store with data extracted from a SPARQL endpoint.
|
48
|
+
#
|
49
|
+
# The locator_query is used to find resources in the Platform Store that should be enriched. The query
|
50
|
+
# should be a SPARQL SELECT query that returns the data to be used to parameterize the enrichment_query.
|
51
|
+
#
|
52
|
+
# For each query result, the enrichment_query will be submitted to the configured SPARQL endpoint, after
|
53
|
+
# first interpolating the string, providing the query result bindings as parameters. (See SparqlHelper.apply_initial_bindings
|
54
|
+
# and SparqlHelper.results_to_query_bindings
|
55
|
+
#
|
56
|
+
# If successful, the result of each enrichment query will then be pushed back into the Platform Store by
|
57
|
+
# posting the results of the query to the metabox. Enrichment queries should therefore be CONSTRUCT or
|
58
|
+
# DESCRIBE queries. The SPARQL protocol request will be sent with an Accept header of application/rdf+xml
|
59
|
+
#
|
60
|
+
# locator_query:: query to locate resources to be enriched
|
61
|
+
# enrichment_query:: query to be used to enrich the resource
|
62
|
+
def enrich(locator_query, enrichment_query)
|
63
|
+
results = Pho::Sparql::SparqlHelper.select(locator_query, @store.sparql_client() )
|
64
|
+
bindings = Pho::Sparql::SparqlHelper.results_to_query_bindings(results)
|
65
|
+
bindings.each do |binding|
|
66
|
+
bound_query = Pho::Sparql::SparqlHelper.apply_initial_bindings(enrichment_query, binding)
|
67
|
+
|
68
|
+
result = @sparql_client.query(bound_query, "application/rdf+xml")
|
69
|
+
|
70
|
+
#TODO error handling and callbacks
|
71
|
+
if result.status == 200
|
72
|
+
resp = @store.store_data( result.content )
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
data/lib/pho/etags.rb
CHANGED
@@ -116,7 +116,12 @@ module Pho
|
|
116
116
|
|
117
117
|
json = JSON.parse( resp.content )
|
118
118
|
|
119
|
-
|
119
|
+
labels = json[fpmap_uri]["http:\/\/www.w3.org\/2000\/01\/rdf-schema#label"]
|
120
|
+
label = ""
|
121
|
+
if labels != nil
|
122
|
+
label = labels[0]["value"]
|
123
|
+
end
|
124
|
+
|
120
125
|
fpmap = FieldPredicateMap.new(fpmap_uri, label)
|
121
126
|
|
122
127
|
mapped_properties = json[fpmap_uri]["http:\/\/schemas.talis.com\/2006\/frame\/schema#mappedDatatypeProperty"]
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Pho
|
2
|
+
|
3
|
+
module FileManagement
|
4
|
+
|
5
|
+
#TODO: move files into hidden directory
|
6
|
+
#TODO: add directory traversal
|
7
|
+
class AbstractFileManager
|
8
|
+
|
9
|
+
attr_reader :dir
|
10
|
+
attr_reader :store
|
11
|
+
|
12
|
+
OK = "ok".freeze
|
13
|
+
FAIL = "fail".freeze
|
14
|
+
|
15
|
+
def initialize(store, dir, ok_suffix=OK, fail_suffix=FAIL, sleep=1)
|
16
|
+
@store = store
|
17
|
+
@dir = dir
|
18
|
+
@sleep = sleep
|
19
|
+
@ok_suffix = ok_suffix
|
20
|
+
@fail_suffix = fail_suffix
|
21
|
+
end
|
22
|
+
|
23
|
+
#Store all files that match the file name in directory
|
24
|
+
def store()
|
25
|
+
files_to_store = new_files()
|
26
|
+
files_to_store.each do |filename|
|
27
|
+
file = File.new(filename)
|
28
|
+
store_file(file, filename)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
#Retry anything known to have failed
|
33
|
+
def retry_failures()
|
34
|
+
retries = failures()
|
35
|
+
retries.each do |filename|
|
36
|
+
File.delete( get_fail_file_for(filename) )
|
37
|
+
#store it
|
38
|
+
file = File.new(filename)
|
39
|
+
store_file(file, filename)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
#Reset the directory to clear out any previous statuses
|
44
|
+
#Store can also be reset at the same time: use with care!
|
45
|
+
def reset(reset_store=false)
|
46
|
+
Dir.glob( File.join(@dir, "*.#{@fail_suffix}") ).each do |file|
|
47
|
+
File.delete(file)
|
48
|
+
end
|
49
|
+
Dir.glob( File.join(@dir, "*.#{@ok_suffix}") ).each do |file|
|
50
|
+
File.delete(file)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
#List failures
|
55
|
+
def failures()
|
56
|
+
fails = Array.new
|
57
|
+
Dir.glob( File.join(@dir, "*") ).each do |file|
|
58
|
+
if File.extname(file) != ".#{@fail_suffix}" && File.extname(file) != ".#{@ok_suffix}"
|
59
|
+
fails << file if File.exists?( get_fail_file_for(file) )
|
60
|
+
end
|
61
|
+
end
|
62
|
+
return fails
|
63
|
+
end
|
64
|
+
|
65
|
+
#List successes
|
66
|
+
def successes()
|
67
|
+
successes = Array.new
|
68
|
+
Dir.glob( File.join(@dir, "*") ).each do |file|
|
69
|
+
if File.extname(file) != ".#{@fail_suffix}" && File.extname(file) != ".#{@ok_suffix}"
|
70
|
+
successes << file if File.exists?( get_ok_file_for(file) )
|
71
|
+
end
|
72
|
+
end
|
73
|
+
return successes
|
74
|
+
end
|
75
|
+
|
76
|
+
#Summarize the state of the collection to the provied IO object
|
77
|
+
#Creates a simple report
|
78
|
+
def summary()
|
79
|
+
failures = failures()
|
80
|
+
successes = successes()
|
81
|
+
newfiles = new_files()
|
82
|
+
total = failures.size + successes.size + newfiles.size
|
83
|
+
summary = "#{@dir} contains #{total} files: #{successes.size} stored, #{failures.size} failed, #{newfiles.size} new"
|
84
|
+
return summary
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_fail_file_for(filename)
|
88
|
+
ext = File.extname(filename)
|
89
|
+
return filename.gsub(/#{ext}/, ".#{@fail_suffix}")
|
90
|
+
end
|
91
|
+
|
92
|
+
def get_ok_file_for(filename)
|
93
|
+
ext = File.extname(filename)
|
94
|
+
return filename.gsub(/#{ext}/, ".#{@ok_suffix}")
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
#end file Module
|
101
|
+
|
102
|
+
end
|