Add DDC and LCC info to book headers in page display.
[quanlib.git] / classify / classify.rb
1 require 'erb'
2 require 'net/http'
3 require 'nokogiri'
4
5 require 'bookclass'
6 require 'classset'
7 require 'fastset'
8
9 class Lookup
10   def initialize
11     @class_set = ClassSet.new()
12     @fast_set = FastSet.new()
13   end
14  
15   def construct_url(params)
16     first = true
17     cmd = 'http://classify.oclc.org/classify2/Classify'
18   
19     params += [ ['summary', 'false' ] ]
20   
21     params.each do |tuple|
22       name, value = tuple
23       if (first)
24         cmd += '?'
25         first = false
26       else
27         cmd += '&'
28       end
29     cmd += name + '='
30       cmd += ERB::Util.url_encode(value)
31     end
32   
33     return cmd
34   end
35   
36   def isUpper?(c)
37       return /[[:upper:]]/.match(c)
38   end
39   
40   def lookup(author_grouping, title)
41     params = [ 
42         ['author', massage_author(author_grouping)],
43         ['title', title]
44       ]
45   
46     cmd = construct_url(params)
47     res = submit_request(cmd)
48   
49     doc = Nokogiri::XML(res.body)
50
51     if "4" == response_code(doc)
52       # Multiple matches; pick the first one and re-query
53       owi = doc.css("works work")[0]["owi"]
54   
55       params = [
56           ['owi', owi]
57         ]
58       cmd = construct_url(params)
59       res = submit_request(cmd)
60     
61       #puts res.body
62     
63       doc = Nokogiri::XML(res.body)
64     end
65   
66     if "2" != response_code(doc)
67       puts "Lookup failed"
68       return nil
69     end
70
71     title = doc.css("classify editions edition")[0]["title"]
72   
73     info = BookClass.new(author_grouping, title)
74
75     author = doc.css("classify editions edition")[0]["author"]
76     info.author = author
77   
78     nodes = doc.css("classify recommendations ddc mostPopular")
79     if nil != nodes && nodes.length > 0
80       ddc = nodes[0]["sfa"]
81       info.ddc = ddc
82     end
83   
84     nodes = doc.css("classify recommendations lcc mostPopular")
85     if nil != nodes && nodes.length > 0
86       lcc = nodes[0]["sfa"]
87     end
88     info.lcc = lcc
89
90     headings = doc.css("classify recommendations fast headings heading")
91     headings.each do |heading|
92       #puts heading.inspect
93       id = heading['ident']
94       #puts 'ID: ' + id
95       descr = heading.content
96       #puts 'DESCR: ' + descr
97       info.add_fast(id)
98       @fast_set.add(id, descr)
99     end
100
101     @class_set.ensure_contains!(info)
102
103     return info
104   end
105
106   def massage_author(input)
107       if nil == input
108         return nil
109       end
110   
111       reading_order = ""
112       input.each_char do |c|
113         if isUpper?(c) and (reading_order.length > 0)
114           reading_order += " "
115        end
116         reading_order += c
117       end
118   
119       return reading_order
120   end
121
122   def response_code(doc)
123     return doc.css("classify response")[0]["code"]
124   end
125
126   def save_state
127     @class_set.save_state()
128     @fast_set.save_state()
129   end
130
131   def submit_request(cmd)
132     puts ('GET ' + cmd)
133   
134     url = URI.parse(cmd)
135     req = Net::HTTP::Get.new(url.to_s)
136     res = Net::HTTP.start(url.host, url.port) {|http|
137       http.request(req)
138     }
139     return res
140   end
141 end
142