2012年7月11日水曜日

クライアント向けインターフェースの実装(1)

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
好きな料理は?と聞かれたら、カレーと即答する、たなけんです。
本エントリでは、プレゼンテーション層とアプリケーション層とをつなぐ、クライアント向けインターフェースの実装について記載します。


クライアント向けインターフェースの実装(1)

プロジェクトファイル

(defproject my-dictionary "0.1.0-SNAPSHOT"
:description "A tiny web application for requesting Dictionary.com web api"
:url "http://"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [
[org.clojure/clojure "1.3.0"]
[org.clojure/tools.logging "0.2.3"]
[log4j/log4j "1.2.16"]
[log4j/apache-log4j-extras "1.1"]
[clj-http "0.4.3"]
[clj-json "0.5.0"]
[clj-xpath "1.3.0"]
[compojure "1.1.0"]
[ring/ring-jetty-adapter "1.1.1"]]
:ring {:handler my-dictionary.core/interface-for-client})
view raw project.clj hosted with ❤ by GitHub

Compojure ver 1.1.0の利用を追記しました
またleiningenからringアプリケーションを起動出来るよう:ringオプションを追記しました。

nsマクロ

(ns my-dictionary.core
(:require
:reload-all
[clojure.tools.logging :as logging]
[clj-http.client :as http-client]
[clj-xpath.core :as xpath]
[clj-json.core :as json]
[compojure.core :as compojure-core]
[compojure.route :as compojure-route])
(:import
(java.io.IOException)
(org.xml.sax.SAXException)
(myDictionary.java.AppException)))
view raw core.clj hosted with ❤ by GitHub

compojure.coreとcompojure.routeの利用を追記しました。

仮実装

(compojure-core/defroutes interface-for-client
(compojure-core/GET "/dictionary/define/:word" [word] (from-build-url-to-generate-json word))
(compojure-route/not-found "Page not found"))
view raw core.clj hosted with ❤ by GitHub

httpクライアントからアクセスを可能にするためurlと関数を結びつけました。

テストコード

(deftest test-interfece-for-client
(is (interface-for-client {:request-method :get :uri "/dictionary/define/test"})
{:status 200, :headers {"Content-Type" "text/html; charset=utf-8"}, :body "{\"word\":\"test\",\"entries\":[{\"pos\":\"noun\",\"mean\":\"the means used to determine the quality, content, etc., of something\"},{\"pos\":\"noun\",\"mean\":\"examination to evaluate a student or class\"},{\"pos\":\"verb (used with object)\",\"mean\":\"to subject to a test\"}]}"}))
(deftest test-interface-for-client-404
(is (interface-for-client {:request-method :get :uri ""})
{:status 404, :headers {"Content-Type" "text/html; charset=utf-8"}, :body "Page not found"}))
view raw core_test.clj hosted with ❤ by GitHub

正常系、以上系の処理の2パターンを追加しました。

対応するAPIを増やす(準備)

これまでDictionary.comのdefine/dictionaryのみを対象に、url構築からjson-文字列抽出を実装しましたが、Dictionary.comではdefinition/dictionary以外にも様々なAPIを提供されています。
そこで、折角ですのでdefine/dictionary以外のAPIにも対応できるよう、これまで実装した関数に変更を加えようと思います。(修正に伴い、関数ごとの機能の切り分けなど、プログラムの見通しも良くしたいと思います。)
表1: Dictionary.comのAPI一覧

サービス名typesite

Dictionary (英英辞書)definedictionary(任意)

Thesaurus (分類語彙辞書)definethesaurus(任意)

Slang (俗語辞書)defineslang(任意)

Etymology (語源)無しetymology

Example (例文)example無し

Questions and Answers (Q&A)無しquestionanswer

Synonyms (同義語)synonyms無し

Random (ランダム)randomdictionary(任意)

randomthesaurus(任意)

Spelling (綴り字)spelling無し

まずはhttpリクエストのパラメータについて整理します。
英英辞典、分類語彙辞書、俗語辞書、ランダムについては、同じ引数でurlを組み立てることができます。(ただしsiteは省略可能、省略時にはdictionaryが指定されます)
しかし例文、同義語、綴り時については上記とは異なり引数にsiteを取りません。また、語源とQ&Aについては、引数にsiteを取らない代わりにtypeを取ります。
つまり、urlのパターンは以下のようになります。
  • typeにdefineが指定される
  • typeにdefineが指定され、siteにdictionaryが指定される
  • typeにdefineが指定され、siteにthesaurusが指定される
  • typeにdefineが指定され、siteにslangが指定される
  • siteにetymologyが指定る
  • typeにsynonymsが指定される
  • typeにrandomが指定される
  • typeにrandomが指定され、siteにdictionaryが指定される
  • typeにrandomが指定され、siteにthesaurusが指定される
  • typeにspellingが指定される
現時点では、引数が固定のため、語源、例文、Q&A、同義語、綴り時のサービスに対応していません。また、レスポンスとして返されるxmlのフォーマットも異なるため、各サービスごとにxpathを変更する必要があります。
つまり、対応APIを増やす為に必要な修正点は以下となります。
  • interface-for-clientで呼び出しサービスを識別
  • 利用するAPIに対応したurlを構築
  • 利用するAPIに対応したxmlからのJSON文字列の生成


今回の作業は以上。最後までお読み頂きありがとうございました。
たなけん (作業時間30分)

0 件のコメント:

コメントを投稿