[Introduction to Decorators] Jetspeedデコレーターへの導入

Decorators are defined as any static or semi-static markup surrounding a dynamically generated Fragment. Decorators are usually written with either Velocity or JSP templates. This guide will focus primarily on using the Velocity scripting language to build decoration. However, most of the standards and approaches described here can be applied to writing decroations in other scripting languages.

デコレーターとは 動的に作成されるフラグメント(画面の一部分)の周りを囲むもので 静的もしくは、半静的な マークアップランゲージで記述できるものと 定義されます。デコレーターは、 通常 Velocityテンプレートもしくは、JSPテンプレートとして書かれます。このガイドでは、主に Velocity スクリプト言語で デコレーターを作成する方法について書きます。しかし、ここに書かれる 標準的な方法とアプローチ手段は、大体の所、 他のスクリプト言語で、デコレーションを作成する際にも応用可能です。

There are two different types of decorations that are used when building a page; Portlet and Layout (or page).

Portlet decorations are the "window dressings" of Jetspeed. They wrap each indivual portlet fragment's rendered content with HTML (XHTML, VXML, etc). Portlet decoration's are responsible for displaying the appropriate title and any buttons associated with changing window states or portlet modes.

Layout or Page decorations responsible for providind a "header" area and "footer" area for a single portal page which is represented by a .psml document (see: Documentation for Designers working with PSML for more information on psml). They also provide general style information for the page and portlets. However, portlet level style settings can be overidden at the portlet decoration level.


ポートレットのデコレーションとは Jetspeed のウインドウの装飾にあたります。これは、個々のポートレットフラグメントの HTML (XHTML, VXML, etc) で表示されるコンテンツ部分を囲むもので、適切なタイトルの表示や、ウインドウの状態やポートレットのモードの変化と連携して変わるボタン群の表示を担当します。

レイアウトもしくはページのデコレーションとは、1つPSMLファイルを元に表される1つのポータルページの ヘッダー部分とフッター部分の装飾を提供するものです (参考: PSMLについての更なる情報については、PSMLを扱ってデザインをする人のための資料) 。これらのデコレーションは、ページとポートレットの一般的なスタイル情報を持ちます。ポートレット内部のスタイル情報は、デコレーターのスタイル情報によって上書きされます。

[Decoration File Structure] デコレーションのファイル構成

All decorations are stored in a directory directly off of the web applications root called decrorations. The two primary directories under the here are layout for layout decorations and portlet for portlet decorations. Individual decoartions are housed in thier own directories underneath these two directories. The name of the directory you create for under either layout or portlet is how Jetspeed will locate your decoration. We will go into further detail on how this works later on in this guide.

全てのデコレーション用のファイルは、webアプリケーションのルートディレクトリの直下にあるdecorationsというディレクトリに保存されます。このディレクトリの下の 重要な2つのディレクトリが、レイアウト装飾用のlayoutディレクトリとポートレット装飾用のportletディレクトリです。個別のデコレーションは、これら2つのディレクトリの下に、それぞれ独自のディレクトリを持ちます。Jetspeedは、layoutportlet の下に あなたが に作成するディレクトリの名称で、デコレーターファイルの場所を特定します。では、これが どういう仕組みで働くかについての 更なる詳細をこのガイドの続き で見ていきましょう。

[Anatomy of a Layout(Page) Decoration] レイアウト(ページ) デコレーションの詳細

[Four Files in a Nutshell] 一言でいうと 4つのファイル

In it's most basic form a Layout Decroation only requires you to define four files:

もっとも基本的な形で レイアウトのデコレーションをするのであれば、4つのファイルを定義するだけです。:

  • decorator.properties
  • styles.css
  • header.vm
  • footer.vm

Three of these files; decorator.properties, header.vm, and footer.vm go directly into the directory you create under /decorations/layout. The styles.css needs to be put into a subdirectory of your decoration names css/.

この中の3つのファイル;decorator.properties, header.vm, と footer.vm は、/decorations/layoutの下に作成したディレクトリに直接置いてください。styles.css は、あなた作ったデコレーションのサブディレクトリ css/ に入れます。[訳注:すなわち/YOUR_WEB_APP/decorations/layout/YOUR_DECORATION_NAME/cssディレクトリにスタイルシートを置く。]

[Basic Layout Decoration Configuration: decorator.properties] レイアウト デコレーションの基本設定: decorator.properties

The decorator.properties file holds basic information about your layout decoration. In all actuallity, this file can be blank, but we still require that it be present as it is used by other APIs to "discover" available decorations. With that being said, it is safe to assume that all the properties defined below are optional.

decorator.properties ファイルは、あなたのレイアウト デコレーションの基本情報を保持します。実際のところ、このファイルは 空白でも構いませんが、他のAPIが使用可能なデコレーションを探すのに使用されるためファイル自体は存在する必要があります。ということで、下の定義にあるプロパティは 全てオプションであると仮定しても問題ありません。

Property NameDescriptionDefault
base.css.class This value is generally placed in the top most element tag of your header template. You will see how it is used when we go into development of a header template. Defaults to the name of your decoration
stylesheet Relative path to your decoration's stylesheet css/styles.css
header Relative path to your decoration's header template header.vm
footer Relative path to your decoration's footer template footer.vm
Property NameDescriptionDefault
base.css.class この値は、一般的に ヘッダーのテンプレートファイルの一番上の要素タグの中に 配置されます。ヘッダーテンプレート作成の説明のところで、この使用方法を 見ることになります。 あなたのデコレーション名がデフォルト値となります。
stylesheet デコレーションのスタイルシートへの相対パス css/styles.css
header デコレーションのヘッダーテンプレートへの相対パス header.vm
footer デコレーションのフッターテンプレートへの相対パス footer.vm

[Top o' the Page to ya: header.vm] 自分専用のページトップ: header.vm

The header.vm represnts the top portion of your portal page. Below is a section by section walkthrough of the basics required to write a functional header template.

NOTICE: It is assumed that the reader is proficient in both the use of HTML and CSS. A rudimentary knowledge of Velocity helps but is not required to develop a decoration.

ファイルheader.vmは、あなたのポータルページのトップ部分を表します。機能的なヘッダーテンプレートを記述すのに必要になる基本事項について 以下に 各セクションごとに 書いてあります。



The first two lines should be obvious, if they are not, this guide from here on out will not be much help to you ;-)

上の最初の2行の意味は明らかでしょう、もし そうでない場合は、これ以降の内容は あまり あなたの助けにならないでしょう。^^)

[Our First Macro: #defineLayoutObjects()] 最初のマクロ: #defineLayoutObjects()

Now the line containing #defineLayoutObjects() will not be as obvious in its purpose as the previous two. #defineLayoutObjects() is what is known, in Velocity vernacular, as a macro. A macro is a predefined snippet of Velocity code that can be reused within any Velocity template. All of the global macros we will be using (including this one) are defined within the WEB-INF/jetspeed_macros.vm. Later in this guide we will discuss supplying your own, custom macros for assisting you in your decoration development, if you choose to. Now, back to the #defineLayoutObjects(). #defineLayoutObjects() adds values to Velocity that will be accessible within header.vm, footer.vm, other macros and all of your portlet decoration templates. We could easily stop here regarding #defineLayoutObjects(), however, I feel it can be helpful to have some insights into the inner workings of Velocity for the uninitiated. With out further ado, the code:

さて、#defineLayoutObjects()を含む行ですが、これは、前の2行ほどは その目的について意味が あまり明らかではありません。#defineLayoutObjects()は、いわゆる Velocityの世界で マクロと 言われるものです。マクロは、事前に定義された Velocityの小さなコードで、Velocityテンプレートの中で再利用されます。これから使用する全てのグローバル マクロ(このマクロも含む)は、WEB-INF/jetspeed_macros.vmで定義されています。後ほど、 このガイドの中で、もし あなたが そうしたいのであれば、自分のデコレーションを作成するにあたって便利であるカスタムマクロの作成方法について議論します。では、#defineLayoutObjects()にもどりましょう。#defineLayoutObjects()は、様々な値をVelocityに対して追加し、それらは、header.vm, footer.vm,他のマクロと そして全てのポートレット デコレーション テンプレートの内部でアクセス可能になります。ここで、#defineLayoutObjects()に関する話を 簡単にやめることはできますが、Velocityをまだはじめたことがない人のために Velocityの内部の動きを見ていく方が 助けになる気がします。では 余計な事をいうのはこれくらいにして、コードは、こうなっています。

  #macro (defineLayoutObjects)
    #set($preferedLocale = $JS2RequestContext.locale)
    #set($rootFragment = $jetspeed.currentFragment)
    #set($site = $request.getAttribute("org.apache.jetspeed.portalsite.PortalSiteRequestContext"))
    #set($theme = $request.getAttribute("org.apache.jetspeed.theme"))
    #set($layoutDecoration = $theme.getDecoration($rootFragment))

Hmm. What is actually happening here. Okay first off we have, #set(), this is what is known as a directive in Velocity. A directive is built-in functionallity and not a macro. #set() is pretty straight forward in that it takes the value on the right of the = and assigns it to the left. Cool, that seems fairly straight forward. But how does one work with these values and where the heck did $JS2RequestContext.locale come from? I guess i should take a quick step back and describe how we work with objects in Velocity. All objects available to a Velocity template can be referenced via the $someObject notation. Knowing that much invoking a method , let's getFoo(), can be done just like this $someObject.getFoo(). Even cooler is the fact we can short-hand getter methods that don't take any arguments like this, $someObject.foo. As for this $JS2RequestContext this is actually an instance of the org.apache.jetspeed.RequestContext that has been availble to Velocity by Jetspeed itself. So, by looking the javadoc for org.apache.jetspeed.RequestContext we see $JS2RequestContext.locale will give us an instance of java.util.Locale that reperesnts the locale of the current user. Couldn't be much simpler than that could it?

Next up we have this line #set($rootFragment = $jetspeed.currentFragment) another set() statement, this time creating an object called $rootFragment which is an instance of org.apache.jetspeed.om.page.ContentFragment. It is really not relevant to this guide to describe what $jetspeed.currentFragment is doing so I am going to skip that and move on.

むむ、この中ではいったい何がおきているのでしょうか?さて、1行目には、#set()があります。これは Velocityで指示子と呼ばれるものです。指示子は オリジナルの関数であり マクロではありません。#set()は、非常にわかりやすいですね。イコール記号の 右辺にある値を 受け取り 左辺へ 割り当てるものです。素晴らしい、これは、かなりわかりやすいですね。しかし、どうやってこの値を取り扱えばいいのでしょうか?いったい$JS2RequestContext.localeは、どこから現れたのでしょう?では、すこしだけ戻って、Velocityのオブジェクトをどうやって使うか書きたいと思います。全てのVelocityテンプレートで利用可能なオブジェクトは、$someObjectという書き方で参照することができます。メソッドの実行は、$someObject.getFoo() の様に書くことで 実行できます。getFoo()を実行してみましょう。実にすばらしいことに、引数を取らないgetterメソッドは、$someObject.fooという風に書けます。この$JS2RequestContextに関していうと、これは、org.apache.jetspeed.RequestContext のインスタンスでVelocityで使用できるように、、Jetspeedによってインスタンス化されます。そして、org.apache.jetspeed.RequestContextの Javadoc を見るとわかりますが、$JS2RequestContext.localeは、現在のポートレットのユーザのロケールとなる、java.util.Localeのインスタンスを渡してくれます。これ以上は シンプルにはできないでしょう?

次に 出てくるのは、#set($rootFragment = $jetspeed.currentFragment) という別の set の行ですね。今回は、$rootFragment と呼ばれるものを作成していすね。これは、org.apache.jetspeed.om.page.ContentFragment のインスタンスです。$jetspeed.currentFragmentが何をするのかは、このガイドでは、重要ではないので、飛ばして 先に進みます。

#set($site = $request.getAttribute("org.apache.jetspeed.portalsite.PortalSiteRequestContext"))

#set($theme = $request.getAttribute("org.apache.jetspeed.theme"))

Ah $request, now that looks familiar, this is actually an instance of javax.servlet.http.HttpServletRequest from which we are retreiving objects that were been placed into Velocity by Jetspeed. The actual objects are: org.apache.jetspeed.portalsite.PortalSiteRequestContext and org.apache.jetspeed.decoration.Theme respectively. We will put all of these objects to good use in just a little while.

おお、$requestです。やっと親しみのあるものが出てきました。これは、実際にjavax.servlet.http.HttpServletRequestのインスタンスで、我々はここから Jetspeedから Velocityに 渡された オブジェクトを取り出します。本当のオブジェクトは、それぞれ org.apache.jetspeed.portalsite.PortalSiteRequestContextorg.apache.jetspeed.decoration.Theme です。もうちょっと後で これら全てのオブジェクトのよい利用方法を見ていきます。

[Feed Your HEAD: How to Properly Code Your Head Tag.] ヘッダーを作る:ヘッダータグの適切なコーディング方法

This section provides you with all the information to prperly code the <HEAD> of your Layout decroation. So, straight to the code.

このセクションでは、レイアウトデコレーションの<HEAD>タグを適切にコーディングするための情報を書きます。では、さっそく コードを見てみましょう。

     <base href="#BaseHref()">
     <meta http-equiv="Content-type" content="#ContentType()" />
     <meta http-equiv="Content-style-type" content="text/css" />   
     <meta name="description" content="#PageDescription()" />
[The <base> Tag] <base>タグ

First off we have <base href="#BaseHref()"> which allows us to define the base path for resolution of web resources, for an in depth discussion of the <base> see: W3C Schools Reference. If you have spent any time playing with Jetspeed, you will have noticed it does all sorts of crazy URL rewriting that will totally hose any attempts to consistently path you html and styles sheets. By defining the BASE tag, this probelms will all but disappear. As for the #BaseHref() macro, it simply generates a fully qualified path to your web application's root. The actual code, interms of the servlet api is synonimous with this:

最初に、 <base href="#BaseHref()">から始めましょう。これは、WEBのリソースの場所の解決をするためのベースを定義する際に使用します。 <base>についての深い議論については、W3C Schools Referenceを見てください。もしすでにあなたが Jetspeed で遊んだ経験があるのであれば、一貫した html やスタイルシートへのパスを取得するのを妨げる、幾通りもの非常にややこしい URL リライトの問題に気づくでしょう。BASEタグを定義することにより、この問題は全て解決されます。#BaseHref()マクロに関していうと、これは、単に あなたのWEBアプリケーションのルートディレクトリへの絶対パスを作成します。実際のコードは、サーブレットAPIを使って記述するとこうなります。:

HttpServletRequest request;
StingBuffer baseHref = new StringBuffer(request.getScheme())
return baseHref.toString();		 

The actual Velocity macro code is a bit more terse ;)

Velocityマクロのコードは もう少し簡潔になります。^^)

[Meta Tag: <meta http-equiv="Content-type" content="#ContentType()" />] メタタグ: <meta http-equiv="Content-type" content="#ContentType()" />

Will return text/html plus the proper encoding, such as UTF.

は  text/htmlと、UTFの様な適切なエンコードの種類を返します。


At the time of the writing of this guide there is really very little javascript required to for the base Jetspeed 2 server to run. However this may change in near future as we try to employ the use of AJAX in things such as configuration and administration.

  このガイドを書いている今の時点では、オリジナルのJetspeed 2サーバを実行させるためには、ほとんど Java Scriptを書く必要はありません。しかし、今後、設定機能や管理機能でAJAXを利用しようと考えているので近い将来変わるかもしれません。