Coverage Report - org.seasar.uruma.core.ComponentUtil
 
Classes in this File Line Coverage Branch Coverage Complexity
ComponentUtil
66%
86/130
46%
25/54
0
 
 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  4
     private static final UrumaLogger logger = UrumaLogger
 52  
             .getLogger(ComponentUtil.class);
 53  
 
 54  
     private static S2Container defaultContainer;
 55  
 
 56  0
     private ComponentUtil() {
 57  0
     }
 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  128
         AssertionUtil.assertNotNull("container", container);
 68  
 
 69  128
         defaultContainer = container;
 70  128
     }
 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  0
         String actionComponentName = StringUtil.decapitalize(id)
 83  
                 + PART_ACTION_SUFFIX;
 84  
 
 85  0
         ComponentDef cd = S2ContainerUtil
 86  
                 .getComponentDefNoException(actionComponentName);
 87  
 
 88  0
         Object workbenchActionComponent = S2ContainerUtil
 89  
                 .getComponentNoException(actionComponentName, defaultContainer);
 90  0
         if (workbenchActionComponent != null) {
 91  0
             S2ContainerUtil.injectDependency(workbenchActionComponent,
 92  
                     defaultContainer);
 93  
 
 94  0
             context.setPartActionObject(workbenchActionComponent);
 95  0
             PartActionDesc desc = PartActionDescFactory.getPartActionDesc(cd
 96  
                     .getComponentClass());
 97  0
             context.setPartActionDesc(desc);
 98  
 
 99  0
             logger.log(WORKBENCH_ACTION_CLASS_FOUND, id, actionComponentName,
 100  
                     workbenchActionComponent.getClass().getName());
 101  
 
 102  0
             return workbenchActionComponent;
 103  
         } else {
 104  0
             logger.log(WORKBENCH_ACTION_CLASS_NOT_FOUND, id,
 105  
                     actionComponentName);
 106  0
             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  112
         String actionComponentName = StringUtil.decapitalize(id)
 125  
                 + PART_ACTION_SUFFIX;
 126  
 
 127  112
         ComponentDef cd = S2ContainerUtil
 128  
                 .getComponentDefNoException(actionComponentName);
 129  
 
 130  112
         Object partActionComponent = null;
 131  112
         if (cd != null) {
 132  
             // ComponentDef が持つコンテナは生成時のものなので、
 133  
             // その範囲でしかDIできない。そんため、コンテナをセットし直す。
 134  112
             cd.setContainer(container);
 135  112
             partActionComponent = cd.getComponent();
 136  
 
 137  112
             S2ContainerUtil.injectDependency(partActionComponent, container);
 138  
 
 139  112
             context.setPartActionObject(partActionComponent);
 140  112
             PartActionDesc desc = PartActionDescFactory.getPartActionDesc(cd
 141  
                     .getComponentClass());
 142  112
             context.setPartActionDesc(desc);
 143  
 
 144  112
             logger.log(PART_ACTION_CLASS_FOUND, id, actionComponentName,
 145  
                     partActionComponent.getClass().getName());
 146  
 
 147  112
             return partActionComponent;
 148  
         } else {
 149  0
             logger.log(PART_ACTION_CLASS_NOT_FOUND, id, actionComponentName);
 150  0
             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  112
         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  112
         Object formObject = null;
 190  112
         FormDesc formDesc = null;
 191  112
         Class<?> formClass = null;
 192  112
         Object actionObject = context.getPartActionObject();
 193  112
         if (actionObject != null) {
 194  112
             Form formAnnotation = context.getPartActionDesc()
 195  
                     .getPartActionClass().getAnnotation(Form.class);
 196  
             // @Form アノテーションが指定されている場合
 197  112
             if (formAnnotation != null) {
 198  0
                 formClass = formAnnotation.value();
 199  0
                 if (formClass == actionObject.getClass()) {
 200  0
                     formObject = actionObject;
 201  
                 } else {
 202  0
                     formObject = S2ContainerUtil.getComponent(formClass,
 203  
                             defaultContainer);
 204  
                 }
 205  
             }
 206  
 
 207  
             // @Form アノテーション未指定の場合
 208  112
             if (formObject == null) {
 209  112
                 String formComponentName = StringUtil.decapitalize(id)
 210  
                         + FORM_SUFFIX;
 211  112
                 formObject = S2ContainerUtil.getComponentNoException(
 212  
                         formComponentName, defaultContainer);
 213  112
                 if (formObject != null) {
 214  
                     // フォームオブジェクトがS2コンテナに見つかった場合
 215  0
                     ComponentDef cd = S2ContainerUtil
 216  
                             .getComponentDef(formComponentName);
 217  0
                     formClass = cd.getComponentClass();
 218  0
                 } else {
 219  
                     // フォームオブジェクトがS2コンテナに見つかった場合
 220  112
                     formObject = actionObject;
 221  112
                     formClass = formObject.getClass();
 222  
                 }
 223  
             }
 224  
 
 225  112
             formDesc = FormDescFactory.getFormDesc(formClass);
 226  
         }
 227  
 
 228  112
         if (formObject != null && formDesc != null) {
 229  112
             logger.log(FORM_CLASS_FOUND, id, formObject.getClass().getName());
 230  
 
 231  112
             context.setFormDesc(formDesc);
 232  112
             context.setFormObject(formObject);
 233  112
             injectFormToAction(context);
 234  112
             return formObject;
 235  
         } else {
 236  0
             logger.log(FORM_CLASS_NOT_FOUND, context.getName(), id);
 237  0
             return null;
 238  
         }
 239  
     }
 240  
 
 241  
     /**
 242  
      * パートアクションオブジェクトにフォームオブジェクトのプロパティが存在する場合、 {@link PartContext}
 243  
      * が保持するフォームオブジェクトをインジェクションします。
 244  
      */
 245  
     protected static void injectFormToAction(final PartContext context) {
 246  112
         Object partActionObject = context.getPartActionObject();
 247  112
         Object formObject = context.getFormObject();
 248  
 
 249  112
         String formObjectName = formObject.getClass().getSimpleName();
 250  112
         BeanDesc beanDesc = context.getPartActionDesc().getBeanDesc();
 251  112
         if (beanDesc.hasPropertyDesc(formObjectName)) {
 252  0
             PropertyDesc pd = beanDesc.getPropertyDesc(formObjectName);
 253  0
             pd.setValue(partActionObject, formObject);
 254  
         }
 255  112
     }
 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  40
         IContentProvider provider = null;
 284  40
         if (!StringUtil.isEmpty(id)) {
 285  40
             Object defined = S2ContainerUtil.getComponentNoException(id
 286  
                     + CONTENT_PROVIDER_SUFFIX, defaultContainer);
 287  40
             if (defined != null) {
 288  0
                 if (defined instanceof IContentProvider) {
 289  0
                     provider = IContentProvider.class.cast(defined);
 290  
                 } else {
 291  0
                     throw new RenderException(UNSUPPORTED_TYPE_ERROR, provider,
 292  
                             IContentProvider.class.getName());
 293  
                 }
 294  
             }
 295  
         }
 296  
 
 297  40
         if (provider == null) {
 298  40
             provider = defaultProvider;
 299  
         }
 300  
 
 301  40
         if (provider != null) {
 302  40
             viewer.setContentProvider(provider);
 303  
 
 304  40
             logger.log(CONTENT_PROVIDER_FOUND, id, provider.getClass());
 305  
         }
 306  40
     }
 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  40
         IBaseLabelProvider provider = null;
 343  40
         if (!StringUtil.isEmpty(id)) {
 344  40
             Object defined = S2ContainerUtil.getComponentNoException(id
 345  
                     + LABEL_PROVIDER_SUFFIX, defaultContainer);
 346  40
             if (defined != null) {
 347  4
                 if (providerClass.isAssignableFrom(defined.getClass())) {
 348  4
                     provider = providerClass.cast(defined);
 349  
                 } else {
 350  0
                     AssertionUtil.assertNotNull("pojoProviderClass",
 351  
                             pojoProviderClass);
 352  0
                     PojoLabelProvider pojoProvider = ClassUtil
 353  
                             .<PojoLabelProvider> newInstance(pojoProviderClass);
 354  0
                     pojoProvider.setPojo(defined);
 355  0
                     provider = pojoProvider;
 356  
                 }
 357  
             }
 358  
         }
 359  
 
 360  40
         if (provider == null) {
 361  36
             provider = defaultProvider;
 362  
         }
 363  
 
 364  40
         if (provider != null) {
 365  40
             viewer.setLabelProvider(provider);
 366  
 
 367  40
             logger.log(LABEL_PROVIDER_FOUND, id, provider.getClass());
 368  
         }
 369  40
     }
 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  40
         if (!StringUtil.isEmpty(id)) {
 396  40
             Object comparator = S2ContainerUtil.getComponentNoException(id
 397  
                     + SORTER_SUFFIX, defaultContainer);
 398  40
             if (comparator != null) {
 399  0
                 if (comparator instanceof ViewerComparator) {
 400  0
                     viewer.setComparator(ViewerComparator.class
 401  
                             .cast(comparator));
 402  
 
 403  0
                     logger.log(COMPARATOR_FOUND, id, comparator.getClass());
 404  
                 } else {
 405  0
                     throw new RenderException(UNSUPPORTED_TYPE_ERROR,
 406  
                             comparator, ViewerComparator.class.getName());
 407  
                 }
 408  
             } else {
 409  40
                 viewer.setComparator(defaultComparator);
 410  
 
 411  40
                 String className = "(null)";
 412  40
                 if (defaultComparator != null) {
 413  8
                     className = defaultComparator.getClass().getName();
 414  8
                     logger.log(COMPARATOR_FOUND, id, className);
 415  
                 }
 416  
             }
 417  
         }
 418  40
     }
 419  
 
 420  
     /**
 421  
      * ワークベンチアクションクラスの初期化メソッドを呼び出します。<br />
 422  
      * 
 423  
      * @param context
 424  
      *            {@link WindowContext}
 425  
      */
 426  
     public static void invokeInitMethodOnAction(final WindowContext context) {
 427  0
         Object workbenchActionObject = context.getPartActionObject();
 428  0
         if (workbenchActionObject != null) {
 429  
             // ApplicationContext からのインポート処理
 430  0
             PartActionDesc desc = context.getPartActionDesc();
 431  0
             ApplicationContextBinder.importObjects(workbenchActionObject, desc
 432  
                     .getApplicationContextDefList(), context
 433  
                     .getApplicationContext());
 434  
 
 435  0
             desc.invokeInitializeMethod(workbenchActionObject);
 436  
         }
 437  0
     }
 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  112
         if (partAction != null) {
 450  112
             WidgetBinder.bindWidgets(partAction, context);
 451  
 
 452  
             // ApplicationContext からのインポート処理
 453  112
             PartActionDesc desc = context.getPartActionDesc();
 454  112
             ApplicationContextBinder.importObjects(partAction, desc
 455  
                     .getApplicationContextDefList(), context.getWindowContext()
 456  
                     .getApplicationContext());
 457  
 
 458  112
             desc.invokeInitializeMethod(partAction);
 459  
         }
 460  112
     }
 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  112
         if (partAction != null) {
 473  112
             WidgetBinder.bindWidgets(partAction, context);
 474  
 
 475  
             // ApplicationContext からのインポート処理
 476  112
             PartActionDesc desc = context.getPartActionDesc();
 477  112
             ApplicationContextBinder.importObjects(partAction, desc
 478  
                     .getApplicationContextDefList(), context.getWindowContext()
 479  
                     .getApplicationContext());
 480  
 
 481  112
             desc.invokePostOpenMethod(partAction);
 482  
         }
 483  112
     }
 484  
 }