はじめに
おはようございます。当ブログにアクセス頂き、ありがとうございます。好きな言語は?と聞かれたら、Clojureと即答する、たなけんです。本エントリでは、プレゼンテーション層とアプリケーション層とをつなぐ、クライアント向けインターフェースの実装について記載します。クライアント向けインターフェースの実装(2)
前回リストアップした以下の項目に従い、各関数を修正します。- interface-for-clientへのリクエストの処理を追加
- 関数を引数に取り、抽出結果のJSON文字列を生成する関数の追加
- 利用APIに対応した抽出関数の追加
interface-for-clientへのリクエストの処理
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(def root-url "http://api-pub.dictionary.com/v001") | |
(compojure-core/defroutes interface-for-client | |
; | |
(compojure-core/GET "/dictionary/:word" [word] | |
(call-api root-url | |
(list | |
[:vid (:vid properties)] ["q" word] ["type" "define"] ["site" "dictionary"]) | |
extract-dictionary)) | |
; | |
(compojure-core/GET "/example/:word" [word] | |
(call-api root-url | |
(list | |
[:vid (:vid properties)] ["q" word] ["type" "example"]) | |
extract-example)) | |
; | |
(compojure-core/context "/random" [] | |
("/dictionary" [] | |
(call-api root-url | |
(list | |
[:vid (:vid properties)] ["type" "random"] ["site" "dictionary"]) | |
extract-random)) | |
("/thesaurus" [] | |
(call-api root-url | |
(list | |
[:vid (:vid properties)] ["type" "random"] ["site" "thesaurus"]) | |
extract-random))) | |
; | |
(compojure-core/GET "/spelling/:word" [word] | |
(call-api root-url | |
(list | |
[:vid (:vid properties)] ["q" word] ["type" "spelling"]) | |
extract-spelling)) | |
; | |
(compojure-route/not-found "Page not found")) |
urlリソースと関数を関連付けます。例えば、http://localhost/dictionary/testへアクセスすると、引数のwordに"test"が拘束された状態で、call-apiが呼び出されます。
- compojure.core/defroutesマクロ: urlリソースを定義
- compojure.core/GETマクロ: http GETメソッドによりアクセスされる節を構成
- call-api関数: url、パラメータリストおよび抽出関数を引数に取り、JSON文字列を生成
抽出結果のJSON文字列を生成する関数
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn call-api | |
[url prms extract-function] | |
(-> (build-url-with-prms url prms) | |
(get-body ,) | |
(extract-function ,) | |
(json/generate-string ,))) | |
(defn build-url-with-prms | |
"to build url string with parameters" | |
[url prms] | |
(str url (string/replace-first (apply str (for [[k v] prms] (str "&" (name k) "=" v))) "&" "?"))) | |
(defn get-body | |
"to send request and get body element of the response" | |
[url] | |
(:body (try | |
(http-client/get url) | |
(catch java.io.IOException ioe (handle-exception ioe))))) |
抽出関数を引数に取り、Dictionary.comから取得したxmlから必要な情報を抽出した結果のJSON文字列を生成します。
- ->マクロ: 左の関数を評価した結果を右の関数の引数とし、順次関数を実行
- build-url-with-prms関数: urlパラメータのリストからurl文字列を生成
- get-body関数: 引数のurlへhttpリクエストを送信し、そのhttpレスポンスのbody要素を取得
- extract-function(引数): 関数呼び出し時に指定される抽出関数
- clj-json.core/generate-string関数: clojureオブジェクトをJSON文字列に変換
抽出関数
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn safety-xpath-call | |
"to call xpath safely" | |
[xpath xml] | |
(try | |
(xpath/$x xpath xml) | |
(catch org.xml.sax.SAXException saxe (handle-exception saxe)))) | |
(defn get-result | |
"to extract text from a xml-string" | |
[xpath xml-string key-list] | |
(for [line (safety-xpath-call xpath xml-string)] | |
(reduce get line key-list))) | |
(defn- get-query-word | |
"to extract query word from a xml-string" | |
[xml-string] | |
(first (get-result "(/*)[1]" xml-string '(:attrs :query)))) | |
(defn extract-dictionary | |
"to extract word and entries from a xml-string of thesaurus" | |
[xml-string] | |
{:word (get-query-word xml-string) | |
:entries | |
(flatten | |
(for [pos (get-result "//partofspeech" xml-string '(:attrs :pos))] | |
(for [line (get-result (str "//partofspeech[@pos=\"" pos "\"]/defset/def") xml-string '(:text))] {:pos pos :text line})))}) | |
(defn extract-example | |
"to extract word and entries from a xml-string of example" | |
[xml-string] | |
{:word (get-query-word xml-string) | |
:entries (get-result "//example" xml-string '(:text))}) | |
(defn extract-random | |
"to extract word from a xml-string of random" | |
[xml-string site] | |
{:word (first (get-result (str "//" site "/random_entry") xml-string '(:text)))}) | |
(defn extract-spelling | |
"to extract word and entries from a xml-string of spelling" | |
[xml-string] | |
{:word (get-query-word xml-string) | |
:entries (get-result "//suggestion" xml-string '(:text))}) |
xpathによりxmlからノードを取得し、さらにそこから指定した要素を抽出します。
- safety-xpath-call関数: xpathによりxmlからノードを取得する。指定したxpathが取得出来なかった場合、handle-exception関数を呼び出す
- get-result関数: safety-xpath-call関数により取得したxmlノード(ネストした状態のハッシュ
- )から、順にキーを指定して、求める値を取得する
- get-query-word関数: xml内に含まれる、問い合わせ単語を取得する。具体的にはxpathが(/*)[1]のノードから、キー:attrs :queryの値を取得する。
- extract-dictionary関数: 英英辞書APIから取得したxmlから、問い合わせ単語と定義を抽出する。
- extract-example関数: 例文辞書APIから取得したxmlから、問い合わせ単語と例文を抽出する。
- extract-random関数: ランダムAPIから取得したxmlから、単語を抽出する。
- extract-spelling関数: 綴り時APIから取得したxmlから、問い合わせ単語と綴り字の候補を抽出する。
今回の作業は以上。最後までお読み頂きありがとうございました。
たなけん (作業時間120分)
0 件のコメント:
コメントを投稿