i2x 0.0.1 → 0.0.3

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: df70dba633aeddf8808df72b37307d6aefd6d0b6
4
- data.tar.gz: 15bf7911acaeb10b7581b2f0cc4f43003dd763a9
3
+ metadata.gz: 335a577dfae00f0024b44efe43882721190a5397
4
+ data.tar.gz: 0ea51a5523b9f0a2b52b001ff853b5219b0a5cbc
5
5
  SHA512:
6
- metadata.gz: 65b0cd1b4018cdf3d78cefc62af8b1089f085b0ecd03c6a34c061cc183f9d43023cc0e9f8d194a0f0c6f7af92cdc6655310ea1c16262ec04ab59ce45b74b651c
7
- data.tar.gz: da2217a5a6e05cbecd8752944ebe064705c6c82ea7ba49eb371c63118a25779323f2575a25aac9b0ec293952d4464bb569857ef7dfe4288cc0b2f404dec80613
6
+ metadata.gz: b835461966de12b01bb793e512d105f48186408f08529e0b163ff14cd39d7580d9c2215b023b3474dc00d614141bd4140221bdd262dcd69560b525fd35ab87ec
7
+ data.tar.gz: fb868fdbe8c44735db9d2b831343d90e2a8d2fc71dd1c3460917bad87545c873222c1e65494249da1439943b6aa7a7390c9ea0ae27b1da342bea9fa226bbce65
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in i2x.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,17 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ i2x (0.0.3)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ rake (10.1.1)
10
+
11
+ PLATFORMS
12
+ ruby
13
+
14
+ DEPENDENCIES
15
+ bundler (~> 1.5)
16
+ i2x!
17
+ rake
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Pedro Lopes
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # I2X
2
+
3
+ ### Automated real-time integration
4
+
5
+ Ruby gem for distributed client agents.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'i2x'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install i2x
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( http://github.com/pdrlps/i2x-gem/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << 'lib/i2x'
8
+ t.test_files = FileList['test/lib/i2x/*_test.rb']
9
+ t.verbose = true
10
+ end
11
+
12
+ task :default => :test
data/i2x.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'i2x/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "i2x"
8
+ spec.version = I2X::VERSION
9
+ spec.authors = ["Pedro Lopes"]
10
+ spec.email = ["hello@pedrolopes.net"]
11
+ spec.summary = %q{i2x client library for distributed agents.}
12
+ spec.description = %q{i2x: integrate everything. Automated real-time integration framework.}
13
+ spec.homepage = "https://bioinformatics.ua.pt/i2x/"
14
+ spec.license = "MIT"
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+ spec.add_development_dependency "bundler", "~> 1.5"
20
+ spec.add_development_dependency "rake"
21
+ end
data/lib/i2x.rb CHANGED
@@ -1,5 +1,6 @@
1
- class I2X
2
- def self.hi
3
- puts "Hello world!"
4
- end
5
- end
1
+ require_relative "./i2x/version"
2
+ require_relative "./i2x/client"
3
+
4
+ module I2X
5
+
6
+ end
@@ -0,0 +1,77 @@
1
+ require 'slog'
2
+
3
+
4
+ module Services
5
+ class Cashier
6
+
7
+
8
+ public
9
+
10
+ ##
11
+ # = Verify
12
+ # => Verify if items have already been seen in the past (on the cache).
13
+ #
14
+ # == Params
15
+ # - *memory*: the key identifier to be verified
16
+ # - *payload*: the value for matching/verification
17
+ # - *agent*: the agent performing the verification
18
+ # - *seed*: seed data (if available)
19
+ #
20
+ def self.verify memory, agent, payload, seed
21
+ ##
22
+ # => Redis implementation, use cache.
23
+ #
24
+ begin
25
+
26
+ # if Redis is enabled...
27
+ if ENV["CACHE_REDIS"] then
28
+ # give me some cache!
29
+ @redis = Redis.new :host => ENV["CACHE_HOST"], :port => ENV["CACHE_PORT"]
30
+ end
31
+ rescue Exception => e
32
+ Services::Slog.exception e
33
+ end
34
+
35
+ # the actual verification
36
+ if ENV["CACHE_REDIS"] then
37
+ # commented, do not log all cache verifications
38
+ #Services::Slog.debug({:message => "Verifying cache", :module => "Cashier", :task => "cache", :extra => {:agent => agent[:identifier], :memory => memory, :payload => payload, :seed => seed}})
39
+ begin
40
+ if @redis.hexists("#{agent[:identifier]}:#{seed}","#{memory}") then
41
+ response = {:status => 200, :message => "[i2x][Cashier] Nothing to update"}
42
+ else
43
+ @redis.hset("#{agent[:identifier]}:#{seed}", "#{memory}", payload)
44
+ response = {:status => 100, :message => "[i2x][Cashier] Memory recorded to cache"}
45
+ end
46
+ rescue Exception => e
47
+ response = {:message => "[i2x][Cashier] unable to verify cache content, #{e}", :status => 301}
48
+ Services::Slog.exception e
49
+ end
50
+ end
51
+
52
+ ##
53
+ # => SQL implementation, use internal database.
54
+ #
55
+ # => To Do: Recheck implementation.
56
+ #
57
+ if ENV["CACHE_INTERNAL"] then
58
+ results = Cache.where memory: memory, agent_id: agent.id, seed: seed
59
+ if results.size == 0 then
60
+ begin
61
+ @cached = Cache.new({:memory => memory, :agent_id => agent.id, :payload => payload, :seed => seed})
62
+ @cached.save
63
+ response = {:status => 100, :message => "[i2x][Cashier] Memory recorded to cache"}
64
+ rescue Exception => e
65
+ response = {:message => "[i2x][Cashier] unable to save new cache content, #{e}", :status => 300}
66
+ Services::Slog.exception e
67
+ end
68
+ else
69
+ response = {:status => 200, :message => "[i2x][Cashier] Nothing to update"}
70
+ end
71
+
72
+ end
73
+
74
+ response
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,37 @@
1
+ module I2X
2
+ class Checkup
3
+
4
+ ##
5
+ # = Perform the actual check execution
6
+ #
7
+ # + *agent*: the agent to verify
8
+ #
9
+ def execute agent
10
+ begin
11
+ @response = agent.execute
12
+ rescue Exception => e
13
+
14
+ @response = {:status => 400, :error => e}
15
+ end
16
+ end
17
+
18
+
19
+ ##
20
+ # = Initiate real-time (poll) check
21
+ #
22
+ # + *schedule*: the scheduling being checked
23
+ def check schedule
24
+ Integration.all.each do |integration|
25
+ @agents = integration.agents.where( :schedule => schedule).where("last_check_at < CURRENT_TIMESTAMP - INTERVAL 5 MINUTE")
26
+ @agents.each do |agent|
27
+ begin
28
+ self.execute agent
29
+ rescue Exception => e
30
+
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ end
37
+ end
data/lib/i2x/client.rb ADDED
@@ -0,0 +1,13 @@
1
+ module I2X
2
+ class Client
3
+
4
+ def initialize config
5
+ @config = config
6
+
7
+ end
8
+
9
+ def ping
10
+ p "PONGING #{@config[:server][:host]}"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,53 @@
1
+ require 'helper'
2
+ require 'csv'
3
+ require 'open-uri'
4
+ require 'seedreader'
5
+ require 'csvseedreader'
6
+ require 'sqlseedreader'
7
+ require 'xmlseedreader'
8
+ require 'jsonseedreader'
9
+
10
+ module I2X
11
+
12
+ ##
13
+ # = CSVDetector
14
+ #
15
+ # Detect changes in CSV files (using column numbers).
16
+ #
17
+ class CSVDetector < Detector
18
+
19
+ public
20
+ ##
21
+ # == Detect the changes
22
+ #
23
+ def detect object
24
+ begin
25
+ CSV.new(open(object[:uri]), :headers => :first_row).each do |row|
26
+ unless object[:cache].nil? then
27
+ @cache = Cashier.verify row[object[:cache].to_i], object, row, object[:seed]
28
+ else
29
+ @cache = Cashier.verify row[0], object, row, object[:seed]
30
+ end
31
+ # The actual processing
32
+ #
33
+ if @cache[:status] == 100 then
34
+
35
+ # add row data to payload from selectors (key => key, value => column name)
36
+ payload = Hash.new
37
+ JSON.parse(object[:selectors]).each do |selector|
38
+ selector.each do |k,v|
39
+ payload[k] = row[v.to_i]
40
+ end
41
+ end
42
+ # add payload object to payloads list
43
+ @payloads.push payload
44
+ end
45
+ end
46
+ rescue Exception => e
47
+ I2X::Slog.exception e
48
+ end
49
+ end
50
+
51
+
52
+ end
53
+ end
@@ -0,0 +1,47 @@
1
+ require 'csv'
2
+
3
+ module I2X
4
+
5
+ # = CSVSeedReader
6
+ #
7
+ # Load content from CSV seed.
8
+ #
9
+ class CSVSeedReader < SeedReader
10
+ ##
11
+ # == Read
12
+ #
13
+ # => Load the seed data into the @objects array for processing.
14
+ #
15
+ def read
16
+ begin
17
+ CSV.new(open(@seed[:payload][:uri]), :headers => :first_row).each do |row|
18
+ begin
19
+ object = @help.deep_copy @agent[:payload]
20
+ object.each_pair do |key,value|
21
+ variables = @help.identify_variables(object[key])
22
+ variables.each do |v|
23
+ object[key].gsub!("%{#{v}}", row[@seed[:payload][:selectors][v].to_i])
24
+ end
25
+ end
26
+
27
+ unless @seed[:payload][:cache].nil? then
28
+ object[:seed] = row[@seed[:payload][:cache].to_i]
29
+ else
30
+ object[:seed] = row[0]
31
+ end
32
+
33
+
34
+ object[:identifier] = @agent.identifier
35
+ @objects.push object
36
+ rescue Exception => e
37
+
38
+ end
39
+ end
40
+ rescue Exception => e
41
+
42
+ end
43
+
44
+ @objects
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,109 @@
1
+ require 'seedreader'
2
+ require 'csvseedreader'
3
+ require 'sqlseedreader'
4
+ require 'xmlseedreader'
5
+ require 'jsonseedreader'
6
+
7
+
8
+ module I2X
9
+
10
+ ##
11
+ # = Detector
12
+ #
13
+ # Main change detection class, to be inherited by SQL, CSV, JSON and XML detectors (and others to come).
14
+ #
15
+ class Detector
16
+ attr_accessor :identifier, :agent, :objects, :payloads, :content
17
+
18
+ def initialize identifier
19
+ begin
20
+ @agent = Agent.find_by! identifier: identifier
21
+ @payloads = Array.new
22
+ @objects = Array.new
23
+ @help = I2X::Helper.new
24
+ rescue Exception => e
25
+
26
+ end
27
+ end
28
+
29
+
30
+ ##
31
+ # == Start original source detection process
32
+ #
33
+ def checkup
34
+ # update checkup time
35
+ @agent.update_check_at @help.datetime
36
+
37
+ begin
38
+
39
+ ##
40
+ # => Process seed data, if available.
41
+ #
42
+ if @agent.seeds.size != 0 then
43
+ @agent.seeds.each do |seed|
44
+ case seed[:publisher]
45
+ when 'csv'
46
+ begin
47
+ @sr = I2X::CSVSeedReader.new(@agent, seed)
48
+ rescue Exception => e
49
+
50
+ end
51
+ when 'sql'
52
+ begin
53
+ @sr = I2X::SQLSeedReader.new(@agent, seed)
54
+ rescue Exception => e
55
+
56
+ end
57
+ when 'xml'
58
+ begin
59
+ @sr = I2X::XMLSeedReader.new(@agent, seed)
60
+ rescue Exception => e
61
+
62
+ end
63
+ when 'json'
64
+ begin
65
+ @sr = I2X::JSONSeedReader.new(@agent, seed)
66
+ rescue Exception => e
67
+
68
+ end
69
+ end
70
+ begin
71
+ @reads = @sr.read
72
+ @reads.each do |read|
73
+ @objects.push read
74
+ end
75
+ rescue Exception => e
76
+
77
+ end
78
+ end
79
+
80
+ else
81
+ ##
82
+ # no seeds, simply copy agent data
83
+ object = @help.deep_copy @agent[:payload]
84
+ object[:identifier] = @agent[:identifier]
85
+ object[:seed] = object[:identifier]
86
+ unless self.content.nil? then
87
+ object[:content] = self.content
88
+ end
89
+ @objects.push object
90
+ end
91
+ rescue Exception => e
92
+ @response = {:status => 404, :message => "[i2x][Detector] failed to load doc, #{e}"}
93
+ I2X::Slog.exception e
94
+ end
95
+
96
+ begin
97
+ # increase detected events count
98
+ @agent.increment!(:events_count, @payloads.size)
99
+ @response = { :payload => @payloads, :status => 100}
100
+ rescue Exception => e
101
+ @response = {:status => 404, :message => "[i2x][Detector] failed to process queries, #{e}"}
102
+ I2X::Slog.exception e
103
+ end
104
+ @response
105
+ end
106
+
107
+
108
+ end
109
+ end
data/lib/i2x/helper.rb ADDED
@@ -0,0 +1,153 @@
1
+ require 'slog'
2
+
3
+ module I2X
4
+
5
+ ##
6
+ # = Helper Class
7
+ # => Miscellaneous helper methods and utils to deal with data.
8
+ #
9
+ class Helper
10
+ attr_accessor :replacements
11
+ @replacements
12
+
13
+ def initialize
14
+ # load each helper function into a map for replacement in the delivery
15
+ @replacements = [ ["%{i2x.date}", self.date], ["%{i2x.datetime}", self.datetime], ["%{i2x.hostname}", self.hostname]]
16
+ end
17
+
18
+ public
19
+ def hostname
20
+ ENV["APP_HOST"]
21
+ end
22
+
23
+ def datetime
24
+ Time.now.to_s
25
+ end
26
+
27
+ def date
28
+ Time.now.strftime("%Y-%m-%d").to_s
29
+ end
30
+
31
+ ##
32
+ # == Identify Variables
33
+ # => Identifies variables on string set, generates array with all scanned variables for processing.
34
+ # => Variables are enclosed in %{variable} string.
35
+ #
36
+ # * +text+ - string to be scanned
37
+ #
38
+ def identify_variables text
39
+ begin
40
+ results = Array.new
41
+ text.scan(/%{(.*?)}/).each do |m|
42
+ results.push m[0]
43
+ end
44
+ rescue Exception => e
45
+
46
+ end
47
+
48
+ results
49
+ end
50
+
51
+ ##
52
+ # == Validate payload
53
+ # => Validates content payload.
54
+ #
55
+ # + *publisher* - for publisher-specific validations
56
+ # + *payload* - content for validation
57
+ #
58
+ def self.validate_payload publisher, payload
59
+ @database_servers = ["mysql","sqlite","postgresql"]
60
+ valid = true
61
+
62
+ begin
63
+ case publisher
64
+ when 'csv', 'xml', 'json', 'file', 'js'
65
+ # file content URI is mandatory
66
+ if payload[:uri].nil? then
67
+ valid = false
68
+ end
69
+ when 'sql'
70
+
71
+ # check if database server is available
72
+ unless database_servers.include? payload[:server] then
73
+ valid = false
74
+ end
75
+
76
+ # database username is mandatory
77
+ if payload[:username].nil? then
78
+ valid = false
79
+ end
80
+
81
+ # database user password is mandatory
82
+ if payload[:password].nil? then
83
+ valid = false
84
+ end
85
+
86
+ # database name is mandatory
87
+ if payload[:database].nil? then
88
+ valid = false
89
+ end
90
+
91
+ # database query is mandatory
92
+ if payload[:query].nil? then
93
+ valid = false
94
+ end
95
+ end
96
+ rescue Exception => e
97
+
98
+ end
99
+ valid
100
+ end
101
+
102
+ ##
103
+ # == Validate Seed
104
+ # => Validates Seed-specific properties
105
+ #
106
+ # + *publisher* - for publisher-specific validations
107
+ # + *seed* - the seed hash
108
+ #
109
+ def self.validate_seed publisher, seed
110
+ begin
111
+ valid = self.validate_payload publisher, seed
112
+ if valid then
113
+ # seed must have selectors
114
+ if seed[:selectors].nil? then
115
+ valid = false
116
+ end
117
+ else
118
+ valid = false
119
+ end
120
+ rescue Exception => e
121
+
122
+ end
123
+
124
+ valid
125
+ end
126
+
127
+ ##
128
+ # == Validate Agent
129
+ # => Validates Agent-specific properties
130
+ #
131
+ # + *agent* - the agent for validation
132
+ #
133
+ def self.validate_agent
134
+ begin
135
+ valid = self.validate_seed(agent[:publisher], agent[:payload]) && self.validate_payload(agent[:publisher], agent[:payload])
136
+ rescue Exception => e
137
+
138
+ end
139
+
140
+ valid
141
+ end
142
+
143
+ ##
144
+ # == Copy Object/Hash/Array...
145
+ # => Copies any object into new object (overcome references).
146
+ #
147
+ # + *o* - the object being copied
148
+ #
149
+ def deep_copy object
150
+ Marshal.load(Marshal.dump(object))
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,64 @@
1
+ require 'helper'
2
+ require 'open-uri'
3
+ require 'jsonpath'
4
+ require 'rest-client'
5
+ require 'csv'
6
+ require 'json'
7
+ require 'seedreader'
8
+ require 'csvseedreader'
9
+ require 'sqlseedreader'
10
+ require 'xmlseedreader'
11
+ require 'jsonseedreader'
12
+
13
+ module I2X
14
+
15
+ # = JSONDetector
16
+ #
17
+ # Detect changes in JSON content files (uses JSONPath).
18
+ #
19
+ class JSONDetector < Detector
20
+
21
+ public
22
+
23
+ ##
24
+ # == Detect the changes
25
+ #
26
+ def detect object
27
+ begin
28
+ if object[:uri] == '' then
29
+ @doc = object[:content]
30
+ else
31
+ url = RestClient.get object[:uri]
32
+ @doc = url.to_str
33
+ end
34
+ JsonPath.on(@doc,object[:query]).each do |element|
35
+ JsonPath.on(element, object[:cache]).each do |c|
36
+ @cache = Cashier.verify c, object, c, object[:seed]
37
+ end
38
+
39
+ ##
40
+ # If not on cache, add to payload for processing
41
+ #
42
+ if @cache[:status] == 100 then
43
+
44
+ # add row data to payload from selectors (key => key, value => column name)
45
+ payload = Hash.new
46
+ JSON.parse(object[:selectors]).each do |selector|
47
+ selector.each do |k,v|
48
+ JsonPath.on(element, v).each do |el|
49
+ payload[k] = el
50
+ end
51
+ end
52
+ end
53
+ # add payload object to payloads list
54
+ @payloads.push payload
55
+ end
56
+
57
+ end
58
+ rescue Exception => e
59
+
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,52 @@
1
+ require 'json'
2
+
3
+ module I2X
4
+
5
+ # = JSONSeedReader
6
+ #
7
+ # Load content from JSON seed.
8
+ #
9
+ class JSONSeedReader < SeedReader
10
+ ##
11
+ # == Read
12
+ #
13
+ # => Load the seed data into the @objects array for processing.
14
+ #
15
+ def read
16
+ begin
17
+ url = RestClient.get @seed[:payload][:uri]
18
+ @doc = url.to_str
19
+ JsonPath.on(@doc,@seed[:payload][:query]).each do |element|
20
+
21
+ begin
22
+ object = @help.deep_copy @agent[:payload]
23
+ object.each_pair do |key,value|
24
+ variables = @help.identify_variables(object[key])
25
+ variables.each do |v|
26
+
27
+ JsonPath.on(element, @seed[:payload][:selectors][v]).each do |el|
28
+
29
+ object[key].gsub!("%{#{v}}", el.to_s)
30
+ end
31
+ end
32
+ end
33
+
34
+ JsonPath.on(element,@seed[:payload][:cache]).each do |el|
35
+ object[:seed] = el
36
+
37
+ end
38
+
39
+ object[:identifier] = @agent.identifier
40
+ @objects.push object
41
+ rescue Exception => e
42
+
43
+ end
44
+ end
45
+ rescue Exception => e
46
+
47
+ end
48
+
49
+ @objects
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,21 @@
1
+ require 'helper'
2
+
3
+ module I2X
4
+
5
+ ##
6
+ # = Seed Reader
7
+ #
8
+ # Main seed reading class, passing data for seeds to agent, to be inherited by SQL, File and URL templates
9
+ #
10
+ class SeedReader
11
+ attr_accessor :seed, :objects, :agent
12
+
13
+ def initialize agent, seed
14
+ @agent = agent
15
+ @help = I2X::Helper.new
16
+ @seed = seed
17
+ @objects = Array.new
18
+ puts "\t\tSeed: #{@seed[:identifier]}"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,48 @@
1
+ require 'helper'
2
+ require 'mysql2'
3
+
4
+ module I2X
5
+
6
+ ##
7
+ # = SQLDetector
8
+ #
9
+ # Detec changes in SQL databases. MySQL support only.
10
+ #
11
+ class SQLDetector < Detector
12
+
13
+ public
14
+ ##
15
+ # == Detect the changes
16
+ #
17
+ def detect object
18
+ puts "Detecting SQL to #{object[:identifier]}"
19
+ begin
20
+ @client = Mysql2::Client.new(:host => object[:host], :username => object[:username] , :password => object[:password] , :database => object[:database])
21
+ @client.query(@agent[:payload][:query]).each(:symbolize_keys => false) do |row|
22
+ unless object[:cache].nil? then
23
+ @cache = Cashier.verify row[object[:cache]], object, row, object[:seed]
24
+ else
25
+ @cache = Cashier.verify row["id"], object, row, object[:seed]
26
+ end
27
+
28
+ # The actual processing
29
+ #
30
+ if @cache[:status] == 100 then
31
+
32
+ # add row data to payload from selectors (key => key, value => column name)
33
+ payload = Hash.new
34
+ JSON.parse(object[:selectors]).each do |selector|
35
+ selector.each do |k,v|
36
+ payload[k] = row[v]
37
+ end
38
+ end
39
+ # add payload object to payloads list
40
+ @payloads.push payload
41
+ end
42
+ end
43
+ rescue Exception => e
44
+
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,47 @@
1
+ require 'slog'
2
+ require 'mysql2'
3
+
4
+ module Services
5
+
6
+ # = SQLSeedReader
7
+ #
8
+ # Load content from SQL seed.
9
+ #
10
+ class SQLSeedReader < SeedReader
11
+ ##
12
+ # == Read
13
+ #
14
+ # => Load the seed data into the @objects array for processing.
15
+ #
16
+ def read
17
+ begin
18
+ @client = Mysql2::Client.new(:host => @seed[:payload][:host], :username => @seed[:payload][:username] , :password => @seed[:payload][:password] , :database => @seed[:payload][:database])
19
+ @client.query(@seed[:payload][:query], :cast => false).each(:symbolize_keys => false) do |row|
20
+ begin
21
+ object = @help.deep_copy @agent[:payload]
22
+ object.each_pair do |key,value|
23
+ variables = @help.identify_variables(object[key])
24
+ variables.each do |v|
25
+ object[key].gsub!("%{#{v}}", row[@seed[:payload][:selectors][v]].to_str)
26
+ end
27
+ end
28
+
29
+ unless @seed[:payload][:cache].nil? then
30
+ object[:seed] = row[@seed[:payload][:cache]]
31
+ else
32
+ object[:seed] = row["id"]
33
+ end
34
+ object[:identifier] = @agent.identifier
35
+ @objects.push object
36
+ rescue Exception => e
37
+
38
+ end
39
+ end
40
+ rescue Exception => e
41
+
42
+ end
43
+
44
+ @objects
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module I2X
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,57 @@
1
+ require 'helper'
2
+ require 'cashier'
3
+ require 'open-uri'
4
+ require 'raven'
5
+ require 'slog'
6
+
7
+ module I2X
8
+
9
+ # = XMLDetector
10
+ #
11
+ # Detect changes in XML files (uses XPath).
12
+ #
13
+ class XMLDetector < Detector
14
+
15
+ public
16
+ ##
17
+ # == Detect the changes
18
+ #
19
+ def detect object
20
+ begin
21
+ if object[:uri] == '' then
22
+ @doc = Nokogiri::XML(object[:content])
23
+ else
24
+ @doc = Nokogiri::XML(open(object[:uri]))
25
+ end
26
+ @doc.remove_namespaces!
27
+ @doc.xpath(object[:query]).each do |element|
28
+ element.xpath(object[:cache]).each do |c|
29
+ @cache = Cashier.verify c.content, object, c.content, object[:seed]
30
+ end
31
+
32
+ ##
33
+ # If not on cache, add to payload for processing
34
+ #
35
+ if @cache[:status] == 100 then
36
+
37
+ # add row data to payload from selectors (key => key, value => column name)
38
+ payload = Hash.new
39
+ JSON.parse(object[:selectors]).each do |selector|
40
+
41
+ selector.each do |k,v|
42
+ element.xpath(v).each do |el|
43
+ payload[k] = el.content
44
+ end
45
+ end
46
+ end
47
+ # add payload object to payloads list
48
+ @payloads.push payload
49
+
50
+ end
51
+ end
52
+ end
53
+ rescue Exception => e
54
+
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,52 @@
1
+ module I2X
2
+
3
+ # = XMLSeedReader
4
+ #
5
+ # Load content from XML seed.
6
+ #
7
+ class XMLSeedReader < SeedReader
8
+ ##
9
+ # == Read
10
+ #
11
+ # => Load the seed data into the @objects array for processing.
12
+ #
13
+ def read
14
+ begin
15
+ @doc = Nokogiri::XML(open(@seed[:payload][:uri]))
16
+ @doc.remove_namespaces!
17
+ @doc.xpath(@seed[:payload][:query]).each do |element|
18
+ begin
19
+ object = @help.deep_copy @agent[:payload]
20
+ object.each_pair do |key,value|
21
+ variables = @help.identify_variables(object[key])
22
+ variables.each do |v|
23
+ element.xpath(@seed[:payload][:selectors][v]).each do |el|
24
+ object[key].gsub!("%{#{v}}", el.content)
25
+ end
26
+ end
27
+ end
28
+
29
+ unless @seed[:payload][:cache].nil? then
30
+ element.xpath(@seed[:payload][:cache]).each do |el|
31
+ object[:seed] = el.content
32
+ end
33
+ else
34
+ element.xpath('id').each do |el|
35
+ object[:seed] = el.content
36
+ end
37
+ end
38
+
39
+ object[:identifier] = @agent.identifier
40
+ @objects.push object
41
+ rescue Exception => e
42
+
43
+ end
44
+ end
45
+ rescue Exception => e
46
+
47
+ end
48
+
49
+ @objects
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,9 @@
1
+ require_relative '../../test_helper'
2
+
3
+ describe I2X do
4
+
5
+ it "must be defined" do
6
+ I2X::VERSION.wont_be_nil
7
+ end
8
+
9
+ end
@@ -0,0 +1,4 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/pride'
3
+
4
+ require File.expand_path('../../lib/i2x.rb', __FILE__)
metadata CHANGED
@@ -1,23 +1,76 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i2x
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pedro Lopes
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-16 00:00:00.000000000 Z
12
- dependencies: []
13
- description: 'i2x: integrate everything'
14
- email: hello@pedrolopes.net
11
+ date: 2014-01-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: 'i2x: integrate everything. Automated real-time integration framework.'
42
+ email:
43
+ - hello@pedrolopes.net
15
44
  executables: []
16
45
  extensions: []
17
46
  extra_rdoc_files: []
18
47
  files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - Gemfile.lock
51
+ - LICENSE
52
+ - README.md
53
+ - Rakefile
54
+ - i2x.gemspec
19
55
  - lib/i2x.rb
20
- homepage: http://rubygems.org/gems/i2x
56
+ - lib/i2x/cashier.rb
57
+ - lib/i2x/checkup.rb
58
+ - lib/i2x/client.rb
59
+ - lib/i2x/csvdetector.rb
60
+ - lib/i2x/csvseedreader.rb
61
+ - lib/i2x/detector.rb
62
+ - lib/i2x/helper.rb
63
+ - lib/i2x/jsondetector.rb
64
+ - lib/i2x/jsonseedreader.rb
65
+ - lib/i2x/seedreader.rb
66
+ - lib/i2x/sqldetector.rb
67
+ - lib/i2x/sqlseedreader.rb
68
+ - lib/i2x/version.rb
69
+ - lib/i2x/xmldetector.rb
70
+ - lib/i2x/xmlseedreader.rb
71
+ - test/lib/i2x/version_test.rb
72
+ - test/test_helper.rb
73
+ homepage: https://bioinformatics.ua.pt/i2x/
21
74
  licenses:
22
75
  - MIT
23
76
  metadata: {}
@@ -40,5 +93,7 @@ rubyforge_project:
40
93
  rubygems_version: 2.2.0
41
94
  signing_key:
42
95
  specification_version: 4
43
- summary: 'i2x: automated real-time integration'
44
- test_files: []
96
+ summary: i2x client library for distributed agents.
97
+ test_files:
98
+ - test/lib/i2x/version_test.rb
99
+ - test/test_helper.rb