resync-client 0.1.2 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/CHANGES.md +10 -0
  4. data/lib/resync/client.rb +63 -0
  5. data/lib/resync/client/http_helper.rb +90 -90
  6. data/lib/resync/client/mixins.rb +1 -0
  7. data/lib/resync/client/mixins/bitstream_resource.rb +26 -0
  8. data/lib/resync/client/mixins/bitstream_resource_list.rb +29 -0
  9. data/lib/resync/client/mixins/client_delegator.rb +38 -0
  10. data/lib/resync/client/mixins/downloadable.rb +36 -0
  11. data/lib/resync/client/mixins/link_client_delegate.rb +19 -0
  12. data/lib/resync/client/mixins/resource_client_delegate.rb +19 -0
  13. data/lib/resync/client/mixins/zipped_resource.rb +20 -0
  14. data/lib/resync/client/mixins/zipped_resource_list.rb +26 -0
  15. data/lib/resync/client/version.rb +1 -1
  16. data/lib/resync/client/zip.rb +1 -0
  17. data/lib/resync/client/zip/bitstream.rb +85 -0
  18. data/lib/resync/client/zip/zip_package.rb +78 -0
  19. data/lib/resync/client/zip/zip_packages.rb +59 -0
  20. data/lib/resync/extensions.rb +36 -0
  21. data/resync-client.gemspec +1 -1
  22. data/spec/acceptance/example_spec.rb +46 -0
  23. data/spec/data/resourcedump/changedump.xml +16 -0
  24. data/spec/data/simulator/capability-list.xml +2 -0
  25. data/spec/data/simulator/change-list.xml +2 -0
  26. data/spec/data/simulator/source-description.xml +2 -0
  27. data/spec/data/simulator/update.txt +1 -0
  28. data/spec/unit/resync/client/bitstream_spec.rb +84 -80
  29. data/spec/unit/resync/client/client_spec.rb +64 -3
  30. data/spec/unit/resync/client/{resync_extensions_spec.rb → extensions_spec.rb} +1 -6
  31. data/spec/unit/resync/client/http_helper_spec.rb +187 -185
  32. data/spec/unit/resync/client/zip_package_spec.rb +47 -32
  33. data/spec/unit/resync/client/zip_packages_spec.rb +42 -38
  34. data/spec/unit/resync/client/zipped_resource_list_spec.rb +61 -0
  35. metadata +35 -16
  36. data/lib/resync/client/bitstream.rb +0 -79
  37. data/lib/resync/client/client.rb +0 -58
  38. data/lib/resync/client/downloadable.rb +0 -35
  39. data/lib/resync/client/dump.rb +0 -26
  40. data/lib/resync/client/resync_extensions.rb +0 -85
  41. data/lib/resync/client/zip_package.rb +0 -66
  42. data/lib/resync/client/zip_packages.rb +0 -51
  43. data/spec/unit/resync/client/dump_spec.rb +0 -26
@@ -1,58 +0,0 @@
1
- require_relative 'version'
2
- require_relative 'http_helper'
3
-
4
- module Resync
5
-
6
- # Utility class for retrieving HTTP content and parsing it as ResourceSync documents.
7
- class Client
8
-
9
- # ------------------------------------------------------------
10
- # Initializer
11
-
12
- # Creates a new +Client+
13
- # @param helper [HTTPHelper] the HTTP helper. Defaults to a new HTTP helper with
14
- # +resync-client VERSION+ as the User-Agent string.
15
- def initialize(helper: HTTPHelper.new(user_agent: "resync-client #{VERSION}"))
16
- @helper = helper
17
- end
18
-
19
- # ------------------------------------------------------------
20
- # Public methods
21
-
22
- # Gets the content of the specified URI and parses it as a ResourceSync document.
23
- def get_and_parse(uri)
24
- uri = Resync::XML.to_uri(uri)
25
- raw_contents = get(uri)
26
- doc = XMLParser.parse(raw_contents)
27
- doc.client = self
28
- doc
29
- end
30
-
31
- # Gets the content of the specified URI as a string.
32
- # @param uri [URI, String] the URI to download
33
- # @return [String] the content of the URI
34
- def get(uri)
35
- uri = Resync::XML.to_uri(uri)
36
- @helper.fetch(uri: uri)
37
- end
38
-
39
- # Gets the content of the specified URI and saves it to a temporary file.
40
- # @param uri [URI, String] the URI to download
41
- # @return [String] the path to the downloaded file
42
- def download_to_temp_file(uri)
43
- uri = Resync::XML.to_uri(uri)
44
- @helper.fetch_to_file(uri: uri)
45
- end
46
-
47
- # Gets the content of the specified URI and saves it to the specified file,
48
- # overwriting it if it exists.
49
- # @param uri [URI, String] the URI to download
50
- # @param path [String] the path to save the download to
51
- # @return [String] the path to the downloaded file
52
- def download_to_file(uri:, path:)
53
- uri = Resync::XML.to_uri(uri)
54
- @helper.fetch_to_file(path: path, uri: uri)
55
- end
56
-
57
- end
58
- end
@@ -1,35 +0,0 @@
1
- require 'resync'
2
-
3
- module Resync
4
-
5
- # Adds +get+, +get_raw+, and +get_file+ methods, delegating
6
- # to the injected client.
7
- #
8
- # @see Augmented#client
9
- module Downloadable
10
- # Delegates to {Client#get_and_parse} to get the contents of
11
- # +:uri+ as a ResourceSync document
12
- def get_and_parse # rubocop:disable Style/AccessorMethodName
13
- client.get_and_parse(uri)
14
- end
15
-
16
- # Delegates to {Client#get} to get the contents of this +:uri+
17
- def get # rubocop:disable Style/AccessorMethodName
18
- client.get(uri)
19
- end
20
-
21
- # Delegates to {Client#download_to_temp_file} to download the
22
- # contents of +:uri+ to a file.
23
- def download_to_temp_file # rubocop:disable Style/AccessorMethodName
24
- client.download_to_temp_file(uri)
25
- end
26
-
27
- # Delegates to {Client#download_to_file} to download the
28
- # contents of +:uri+ to the specified path.
29
- # @param path [String] the path to download to
30
- def download_to_file(path)
31
- client.download_to_file(uri: uri, path: path)
32
- end
33
- end
34
-
35
- end
@@ -1,26 +0,0 @@
1
- require_relative 'zip_packages'
2
-
3
- module Resync
4
- # Extends {ChangeDump} and {ResourceDump} to provide
5
- # transparent access to the linked bitstream packages
6
- module Dump
7
- # Injects a +:zip_package+ method into each resource,
8
- # downloading the (presumed) bitstream package to a
9
- # temp file and returning it as a {ZipPackage}
10
- def resources=(value)
11
- super
12
- resources.each do |r|
13
- def r.zip_package
14
- @zip_package ||= ZipPackage.new(download_to_temp_file)
15
- end
16
- end
17
- end
18
-
19
- # A list (downloaded lazily) of the {ZipPackage}s for each resource
20
- # @return [ZipPackages] the zip packages for each resource
21
- def zip_packages
22
- @zip_packages ||= ZipPackages.new(resources)
23
- end
24
- end
25
-
26
- end
@@ -1,85 +0,0 @@
1
- require 'resync'
2
- require_relative 'downloadable'
3
- require_relative 'dump'
4
-
5
- # Extensions to the core Resync classes to simplify retrieval
6
- module Resync
7
-
8
- # ------------------------------------------------------------
9
- # Base classes
10
-
11
- # Injects a {Client} that subclasses can use to fetch
12
- # resources and links
13
- #
14
- # @!attribute [rw] client
15
- # @return [Client] the injected {Client}. Defaults to
16
- # a new {Client} instance.
17
- class Augmented
18
- attr_writer :client
19
-
20
- def client
21
- @client ||= Client.new
22
- end
23
-
24
- alias_method :base_links=, :links=
25
- private :base_links=
26
-
27
- # Adds a +:client+ method to each link, delegating
28
- # to {#client}
29
- def links=(value)
30
- self.base_links = value
31
- self.base_links = value
32
- parent = self
33
- links.each do |l|
34
- l.define_singleton_method(:client) do
35
- parent.client
36
- end
37
- end
38
- end
39
- end
40
-
41
- # Adds a +:client+ method to each resource, delegating
42
- # to {Augmented#client}
43
- class BaseResourceList
44
- alias_method :base_resources=, :resources=
45
- private :base_resources=
46
-
47
- # Adds a +:client+ method to each resource, delegating
48
- # to {Augmented#client}
49
- def resources=(value)
50
- self.base_resources = value
51
- parent = self
52
- resources.each do |r|
53
- r.define_singleton_method(:client) do
54
- parent.client
55
- end
56
- end
57
- end
58
- end
59
-
60
- # ------------------------------------------------------------
61
- # Resource and Link
62
-
63
- # Includes the {Downloadable} module
64
- class Resource
65
- include Downloadable
66
- end
67
-
68
- # Includes the {Link} module
69
- class Link
70
- include Downloadable
71
- end
72
-
73
- # ------------------------------------------------------------
74
- # ResourceDump and ChaneDump
75
-
76
- # Includes the {Dump} module
77
- class ResourceDump
78
- include Dump
79
- end
80
-
81
- # Includes the {Dump} module
82
- class ChangeDump
83
- include Dump
84
- end
85
- end
@@ -1,66 +0,0 @@
1
- require 'rexml/document'
2
- require 'zip'
3
- require_relative 'bitstream'
4
-
5
- module Resync
6
- # A ZIP package of resources or changes, providing access to individual
7
- # bitstreams based on the included manifest file.
8
- #
9
- class ZipPackage
10
-
11
- # ------------------------------------------------------------
12
- # Attributes
13
-
14
- # @return [Zip::File] the ZIP file wrapped by this package
15
- attr_reader :zipfile
16
-
17
- # @return [ResourceDumpManifest, ChangeDumpManifest] the manifest
18
- # for the ZIP package
19
- attr_reader :manifest
20
-
21
- # ------------------------------------------------------------
22
- # Initializer
23
-
24
- # Creates a new +ZipPackage+ for the specified file.
25
- #
26
- # @param zipfile [Zip::File, String] the ZIP file, or a path to it.
27
- def initialize(zipfile)
28
- self.zipfile = zipfile
29
- end
30
-
31
- # ------------------------------------------------------------
32
- # Public methods
33
-
34
- # Gets the bitstream for the specified resource. (Note that this
35
- # does no validation; if the resource is not in the manifest, or
36
- # the corresponding entry is not in the ZIP file, the behavior of
37
- # the returned {Bitstream} is undefined.)
38
- #
39
- # @return [Bitstream] a bitstream wrapping the ZIP entry for the
40
- # specified resource.
41
- def bitstream_for(resource)
42
- Bitstream.new(zipfile: @zipfile, resource: resource)
43
- end
44
-
45
- # Gets all bitstreams declared in the package manifest.
46
- # @return [Array<Bitstream>] a list of all bitstreams in the package
47
- def bitstreams
48
- manifest.resources.map { |r| bitstream_for(r) }
49
- end
50
-
51
- # ------------------------------------------------------------
52
- # Private methods
53
-
54
- private
55
-
56
- def zipfile=(value)
57
- zipfile = value.is_a?(Zip::File) ? value : Zip::File.open(value)
58
- manifest_entry = zipfile.find_entry('manifest.xml')
59
- fail "No manifest.xml found in zipfile #{zipfile.name}" unless manifest_entry
60
- manifest_stream = manifest_entry.get_input_stream
61
- @manifest = XMLParser.parse(manifest_stream)
62
- @zipfile = zipfile
63
- end
64
-
65
- end
66
- end
@@ -1,51 +0,0 @@
1
- module Resync
2
- # Lazily retrieves and caches the zip packages for the specified
3
- # list of resources. The packages are cached to temporary files
4
- # which are deleted on exit; if they are deleted while the
5
- # interpreter is running, the behavior is undefined (but bad things
6
- # are likely to happen).
7
- class ZipPackages
8
- include Enumerable
9
-
10
- # Creates a new {ZipPackages} wrapper for the specified list
11
- # of resources.
12
- # @param resources [Array<Resource>] The list of resources to
13
- # get zip packages for.
14
- def initialize(resources)
15
- @resources = resources
16
- @packages = {}
17
- end
18
-
19
- # Gets the size of this list of packages.
20
- # @return the size of the underlying array.
21
- def size
22
- @resources.size
23
- end
24
-
25
- # Gets the zip package at the specified index, downloading it
26
- # if necessary.
27
- #
28
- # @return [ZipPackage] the zip package for the resource at the
29
- # specified index in the underlying array.
30
- def [](key)
31
- resource = @resources[key]
32
- package_for(resource)
33
- end
34
-
35
- # Gets the zip package for the specified resource, downloading it
36
- # if necessary.
37
- # @return [ZipPackage] the package for the resource
38
- def package_for(resource)
39
- @packages[resource] ||= resource.zip_package
40
- end
41
-
42
- # Lazily iterates the given block for each zip package, downloading
43
- # as necessary.
44
- # @param &block [Block] The block to iterate
45
- def each
46
- @resources.lazy.each do |resource|
47
- yield package_for(resource)
48
- end
49
- end
50
- end
51
- end
@@ -1,26 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Resync
4
- describe Dump do
5
- it 'transparently extracts bitstreams' do
6
- package_uri = URI('http://example.com/resourcedump.zip')
7
- client = instance_double(Client)
8
- expect(client).to receive(:download_to_temp_file).once.with(package_uri).and_return('spec/data/resourcedump/resourcedump.zip')
9
-
10
- resource_dump = XMLParser.parse(File.read('spec/data/resourcedump/resourcedump.xml'))
11
- resource_dump.client = client
12
-
13
- zip_packages = resource_dump.zip_packages
14
- expect(zip_packages.size).to eq(1)
15
-
16
- zip_package = zip_packages[0]
17
- expect(zip_package).to be_a(ZipPackage)
18
-
19
- bitstreams = zip_package.bitstreams
20
- expect(bitstreams.size).to eq(2)
21
-
22
- stream1 = bitstreams[0]
23
- expect(stream1.content).to eq(File.read('spec/data/resourcedump/resources/res1'))
24
- end
25
- end
26
- end