rea 0.0.1
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.
- data/CHANGELOG.md +5 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +48 -0
- data/LICENCE.md +22 -0
- data/Manifest.txt +15 -0
- data/README.md +7 -0
- data/Rakefile +23 -0
- data/bin/rea +8 -0
- data/lib/rea-dblp/rea/dblp.rb +59 -0
- data/lib/rea-dblp/rea/dblp/entry_parser.rb +48 -0
- data/lib/rea-dblp/rea/dblp/grab.rb +14 -0
- data/lib/rea-dblp/rea/dblp/parser.rb +36 -0
- data/lib/rea-dblp/rea/dblp/query_result_parser.rb +38 -0
- data/lib/rea-dblp/rea/dblp/search.rb +18 -0
- data/lib/rea.rb +28 -0
- data/lib/rea/command.rb +62 -0
- data/lib/rea/command/search.rb +52 -0
- data/lib/rea/command/utils.rb +31 -0
- data/lib/rea/errors.rb +62 -0
- data/lib/rea/loader.rb +8 -0
- data/lib/rea/version.rb +14 -0
- data/lib/rea/work_key.rb +33 -0
- data/rea.gemspec +192 -0
- data/rea.noespec +33 -0
- data/spec/rea-dblp/fixtures/entries/Damas2005.xml +17 -0
- data/spec/rea-dblp/fixtures/entries/Damas2009.xml +16 -0
- data/spec/rea-dblp/fixtures/entries/Erroneous.xml +1 -0
- data/spec/rea-dblp/fixtures/entries/QueryEntry.xml +15 -0
- data/spec/rea-dblp/fixtures/entries/Unrecognized.xml +3 -0
- data/spec/rea-dblp/fixtures/query_results/Erroneous.xml +1 -0
- data/spec/rea-dblp/fixtures/query_results/QueryResult.xml +25 -0
- data/spec/rea-dblp/fixtures/query_results/Unrecognized.xml +3 -0
- data/spec/rea-dblp/test_entry_parser.rb +72 -0
- data/spec/rea-dblp/test_grab.rb +18 -0
- data/spec/rea-dblp/test_query_result_parser.rb +38 -0
- data/spec/rea-dblp/test_search.rb +18 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/test_rea.rb +12 -0
- data/spec/work_key/test_parse.rb +28 -0
- data/spec/work_key/test_to_ruby_literal.rb +20 -0
- data/spec/work_key/test_to_s.rb +12 -0
- data/tasks/debug_mail.rake +75 -0
- data/tasks/debug_mail.txt +13 -0
- data/tasks/gem.rake +68 -0
- data/tasks/spec_test.rake +71 -0
- data/tasks/unit_test.rake +76 -0
- data/tasks/yard.rake +51 -0
- metadata +215 -0
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source 'http://rubygems.org'
|
2
|
+
|
3
|
+
group :runtime do
|
4
|
+
gem "http", "~> 0.1.0"
|
5
|
+
gem "nokogiri", "~> 1.5"
|
6
|
+
gem "quickl", "~> 0.4.2"
|
7
|
+
gem "pdf-toolkit", "= 1.0.0.rc1"
|
8
|
+
gem "epath", "~> 0.0.1"
|
9
|
+
gem "alf", "~> 0.12.0"
|
10
|
+
gem "bibtex-ruby", "~> 2.0"
|
11
|
+
end
|
12
|
+
|
13
|
+
group :development do
|
14
|
+
gem "rake", "~> 0.9.2"
|
15
|
+
gem "rspec", "~> 2.8.0"
|
16
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
alf (0.12.0)
|
5
|
+
backports (~> 2.3.0)
|
6
|
+
myrrha (~> 1.2.1)
|
7
|
+
quickl (~> 0.4.2)
|
8
|
+
backports (2.3.0)
|
9
|
+
bibtex-ruby (2.0.4)
|
10
|
+
latex-decode (>= 0.0.6)
|
11
|
+
multi_json (~> 1.0)
|
12
|
+
diff-lcs (1.1.3)
|
13
|
+
epath (0.0.1)
|
14
|
+
http (0.1.0)
|
15
|
+
latex-decode (0.0.12)
|
16
|
+
unicode (~> 0.4)
|
17
|
+
latex-decode (0.0.12-java)
|
18
|
+
multi_json (1.0.4)
|
19
|
+
myrrha (1.2.2)
|
20
|
+
nokogiri (1.5.0)
|
21
|
+
nokogiri (1.5.0-java)
|
22
|
+
pdf-toolkit (1.0.0.rc1)
|
23
|
+
quickl (0.4.2)
|
24
|
+
rake (0.9.2.2)
|
25
|
+
rspec (2.8.0)
|
26
|
+
rspec-core (~> 2.8.0)
|
27
|
+
rspec-expectations (~> 2.8.0)
|
28
|
+
rspec-mocks (~> 2.8.0)
|
29
|
+
rspec-core (2.8.0)
|
30
|
+
rspec-expectations (2.8.0)
|
31
|
+
diff-lcs (~> 1.1.2)
|
32
|
+
rspec-mocks (2.8.0)
|
33
|
+
unicode (0.4.1)
|
34
|
+
|
35
|
+
PLATFORMS
|
36
|
+
java
|
37
|
+
ruby
|
38
|
+
|
39
|
+
DEPENDENCIES
|
40
|
+
alf (~> 0.12.0)
|
41
|
+
bibtex-ruby (~> 2.0)
|
42
|
+
epath (~> 0.0.1)
|
43
|
+
http (~> 0.1.0)
|
44
|
+
nokogiri (~> 1.5)
|
45
|
+
pdf-toolkit (= 1.0.0.rc1)
|
46
|
+
quickl (~> 0.4.2)
|
47
|
+
rake (~> 0.9.2)
|
48
|
+
rspec (~> 2.8.0)
|
data/LICENCE.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# The MIT Licence
|
2
|
+
|
3
|
+
Copyright (c) 2012 - Bernard Lambeau
|
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/Manifest.txt
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
begin
|
2
|
+
gem "bundler", "~> 1.0"
|
3
|
+
require "bundler/setup"
|
4
|
+
rescue LoadError => ex
|
5
|
+
puts ex.message
|
6
|
+
abort "Bundler failed to load, (did you run 'gem install bundler' ?)"
|
7
|
+
end
|
8
|
+
|
9
|
+
# Dynamically load the gem spec
|
10
|
+
$gemspec_file = File.expand_path('../rea.gemspec', __FILE__)
|
11
|
+
$gemspec = Kernel.eval(File.read($gemspec_file))
|
12
|
+
|
13
|
+
# We run tests by default
|
14
|
+
task :default => :test
|
15
|
+
|
16
|
+
#
|
17
|
+
# Install all tasks found in tasks folder
|
18
|
+
#
|
19
|
+
# See .rake files there for complete documentation.
|
20
|
+
#
|
21
|
+
Dir["tasks/*.rake"].each do |taskfile|
|
22
|
+
load taskfile
|
23
|
+
end
|
data/bin/rea
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
module Rea
|
2
|
+
module DBLP
|
3
|
+
|
4
|
+
def grab(identifier)
|
5
|
+
Grab.new.call(identifier)
|
6
|
+
end
|
7
|
+
module_function :grab
|
8
|
+
|
9
|
+
def search(query)
|
10
|
+
Search.new.call(query)
|
11
|
+
end
|
12
|
+
module_function :search
|
13
|
+
|
14
|
+
def url
|
15
|
+
"http://www.dblp.org"
|
16
|
+
end
|
17
|
+
module_function :url
|
18
|
+
|
19
|
+
def shortcut
|
20
|
+
"dblp"
|
21
|
+
end
|
22
|
+
module_function :shortcut
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
include Rea::ErrorUtils
|
27
|
+
|
28
|
+
def entry_url(identifier)
|
29
|
+
"#{url}/rec/bibtex/#{identifier}.xml"
|
30
|
+
end
|
31
|
+
|
32
|
+
def search_url
|
33
|
+
"#{url}/search/api"
|
34
|
+
end
|
35
|
+
|
36
|
+
def get(url)
|
37
|
+
got = Http.get(url, :response => :object)
|
38
|
+
case got.status
|
39
|
+
when 200...300
|
40
|
+
not_found_error!(url) if got.body.empty?
|
41
|
+
got.body
|
42
|
+
when 400...500
|
43
|
+
not_found_error!(url)
|
44
|
+
when 500...600
|
45
|
+
third_party_error!(url)
|
46
|
+
else
|
47
|
+
unexpected_error!(url)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
Rea::register_provider(self)
|
52
|
+
end # module DBLP
|
53
|
+
end # module Rea
|
54
|
+
require_relative 'dblp/parser'
|
55
|
+
require_relative 'dblp/entry_parser'
|
56
|
+
require_relative 'dblp/query_result_parser'
|
57
|
+
require_relative 'dblp/grab'
|
58
|
+
require_relative 'dblp/search'
|
59
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Rea
|
2
|
+
module DBLP
|
3
|
+
class EntryParser < Parser
|
4
|
+
|
5
|
+
def parse_text(entry, source = nil)
|
6
|
+
entries = []
|
7
|
+
parse_xml(entry, source) do |doc|
|
8
|
+
doc.xpath("/dblp/*").each do |entry|
|
9
|
+
entries << send(:"parse_#{entry.name}", entry)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
entries
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
###
|
18
|
+
|
19
|
+
def parse_inproceedings(entry)
|
20
|
+
{ :kind => "inproceedings",
|
21
|
+
:key => work_key(entry.attribute("key").text),
|
22
|
+
:title => entry.xpath("title").text,
|
23
|
+
:source => entry.xpath("booktitle").text,
|
24
|
+
:year => entry.xpath("year").text,
|
25
|
+
:authors => entry.xpath("author").map(&:text) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def parse_article(entry)
|
29
|
+
{ :kind => "article",
|
30
|
+
:key => work_key(entry.attribute("key").text),
|
31
|
+
:title => entry.xpath("title").text,
|
32
|
+
:source => entry.xpath("journal").text,
|
33
|
+
:year => entry.xpath("year").text,
|
34
|
+
:authors => entry.xpath("author").map(&:text) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse_queryentry(entry)
|
38
|
+
{ :kind => entry.xpath('type').text,
|
39
|
+
:key => work_key(entry.attribute("key").text),
|
40
|
+
:title => entry.xpath("title").text,
|
41
|
+
:source => entry.xpath("venue").text,
|
42
|
+
:year => entry.xpath("year").text,
|
43
|
+
:authors => entry.xpath("authors/author").map(&:text) }
|
44
|
+
end
|
45
|
+
|
46
|
+
end # class EntryParser
|
47
|
+
end # module DBLP
|
48
|
+
end # module Rea
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Rea
|
2
|
+
module DBLP
|
3
|
+
class Parser
|
4
|
+
include Rea::ErrorUtils
|
5
|
+
|
6
|
+
def self.parse(*args, &bl)
|
7
|
+
new.parse(*args, &bl)
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse(path)
|
11
|
+
if path.respond_to?(:to_path)
|
12
|
+
parse_text(Path(path).read, path)
|
13
|
+
else
|
14
|
+
parse_text(path, nil)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def work_key(identifier)
|
21
|
+
WorkKey.new("dblp", identifier)
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse_xml(xml, source)
|
25
|
+
options = Nokogiri::XML::ParseOptions::STRICT
|
26
|
+
parsed = Nokogiri::XML(xml.to_s, source.to_s, nil, options)
|
27
|
+
block_given? ? yield(parsed) : parsed
|
28
|
+
rescue NoMethodError
|
29
|
+
parse_format_error!(source)
|
30
|
+
rescue Nokogiri::XML::SyntaxError
|
31
|
+
parse_error!(source)
|
32
|
+
end
|
33
|
+
|
34
|
+
end # class Parser
|
35
|
+
end # module DBLP
|
36
|
+
end # module Rea
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Rea
|
2
|
+
module DBLP
|
3
|
+
class QueryResultParser < Parser
|
4
|
+
|
5
|
+
def parse_text(result, source = nil)
|
6
|
+
entries = []
|
7
|
+
parse_xml(result, source) do |doc|
|
8
|
+
unrecognized!(source) if doc.xpath('/result').empty?
|
9
|
+
doc.xpath("/result/hits/hit").each do |entry|
|
10
|
+
entries << send(:"xml_parse_hit", entry)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
entries
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def fix_xmlns(xml)
|
19
|
+
xml.gsub %r{<result>},
|
20
|
+
%q{<result xmlns:dblp="http://www.dblp.org/xmlns/dblp">}
|
21
|
+
end
|
22
|
+
|
23
|
+
def xml_parse_hit(hit)
|
24
|
+
key = hit.xpath('url').text[%r{http://www.dblp.org/rec/bibtex/(.*)}, 1]
|
25
|
+
content = <<-XML.gsub(/\n\s*/, "")
|
26
|
+
<dblp>
|
27
|
+
<queryentry key="#{key}">
|
28
|
+
#{hit.xpath('title').inner_text}
|
29
|
+
</queryentry>
|
30
|
+
</dblp>
|
31
|
+
XML
|
32
|
+
EntryParser.parse(content).first
|
33
|
+
end
|
34
|
+
|
35
|
+
end # class QueryResultParser
|
36
|
+
end # module DBLP
|
37
|
+
end # module Rea
|
38
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Rea
|
2
|
+
module DBLP
|
3
|
+
class Search
|
4
|
+
include DBLP
|
5
|
+
|
6
|
+
def call(query)
|
7
|
+
unless query.size == 1 and query[:title]
|
8
|
+
not_implemented_error!("Unable to search with #{query.inspect}")
|
9
|
+
end
|
10
|
+
title = query[:title].gsub(/\s+/, "%20")
|
11
|
+
xml = get("#{search_url}?q=#{title}")
|
12
|
+
tuples = QueryResultParser.parse(xml)
|
13
|
+
Relation(tuples)
|
14
|
+
end
|
15
|
+
|
16
|
+
end # class Search
|
17
|
+
end # module DBLP
|
18
|
+
end # module Rea
|
data/lib/rea.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require_relative "rea/version"
|
2
|
+
require_relative "rea/loader"
|
3
|
+
require_relative "rea/errors"
|
4
|
+
|
5
|
+
#
|
6
|
+
# Research Exploring Assistant
|
7
|
+
#
|
8
|
+
module Rea
|
9
|
+
|
10
|
+
def WorkKey(str)
|
11
|
+
WorkKey.parse(str)
|
12
|
+
end
|
13
|
+
module_function :WorkKey
|
14
|
+
|
15
|
+
def register_provider(provider)
|
16
|
+
providers << provider
|
17
|
+
end
|
18
|
+
module_function :register_provider
|
19
|
+
|
20
|
+
def providers
|
21
|
+
@providers ||= []
|
22
|
+
end
|
23
|
+
module_function :providers
|
24
|
+
|
25
|
+
end # module Rea
|
26
|
+
|
27
|
+
require_relative 'rea/work_key'
|
28
|
+
require_relative 'rea-dblp/rea/dblp'
|
data/lib/rea/command.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'rea'
|
2
|
+
module Rea
|
3
|
+
#
|
4
|
+
# rea - The Research Exploring Assistant
|
5
|
+
#
|
6
|
+
# SYNOPSIS
|
7
|
+
# #{program_name} [--version] [--help] COMMAND [cmd opts] ARGS...
|
8
|
+
#
|
9
|
+
# OPTIONS
|
10
|
+
# #{summarized_options}
|
11
|
+
#
|
12
|
+
# COMMANDS
|
13
|
+
# #{summarized_subcommands}
|
14
|
+
#
|
15
|
+
# See '#{program_name} help COMMAND' for more information on a specific command.
|
16
|
+
#
|
17
|
+
class Command < Quickl::Delegator(__FILE__, __LINE__)
|
18
|
+
|
19
|
+
# Install options
|
20
|
+
options do |opt|
|
21
|
+
@trace = false
|
22
|
+
opt.on('--trace') do
|
23
|
+
@trace = true
|
24
|
+
end
|
25
|
+
opt.on_tail("--help", "Show help") do
|
26
|
+
raise Quickl::Help
|
27
|
+
end
|
28
|
+
opt.on_tail("--version", "Show version") do
|
29
|
+
raise Quickl::Exit,
|
30
|
+
"rea #{Rea::VERSION} (c) 2012, Bernard Lambeau"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def execute(*args)
|
35
|
+
super
|
36
|
+
rescue Quickl::Error
|
37
|
+
raise
|
38
|
+
rescue Rea::Error => ex
|
39
|
+
if @trace
|
40
|
+
dump_exception(ex)
|
41
|
+
else
|
42
|
+
$stderr.puts ex.message
|
43
|
+
end
|
44
|
+
rescue Exception => ex
|
45
|
+
puts "Sorry, an internal error occured. Please report --trace to developers."
|
46
|
+
dump_exception(ex) if @trace
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def dump_exception(ex, indent = 0)
|
52
|
+
$stderr.puts ex.message.gsub(/^/m," "*indent)
|
53
|
+
$stderr.puts ex.backtrace.map{|s|
|
54
|
+
s.gsub(/^/m," "*(indent+1))
|
55
|
+
}.join("\n")
|
56
|
+
dump_exception(ex.cause, indent + 1) if ex.respond_to?(:cause)
|
57
|
+
end
|
58
|
+
|
59
|
+
end # class Command
|
60
|
+
end # module Rea
|
61
|
+
require_relative "command/utils"
|
62
|
+
require_relative "command/search"
|