rea 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/Gemfile +16 -0
  3. data/Gemfile.lock +48 -0
  4. data/LICENCE.md +22 -0
  5. data/Manifest.txt +15 -0
  6. data/README.md +7 -0
  7. data/Rakefile +23 -0
  8. data/bin/rea +8 -0
  9. data/lib/rea-dblp/rea/dblp.rb +59 -0
  10. data/lib/rea-dblp/rea/dblp/entry_parser.rb +48 -0
  11. data/lib/rea-dblp/rea/dblp/grab.rb +14 -0
  12. data/lib/rea-dblp/rea/dblp/parser.rb +36 -0
  13. data/lib/rea-dblp/rea/dblp/query_result_parser.rb +38 -0
  14. data/lib/rea-dblp/rea/dblp/search.rb +18 -0
  15. data/lib/rea.rb +28 -0
  16. data/lib/rea/command.rb +62 -0
  17. data/lib/rea/command/search.rb +52 -0
  18. data/lib/rea/command/utils.rb +31 -0
  19. data/lib/rea/errors.rb +62 -0
  20. data/lib/rea/loader.rb +8 -0
  21. data/lib/rea/version.rb +14 -0
  22. data/lib/rea/work_key.rb +33 -0
  23. data/rea.gemspec +192 -0
  24. data/rea.noespec +33 -0
  25. data/spec/rea-dblp/fixtures/entries/Damas2005.xml +17 -0
  26. data/spec/rea-dblp/fixtures/entries/Damas2009.xml +16 -0
  27. data/spec/rea-dblp/fixtures/entries/Erroneous.xml +1 -0
  28. data/spec/rea-dblp/fixtures/entries/QueryEntry.xml +15 -0
  29. data/spec/rea-dblp/fixtures/entries/Unrecognized.xml +3 -0
  30. data/spec/rea-dblp/fixtures/query_results/Erroneous.xml +1 -0
  31. data/spec/rea-dblp/fixtures/query_results/QueryResult.xml +25 -0
  32. data/spec/rea-dblp/fixtures/query_results/Unrecognized.xml +3 -0
  33. data/spec/rea-dblp/test_entry_parser.rb +72 -0
  34. data/spec/rea-dblp/test_grab.rb +18 -0
  35. data/spec/rea-dblp/test_query_result_parser.rb +38 -0
  36. data/spec/rea-dblp/test_search.rb +18 -0
  37. data/spec/spec_helper.rb +12 -0
  38. data/spec/test_rea.rb +12 -0
  39. data/spec/work_key/test_parse.rb +28 -0
  40. data/spec/work_key/test_to_ruby_literal.rb +20 -0
  41. data/spec/work_key/test_to_s.rb +12 -0
  42. data/tasks/debug_mail.rake +75 -0
  43. data/tasks/debug_mail.txt +13 -0
  44. data/tasks/gem.rake +68 -0
  45. data/tasks/spec_test.rake +71 -0
  46. data/tasks/unit_test.rake +76 -0
  47. data/tasks/yard.rake +51 -0
  48. metadata +215 -0
@@ -0,0 +1,5 @@
1
+ # 0.0.1 / FIX ME
2
+
3
+ * Enhancements
4
+
5
+ * Birthday!
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
@@ -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)
@@ -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.
@@ -0,0 +1,15 @@
1
+ rea.gemspec
2
+ rea.noespec
3
+ .gemtest
4
+ CHANGELOG.md
5
+ Gemfile
6
+ Gemfile.lock
7
+ bin/**/*
8
+ lib/**/*
9
+ LICENCE.md
10
+ Manifest.txt
11
+ Rakefile
12
+ README.md
13
+ spec/**/*
14
+ tasks/**/*
15
+ test/**/*
@@ -0,0 +1,7 @@
1
+ # Rea
2
+
3
+ Research Exploring Assistant
4
+
5
+ ## Links
6
+
7
+ https://github.com/blambeau/rea
@@ -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,8 @@
1
+ #!/usr/bin/env ruby
2
+ Dir.chdir File.dirname(__FILE__) do
3
+ require 'bundler/setup'
4
+ end
5
+ $:.unshift File.expand_path('../../lib', __FILE__)
6
+ require 'rea/command'
7
+ Rea::Command.run(ARGV)
8
+
@@ -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,14 @@
1
+ module Rea
2
+ module DBLP
3
+ class Grab
4
+ include DBLP
5
+
6
+ def call(identifier)
7
+ xml = get entry_url(identifier)
8
+ tuples = EntryParser.parse(xml)
9
+ tuples.first
10
+ end
11
+
12
+ end # class Grab
13
+ end # module DBLP
14
+ 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
@@ -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'
@@ -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"