placemaker 0.0.2

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/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source :rubygems
2
+
3
+ gem 'curb'
4
+ gem 'nokogiri'
5
+
6
+ group :test do
7
+ gem 'rspec', '1.3.0'
8
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,14 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ curb (0.7.9)
5
+ nokogiri (1.4.4)
6
+ rspec (1.3.0)
7
+
8
+ PLATFORMS
9
+ ruby
10
+
11
+ DEPENDENCIES
12
+ curb
13
+ nokogiri
14
+ rspec (= 1.3.0)
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Justin S. Leitgeb
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,76 @@
1
+ = Description
2
+
3
+ Yahoo! Placemaker is a freely available geoparsing Web service. It helps developers make their applications location-aware by
4
+ identifying places in unstructured and atomic content - feeds, web pages, news, status updates - and returning geographic metadata
5
+ for geographic indexing and markup.
6
+
7
+ This library is a Ruby interface for accessing the {Yahoo PlaceMaker API}[http://developer.yahoo.com/geo/placemaker/].
8
+
9
+ = Installation
10
+
11
+ Assuming that you've set up your ruby environment to pull gems from GitHub
12
+ (see {the GitHub instructions if you haven't yet done this}[http://gems.github.com]),
13
+ install placemaker with the following command:
14
+
15
+ sudo gem install jsl-placemaker
16
+
17
+ = Usage
18
+
19
+ The following is an example of using the Placemaker gem to read places in a standard feed. You'll have to get a Yahoo App ID first if you haven't
20
+ already done so.
21
+
22
+ require 'placemaker'
23
+ p = Placemaker::Client.new(:appid => YOUR_APP_ID, :document_url => 'http://feeds.feedburner.com/wooster', :document_type => 'text/xml')
24
+ p.fetch!
25
+
26
+ This will make a call to the Placemaker service and populate the Placemaker::Client object with data about the places in the content that you
27
+ sent to Yahoo. The information that you'll be interested in may be divided into "documents" and "meta-data."
28
+
29
+ You can also use placemaker with a document that you upload. Use +document_content+ in the configuration options instead of +document_url+, and
30
+ make sure to set the appropriate value for +document_type+. Acceptable mime types are text/plain, text/html, text/xml, text/rss, application/xml,
31
+ and application/rss+xml. The following is an example of using jsl-placemaker to encode content that you upload:
32
+
33
+ p = Placemaker::Client.new(:appid => YOUR_APP_ID, :document_content => 'railsconf was in las vegas this year', :document_type => 'text/plain')
34
+ p.fetch!
35
+
36
+ Afterwards, you have access to the same Placemaker::Client methods as if you had pointed placemaker to a +document_url+.
37
+
38
+ == Documents
39
+
40
+ Once you've run the +fetch!+ method on the Placemaker::Client, you may invoke the method +documents+ which will return a set of Placemaker::Document
41
+ objects corresponding to each of the entries in the feed given to the placemaker service. For example, if you gave a +document_url+ pointing
42
+ to a feed containing 15 entries, there will be 15 documents in the resulting client object.
43
+
44
+ The following are methods that you may invoke on each of the Placemaker::Document objects to find out more about the place information that
45
+ Yahoo was able to glean from the input document:
46
+
47
+ * place_details - Returns a Placemaker::Location object that is a container for one named place mentioned in the document
48
+ * administrative_scope - Returns a Placemaker::Location object that is a container for the smallest administrative place that best describes the document
49
+ * geographic_scope - Returns a Placemaker::Location object that is a container for the smallest place that best describes the document
50
+ * extents - Returns a Placemaker::Extents object that is a container for the the map extents covering the places mentioned in the document
51
+
52
+ Below is a summary of the methods that these objects respond to. You may wish to browse the Placemaker rdoc files for these classes to see
53
+ for more details.
54
+
55
+ === Placemaker::Location
56
+
57
+ Placemaker::Location objects contain a woe_id, name, location_type and centroid.
58
+
59
+ * woe_id - permanent identifier for the place
60
+ * name - fully qualified name for the place
61
+ * location_type - type name for the place
62
+ * centroid - centroid for the place, responds to +lat+ and +lng+
63
+
64
+ === Placemaker::Extents
65
+
66
+ Placemaker::Extents are bounding boxes for an area of interest. They respond to methods for +center+, +south_west+ and +north_east+. In
67
+ all of these cases, they return a Placemaker::Coordinates object responding to +lat+ and +lng+.
68
+
69
+ == Meta-data
70
+
71
+ The request to the Yahoo place coding service returns information about the request. You may invoke the methods +processing_time+,
72
+ +version+, and +document_length+ to find out more about the request.
73
+
74
+ = Author
75
+
76
+ Justin S. Leitgeb, justin@phq.org
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ require 'rake'
5
+ require 'spec/rake/spectask'
6
+ require 'rake/rdoctask'
7
+
8
+ require 'lib/placemaker'
9
+
10
+ desc 'Test the plugin.'
11
+ Spec::Rake::SpecTask.new(:spec) do |t|
12
+ t.spec_opts = ["--format", "progress", "--colour"]
13
+ t.libs << 'lib'
14
+ t.verbose = true
15
+ end
16
+
17
+ desc "Run all the tests"
18
+ task :default => :spec
19
+
20
+ desc 'Generate documentation'
21
+ Rake::RDocTask.new(:rdoc) do |rdoc|
22
+ rdoc.rdoc_dir = 'rdoc'
23
+ rdoc.title = 'Placemaker'
24
+ rdoc.options << '--line-numbers' << '--inline-source'
25
+ rdoc.rdoc_files.include('README.rdoc')
26
+ rdoc.rdoc_files.include('lib/placemaker/**/*.rb')
27
+ end
28
+
@@ -0,0 +1,75 @@
1
+ require 'placemaker/xml_parser'
2
+
3
+ module Placemaker
4
+
5
+ # Main interface to the Placemaker API.
6
+ class Client
7
+ POST_FIELDS = %w[ appid document_content document_url document_type document_title
8
+ auto_disambiguate focus_woe_id input_language output_type ].map{|f| f.to_sym}
9
+
10
+ def initialize(options = {})
11
+ @options = options
12
+ @options[:appid] ||= ENV['PLACEMAKER_APPID']
13
+
14
+ @xml_parser = Placemaker::XmlParser.new('NODOC')
15
+
16
+ verify_content_set
17
+ verify_document_type_set
18
+ end
19
+
20
+ # Fetches the place information for input parameters from the Yahoo Placemaker service
21
+ def fetch!
22
+ fields = POST_FIELDS.reject{|f| @options[f].nil? }.map do |f|
23
+ # Change ruby-form fields to url type, e.g., document_content => documentContent
24
+ cgi_param = f.to_s.gsub(/\_(.)/) {|s| s.upcase}.gsub('_', '').sub(/url/i, 'URL')
25
+ Curl::PostField.content(cgi_param, @options[f])
26
+ end
27
+
28
+ res = Curl::Easy.http_post('http://wherein.yahooapis.com/v1/document', *fields)
29
+ @xml_parser = Placemaker::XmlParser.new(res.body_str)
30
+ end
31
+
32
+ # Returns a collection of Placemaker::Document items as containers for content location information
33
+ def documents
34
+ @xml_parser.documents
35
+ end
36
+
37
+ # time in seconds to process the document
38
+ def processing_time
39
+ @xml_parser.processing_time
40
+ end
41
+
42
+ # version of the software used to process the document
43
+ def version
44
+ @xml_parser.version
45
+ end
46
+
47
+ # length in bytes of the document
48
+ def document_length
49
+ @xml_parser.document_length
50
+ end
51
+
52
+ # Create convenience methods to access post fields from the @options hash, mostly for testing.
53
+ POST_FIELDS.each do |f|
54
+ define_method(f) do # def appid
55
+ @options[f] # @options[:appid]
56
+ end # end
57
+ end
58
+
59
+ private
60
+
61
+ def verify_document_type_set
62
+ valid_types = %w[
63
+ text/plain
64
+ text/html text/xml text/rss
65
+ application/xml application/rss+xml
66
+ ]
67
+
68
+ raise ArgumentError, "Document type must be in #{valid_types.join(', ')}" unless valid_types.include?(@options[:document_type])
69
+ end
70
+
71
+ def verify_content_set
72
+ raise ArgumentError, "Either document_url or document_content must be set" if (@options[:document_content].nil? && @options[:document_url].nil?)
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,13 @@
1
+ module Placemaker
2
+ class Coordinates
3
+ include Placemaker::XmlHelper
4
+
5
+ def lat
6
+ @nodeset.search('.//xmlns:latitude', 'xmlns' => 'http://wherein.yahooapis.com/v1/schema').inner_text.to_f
7
+ end
8
+
9
+ def lng
10
+ @nodeset.search('.//xmlns:longitude', 'xmlns' => 'http://wherein.yahooapis.com/v1/schema').inner_text.to_f
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,44 @@
1
+ require 'placemaker/xml_helper'
2
+ require 'placemaker/place_details'
3
+ require 'placemaker/location'
4
+ require 'placemaker/extents'
5
+ require 'placemaker/reference'
6
+
7
+ module Placemaker
8
+
9
+ class Document
10
+ include Placemaker::XmlHelper
11
+
12
+ # Returns a Placemaker::Location object that is a container for one named place mentioned in the document
13
+ def place_details
14
+ @nodeset.search('.//xmlns:placeDetails', 'xmlns' => 'http://wherein.yahooapis.com/v1/schema').map do |p|
15
+ Placemaker::PlaceDetails.new(p)
16
+ end
17
+ end
18
+
19
+ # Returns a Placemaker::Location object that is a container for the smallest administrative place that best describes the document
20
+ def administrative_scope
21
+ as = @nodeset.search('.//xmlns:administrativeScope', 'xmlns' => 'http://wherein.yahooapis.com/v1/schema').first
22
+ Placemaker::Location.new(as) unless as.nil?
23
+ end
24
+
25
+ # Returns a Placemaker::Location object that is a container for the smallest place that best describes the document
26
+ def geographic_scope
27
+ gs = @nodeset.search('.//xmlns:geographicScope', 'xmlns' => 'http://wherein.yahooapis.com/v1/schema').first
28
+ Placemaker::Location.new(gs) unless gs.nil?
29
+ end
30
+
31
+ # Returns a Placemaker::Extents object that is a container for the the map extents covering the places mentioned in the document
32
+ def extents
33
+ extents = @nodeset.search('.//xmlns:extents', 'xmlns' => 'http://wherein.yahooapis.com/v1/schema').first
34
+ Placemaker::Extents.new(extents) unless extents.nil?
35
+ end
36
+
37
+ def reference_list
38
+ @nodeset.search('.//xmlns:referenceList[1]/xmlns:reference', 'xmlns' => 'http://wherein.yahooapis.com/v1/schema').map do |reference|
39
+ Placemaker::Reference.new(reference)
40
+ end
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,25 @@
1
+ require 'placemaker/coordinates'
2
+
3
+ module Placemaker
4
+
5
+ # container for the the map extents covering the places mentioned in the document
6
+ class Extents
7
+ include Placemaker::XmlHelper
8
+
9
+ # coordinates of center (WGS84)
10
+ def center
11
+ Placemaker::Coordinates.new(@nodeset.search('.//xmlns:center', 'xmlns' => 'http://wherein.yahooapis.com/v1/schema'))
12
+ end
13
+
14
+ # coordinates of southwest corner of bounding box (WGS84)
15
+ def south_west
16
+ Placemaker::Coordinates.new(@nodeset.search('.//xmlns:southWest', 'xmlns' => 'http://wherein.yahooapis.com/v1/schema'))
17
+ end
18
+
19
+ # coordinates of northeast corner of bounding box (WGS84)
20
+ def north_east
21
+ Placemaker::Coordinates.new(@nodeset.search('.//xmlns:northEast', 'xmlns' => 'http://wherein.yahooapis.com/v1/schema'))
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,35 @@
1
+ require 'placemaker/coordinates'
2
+
3
+ module Placemaker
4
+
5
+ # Parses and contains data for +place+, +administrative scope+ and +geographic scope+ elements.
6
+ class Location
7
+ include Placemaker::XmlHelper
8
+
9
+ # permanent identifier for the place
10
+ def woe_id
11
+ nested_node('woeId').to_i
12
+ end
13
+
14
+ # fully qualified name for the place
15
+ def name
16
+ nested_node('name')
17
+ end
18
+
19
+ # place type name for the place
20
+ def location_type
21
+ nested_node('type')
22
+ end
23
+
24
+ # centroid for the place
25
+ def centroid
26
+ Placemaker::Coordinates.new(@nodeset.search('.//xmlns:centroid', 'xmlns' => 'http://wherein.yahooapis.com/v1/schema'))
27
+ end
28
+
29
+ private
30
+
31
+ def nested_node(name)
32
+ @nodeset.search(".//xmlns:#{name}", 'xmlns' => 'http://wherein.yahooapis.com/v1/schema').inner_text
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,28 @@
1
+ module Placemaker
2
+
3
+ # container for one named place mentioned in the document
4
+ class PlaceDetails
5
+ include Placemaker::XmlHelper
6
+
7
+ # Returns a Placemaker::Location object as a container for place information.
8
+ def place
9
+ Placemaker::Location.new(@nodeset.search('.//xmlns:place', 'xmlns' => 'http://wherein.yahooapis.com/v1/schema'))
10
+ end
11
+
12
+ # type of match (0=text or text and coordinates, 1=coordinates only)
13
+ def match_type
14
+ nested_node('matchType').to_i
15
+ end
16
+
17
+ # relative weight of the place within the document (range 1-100)
18
+ def weight
19
+ nested_node('weight').to_i
20
+ end
21
+
22
+ # confidence that the document mentions the place (range 1-10)
23
+ def confidence
24
+ nested_node('confidence').to_i
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,34 @@
1
+ module Placemaker
2
+
3
+ class Reference
4
+ include Placemaker::XmlHelper
5
+
6
+ def woe_ids
7
+ nested_node('woeIds')
8
+ end
9
+
10
+ def start
11
+ nested_node('start')
12
+ end
13
+
14
+ def end
15
+ nested_node('end')
16
+ end
17
+
18
+ def is_plain_text_marker
19
+ nested_node('isPlainTextMarker')
20
+ end
21
+
22
+ def text
23
+ nested_node('text')
24
+ end
25
+
26
+ def type
27
+ nested_node('type')
28
+ end
29
+
30
+ def xpath
31
+ nested_node('xpath')
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,14 @@
1
+ module Placemaker
2
+ module XmlHelper
3
+ def initialize(nodeset)
4
+ @nodeset = nodeset
5
+ end
6
+
7
+ # Returns the inner text of a node with the given name under the current @nodeset
8
+ def nested_node(name)
9
+ @nodeset.search(".//xmlns:#{name}", 'xmlns' => 'http://wherein.yahooapis.com/v1/schema').inner_text
10
+ end
11
+
12
+ private :nested_node
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ require 'placemaker/document'
2
+
3
+ module Placemaker
4
+ class XmlParser
5
+ def initialize(xml_body)
6
+ @body = xml_body
7
+ @xml = Nokogiri::XML(xml_body)
8
+ end
9
+
10
+ # time in seconds to process the document
11
+ def processing_time
12
+ @xml.xpath('.//xmlns:processingTime', 'xmlns' => 'http://wherein.yahooapis.com/v1/schema').inner_text.to_f
13
+ end
14
+
15
+ # version of the software used to process the document
16
+ def version
17
+ @xml.xpath('.//xmlns:version', 'xmlns' => 'http://wherein.yahooapis.com/v1/schema').inner_text.strip
18
+ end
19
+
20
+ # length in bytes of the document
21
+ def document_length
22
+ @xml.xpath('.//xmlns:documentLength', 'xmlns' => 'http://wherein.yahooapis.com/v1/schema').inner_text.to_i
23
+ end
24
+
25
+ # Returns a set of Placemaker::Document objects as containers for content location information
26
+ def documents
27
+ @xml.xpath('//xmlns:document', 'xmlns' => 'http://wherein.yahooapis.com/v1/schema').map do |d|
28
+ Placemaker::Document.new(d)
29
+ end
30
+ end
31
+
32
+ end
33
+ end
data/lib/placemaker.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'curb'
3
+ require 'nokogiri'
4
+ require 'cgi'
5
+
6
+ dir = File.dirname(__FILE__)
7
+ $LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir)
8
+
9
+ require 'placemaker/client'