2 年目の連載「Grails をマスターする」にようこそ。2008年の最後の記事でお約束したとおり、新たな年は新たなアプリケーションで迎えるべく、Trip Planner に代わって新ブログ公開システムが登場します。
新しいアプリケーションには、Blogito という名前を付けました。これはスペイン語で「簡易的なブログ」を意味する一方、デカルトの Cogito ergo sum (我思う、故に我あり) に敬意を表した名前でもあります。アプリケーションの完成版は、blogito.org からダウンロードすることができます。今後数回の記事にわたって、このアプリケーションのコアとなる機能を段階的に構築していきます。
今回の記事で焦点とするのは、Grails アプリケーションのルック・アンド・フィールの大掛かりな変更です。昨年の連載で扱った Trip Planner のルック・アンド・フィールはフランケンシュタインの如くで、開発者にしか好まれないものでした (それというのも、アプリケーションの美しさよりも、コア機能が興味の対象だったからです)。今回は、CSS による多少の調整といくつかの部分テンプレートを散りばめて、そのままの Grails アプリケーションとはまったく違う外見の Web アプリケーションに仕上げます。この過程のなかで、scaffold 生成、自動タイムスタンプ設定、デフォルト・テンプレートの変更、カスタム TagLib の作成、Bootstrap.groovy や URLMapper.groovy といった重要な構成ファイルの調整など、Grails の機能についても簡単に復習していきます。
手順を始めるにあたり、まずは Grails 1.1 (この記事を作成している時点ではまだベータ版です) をインストールする必要があります。
Grails を実行する上では Java 1.5 または 1.6 を使用するのが最適です。コマンド・プロンプトで java -version と入力して、最新の Java バージョンを使用していることを確認してください。
Java 1.5 または 1.6 が使われていることを確認したら、以下のように、いつもながらの単純なステップで Grails をインストールすることができます。
- Grails サイトから grails.zip をダウンロードします。
- grails.zip を解凍します。
GRAILS_HOME環境変数を作成します。PATHに GRAILS_HOME/bin を追加します。
以前の Grails バージョンで作成されたアプリケーションについては、grails upgrade と入力すれば現行バージョンにマイグレーションできますが、Grails の複数のバージョンを使いたい場合にはどうすればよいでしょうか。
UNIX® ライクな OS (UNIX、Linux®、または OS X) を使用している場合、$GRAILS_HOME 環境変数の値をシンボリック・リンクに指定するだけで、簡単に Grails バージョンを切り替えることができます。私が使用しているシステムでは、GRAILS_HOME が /opt/grails を指しています。このように設定されていれば、リスト 1 に記載するような単純な ln -s によってリリース間を切り替えることができます。
リスト 1. UNIX、Linux、または Mac OS X での
$GRAILS_HOME のシンボリック・リンクの作成$ ln -s /opt/grails-1.1-beta1 grails $ ls -l | grep "grails" lrwxr-xr-x 1 sdavis admin 17 Dec 5 11:12 grails -> grails-1.1-beta1/ drwxr-xr-x 14 sdavis admin 476 Nov 10 2006 grails-0.3.1 drwxr-xr-x 16 sdavis admin 544 Feb 9 2007 grails-0.4.1 drwxr-xr-x 17 sdavis admin 578 Apr 6 2007 grails-0.4.2 drwxr-xr-x 17 sdavis admin 578 Jun 15 2007 grails-0.5 drwxr-xr-x 19 sdavis admin 646 Jul 30 2007 grails-0.5.6 drwxr-xr-x 18 sdavis admin 612 Sep 18 2007 grails-0.6 drwxr-xr-x 19 sdavis admin 646 Feb 19 2008 grails-1.0 drwxr-xr-x 18 sdavis admin 612 Apr 5 2008 grails-1.0.2 drwxr-xr-x 18 sdavis admin 612 Oct 9 21:46 grails-1.0.3 drwxr-xr-x 18 sdavis admin 612 Nov 24 20:43 grails-1.0.4 drwxr-xr-x 18 sdavis admin 612 Dec 5 11:13 grails-1.1-beta1 |
Windows® システムを使用している場合に最も確実な方法は、%GRAILS_HOME% 変数を直接変更することです。ただし変更した後は、既存のコマンド・プロンプトを忘れずに再起動してください。
grails -version と入力して、最新のリリースが使用されていること、そして GRAILS_HOME 変数が正しく設定されていることを確認します。このコマンドを実行すると、リスト 2 のような出力が表示されます。
リスト 2.
grails -version による出力$ grails -version Welcome to Grails 1.1-beta2 - http://grails.org/ Licensed under Apache Standard License 2.0 Grails home is set to: /opt/grails |
Grails 1.1 がインストールされたので、これで、新しいアプリケーションの作成に取り掛かれます。
grails create-app blogito と入力して、初期ディレクトリー構造の scaffold を生成します。新規 blogito ディレクトリーにカレント・ディレクトリーを変更し、grails create-domain-class Entry と入力します。これによって作成されたクラスが、ブログ・エントリーを表すことになります。grails-app/domain で Entry.groovy ファイルを探し、このファイルにリスト 3 のコードを追加します。
リスト 3.
Entry クラスの作成
class Entry {
static constraints = {
title()
summary(maxSize:1000)
dateCreated()
lastUpdated()
}
String title
String summary
Date dateCreated
Date lastUpdated
}
|
Entry のそれぞれに、title フィールドと summary フィールドがあります。maxSize 制約を 1,000 文字に設定すると、動的に scaffold として生成される HTML フォームには、単純なテキスト・フィールドの代わりに summary フィールドのテキスト域が用意されます。
dateCreated と lastUpdated は、Grails では魔法のようなフィールドの名前であることを思い出してください。この 2 つのフィールドを使えば、最新の Entry が常にリストの先頭に配置されるようにできるため、ブログ・アプリケーションには申し分のないタイムスタンプ・フィールドとなります。
ドメイン・クラスが準備できたら、次のステップとしてコントローラーを作成します。まず、grails create-controller Entry と入力します。grails-app/controllers/EntryController.groovy に、リスト 4 のコードを追加してください。
リスト 4.
EntryController の作成
class EntryController {
def scaffold = Entry
}
|
一見単純に見える def scaffold = Entry の行が、Grails に Entry クラスの残りのサポートの scaffold を生成するように指示します。この後すぐにわかりますが、生成されるエントリー・テーブルには、Entry クラスの各フィールド列に対応する列があります (それに加え、主キーに対応する ID フィールドと、オプティミスティック・ロック用のバージョン・フィールド)。さらに、平凡ながらも重要な CRUD (Create/Retrieve/Update/Delete) 機能すべてを提供する GSP (Groovy Server Page) の一式も生成されます。
grails run-app と入力して、Web ブラウザーで http://localhost:8080/blogito にアクセスしてください。EntryController、New Entry の順にクリックします。嬉しいことに、すべての Entry フィールドが作成フォームに表示されるはずです (図 1 を参照)。しかし同時に悪い知らせもあります。それは、ユーザーがこれらのタイムスタンプ・フィールドをあれこれ編集できるようになっていることです。この問題を解決するには、デフォルト・テンプレートを調整する必要があります。
図 1. Create Entry フォームの編集可能なタイムスタンプ・フィールド
問題の解決策としては、grails generate-views Entry と入力し、GSP ファイルから手動で dateCreated フィールドと lastUpdated フィールドを削除するという方法が考えられますが、それは症状を取り除くだけであって、問題を根本から解決することにはなりません。必要な対策は、この 2 つのフィールドが二度と作成フォームと編集フォームに表示されないようにすることです。そのための最善の方法は def scaffold の背後にあるテンプレートを変更することです。
grails install-templates と入力し、src/templates/scaffolding で create.gsp ファイルと edit.gsp ファイルを探します。この 2 つのファイルのそれぞれで、excludedProps に dateCreated と lastUpdated を追加します (リスト 5 を参照)。
リスト 5. list.gsp および show.gsp テンプレートでのタイムスタンプ・フィールドの除外
excludedProps = ['version',
'id',
'dateCreated',
'lastUpdated',
Events.ONLOAD_EVENT,
Events.BEFORE_DELETE_EVENT,
Events.BEFORE_INSERT_EVENT,
Events.BEFORE_UPDATE_EVENT]
|
Grails を再起動して、タイムスタンプ・フィールドが表示されないことを確認してください (図 2 を参照)。
図 2. タイムスタンプ・フィールドが除外されたフォーム
新しいエントリーを追加するとすぐに、テーブルが ID 順にソートされます (デフォルト)。ブログのエントリーは、通常、新しい順にソートされて最新のエントリーが先頭にリストされます。Grails の以前のバージョンでデフォルトのソート順を変更するということは、EntryController.groovy ファイルのリスト・クロージャーを手作業で編集することを意味します。既存の max 行の下に 2 つの新しいソート行を追加する作業は、特に面倒というわけではありません (リスト 6 を参照)。問題は、このコードが裏で動的に scaffold として生成されなくなることです (ベースとなるデフォルトの実装を確認するには、src/templates/scaffolding/Controller.groovy を調べるか、grails generate-controller Entry と入力してください)。
リスト 6. Grails 1.0.x でのソート
def list = {
if(!params.max) params.max = 10
if(!params.sort) params.sort = "lastUpdated"
if(!params.order) params.order = "desc"
[ entryList: Entry.list( params ) ]
}
|
Grails 1.1 では、単純ながらも非常に便利な機能を静的マッピング・ブロックに追加しています。それが、sort です。リスト 7 のマッピング・ブロックを Entry.groovy ファイルに追加してください。ドメイン・クラスでソートを操作することによって、引き続きコントローラーの def scaffold を実行することができます。
リスト 7.
static mapping ブロックへの sort の追加
class Entry {
static constraints = {
title()
summary(maxSize:1000)
dateCreated()
lastUpdated()
}
static mapping = {
sort "lastUpdated":"desc"
}
String title
String summary
Date dateCreated
Date lastUpdated
}
|
Grails を再起動して、編集後のエントリーが実際にリストの先頭に配置されることを確認してください (図 3 を参照)。
図 3. 新しいソート順の確認
Grails を再起動する度に、エントリーがなくなっていることにお気付きですか。思い出してください。これは 1 つの機能であって、バグではありません。エントリー・テーブルは Grails を起動する度に作成され、シャットダウンする度に破棄されます。これを確かめるには、grails-app/conf/DataSource.groovy を開いてください。開発モードの db-create の値は明らかに、create-drop に設定されているはずです。
この値を update に変更しても構いませんが、この設定は理想的とは言えません。開発プロセスの初期段階では、一般にスキーマはかなり流動的です。通常はフィールドの追加と削除、制約の変更などを繰り返すことになるため、すべてが落ち着くまでは、db-create をそのまま create-drop に設定しておくのが最善だと思います。
開発モードでサンプル・データを何度も入力し直す面倒を省くには、ちょっとしたロジックを grails-app/conf/BootStrap.groovy に追加します。リスト 8 は、Grails が起動する度に新しいレコードを挿入するコードです。
リスト 8. 開発モードでのダミー・レコードの追加
import grails.util.GrailsUtil
class BootStrap {
def init = { servletContext ->
switch(GrailsUtil.environment){
case "development":
new Entry(
title:"Grails 1.1 beta is out", summary:"Check out the new features").save()
new Entry(
title:"Just Released - Groovy 1.6 beta 2", summary:"It is looking good.").save()
break
case "production":
break
}
}
def destroy = {
}
}
|
Grails をもう一度再起動してください。今度は、レコードが入力された状態のエントリー・テーブルが表示されるはずです (図 4 を参照)。
図 4. 起動時に表示されるダミー・レコード
リスト・ビューに表示されるデフォルトの HTML テーブルは手始めとしては十分なものですが、Blogito の場合に長期的なソリューションにならないのは明らかです。一般に、ブログ・ページの日付、タイトル、要約フィールドは横に並べられるのではなく、エントリーごとに縦に表示されます。
このように変更するには、まず grails generate-views Entry と入力します。以前は動的に scaffold として生成されていた GSP ファイルが grails-app/views/entry にあるはずです。list.gsp をテキスト・エディターで開いて、ヘッダーのタイトルを Entry List から Blogito に変更します。<h1> と <g:if> のブロックを削除し、既存の <div class="list"> をリスト 9 のコードに置き換えます。
リスト 9. list.gsp ビューの変更
<div class="list">
<g:each in="${entryInstanceList}" status="i" var="entryInstance">
<div class="entry">
<span class="entry-date">${entryInstance.lastUpdated}</span>
<h2><g:link action="show" id="${entryInstance.id}">${entryInstance.title}</g:link></h2>
<p>${entryInstance.summary}</p>
</div>
</g:each>
</div>
|
コードが大幅に単純になっていることに注目してください。<fieldValue> タグは削除して構いません。このタグは、ドメイン・クラス・フィールドを HTML フォームのフィールドにバインドするのに役立ちますが、ここでは実際の値を追加するわけではないからです。各 Entry はクラスが指定された <div> にラップし、lastUpdated フィールドはクラスが指定された <span> にラップします。クラス属性が提供するのは、この後取り掛かる CSS フォーマット設定のフックです。title フィールドと summary フィールドは、昔ながらの簡素な HTML タグである <h> タグと <p> タグにラップします。
ブラウザーでリスト・ビューを最新の表示にしてください (図 5 を参照)。この時点ではまだ改善されているとは言い難い外観ですが、いくつかの新しい CSS 命令を追加することによって、外観は見違えるほど良くなります。
図 5. CSS を使用していない新しいリスト
リスト 10 の CSS を web-app/css/main.css の末尾に追加します。
リスト 10. CSS による list.gsp ビューのカスタマイズ
/* Blogito customizations */
.entry {
padding-bottom: 2em;
}
.entry-date {
color: #999;
}
|
もう一度 Web ブラウザーを最新の表示にすると、多少見栄えが良くなっているはずです (図 6 を参照)。CSS での作業はこれで終わったわけではありませんが、最初の作業としては良い出来栄えと言えます。
図 6. CSS を使用した新しいリスト
ここで、lastUpdated の日付がもっとユーザー・フレンドリーに表示されるように手を加えます。再利用可能なコードのスニペットを配置するのに最適な場所は、カスタム TagLib です。grails create-tag-lib Date と入力して、リスト 11 のコードを grails-app/taglib/DateTagLib.groovy ファイルに追加してください。
リスト 11.
DateTagLib のコード
import java.text.SimpleDateFormat
class DateTagLib {
def longDate = {attrs, body ->
//parse the incoming date
def b = attrs.body ?: body()
def d = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(b)
//if no format attribute is supplied, use this
def pattern = attrs["format"] ?: "EEEE, MMM d, yyyy"
out << new SimpleDateFormat(pattern).format(d)
}
}
|
今度は grails-app/views/entry/list.gsp ファイルで、lastUpdated フィールドを新しく作成した <g:longDate> タグにラップします (リスト 12 を参照)。
リスト 12. list.gsp での
<g:longDate> タグの使用
<div class="entry">
<span class="entry-date"><g:longDate>${entryInstance.lastUpdated}</g:longDate></span>
<h2>${entryInstance.title}</h2>
<p>${entryInstance.summary}</p>
</div>
|
Grails を再起動して Web ブラウザーを最新の表示にすると、図 7 に示すフォーマット設定しなおされた日付が表示されます。
図 7. カスタム
<g:longDate> タグを使用して新しくフォーマット設定された日付
レイアウトの見栄えはかなり上出来です。そこで、このレイアウトを show.gsp にも使用することにします。grails-app/views/entry に _entry.gsp ファイルを作成して、リスト 13 のコードを追加してください (もちろん、list.gsp のコードをカット・アンド・ペーストするだけでも構いません)。
リスト 13. _entry.gsp のコード
<div class="entry">
<span class="entry-date"><g:longDate>${entryInstance.lastUpdated}</g:longDate></span>
<h2><g:link action="show" id="${entryInstance.id}">${entryInstance.title}</g:link></h2>
<p>${entryInstance.summary}</p>
</div>
|
新しく作成した部分テンプレートを使用するには、list.gsp をリスト 14 のように調整します。
リスト 14. list.gsp での _entry.gsp 部分テンプレートの使用
<div class="list">
<g:each in="${entryInstanceList}" status="i" var="entryInstance">
<g:render template="entry" bean="${entryInstance}" var="entryInstance" />
</g:each>
</div>
|
これで、部分テンプレートを show.gsp でも使用することができます (リスト 15 を参照)。
リスト 15. show.gsp での _entry.gsp 部分テンプレートの使用
<div class="body">
<g:render template="entry" bean="${entryInstance}" var="entryInstance" />
<div class="buttons">
<!-- snip -->
</div>
</div>
|
ブラウザーでリスト・ビューを最新の表示にすると、前とまったく同じように表示されるはずです。任意のエントリーのタイトルをクリックして、表示ビューでも日付のフォーマット設定が機能することを確認してください。
全体的に、いい感じにまとまってきました。ここで、Grails のブランドを独自のブランドに置き換えます。
list.gsp または show.gsp で Grails ロゴが参照されている箇所は見当たりません。これは、Grails は SiteMesh を使用して、各種パーツを 1 つのページに組み立てるためです。grails-app/views/layouts/main.gsp を調べると、grails_logo.jpg ファイルがどこで組み込まれているかがわかります。
grails-app/views/layouts に、_header.gsp という名前の別の部分テンプレートを作成して、リスト 16 のコードを追加します。Blogito はメイン・ページに戻るハイパーリングであることに注意してください。
リスト 16. _header.gsp 部分テンプレートのコード
<div id="header"> <p><g:link class="header-main" controller="entry">Blogito</g:link></p> <p class="header-sub">A tiny little blog</p> </div> |
次に、リスト 17 に示すように main.gsp を編集して _header.gsp ファイルをインクルードします。
リスト 17. main.gsp での新しい _header.gsp 部分テンプレートの使用
<body>
<div id="spinner" class="spinner" style="display:none;">
<img src="${createLinkTo(dir:'images',file:'spinner.gif')}" alt="Spinner" />
</div>
<g:render template="/layouts/header"/>
<g:layoutBody />
</body>
|
最後の仕上げとして、リスト 18 のコードを web-app/css/main.css に追加します。
リスト 18. _header.gsp 部分テンプレートの CSS フォーマット
#header {
background: #67c;
padding: 2em 1em 2em 1em;
margin-bottom: 1em;
}
a.header-main:link, a.header-main:visited {
color: #fff;
font-size: 3em;
font-weight: bold;
}
.header-sub {
color: #fff;
font-size: 1.25em;
font-style: italic;
}
|
ブラウザーを最新の表示にして変更を確認してください (図 8 を参照)。任意のエントリーのタイトルをクリックした後、ヘッダーの Blogito をクリックするとメイン・ページが再表示されます。
図 8. 新しいヘッダーのお披露目
ログインしている場合にのみナビゲーション・バーを表示させる方法
これが Grails アプリケーションであることを示すもう 1 つの目印にも対処する必要があります。この目印とは、ナビゲーション・バーのことです。認証は次回の記事まで実装しませんが、認証されれいないユーザーに対して今の段階でナビゲーション・バーを非表示にするには、単純な <g:if> テストに <div> をラップします。このテストでは、セッション・スコープに保管された user 変数を調べます。
list.gsp と show.gsp の両方をリスト 19 のように変更してください。
リスト 19. ログインしている場合にのみナビゲーション・バーを表示させる方法
<g:if test="${session.user}">
<div class="nav">
<span class="menuButton">
<a class="home" href="${createLinkTo(dir:'')}">Home</a>
</span>
<span class="menuButton">
<g:link class="create" action="create">New Entry</g:link>
</span>
</div>
</g:if>
|
show.gsp では、同じテストでボタンの <div> を囲みます (最も避けなければならないのは、認証されていないユーザーがブログ・エントリーを編集したり、削除したりすることだからです)。
list.gsp に対しては、もう 1 つ見栄えを良くするための調整を加えます。そのために、paginateButtons <div> を body <div> の外側に移動します (リスト 20 を参照)。こうすることによって、バーが画面の端から端まで伸びるため、画面の下部に見栄えの良い視覚的アンカーが追加されることになります。
リスト 20. 見栄えを良くするために
body <div> の外側に移動した paginateButtons <div>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="layout" content="main" />
<title>Blogito</title>
</head>
<body>
<g:if test="${session.user}">
<div class="nav">
<span class="menuButton">
<a class="home" href="${createLinkTo(dir:'')}">Home</a>
</span>
<span class="menuButton">
<g:link class="create" action="create">New Entry</g:link>
</span>
</div>
</g:if>
<div class="body">
<div class="list">
<g:each in="${entryInstanceList}" status="i" var="entryInstance">
<g:render template="entry" bean="${entryInstance}" var="entryInstance" />
</g:each>
</div>
</div>
<div class="paginateButtons">
<g:paginate total="${Entry.count()}" />
</div>
</body>
</html>
|
paginateButtons <div> が body <div> の隣ではなく、その下に確実に表示されるようにするため、さらにリスト 21 の CSS を追加します。
リスト 21.
paginateButtons <div> が画面下部に確実に表示されるようにするための CSS
.paginateButtons{
clear: left;
}
|
最後にもう 1 度、ブラウザーを最新の表示にしてください。画面は図 9 のようになっているはずです。
図 9. 非表示にされたナビゲーション・バー
これですべて準備万端に整ったので、EntryController をデフォルト・ホーム・ページに設定します。それには、/ (URL http://localhost:9090/blogito/ の末尾のスラッシュ) を EntryController にリダイレクトするマッピングを追加します。grails-app/conf/UrlMappings.groovy をリスト 22 と同じになるように編集してください。
リスト 22.
EntryController をデフォルト・ホーム・ページに設定する方法
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
"/"(controller:"entry")
"500"(view:'/error')
}
}
|
今回の記事で目的としたのは、Grails アプリケーションの見栄えを良くする方法を紹介することです。数行の CSS を追加することで、色、フォント、ブロック要素周囲のスペースなどを変更することができます。また、部分テンプレートと TagLib によって、再利用可能なコード・スニペットを作成することもできます。その結果として出来上がるのは、Grails フレームワークのすべての利点が生かされた、独特なルック・アンド・フィールを持つアプリケーションです。
次回の記事でも引き続き Blogito アプリケーションに肉付けするため、User ドメイン・クラスを追加して複数のユーザーがブログ・エントリーを追加できるようにします。さらに、Grails のコーデックの詳細を探り、カスタム URL マッピングも操作します。完成版のアプリケーションは、http://blogito.org からダウンロードできることをお忘れなく。それでは、次回の記事まで Grails を楽しみながらマスターしてください。
学ぶために
- 連載「Grails をマスターする」: この連載の他の記事を読んで、Grails とこのフレームワークを使って実現可能なすべての内容をよく理解してください。
- Grails: Grails の Web サイトにアクセスしてください。
- Grails Framework Reference Documentation: Grails のバイブルとなります。
- 「Design Web pages with class」(Molly Holzschlag 著、developerWorks、1999年9月): スタイル・シートのクラスを使用することで、HTML 文書を素早く設計 (または再設計) する 2 通りの方法を調べてください。
- Care With Font Size: W3C Quality Assurance シリーズで紹介しているフォント・サイズについてのヒントを読んでください。
- Box Model: CSS での
paddingとmarginについて詳しく学んでください。 - 『Groovy Recipes』(Scott Davis 著、Pragmatic Programmers、2007年): Scott Davis の最新の著作で Groovy と Grails の詳細を学んでください。
- 連載「実用的な Groovy」: developerWorks のこの連載記事では、実用的な Groovy の使用方法を探り、それぞれの方法をいつ、どんな場合に適用するかを解説しています。
- Groovy: Groovy の Web サイトで、このプロジェクトの詳細を学んでください。
- AboutGroovy.com: Groovy に関する最新のニュースと記事へのリンクが記載されています。
- technology bookstore: この記事で紹介した技術やその他の技術に関する本を参照してください。
- developerWorks Java technology ゾーン: Java プログラミングのあらゆる側面を網羅した記事が豊富に用意されています。
製品や技術を入手するために
- Grails: Grails の最新リリースをダウンロードしてください。
議論するために
- developerWorks blogs から developerWorks コミュニティーに加わってください。

Scott Davis は国際的に知られた著者、講演者、そしてソフトウェア開発者で、Groovy と Grails の教育を目的とした会社、ThirstyHead.com の創設者でもあります。彼の著書には、『Groovy Recipes: Greasing the Wheels of Java』、『GIS for Web Developers: Adding Where to Your Application』、『The Google Maps API』、『JBoss At Work』などがあります。現在、IBM developerWorks の「Grails をマスターする」と「実用的な Groovy」の 2 本の連載を執筆中です。