opener-outlet 1.1.2 → 2.0.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: 033e417f95cd7e01b1e02a55e3afd3d9ee79a745
4
- data.tar.gz: 80ad500cd5db3e2fcab1a43649d66a618dac3fed
3
+ metadata.gz: 4f3d92a8588ca78a7e1d07bbffe6d634a83a989a
4
+ data.tar.gz: 811797473b1e4bd1ec23da927ecf9e1769046c72
5
5
  SHA512:
6
- metadata.gz: 4ffa23c699e9ba8c28b3e1a9ce30eb5ad2c43df54ec1ac0bf2da9ff03b8bf750cdd378dc7d20e583a8bb13623960b8e49b41f64e855c70d83d359f669eae4e29
7
- data.tar.gz: 4a8756872450080c3c939de8fbaa9453c8409d6271aeaad5d1f00791806e83365ed578167d66094f019c09362a6625894f994a2cb76d4b39d7bcb41e2355a063
6
+ metadata.gz: d47525b3693fcf0faf4f939a3f47481101bee5a850df55636cc521db404d1cbcdc4eab20a11ecfaa35dd59c87246051c0df03883a7cbc9620f9d2327ab3f25b3
7
+ data.tar.gz: c06881374a30bafbd37562f51d4114db03cf7b93a5a942d8066de59170598265aac9571d217fc326dabd87a6934d6a94a72ca07814b4065db9f434ffaef28fdc
data/README.md CHANGED
@@ -1,20 +1,24 @@
1
- Outlet
2
- ------------
1
+ # Outlet
3
2
 
4
- Component that stores results from the Opener Web Services chain into a SQLite Database and shows them into your browser.
3
+ Component that stores results from the Opener Web Services chain into a SQLite
4
+ Database and shows them into your browser.
5
5
 
6
- ### Confused by some terminology?
6
+ ## Confused by some terminology?
7
7
 
8
- This software is part of a larger collection of natural language processing tools known as "the OpeNER project". You can find more information about the project at [the OpeNER portal](http://opener-project.github.io). There you can also find references to terms like KAF (an XML standard to represent linguistic annotations in texts), component, cores, scenario's and pipelines.
8
+ This software is part of a larger collection of natural language processing
9
+ tools known as "the OpeNER project". You can find more information about the
10
+ project at [the OpeNER portal](http://opener-project.github.io). There you can
11
+ also find references to terms like KAF (an XML standard to represent linguistic
12
+ annotations in texts), component, cores, scenario's and pipelines.
9
13
 
10
- Quick Use Example
11
- -----------------
14
+ ## Quick Use Example
12
15
 
13
16
  Installing the outlet can be done by executing:
14
17
 
15
18
  gem install opener-outlet
16
19
 
17
- Please bare in mind that all components in OpeNER take KAF as an input and output KAF by default.
20
+ Please keep in mind that all components in OpeNER take KAF as an input and
21
+ output KAF by default.
18
22
 
19
23
  ### Webservices
20
24
 
@@ -22,28 +26,32 @@ You can launch a webservice by executing:
22
26
 
23
27
  outlet-server
24
28
 
25
- This will launch a mini webserver with the webservice. It defaults to port 9292, so you can access it at <http://localhost:9292>.
29
+ This will launch a mini webserver with the webservice. It defaults to port 9292,
30
+ so you can access it at <http://localhost:9292>.
26
31
 
27
- To launch it on a different port provide the `-p [port-number]` option like this:
32
+ To launch it on a different port provide the `-p [port-number]` option like
33
+ this:
28
34
 
29
35
  outlet-server -p 1234
30
36
 
31
37
  It then launches at <http://localhost:1234>
32
38
 
33
- Documentation on the Webservice is provided by surfing to the urls provided above. For more information on how to launch a webservice run the command with the ```-h``` option.
34
-
39
+ Documentation on the Webservice is provided by surfing to the urls provided
40
+ above. For more information on how to launch a webservice run the command with
41
+ the `--help` option.
35
42
 
36
43
  ### Daemon
37
44
 
38
- Last but not least the outlet comes shipped with a daemon that can read jobs (and write) jobs to and from Amazon SQS queues. For more information type:
45
+ Last but not least the outlet comes shipped with a daemon that can read jobs
46
+ (and write) jobs to and from Amazon SQS queues. For more information type:
39
47
 
40
48
  outlet-daemon -h
41
49
 
50
+ ## Description of dependencies
42
51
 
43
- Description of dependencies
44
- ---------------------------
45
-
46
- This component runs best if you run it in an environment suited for OpeNER components. You can find an installation guide and helper tools in the [OpeNER installer](https://github.com/opener-project/opener-installer) and an
52
+ This component runs best if you run it in an environment suited for OpeNER
53
+ components. You can find an installation guide and helper tools in the [OpeNER
54
+ installer](https://github.com/opener-project/opener-installer) and an
47
55
  installation guide on the [Opener Website](http://opener-project.github.io/getting-started/how-to/local-installation.html)
48
56
 
49
57
  At least you need the following system setup:
@@ -53,28 +61,17 @@ At least you need the following system setup:
53
61
  * JRuby 1.7.9 or newer
54
62
  * Ruby 1.9.3 or newer
55
63
 
56
- The Core
57
- --------
58
-
59
- The component is a fat wrapper around the actual language technology core. You can find the core technolies in the following repositories:
60
-
61
- * (link to) Related Core readmes
62
-
63
- Where to go from here
64
- ---------------------
64
+ ## Where to go from here
65
65
 
66
66
  * [Check the project website](http://opener-project.github.io)
67
67
  * [Checkout the webservice](http://opener.olery.com/outlet)
68
68
 
69
- Report problem/Get help
70
- -----------------------
71
-
72
- If you encounter problems, please email support@opener-project.eu or leave an issue in the
73
- [issue tracker](https://github.com/opener-project/outlet/issues).
69
+ ## Report problem/Get help
74
70
 
71
+ If you encounter problems, please email support@opener-project.eu or leave an
72
+ issue in the [issue tracker](https://github.com/opener-project/outlet/issues).
75
73
 
76
- Contributing
77
- ------------
74
+ ## Contributing
78
75
 
79
76
  1. Fork it <http://github.com/opener-project/outlet/fork>
80
77
  2. Create your feature branch (`git checkout -b my-new-feature`)
data/bin/outlet-daemon CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  require 'opener/daemons'
4
4
 
5
- exec_path = File.expand_path('../../exec/outlet.rb', __FILE__)
5
+ controller = Opener::Daemons::Controller.new(
6
+ :name => 'opener-outlet',
7
+ :exec_path => File.expand_path('../../exec/outlet.rb', __FILE__)
8
+ )
6
9
 
7
- Opener::Daemons::Controller.new(
8
- :name => 'outlet',
9
- :exec_path => exec_path
10
- )
10
+ controller.run
data/bin/outlet-server CHANGED
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'puma/cli'
3
+ require 'opener/webservice'
4
4
 
5
- rack_config = File.expand_path('../../config.ru', __FILE__)
5
+ parser = Opener::Webservice::OptionParser.new(
6
+ 'opener-outlet',
7
+ File.expand_path('../../config.ru', __FILE__)
8
+ )
6
9
 
7
- cli = Puma::CLI.new([rack_config] + ARGV)
8
- cli.run
10
+ parser.run
data/exec/outlet.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'opener/daemons'
4
+
4
5
  require_relative '../lib/opener/outlet'
5
6
 
6
- options = Opener::Daemons::OptParser.parse!(ARGV)
7
- daemon = Opener::Daemons::Daemon.new(Opener::Outlet, options)
7
+ daemon = Opener::Daemons::Daemon.new(Opener::Outlet)
8
8
 
9
- daemon.start
9
+ daemon.start
@@ -1,9 +1,7 @@
1
- require 'active_record'
2
-
3
1
  module Opener
4
2
  class Outlet
5
- class Output < ActiveRecord::Base
3
+ class Output < ActiveRecord::Base
6
4
  validates_uniqueness_of :uuid
7
5
  end
8
6
  end
9
- end
7
+ end
@@ -1,21 +1,10 @@
1
- require 'sinatra'
2
- require 'sinatra/json'
3
- require 'nokogiri'
4
- require 'stringio'
5
- require_relative './visualizer'
6
-
7
- require File.expand_path('../../../../config/database', __FILE__)
8
-
9
1
  module Opener
10
2
  class Outlet
11
- class Server < Sinatra::Base
3
+ class Server < Webservice::Server
4
+ set :views, File.expand_path('../views', __FILE__)
12
5
 
13
- post '/' do
14
- output = Output.new
15
- output.uuid = params[:request_id]
16
- output.text = params[:input]
17
- output.save
18
- end
6
+ self.text_processor = Outlet
7
+ self.accepted_params = [:request_id]
19
8
 
20
9
  get '/' do
21
10
  if params[:request_id]
@@ -24,99 +13,72 @@ module Opener
24
13
  erb :index
25
14
  end
26
15
  end
27
-
16
+
28
17
  get '/:request_id.json' do
29
18
  unless params[:request_id] == 'favicon.ico'
30
- begin
31
- output = Output.find_by_uuid(params[:request_id])
32
- if output
33
- content_type(:json)
34
- kj = Opener::KafToJson.new
35
- json = kj.run(output.text) rescue output.text
36
- body(json)
37
- else
38
- halt(404, "No record found for ID #{params[:request_id]}")
39
- end
40
- rescue => error
41
- error_callback = params[:error_callback]
42
-
43
- submit_error(error_callback, error.message) if error_callback
44
-
45
- raise(error)
19
+ output = Output.find_by_uuid(params[:request_id])
20
+
21
+ if output
22
+ content_type(:json)
23
+
24
+ kj = Opener::KafToJson.new
25
+ json = kj.run(output.text)
26
+
27
+ body(json)
28
+ else
29
+ halt(404, "No record found for ID #{params[:request_id]}")
46
30
  end
47
31
  end
48
32
  end
49
33
 
50
34
  get '/:request_id' do
51
35
  unless params[:request_id] == 'favicon.ico'
52
- begin
53
- output = Output.find_by_uuid(params[:request_id])
54
- if output
55
- content_type(:xml)
56
- body(output.text)
57
- else
58
- halt(404, "No record found for ID #{params[:request_id]}")
59
- end
60
- rescue => error
61
- error_callback = params[:error_callback]
62
-
63
- submit_error(error_callback, error.message) if error_callback
64
-
65
- raise(error)
36
+ output = Output.find_by_uuid(params[:request_id])
37
+
38
+ if output
39
+ content_type(:xml)
40
+
41
+ body(output.text)
42
+ else
43
+ halt(404, "No record found for ID #{params[:request_id]}")
66
44
  end
67
45
  end
68
46
  end
69
47
 
70
48
  get '/html/:request_id' do
71
49
  unless params[:request_id] == 'favicon.ico'
72
- begin
73
- output = Output.find_by_uuid(params[:request_id])
74
- if output
75
- output = StringIO.new(output.text)
76
- parser = Opener::Kaf::Visualizer::Parser.new(output)
77
- doc = parser.parse
78
- html = Opener::Kaf::Visualizer::HTMLTextPresenter.new(doc)
79
- @parsed = html.to_html
80
- erb :show
81
- else
82
- halt(404, "No record found for ID #{params[:request_id]}")
83
- end
84
- rescue => error
85
- error_callback = params[:error_callback]
86
-
87
- submit_error(error_callback, error.message) if error_callback
88
-
89
- raise(error)
50
+ output = Output.find_by_uuid(params[:request_id])
51
+
52
+ if output
53
+ output = StringIO.new(output.text)
54
+ parser = Opener::Kaf::Visualizer::Parser.new(output)
55
+ doc = parser.parse
56
+ html = Opener::Kaf::Visualizer::HTMLTextPresenter.new(doc)
57
+
58
+ @parsed = html.to_html
59
+
60
+ erb :show
61
+ else
62
+ halt(404, "No record found for ID #{params[:request_id]}")
90
63
  end
91
64
  end
92
65
  end
93
-
66
+
94
67
  get '/score/:request_id' do
95
68
  unless params[:request_id] == 'favicon.ico'
96
- begin
97
- output = Output.find_by_uuid(params[:request_id])
98
- if output
99
- content_type('text/json')
100
- processor = Opener::Scorer::OutputProcessor.new(output.text)
101
- result = processor.process
102
- body(result.to_json)
103
- else
104
- halt(404, "No record found for ID #{params[:request_id]}")
105
- end
106
- rescue => error
107
- error_callback = params[:error_callback]
108
-
109
- submit_error(error_callback, error.message) if error_callback
110
-
111
- raise(error)
112
- end
113
- end
114
- end
69
+ output = Output.find_by_uuid(params[:request_id])
70
+
71
+ if output
72
+ content_type('text/json')
115
73
 
116
- private
74
+ processor = Opener::Scorer::OutputProcessor.new(output.text)
75
+ result = processor.process
117
76
 
118
- def submit_error(url, message)
119
- HTTPClient.post(url, :body => {:error => message})
77
+ body(result.to_json)
78
+ else
79
+ halt(404, "No record found for ID #{params[:request_id]}")
80
+ end
81
+ end
120
82
  end
121
83
  end # Server
122
84
  end # Outlet
@@ -1,5 +1,5 @@
1
1
  module Opener
2
2
  class Outlet
3
- VERSION = "1.1.2"
3
+ VERSION = '2.0.0'
4
4
  end
5
5
  end
@@ -1,6 +1,3 @@
1
- #require "opener/kaf/visualizer/version"
2
- require 'nokogiri'
3
-
4
1
  module Opener
5
2
  module Kaf
6
3
  module Visualizer
data/lib/opener/outlet.rb CHANGED
@@ -1,14 +1,30 @@
1
+ require 'securerandom'
2
+ require 'stringio'
3
+
4
+ require 'active_record'
5
+ require 'nokogiri'
6
+ require 'opener/kaf_to_json'
7
+ require 'opener/scorer'
8
+
1
9
  require_relative 'outlet/output'
2
10
  require_relative 'outlet/version'
3
11
  require_relative 'outlet/server'
4
- require 'opener/kaf_to_json'
5
- require 'opener/scorer/output_processor'
12
+ require_relative 'outlet/visualizer'
13
+
14
+ require_relative '../../config/database'
6
15
 
7
16
  module Opener
8
17
  class Outlet
9
- def run(input, uuid)
18
+ attr_reader :uuid
19
+
20
+ def initialize(options = {})
21
+ @uuid = options[:request_id] || SecureRandom.hex
22
+ end
23
+
24
+ def run(input)
10
25
  output = Output.new(:uuid=>uuid, :text=>input)
11
- output.save
26
+
27
+ output.save!
12
28
 
13
29
  return input
14
30
  end
@@ -26,18 +26,15 @@ Gem::Specification.new do |gem|
26
26
  gem.executables = Dir.glob('bin/*').map { |file| File.basename(file) }
27
27
 
28
28
  gem.add_dependency 'builder', '~>3.0.0'
29
- gem.add_dependency 'sinatra', '~>1.4.2'
30
- gem.add_dependency 'sinatra-contrib'
31
29
  gem.add_dependency 'nokogiri'
32
- gem.add_dependency 'puma'
33
- gem.add_dependency 'opener-daemons'
34
- gem.add_dependency 'httpclient'
35
- gem.add_dependency 'uuidtools'
36
30
  gem.add_dependency 'jdbc-mysql'
37
31
  gem.add_dependency 'activerecord-jdbcmysql-adapter'
38
- gem.add_dependency 'activerecord', '~>3.2'
39
- gem.add_dependency 'activesupport', '~>3.2'
40
- gem.add_dependency 'opener-webservice'
32
+ gem.add_dependency 'activerecord', '~> 3.2'
33
+
34
+ gem.add_dependency 'opener-daemons', '~> 2.2'
35
+ gem.add_dependency 'opener-webservice', '~> 2.1'
36
+ gem.add_dependency 'opener-core', '~> 2.2'
37
+
41
38
  gem.add_dependency 'opener-kaf2json'
42
39
  gem.add_dependency 'opener-scorer'
43
40
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opener-outlet
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - development@olery.com
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-01 00:00:00.000000000 Z
11
+ date: 2014-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: builder
@@ -24,34 +24,6 @@ dependencies:
24
24
  version: 3.0.0
25
25
  prerelease: false
26
26
  type: :runtime
27
- - !ruby/object:Gem::Dependency
28
- name: sinatra
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ~>
32
- - !ruby/object:Gem::Version
33
- version: 1.4.2
34
- requirement: !ruby/object:Gem::Requirement
35
- requirements:
36
- - - ~>
37
- - !ruby/object:Gem::Version
38
- version: 1.4.2
39
- prerelease: false
40
- type: :runtime
41
- - !ruby/object:Gem::Dependency
42
- name: sinatra-contrib
43
- version_requirements: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - '>='
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- requirement: !ruby/object:Gem::Requirement
49
- requirements:
50
- - - '>='
51
- - !ruby/object:Gem::Version
52
- version: '0'
53
- prerelease: false
54
- type: :runtime
55
27
  - !ruby/object:Gem::Dependency
56
28
  name: nokogiri
57
29
  version_requirements: !ruby/object:Gem::Requirement
@@ -67,49 +39,7 @@ dependencies:
67
39
  prerelease: false
68
40
  type: :runtime
69
41
  - !ruby/object:Gem::Dependency
70
- name: puma
71
- version_requirements: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - '>='
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- requirement: !ruby/object:Gem::Requirement
77
- requirements:
78
- - - '>='
79
- - !ruby/object:Gem::Version
80
- version: '0'
81
- prerelease: false
82
- type: :runtime
83
- - !ruby/object:Gem::Dependency
84
- name: opener-daemons
85
- version_requirements: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - '>='
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- requirement: !ruby/object:Gem::Requirement
91
- requirements:
92
- - - '>='
93
- - !ruby/object:Gem::Version
94
- version: '0'
95
- prerelease: false
96
- type: :runtime
97
- - !ruby/object:Gem::Dependency
98
- name: httpclient
99
- version_requirements: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - '>='
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- requirement: !ruby/object:Gem::Requirement
105
- requirements:
106
- - - '>='
107
- - !ruby/object:Gem::Version
108
- version: '0'
109
- prerelease: false
110
- type: :runtime
111
- - !ruby/object:Gem::Dependency
112
- name: uuidtools
42
+ name: jdbc-mysql
113
43
  version_requirements: !ruby/object:Gem::Requirement
114
44
  requirements:
115
45
  - - '>='
@@ -123,7 +53,7 @@ dependencies:
123
53
  prerelease: false
124
54
  type: :runtime
125
55
  - !ruby/object:Gem::Dependency
126
- name: jdbc-mysql
56
+ name: activerecord-jdbcmysql-adapter
127
57
  version_requirements: !ruby/object:Gem::Requirement
128
58
  requirements:
129
59
  - - '>='
@@ -137,59 +67,59 @@ dependencies:
137
67
  prerelease: false
138
68
  type: :runtime
139
69
  - !ruby/object:Gem::Dependency
140
- name: activerecord-jdbcmysql-adapter
70
+ name: activerecord
141
71
  version_requirements: !ruby/object:Gem::Requirement
142
72
  requirements:
143
- - - '>='
73
+ - - ~>
144
74
  - !ruby/object:Gem::Version
145
- version: '0'
75
+ version: '3.2'
146
76
  requirement: !ruby/object:Gem::Requirement
147
77
  requirements:
148
- - - '>='
78
+ - - ~>
149
79
  - !ruby/object:Gem::Version
150
- version: '0'
80
+ version: '3.2'
151
81
  prerelease: false
152
82
  type: :runtime
153
83
  - !ruby/object:Gem::Dependency
154
- name: activerecord
84
+ name: opener-daemons
155
85
  version_requirements: !ruby/object:Gem::Requirement
156
86
  requirements:
157
87
  - - ~>
158
88
  - !ruby/object:Gem::Version
159
- version: '3.2'
89
+ version: '2.2'
160
90
  requirement: !ruby/object:Gem::Requirement
161
91
  requirements:
162
92
  - - ~>
163
93
  - !ruby/object:Gem::Version
164
- version: '3.2'
94
+ version: '2.2'
165
95
  prerelease: false
166
96
  type: :runtime
167
97
  - !ruby/object:Gem::Dependency
168
- name: activesupport
98
+ name: opener-webservice
169
99
  version_requirements: !ruby/object:Gem::Requirement
170
100
  requirements:
171
101
  - - ~>
172
102
  - !ruby/object:Gem::Version
173
- version: '3.2'
103
+ version: '2.1'
174
104
  requirement: !ruby/object:Gem::Requirement
175
105
  requirements:
176
106
  - - ~>
177
107
  - !ruby/object:Gem::Version
178
- version: '3.2'
108
+ version: '2.1'
179
109
  prerelease: false
180
110
  type: :runtime
181
111
  - !ruby/object:Gem::Dependency
182
- name: opener-webservice
112
+ name: opener-core
183
113
  version_requirements: !ruby/object:Gem::Requirement
184
114
  requirements:
185
- - - '>='
115
+ - - ~>
186
116
  - !ruby/object:Gem::Version
187
- version: '0'
117
+ version: '2.2'
188
118
  requirement: !ruby/object:Gem::Requirement
189
119
  requirements:
190
- - - '>='
120
+ - - ~>
191
121
  - !ruby/object:Gem::Version
192
- version: '0'
122
+ version: '2.2'
193
123
  prerelease: false
194
124
  type: :runtime
195
125
  - !ruby/object:Gem::Dependency
@@ -299,7 +229,6 @@ files:
299
229
  - README.md
300
230
  - LICENSE.txt
301
231
  - exec/outlet.rb
302
- - visualizer.rb
303
232
  - bin/outlet-server
304
233
  - bin/outlet-daemon
305
234
  homepage: http://opener-project.github.com/
data/visualizer.rb DELETED
@@ -1,278 +0,0 @@
1
- require 'nokogiri'
2
-
3
- module Opener
4
- module Kaf
5
- module Visualizer
6
- class Parser
7
- attr_reader :doc
8
- attr_reader :words, :terms, :entities, :properties, :opinions, :document
9
-
10
- def initialize(input_file_handler)
11
- @doc = Nokogiri::XML(input_file_handler)
12
- end
13
-
14
- def parse
15
- @words = parse_words
16
- @terms = parse_terms
17
- @entities = parse_entities
18
- @properties = parse_properties
19
- @opinions = parse_opinions
20
- @document = KAFDocument.new(
21
- :words => words,
22
- :terms => terms,
23
- :entities => entities,
24
- :properties => properties,
25
- :opinions => opinions
26
- )
27
-
28
- return document
29
- end
30
-
31
- def parse_words
32
- parse_elements("//wf", Word)
33
- end
34
-
35
- def parse_terms
36
- # Of course terms should be words here.
37
- # Dirty Hack, sufficient for now.
38
- parse_elements("//term", Term, :terms=>words)
39
- end
40
-
41
- def parse_entities
42
- parse_elements("//entity", Entity, :terms=>terms)
43
- end
44
-
45
- def parse_properties
46
- parse_elements("//property", Property, :terms=>terms)
47
- end
48
-
49
- def parse_opinions
50
- parse_elements("//opinion", Opinion, :terms=>terms)
51
- end
52
-
53
- def parse_elements(xpath, klass, opts={})
54
- elements = doc.xpath(xpath)
55
- lookup_table = Hash.new
56
- elements.each do |element|
57
- instance = klass.new(element, opts)
58
- lookup_table[instance.id] = instance
59
- end
60
- lookup_table
61
- end
62
-
63
- end
64
-
65
- class KAFNode
66
- attr_reader :content, :targets, :tag, :references
67
-
68
- def initialize(tag, references)
69
- @references = references
70
- @tag = tag
71
-
72
- set_instance_variables
73
- set_content
74
- set_targets
75
- process_subnodes
76
- end
77
-
78
- def set_content
79
- @content = tag.content
80
- end
81
-
82
- def set_instance_variables
83
- tag.keys.each do |key|
84
- if respond_to?("#{key}=".to_sym)
85
- send("#{key}=".to_sym, tag[key])
86
- else
87
- instance_variable_set("@#{key}", tag[key])
88
- end
89
- end
90
- end
91
-
92
- def set_targets
93
- @targets = []
94
- tag.css("span target").each do |target|
95
- id = target["id"]
96
- @targets << references[:terms][id]
97
- end
98
- end
99
-
100
- def process_subnodes
101
- end
102
-
103
- def has_target?(*ids)
104
- ids.flatten.each do |id|
105
- return true if target_ids.include?(id)
106
- end
107
- return false
108
- end
109
-
110
- def to_s
111
- if targets.size > 0
112
- return targets.map(&:to_s).join(" ")
113
- else
114
- return content
115
- end
116
- end
117
-
118
- def target_ids
119
- @targets.map(&:id)
120
- end
121
-
122
- end
123
-
124
- class Word < KAFNode
125
- attr_reader :wid, :sent, :para, :offset
126
-
127
- def id
128
- wid
129
- end
130
-
131
- def offset=(offset)
132
- @offset = offset.to_i
133
- end
134
-
135
- def length
136
- content.nil? ? 0 : content.length
137
- end
138
-
139
- end
140
-
141
- class Term < KAFNode
142
- attr_reader :tid, :type, :lemma, :pos, :morphofeat
143
-
144
- def id
145
- tid
146
- end
147
- end
148
-
149
- class Entity < KAFNode
150
- attr_reader :eid, :type
151
-
152
- def id
153
- eid
154
- end
155
-
156
- def to_s
157
- "#{type}: #{targets.map(&:to_s).join(", ")}"
158
- end
159
- end
160
-
161
- class Property < KAFNode
162
- attr_reader :pid, :lemma
163
-
164
- def id
165
- pid
166
- end
167
-
168
- def to_s
169
- "#{lemma}: #{targets.map(&:to_s).join(", ")}"
170
- end
171
- end
172
-
173
- class Opinion < KAFNode
174
- attr_reader :oid, :expression
175
-
176
- def id
177
- oid
178
- end
179
-
180
- def process_subnodes
181
- @expression = tag.xpath("//opinion_expression").first["polarity"].to_sym
182
- end
183
-
184
- def to_s
185
- "#{expression}: #{targets.map(&:to_s).join(", ")}"
186
- end
187
-
188
- end
189
-
190
- class KAFDocument
191
- attr_reader :words, :terms, :entities, :properties, :opinions
192
-
193
- def initialize(opts={})
194
- @words = opts.fetch(:words)
195
- @terms = opts.fetch(:terms)
196
- @entities = opts.fetch(:entities)
197
- @properties = opts.fetch(:properties)
198
- @opinions = opts.fetch(:opinions)
199
- end
200
-
201
- end
202
-
203
- class HTMLTextPresenter
204
- attr_reader :document
205
- def initialize(document)
206
- @document = document
207
- end
208
-
209
- def to_html
210
- offset = 0
211
- prev = Struct.new(:offset).new(0)
212
-
213
- builder = Nokogiri::HTML::Builder.new do |html|
214
- html.div(:class=>"opener") do
215
- html.p do
216
- document.words.values.sort_by(&:offset).each do |word|
217
- if offset < word.offset
218
- spacer = word.offset - offset
219
- spacer = Array.new(spacer, " ").join
220
- html.span(spacer)
221
- end
222
-
223
- terms = targets_for(:terms, word.id)
224
- entities = targets_for(:entities, terms)
225
- opinions = opinions_for(terms)
226
- properties = targets_for(:properties, terms)
227
-
228
- generics = []
229
- generics << "term" if terms.size > 0
230
- generics << "entity" if entities.size > 0
231
- generics << "opinion" if opinions.size > 0
232
- generics << "property" if properties.size > 0
233
-
234
- classes = [terms, entities, opinions, properties, generics].flatten.uniq
235
-
236
- word_annotations = classes.join(" ")
237
-
238
- html.span(word.content, :class=>word_annotations, :id=>word.id)
239
- offset = word.offset + word.length
240
- end
241
- end
242
-
243
- [:entities, :opinions, :properties].each do |sym|
244
- html.div(:class=>sym) do
245
- document.public_send(sym).values.each do |entity|
246
- html.div(entity.to_s, :id=>entity.id, :class=>entity.target_ids.join(" "))
247
- end
248
- end
249
- end
250
- end
251
- end
252
-
253
- builder.to_html
254
- end
255
-
256
- def targets_for(variable, *ids)
257
- targets = document.public_send(variable.to_sym).values.select do |value|
258
- value.has_target?(ids.flatten)
259
- end
260
-
261
- targets.map(&:id)
262
- end
263
-
264
- def opinions_for(*ids)
265
- targets = document.opinions.values.select do |value|
266
- value.has_target?(ids.flatten)
267
- end
268
-
269
- ids = targets.map(&:id)
270
- sentiments = targets.map(&:expression)
271
- return ids.concat(sentiments).uniq
272
- end
273
-
274
- end
275
- end
276
- end
277
- end
278
-