View Javadoc

1   /*
2    * Copyright 2004-2008 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.seasar.uruma.core;
17  
18  import org.eclipse.jface.viewers.ContentViewer;
19  import org.eclipse.jface.viewers.IBaseLabelProvider;
20  import org.eclipse.jface.viewers.IContentProvider;
21  import org.eclipse.jface.viewers.ILabelProvider;
22  import org.eclipse.jface.viewers.StructuredViewer;
23  import org.eclipse.jface.viewers.ViewerComparator;
24  import org.seasar.framework.beans.BeanDesc;
25  import org.seasar.framework.beans.PropertyDesc;
26  import org.seasar.framework.container.ComponentDef;
27  import org.seasar.framework.container.S2Container;
28  import org.seasar.framework.util.StringUtil;
29  import org.seasar.uruma.annotation.Form;
30  import org.seasar.uruma.binding.context.ApplicationContextBinder;
31  import org.seasar.uruma.binding.widget.WidgetBinder;
32  import org.seasar.uruma.context.PartContext;
33  import org.seasar.uruma.context.WindowContext;
34  import org.seasar.uruma.desc.FormDesc;
35  import org.seasar.uruma.desc.FormDescFactory;
36  import org.seasar.uruma.desc.PartActionDesc;
37  import org.seasar.uruma.desc.PartActionDescFactory;
38  import org.seasar.uruma.exception.RenderException;
39  import org.seasar.uruma.log.UrumaLogger;
40  import org.seasar.uruma.util.AssertionUtil;
41  import org.seasar.uruma.util.ClassUtil;
42  import org.seasar.uruma.util.S2ContainerUtil;
43  import org.seasar.uruma.viewer.PojoLabelProvider;
44  
45  /**
46   * パートアクションクラスに関するユーティリティクラスです。<br />
47   * 
48   * @author y-komori
49   */
50  public class ComponentUtil implements UrumaConstants, UrumaMessageCodes {
51      private static final UrumaLogger logger = UrumaLogger
52              .getLogger(ComponentUtil.class);
53  
54      private static S2Container defaultContainer;
55  
56      private ComponentUtil() {
57      }
58  
59      /**
60       * 各種コンポーネントを検索する際の {@link S2Container} を設定します。<br />
61       * 本クラスの他のメソッドを使用する前に呼び出してください。<br />
62       * 
63       * @param container
64       *            {@link S2Container} オブジェクト
65       */
66      public static void setS2Container(final S2Container container) {
67          AssertionUtil.assertNotNull("container", container);
68  
69          defaultContainer = container;
70      }
71  
72      /**
73       * ワークベンチアクションクラスを準備します。<br />
74       * 
75       * @param context
76       *            {@link WindowContext} オブジェクト
77       * @return ワークベンチアクションクラスが見つかった場合、そのオブジェクト。<br />
78       *         見つからなかった場合は <code>null</code>
79       */
80      public static Object setupWorkbenchAction(final WindowContext context,
81              final String id) {
82          String actionComponentName = StringUtil.decapitalize(id)
83                  + PART_ACTION_SUFFIX;
84  
85          ComponentDef cd = S2ContainerUtil
86                  .getComponentDefNoException(actionComponentName);
87  
88          Object workbenchActionComponent = S2ContainerUtil
89                  .getComponentNoException(actionComponentName, defaultContainer);
90          if (workbenchActionComponent != null) {
91              S2ContainerUtil.injectDependency(workbenchActionComponent,
92                      defaultContainer);
93  
94              context.setPartActionObject(workbenchActionComponent);
95              PartActionDesc desc = PartActionDescFactory.getPartActionDesc(cd
96                      .getComponentClass());
97              context.setPartActionDesc(desc);
98  
99              logger.log(WORKBENCH_ACTION_CLASS_FOUND, id, actionComponentName,
100                     workbenchActionComponent.getClass().getName());
101 
102             return workbenchActionComponent;
103         } else {
104             logger.log(WORKBENCH_ACTION_CLASS_NOT_FOUND, id,
105                     actionComponentName);
106             return null;
107         }
108     }
109 
110     /**
111      * パートアクションクラスを準備します。<br />
112      * 
113      * @param context
114      *            {@link PartContext} オブジェクト
115      * @param id
116      *            対応するパートの ID
117      * @param container
118      *            各種コンポーネントを検索する {@link S2Container}
119      * @return パートアクションクラスが見つかった場合、そのオブジェクト。<br />
120      *         見つからなかった場合は <code>null</code>
121      */
122     public static Object setupPartAction(final PartContext context,
123             final String id, final S2Container container) {
124         String actionComponentName = StringUtil.decapitalize(id)
125                 + PART_ACTION_SUFFIX;
126 
127         ComponentDef cd = S2ContainerUtil
128                 .getComponentDefNoException(actionComponentName);
129 
130         Object partActionComponent = null;
131         if (cd != null) {
132             // ComponentDef が持つコンテナは生成時のものなので、
133             // その範囲でしかDIできない。そんため、コンテナをセットし直す。
134             cd.setContainer(container);
135             partActionComponent = cd.getComponent();
136 
137             S2ContainerUtil.injectDependency(partActionComponent, container);
138 
139             context.setPartActionObject(partActionComponent);
140             PartActionDesc desc = PartActionDescFactory.getPartActionDesc(cd
141                     .getComponentClass());
142             context.setPartActionDesc(desc);
143 
144             logger.log(PART_ACTION_CLASS_FOUND, id, actionComponentName,
145                     partActionComponent.getClass().getName());
146 
147             return partActionComponent;
148         } else {
149             logger.log(PART_ACTION_CLASS_NOT_FOUND, id, actionComponentName);
150             return null;
151         }
152     }
153 
154     /**
155      * パートアクションクラスを準備します。<br />
156      * 
157      * @param context
158      *            {@link PartContext} オブジェクト
159      * @param id
160      *            対応するパートの ID
161      * @return パートアクションクラスが見つかった場合、そのオブジェクト。<br />
162      *         見つからなかった場合は <code>null</code>
163      */
164     public static Object setupPartAction(final PartContext context,
165             final String id) {
166         return setupPartAction(context, id, defaultContainer);
167     }
168 
169     /**
170      * フォームクラスを準備します。<br />
171      * <dt>アクションクラスに {@link Form} アノテーションが指定されている場合</dt>
172      * <dd> {@link Form} アノテーションで指定されたクラスをフォームオブジェクトとして読み込みます。<br />
173      * (フォームオブジェクトはS2コンポーネントとして登録されている必要があります)</dd>
174      * <dt>アクションクラスに {@link Form} アノテーションが指定されていない場合</dt>
175      * <dd>S2コンテナに <i>アクションコンポーネント名</i> + <b>Form</b>
176      * という名前のコンポーネントが登録されていれば、そのコンポーネントをフォームオブジェクトとして読み込みます。<br />
177      * 規約に一致する名前のコンポーネントが存在しない場合は、アクションオブジェクトをフォームオブジェクトとして認識します。</dd>
178      * また、パートアクションクラスにフォームクラスのプロパティが存在する場合、 そのプロパティにフォームオブジェクトをインジェクションします。<br />
179      * 
180      * @param context
181      *            {@link PartContext} オブジェクト
182      * @param id
183      *            対応するパートの ID
184      * @return フォームクラスが見つかった場合、そのオブジェクト。<br />
185      *         見つからなかった場合は <code>null</code>
186      */
187     public static Object setupFormComponent(final PartContext context,
188             final String id) {
189         Object formObject = null;
190         FormDesc formDesc = null;
191         Class<?> formClass = null;
192         Object actionObject = context.getPartActionObject();
193         if (actionObject != null) {
194             Form formAnnotation = context.getPartActionDesc()
195                     .getPartActionClass().getAnnotation(Form.class);
196             // @Form アノテーションが指定されている場合
197             if (formAnnotation != null) {
198                 formClass = formAnnotation.value();
199                 if (formClass == actionObject.getClass()) {
200                     formObject = actionObject;
201                 } else {
202                     formObject = S2ContainerUtil.getComponent(formClass,
203                             defaultContainer);
204                 }
205             }
206 
207             // @Form アノテーション未指定の場合
208             if (formObject == null) {
209                 String formComponentName = StringUtil.decapitalize(id)
210                         + FORM_SUFFIX;
211                 formObject = S2ContainerUtil.getComponentNoException(
212                         formComponentName, defaultContainer);
213                 if (formObject != null) {
214                     // フォームオブジェクトがS2コンテナに見つかった場合
215                     ComponentDef cd = S2ContainerUtil
216                             .getComponentDef(formComponentName);
217                     formClass = cd.getComponentClass();
218                 } else {
219                     // フォームオブジェクトがS2コンテナに見つかった場合
220                     formObject = actionObject;
221                     formClass = formObject.getClass();
222                 }
223             }
224 
225             formDesc = FormDescFactory.getFormDesc(formClass);
226         }
227 
228         if (formObject != null && formDesc != null) {
229             logger.log(FORM_CLASS_FOUND, id, formObject.getClass().getName());
230 
231             context.setFormDesc(formDesc);
232             context.setFormObject(formObject);
233             injectFormToAction(context);
234             return formObject;
235         } else {
236             logger.log(FORM_CLASS_NOT_FOUND, context.getName(), id);
237             return null;
238         }
239     }
240 
241     /**
242      * パートアクションオブジェクトにフォームオブジェクトのプロパティが存在する場合、 {@link PartContext}
243      * が保持するフォームオブジェクトをインジェクションします。
244      */
245     protected static void injectFormToAction(final PartContext context) {
246         Object partActionObject = context.getPartActionObject();
247         Object formObject = context.getFormObject();
248 
249         String formObjectName = formObject.getClass().getSimpleName();
250         BeanDesc beanDesc = context.getPartActionDesc().getBeanDesc();
251         if (beanDesc.hasPropertyDesc(formObjectName)) {
252             PropertyDesc pd = beanDesc.getPropertyDesc(formObjectName);
253             pd.setValue(partActionObject, formObject);
254         }
255     }
256 
257     /**
258      * <code>viewer</code> に対して {@link IContentProvider} を設定します。<br />
259      * <p>
260      * 本メソッドでは以下の動作を行います。<br />
261      * <ol>
262      * <li>S2Container 上に、&lt;コンポーネントのID&gt;ContentProvider という名称で S2
263      * コンポーネントが登録されているか確認する。
264      * <li>登録されていれば、その S2 コンポーネントが {@link IContentProvider} の実装クラスであるかどうかを確認する。
265      * <li>サブクラスであれば、その S2 コンポーネントをコンテントプロバイダとして <code>viewer</code> へ設定する。
266      * <li>S2 コンポーネントが見つからない場合、 <code>defaultProvider</code> で指定された
267      * オブジェクトをコンテントプロバイダとして <code>viewer</code> へ設定する。
268      * </ol>
269      * </p>
270      * 
271      * @param viewer
272      *            設定対象のビューア
273      * @param id
274      *            ビューアのコンポーネントID
275      * @param defaultProvider
276      *            デフォルトで指定するコンテントプロバイダ
277      * @throws RenderException
278      *             該当する名称の S2 コンポーネントが {@link IContentProvider} の実装クラスでない場合
279      * @see ContentViewer#setContentProvider(IContentProvider)
280      */
281     public static void setupContentProvider(final ContentViewer viewer,
282             final String id, final IContentProvider defaultProvider) {
283         IContentProvider provider = null;
284         if (!StringUtil.isEmpty(id)) {
285             Object defined = S2ContainerUtil.getComponentNoException(id
286                     + CONTENT_PROVIDER_SUFFIX, defaultContainer);
287             if (defined != null) {
288                 if (defined instanceof IContentProvider) {
289                     provider = IContentProvider.class.cast(defined);
290                 } else {
291                     throw new RenderException(UNSUPPORTED_TYPE_ERROR, provider,
292                             IContentProvider.class.getName());
293                 }
294             }
295         }
296 
297         if (provider == null) {
298             provider = defaultProvider;
299         }
300 
301         if (provider != null) {
302             viewer.setContentProvider(provider);
303 
304             logger.log(CONTENT_PROVIDER_FOUND, id, provider.getClass());
305         }
306     }
307 
308     /**
309      * <code>viewer</code> に対して {@link ILabelProvider} を設定します。<br />
310      * <p>
311      * 本メソッドでは以下の動作を行います。<br />
312      * <ol>
313      * <li>S2Container 上に、&lt;コンポーネントのID&gt;LabelProvider という名称で S2
314      * コンポーネントが登録されているか確認する。
315      * <li>登録されていれば、その S2 コンポーネントが <code>providerClass</code>
316      * のサブクラスであるかどうかを確認する。
317      * <li>サブクラスであれば、その S2 コンポーネントをラベルプロバイダとして <code>viewer</code> へ設定する。
318      * <li>サブクラスであれば、POJO によるラベルプロバイダと認識して <code>pojoProviderClass</code>
319      * で与えられたオブジェクトでラップする。
320      * <li>S2 コンポーネントが見つからない場合、 <code>defaultProvider</code> をラベルプロバイダとして
321      * <code>viewer</code> へ設定する。
322      * </ol>
323      * </p>
324      * 
325      * @param viewer
326      *            設定対象のビューア
327      * @param id
328      *            ビューアのコンポーネントID
329      * @param defaultProvider
330      *            デフォルトのラベルプロバイダ
331      * @param providerClass
332      *            S2コンポーネントをラベルプロバイダとして認識するためのクラス
333      * @param pojoProviderClass
334      *            S2コンポーネントが <code>providerClass</code> ではなかった場合に使用する {@link
335      *            PojoLabelProvider} のクラス
336      * @see StructuredViewer#setLabelProvider(IBaseLabelProvider)
337      */
338     public static void setupLabelProvider(final StructuredViewer viewer,
339             final String id, final IBaseLabelProvider defaultProvider,
340             final Class<? extends IBaseLabelProvider> providerClass,
341             final Class<? extends PojoLabelProvider> pojoProviderClass) {
342         IBaseLabelProvider provider = null;
343         if (!StringUtil.isEmpty(id)) {
344             Object defined = S2ContainerUtil.getComponentNoException(id
345                     + LABEL_PROVIDER_SUFFIX, defaultContainer);
346             if (defined != null) {
347                 if (providerClass.isAssignableFrom(defined.getClass())) {
348                     provider = providerClass.cast(defined);
349                 } else {
350                     AssertionUtil.assertNotNull("pojoProviderClass",
351                             pojoProviderClass);
352                     PojoLabelProvider pojoProvider = ClassUtil
353                             .<PojoLabelProvider> newInstance(pojoProviderClass);
354                     pojoProvider.setPojo(defined);
355                     provider = pojoProvider;
356                 }
357             }
358         }
359 
360         if (provider == null) {
361             provider = defaultProvider;
362         }
363 
364         if (provider != null) {
365             viewer.setLabelProvider(provider);
366 
367             logger.log(LABEL_PROVIDER_FOUND, id, provider.getClass());
368         }
369     }
370 
371     /**
372      * <code>viewer</code> に対して {@link ViewerComparator} を設定します。<br />
373      * <p>
374      * 本メソッドでは以下の動作を行います。<br />
375      * <ol>
376      * <li>S2Container 上に、&lt;コンポーネントのID&gt;Comparator という名称で S2
377      * コンポーネントが登録されているか確認する。
378      * <li>登録されていれば、その S2 コンポーネントが {@link ViewerComparator} のサブクラスであるかどうかを確認する。
379      * <li>サブクラスであれば、その S2 コンポーネントをコンパレータとして <code>viewer</code> へ設定する。
380      * <li>S2 コンポーネントが見つからない場合、 <code>defaultComparator</code> をコンパレータとして
381      * <code>viewer</code> へ設定する。
382      * </ol>
383      * </p>
384      * 
385      * @param viewer
386      *            設定対象のビューア
387      * @param id
388      *            ビューアのコンポーネントID
389      * @throws RenderException
390      *             該当する名称の S2 コンポーネントが {@link ViewerComparator} のサブクラスでない場合
391      * @see StructuredViewer#setComparator(ViewerComparator)
392      */
393     public static void setupComparator(final StructuredViewer viewer,
394             final String id, final ViewerComparator defaultComparator) {
395         if (!StringUtil.isEmpty(id)) {
396             Object comparator = S2ContainerUtil.getComponentNoException(id
397                     + SORTER_SUFFIX, defaultContainer);
398             if (comparator != null) {
399                 if (comparator instanceof ViewerComparator) {
400                     viewer.setComparator(ViewerComparator.class
401                             .cast(comparator));
402 
403                     logger.log(COMPARATOR_FOUND, id, comparator.getClass());
404                 } else {
405                     throw new RenderException(UNSUPPORTED_TYPE_ERROR,
406                             comparator, ViewerComparator.class.getName());
407                 }
408             } else {
409                 viewer.setComparator(defaultComparator);
410 
411                 String className = "(null)";
412                 if (defaultComparator != null) {
413                     className = defaultComparator.getClass().getName();
414                     logger.log(COMPARATOR_FOUND, id, className);
415                 }
416             }
417         }
418     }
419 
420     /**
421      * ワークベンチアクションクラスの初期化メソッドを呼び出します。<br />
422      * 
423      * @param context
424      *            {@link WindowContext}
425      */
426     public static void invokeInitMethodOnAction(final WindowContext context) {
427         Object workbenchActionObject = context.getPartActionObject();
428         if (workbenchActionObject != null) {
429             // ApplicationContext からのインポート処理
430             PartActionDesc desc = context.getPartActionDesc();
431             ApplicationContextBinder.importObjects(workbenchActionObject, desc
432                     .getApplicationContextDefList(), context
433                     .getApplicationContext());
434 
435             desc.invokeInitializeMethod(workbenchActionObject);
436         }
437     }
438 
439     /**
440      * パートアクションクラスの初期化メソッドを呼び出します。<br />
441      * 
442      * @param partAction
443      *            パートアクションオブジェクト
444      * @param context
445      *            {@link PartContext}
446      */
447     public static void invokeInitMethodOnAction(final Object partAction,
448             final PartContext context) {
449         if (partAction != null) {
450             WidgetBinder.bindWidgets(partAction, context);
451 
452             // ApplicationContext からのインポート処理
453             PartActionDesc desc = context.getPartActionDesc();
454             ApplicationContextBinder.importObjects(partAction, desc
455                     .getApplicationContextDefList(), context.getWindowContext()
456                     .getApplicationContext());
457 
458             desc.invokeInitializeMethod(partAction);
459         }
460     }
461 
462     /**
463      * パートアクションクラスのPostOpenメソッドを呼び出します。<br />
464      * 
465      * @param partAction
466      *            パートアクションオブジェクト
467      * @param context
468      *            {@link PartContext}
469      */
470     public static void invokePostOpenMethodOnAction(final Object partAction,
471             final PartContext context) {
472         if (partAction != null) {
473             WidgetBinder.bindWidgets(partAction, context);
474 
475             // ApplicationContext からのインポート処理
476             PartActionDesc desc = context.getPartActionDesc();
477             ApplicationContextBinder.importObjects(partAction, desc
478                     .getApplicationContextDefList(), context.getWindowContext()
479                     .getApplicationContext());
480 
481             desc.invokePostOpenMethod(partAction);
482         }
483     }
484 }