metacrunch 2.1.0.pre1 → 2.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3651a2620048f6cf78fd1d1670a1f211c5c39dac
4
- data.tar.gz: acdfb9744c06a0d7f8725434b9fde56588135bad
3
+ metadata.gz: d28e81a93e97edc9aa9016c18587317304ca0d68
4
+ data.tar.gz: 19ec0fccbef5888f0397b6d2abd3c404f7878172
5
5
  SHA512:
6
- metadata.gz: e2ce0cf3aef3e033c60402ca81d9b568c598b2039c75adb4658fa930d2b9b41c5f2c14ca90e9df058bccb32da08f7c9a3e5f7d87c09d92566426cb46854b3868
7
- data.tar.gz: 046c114e1d674aff5d4ce17539da4fac30b58ed3960307fc24f00bbe4f67fbfece6c483830da099eca912423c74485bc8b0aba617d307cdc72fe07fd947d7828
6
+ metadata.gz: 7f5636649b8bb785b58ba4995aac662803a1901a0b24910ea3eaa2847f86c90a7382a45bd3ad99562548246f8ddefe97af017161074bf09e57ed6686a65c6d6b
7
+ data.tar.gz: 121cb6f44102a87e13520f8dfde8e8b2feef04329649fbc7d9ec7f93fff652d07bc42b9a84e8cde71760edaf690ccf3e5d5954439d47ce13bc96c6bf2121cd29
data/.gitignore CHANGED
@@ -1,5 +1,5 @@
1
1
  .DS_Store
2
- pkg
3
- Gemfile.lock
4
- .yardoc
5
- doc
2
+ /Gemfile.lock
3
+ /.yardoc
4
+ /doc
5
+ /*.gem
data/Readme.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # metacrunch
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/metacrunch.svg)](http://badge.fury.io/rb/metacrunch)
3
4
  [![Code Climate](https://codeclimate.com/github/ubpb/metacrunch/badges/gpa.svg)](https://codeclimate.com/github/ubpb/metacrunch)
4
5
  [![Build Status](https://travis-ci.org/ubpb/metacrunch.svg)](https://travis-ci.org/ubpb/metacrunch)
5
6
 
@@ -0,0 +1,29 @@
1
+ module Metacrunch
2
+ class Cli
3
+ class Base < Thor
4
+ no_commands do
5
+ def self.register_thor_command(command_definition)
6
+ desc(command_definition.usage, command_definition.desc)
7
+
8
+ command_definition.options.each do |key, value|
9
+ option(key, value)
10
+ end
11
+
12
+ define_method(command_definition.name) do |*params|
13
+ run_command(command_definition.command_class, params)
14
+ end
15
+ end
16
+
17
+ def run_command(command, params = [])
18
+ klass = command.class == Class ? command : command.to_s.constantize
19
+ raise ArgumentError, "command must be a Metacrunch::Command class" unless klass < Metacrunch::Command
20
+
21
+ command = klass.new(shell, options, params)
22
+ command.pre_perform
23
+ command.perform
24
+ command.post_perform
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,41 @@
1
+ module Metacrunch
2
+ class Cli
3
+ class CommandDefinition
4
+ def initialize(command_class, description)
5
+ @klass = command_class
6
+ @name = nil
7
+ @description = description
8
+ @usage = nil
9
+ @options = {}
10
+ end
11
+
12
+ def command_class(value = nil)
13
+ @klass if value
14
+ @klass
15
+ end
16
+
17
+ def name
18
+ name = @klass.to_s.demodulize.underscore
19
+ name.gsub!(/_command\Z/, "")
20
+ end
21
+
22
+ def usage(value = nil)
23
+ @usage = value if value.present?
24
+ @usage || name
25
+ end
26
+
27
+ def desc(value = nil)
28
+ @description = value if value.present?
29
+ @description
30
+ end
31
+
32
+ def option(name, options = {})
33
+ @options[name] = options
34
+ end
35
+
36
+ def options
37
+ @options
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,17 @@
1
+ module Metacrunch
2
+ class Cli
3
+ class CommandRegistry
4
+ attr_reader :commands
5
+
6
+ def initialize
7
+ @commands = []
8
+ end
9
+
10
+ def register(klass, description = nil, &block)
11
+ command = CommandDefinition.new(klass, description)
12
+ yield(command) if block_given?
13
+ @commands << command
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ module Metacrunch
2
+ class Cli
3
+ class Main < Thor
4
+ # Define metacrunch root commands here
5
+ end
6
+ end
7
+ end
@@ -1,4 +1,26 @@
1
1
  module Metacrunch
2
- class Cli < Thor
2
+ class Cli
3
+ require_relative "./cli/main"
4
+ require_relative "./cli/base"
5
+ require_relative "./cli/command_registry"
6
+ require_relative "./cli/command_definition"
7
+
8
+ def self.start(argv)
9
+ Main.start(argv)
10
+ end
11
+
12
+ def self.setup(namespace, description, &block)
13
+ klass = Class.new(Base)
14
+ klass.namespace(namespace)
15
+
16
+ registry = CommandRegistry.new
17
+ yield(registry)
18
+
19
+ registry.commands.each do |c|
20
+ klass.register_thor_command(c)
21
+ end
22
+
23
+ Main.register(klass, namespace, "#{namespace} [COMMAND]", description)
24
+ end
3
25
  end
4
26
  end
@@ -3,11 +3,24 @@ module Metacrunch
3
3
 
4
4
  attr_reader :shell
5
5
  attr_reader :options
6
+ attr_reader :params
6
7
 
7
- def initialize(shell:, options:)
8
+ def initialize(shell, options = {}, params = [])
8
9
  @shell = shell
9
10
  @options = options
10
- setup if self.respond_to?(:setup)
11
+ @params = params
12
+ end
13
+
14
+ def pre_perform
15
+ # can be implemented in sub-class
16
+ end
17
+
18
+ def perform
19
+ raise NotImplementedError, "You must implement .perform() in your command sub-class"
20
+ end
21
+
22
+ def post_perform
23
+ # can be implemented in sub-class
11
24
  end
12
25
 
13
26
  end
@@ -0,0 +1,31 @@
1
+ module Metacrunch
2
+ class SNR
3
+ class Section
4
+ class Field
5
+
6
+ attr_reader :name
7
+ attr_accessor :value
8
+
9
+ def initialize(name, value)
10
+ raise ArgumentError, "required Field#name not given" if name.nil?
11
+
12
+ @name = name
13
+ @value = value
14
+ end
15
+
16
+ # ------------------------------------------------------------------------------
17
+ # Serialization
18
+ # ------------------------------------------------------------------------------
19
+
20
+ def to_xml(builder)
21
+ if value.respond_to?(:to_xml)
22
+ value.to_xml(root: self.name, builder: builder, skip_instruct: true)
23
+ else
24
+ builder.tag!(self.name, self.value)
25
+ end
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,63 @@
1
+ module Metacrunch
2
+ class SNR
3
+ class Section
4
+
5
+ attr_reader :name
6
+
7
+ def initialize(name)
8
+ raise ArgumentError, "required Section#name not given" if name.nil?
9
+
10
+ @name = name
11
+ @fields = []
12
+ end
13
+
14
+ # ------------------------------------------------------------------------------
15
+ # Common API
16
+ # ------------------------------------------------------------------------------
17
+
18
+ #
19
+ # Adds a field
20
+ #
21
+ def add(field_name, value)
22
+ add_field(Field.new(field_name, value))
23
+ end
24
+
25
+ # ------------------------------------------------------------------------------
26
+ # Fields
27
+ # ------------------------------------------------------------------------------
28
+
29
+ #
30
+ # Return all fields.
31
+ #
32
+ # @return [Array<Metacrunch::SNR::Section::Field>]
33
+ #
34
+ def fields
35
+ @fields
36
+ end
37
+
38
+ #
39
+ # Adds a new field to this section.
40
+ #
41
+ # @param [Metacrunch::SNR::Section::Field] field
42
+ # @return [Metacrunch::SNR::Section::Field]
43
+ #
44
+ def add_field(field)
45
+ @fields << field
46
+ field
47
+ end
48
+
49
+ # ------------------------------------------------------------------------------
50
+ # Serialization
51
+ # ------------------------------------------------------------------------------
52
+
53
+ def to_xml(builder)
54
+ builder.tag!(self.name) do
55
+ @fields.each do |_field|
56
+ _field.to_xml(builder)
57
+ end
58
+ end
59
+ end
60
+
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,101 @@
1
+ module Metacrunch
2
+ #
3
+ # A SNR object (Simple Normalized Record) is a simple data structure
4
+ # that you can use as a target resource when performing data normalization routines.
5
+ # A DNSR record consists of unique sections. A section is unique identified by it's
6
+ # name. Each section can hold many fields that store the actual values.
7
+ #
8
+ # A SNR object can be transformed into XML or JSON to allow easy integration into
9
+ # existing tools and workflows.
10
+ #
11
+ # For example: If you normalize MAB XML data for use in a search engine you can
12
+ # use a SNR object to store your normalized values.
13
+ #
14
+ class SNR
15
+ require_relative "./snr/section"
16
+ require_relative "./snr/field"
17
+
18
+ # ------------------------------------------------------------------------------
19
+ # Common API
20
+ # ------------------------------------------------------------------------------
21
+
22
+ #
23
+ # Adds a field with a value to a section. If the section with the given name
24
+ # doesn't exists it will be created.
25
+ #
26
+ # @param [String] section_name
27
+ # @param [String] field_name
28
+ # @param [#to_s] value
29
+ #
30
+ def add(section_name, field_name, value)
31
+ section = self.section(section_name) || Section.new(section_name)
32
+ section.add(field_name, value)
33
+ add_section(section)
34
+ end
35
+
36
+ # ------------------------------------------------------------------------------
37
+ # Sections
38
+ # ------------------------------------------------------------------------------
39
+
40
+ #
41
+ # @return [Hash{String => Metacrunch::SNR::Section}]
42
+ # @private
43
+ #
44
+ def sections_struct
45
+ @sections_struct ||= {}
46
+ end
47
+ private :sections_struct
48
+
49
+ #
50
+ # Return all sections.
51
+ #
52
+ # @return [Array<Metacrunch::SNR::Section>]
53
+ #
54
+ def sections
55
+ sections_struct.values
56
+ end
57
+
58
+ #
59
+ # Get section by name.
60
+ #
61
+ # @param [String] name Name of the section
62
+ # @return [Metacrunch::SNR::Section, nil] section by name or nil if a section
63
+ # with the given name doesn't exists.
64
+ #
65
+ def section(name)
66
+ sections_struct[name]
67
+ end
68
+
69
+ #
70
+ # Adds / replaces a section. The name of the section is used as a unique identifier.
71
+ # Therefore if you add a section with a name that already exists, the new section
72
+ # will override the existing one.
73
+ #
74
+ # @param [Metacrunch::SNR::Section] section
75
+ # @return [Metacrunch::SNR::Section]
76
+ #
77
+ def add_section(section)
78
+ sections_struct[section.name] = section
79
+ end
80
+
81
+ # ------------------------------------------------------------------------------
82
+ # Serialization
83
+ # ------------------------------------------------------------------------------
84
+
85
+ #
86
+ # Transforms the SNR into XML.
87
+ #
88
+ # @return [String] The SNR as XML string.
89
+ #
90
+ def to_xml
91
+ builder = Builder::XmlMarkup.new(indent: 2)
92
+ builder.instruct!(:xml, :encoding => "UTF-8")
93
+ builder.snr do
94
+ sections.each do |_section|
95
+ _section.to_xml(builder)
96
+ end
97
+ end
98
+ end
99
+
100
+ end
101
+ end
@@ -0,0 +1,33 @@
1
+ require_relative "../transformer"
2
+
3
+ module Metacrunch
4
+ class Transformer
5
+ class Step
6
+
7
+ def initialize(transformer)
8
+ @transformer = transformer
9
+ end
10
+
11
+ def perform
12
+ raise NotImplementedError, "You must implement .perform() in your rule sub-class"
13
+ end
14
+
15
+ def transformer
16
+ @transformer
17
+ end
18
+
19
+ def source
20
+ transformer.source
21
+ end
22
+
23
+ def target
24
+ transformer.target
25
+ end
26
+
27
+ def options
28
+ transformer.options
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ module Metacrunch
2
+ class Transformer
3
+ require_relative "./transformer/step"
4
+
5
+ attr_reader :source, :target, :options
6
+
7
+ def initialize(source:, target:, options: {})
8
+ @source = source
9
+ @target = target
10
+ @options = options
11
+ end
12
+
13
+ def transform(step_class = nil, &block)
14
+ if block_given?
15
+ Step.new(self).instance_eval(&block) # TODO: Benchmark this
16
+ else
17
+ raise ArgumentError, "You need to provide a STEP or a block" if step_class.nil?
18
+ step_class.new(self).perform
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -1,3 +1,3 @@
1
1
  module Metacrunch
2
- VERSION = "2.1.0.pre1"
2
+ VERSION = "2.1.0"
3
3
  end
data/lib/metacrunch.rb CHANGED
@@ -1,16 +1,23 @@
1
1
  require "active_support"
2
2
  require "active_support/core_ext"
3
+ require "active_support/builder"
3
4
  require "parallel"
4
5
  require "rubygems"
5
6
  require "rubygems/package"
6
7
  require "thor"
7
- require "thor/group"
8
+ require "ox"
8
9
 
9
10
  begin
10
11
  require "pry"
11
12
  rescue LoadError ; end
12
13
 
13
14
  module Metacrunch
15
+ require_relative "./metacrunch/version"
16
+ require_relative "./metacrunch/cli"
17
+ require_relative "./metacrunch/command"
18
+ require_relative "./metacrunch/utils"
19
+ require_relative "./metacrunch/snr"
20
+ require_relative "./metacrunch/transformer"
14
21
 
15
22
  def self.load_plugins
16
23
  Gem.find_latest_files("metacrunch_plugin.rb").each do |path|
@@ -19,8 +26,3 @@ module Metacrunch
19
26
  end
20
27
 
21
28
  end
22
-
23
- require "metacrunch/version"
24
- require "metacrunch/cli"
25
- require "metacrunch/command"
26
- require "metacrunch/utils"
data/metacrunch.gemspec CHANGED
@@ -3,7 +3,7 @@ require File.expand_path("../lib/metacrunch/version", __FILE__)
3
3
  Gem::Specification.new do |s|
4
4
  s.authors = ["René Sprotte", "Michael Sievers", "Marcel Otto"]
5
5
  s.email = "r.sprotte@ub.uni-paderborn.de"
6
- s.summary = %q{Metadata processing toolkit for Ruby}
6
+ s.summary = %q{Data processing toolkit for Ruby}
7
7
  s.description = s.summary
8
8
  s.homepage = "http://github.com/ubpb/metacrunch"
9
9
  s.licenses = ["MIT"]
@@ -20,6 +20,8 @@ Gem::Specification.new do |s|
20
20
  s.required_ruby_version = ">= 2.2.0"
21
21
 
22
22
  s.add_dependency "activesupport", "~> 4.2", ">= 4.2.0"
23
+ s.add_dependency "builder", "~> 3.2", ">= 3.2.2"
23
24
  s.add_dependency "parallel", "~> 1.4", ">= 1.4.1"
24
25
  s.add_dependency "thor", "~> 0.19"
26
+ s.add_dependency "ox", "~> 2.1"
25
27
  end
data/spec/snr_spec.rb ADDED
@@ -0,0 +1,73 @@
1
+ describe Metacrunch::SNR do
2
+
3
+ let(:snr) { Metacrunch::SNR.new }
4
+
5
+
6
+ describe ".add" do
7
+ it "adds a field and creates a section if the section doesn't exists" do
8
+ expect {
9
+ snr.add("mysection", "myfield", "My Value")
10
+ }.to change { snr.sections.count }.by(1)
11
+ end
12
+
13
+ it "adds a field to an existsing section" do
14
+ snr.add_section(Metacrunch::SNR::Section.new("mysection"))
15
+
16
+ expect {
17
+ snr.add("mysection", "myfield", "My Value")
18
+ }.not_to change { snr.sections.count }
19
+ end
20
+ end
21
+
22
+ describe ".sections" do
23
+ let(:section1) { Metacrunch::SNR::Section.new("section1") }
24
+ let(:section2) { Metacrunch::SNR::Section.new("section2") }
25
+
26
+ before {
27
+ snr.add_section(section1)
28
+ snr.add_section(section2)
29
+ }
30
+
31
+ subject { snr.sections }
32
+
33
+ it "returns all sections" do
34
+ expect(snr.sections.count).to be(2)
35
+ end
36
+
37
+ it { is_expected.not_to be_empty }
38
+ it { is_expected.to include(section1) }
39
+ it { is_expected.to include(section2) }
40
+ end
41
+
42
+ describe ".section(name)" do
43
+ context "when section exists" do
44
+ let(:section1) { Metacrunch::SNR::Section.new("section1") }
45
+ before { snr.add_section(section1) }
46
+ subject { snr.section("section1") }
47
+
48
+ it { is_expected.not_to be_nil }
49
+ it { is_expected.to be(section1) }
50
+ end
51
+
52
+ context "when section doesn't exists" do
53
+ subject { snr.section("no_such_section") }
54
+
55
+ it { is_expected.to be_nil }
56
+ end
57
+ end
58
+
59
+ describe ".to_xml" do
60
+ before {
61
+ snr.add("section1", "title", "Foo Bar")
62
+ snr.add("section1", "artists", ["Sievers, Michael", "Sprotte, René"])
63
+ snr.add("section2", "link", {label: "Click here", url: "http://example.com"})
64
+ }
65
+
66
+ subject { snr.to_xml }
67
+
68
+ it { is_expected.not_to be_nil }
69
+ it { is_expected.not_to be_empty }
70
+ it { is_expected.to eq("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<snr>\n <section1>\n <title>Foo Bar</title>\n <artists type=\"array\">\n <artist>Sievers, Michael</artist>\n <artist>Sprotte, René</artist>\n </artists>\n </section1>\n <section2>\n <link>\n <label>Click here</label>\n <url>http://example.com</url>\n </link>\n </section2>\n</snr>\n") }
71
+ end
72
+
73
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metacrunch
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0.pre1
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - René Sprotte
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-04-23 00:00:00.000000000 Z
13
+ date: 2015-05-07 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -32,6 +32,26 @@ dependencies:
32
32
  - - ">="
33
33
  - !ruby/object:Gem::Version
34
34
  version: 4.2.0
35
+ - !ruby/object:Gem::Dependency
36
+ name: builder
37
+ requirement: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '3.2'
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 3.2.2
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - "~>"
50
+ - !ruby/object:Gem::Version
51
+ version: '3.2'
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 3.2.2
35
55
  - !ruby/object:Gem::Dependency
36
56
  name: parallel
37
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +86,21 @@ dependencies:
66
86
  - - "~>"
67
87
  - !ruby/object:Gem::Version
68
88
  version: '0.19'
69
- description: Metadata processing toolkit for Ruby
89
+ - !ruby/object:Gem::Dependency
90
+ name: ox
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '2.1'
96
+ type: :runtime
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '2.1'
103
+ description: Data processing toolkit for Ruby
70
104
  email: r.sprotte@ub.uni-paderborn.de
71
105
  executables:
72
106
  - metacrunch
@@ -83,7 +117,16 @@ files:
83
117
  - bin/metacrunch
84
118
  - lib/metacrunch.rb
85
119
  - lib/metacrunch/cli.rb
120
+ - lib/metacrunch/cli/base.rb
121
+ - lib/metacrunch/cli/command_definition.rb
122
+ - lib/metacrunch/cli/command_registry.rb
123
+ - lib/metacrunch/cli/main.rb
86
124
  - lib/metacrunch/command.rb
125
+ - lib/metacrunch/snr.rb
126
+ - lib/metacrunch/snr/field.rb
127
+ - lib/metacrunch/snr/section.rb
128
+ - lib/metacrunch/transformer.rb
129
+ - lib/metacrunch/transformer/step.rb
87
130
  - lib/metacrunch/utils.rb
88
131
  - lib/metacrunch/utils/file_reader.rb
89
132
  - lib/metacrunch/utils/file_reader_result.rb
@@ -93,8 +136,9 @@ files:
93
136
  - spec/assets/archive.tar.gz
94
137
  - spec/assets/regular_file.txt
95
138
  - spec/assets/regular_file.txt.gz
96
- - spec/file_reader_spec.rb
139
+ - spec/snr_spec.rb
97
140
  - spec/spec_helper.rb
141
+ - spec/utils/file_reader_spec.rb
98
142
  homepage: http://github.com/ubpb/metacrunch
99
143
  licenses:
100
144
  - MIT
@@ -110,20 +154,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
110
154
  version: 2.2.0
111
155
  required_rubygems_version: !ruby/object:Gem::Requirement
112
156
  requirements:
113
- - - ">"
157
+ - - ">="
114
158
  - !ruby/object:Gem::Version
115
- version: 1.3.1
159
+ version: '0'
116
160
  requirements: []
117
161
  rubyforge_project:
118
- rubygems_version: 2.4.6
162
+ rubygems_version: 2.4.5
119
163
  signing_key:
120
164
  specification_version: 4
121
- summary: Metadata processing toolkit for Ruby
165
+ summary: Data processing toolkit for Ruby
122
166
  test_files:
123
167
  - spec/assets/archive.tar
124
168
  - spec/assets/archive.tar.gz
125
169
  - spec/assets/regular_file.txt
126
170
  - spec/assets/regular_file.txt.gz
127
- - spec/file_reader_spec.rb
171
+ - spec/snr_spec.rb
128
172
  - spec/spec_helper.rb
129
- has_rdoc:
173
+ - spec/utils/file_reader_spec.rb