Coverage Report - org.seasar.uruma.component.factory.handler.GenericTagHandler
 
Classes in this File Line Coverage Branch Coverage Complexity
GenericTagHandler
96%
67/70
77%
20/26
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.component.factory.handler;
 17  
 
 18  
 import org.seasar.framework.beans.BeanDesc;
 19  
 import org.seasar.framework.beans.PropertyDesc;
 20  
 import org.seasar.framework.beans.factory.BeanDescFactory;
 21  
 import org.seasar.framework.util.StringUtil;
 22  
 import org.seasar.framework.xml.TagHandlerContext;
 23  
 import org.seasar.uruma.component.UIComponent;
 24  
 import org.seasar.uruma.component.UIElement;
 25  
 import org.seasar.uruma.component.UIElementContainer;
 26  
 import org.seasar.uruma.component.factory.UrumaTagHandler;
 27  
 import org.seasar.uruma.core.UrumaMessageCodes;
 28  
 import org.seasar.uruma.exception.NotFoundException;
 29  
 import org.seasar.uruma.exception.ParseException;
 30  
 import org.seasar.uruma.renderer.Renderer;
 31  
 import org.seasar.uruma.renderer.RendererFactory;
 32  
 import org.seasar.uruma.util.ClassUtil;
 33  
 import org.seasar.uruma.util.PathUtil;
 34  
 import org.xml.sax.Attributes;
 35  
 
 36  
 /**
 37  
  * 汎用のタグハンドラクラスです。<br />
 38  
  * 
 39  
  * @author y-komori
 40  
  */
 41  
 public class GenericTagHandler extends UrumaTagHandler {
 42  
     private static final long serialVersionUID = 4075680211563734762L;
 43  
 
 44  
     private Class<? extends UIElement> uiElementClass;
 45  
 
 46  
     /**
 47  
      * 生成するクラスを指定してインスタンスを構築します。
 48  
      * 
 49  
      * @param uiElementClass
 50  
      *            生成するクラス
 51  
      */
 52  5568
     public GenericTagHandler(final Class<? extends UIElement> uiElementClass) {
 53  5568
         this.uiElementClass = uiElementClass;
 54  5568
     }
 55  
 
 56  
     /*
 57  
      * @see org.seasar.framework.xml.TagHandler#start(org.seasar.framework.xml.TagHandlerContext,
 58  
      *      org.xml.sax.Attributes)
 59  
      */
 60  
     @Override
 61  
     public void start(final TagHandlerContext context,
 62  
             final Attributes attributes) {
 63  2820
         UIElement uiElement = createUIElement(uiElementClass, context);
 64  
 
 65  2820
         setPath(uiElement, context);
 66  
 
 67  2820
         setBasePath(uiElement, context);
 68  
 
 69  2820
         setLocation(uiElement, context);
 70  
 
 71  2820
         setAttributes(uiElement, attributes);
 72  
 
 73  2820
         if (uiElement instanceof UIComponent) {
 74  1852
             setRenderer((UIComponent) uiElement);
 75  
         }
 76  
 
 77  2820
         setParent(uiElement, context);
 78  
 
 79  2820
         if (enableAutoId()) {
 80  116
             setupAutoId(uiElement);
 81  
         }
 82  
 
 83  2820
         if (enableAutoTitle()) {
 84  116
             setupAutoTitle(uiElement);
 85  
         }
 86  
 
 87  2820
         context.push(uiElement);
 88  2820
     }
 89  
 
 90  
     /*
 91  
      * @see org.seasar.framework.xml.TagHandler#end(org.seasar.framework.xml.TagHandlerContext,
 92  
      *      java.lang.String)
 93  
      */
 94  
     @Override
 95  
     public void end(final TagHandlerContext context, final String body) {
 96  2820
         context.pop();
 97  2820
     }
 98  
 
 99  
     /**
 100  
      * {@link UIElement} オブジェクトを生成します。<br />
 101  
      * 
 102  
      * @param uiElementClass
 103  
      *            {@link UIElement} クラス
 104  
      * @param context
 105  
      *            {@link TagHandlerContext} オブジェクト。<br />
 106  
      *            コンテクストに応じて生成する {@link UIElement} を変更するために使用します。<br />
 107  
      *            本クラスでは利用しませんが、サブクラスで必要に応じて利用することができます。<br />
 108  
      * @return {@link UIElement} オブジェクト
 109  
      */
 110  
     protected UIElement createUIElement(
 111  
             final Class<? extends UIElement> uiElementClass,
 112  
             final TagHandlerContext context) {
 113  2820
         return ClassUtil.<UIElement> newInstance(uiElementClass);
 114  
     }
 115  
 
 116  
     /**
 117  
      * {@link UIElement} へXMLのパスを設定します。<br />
 118  
      * 
 119  
      * @param uiElement
 120  
      *            {@link UIElement} オブジェクト
 121  
      * @param context
 122  
      *            コンテクスト情報
 123  
      */
 124  
     protected void setPath(final UIElement uiElement,
 125  
             final TagHandlerContext context) {
 126  2820
         uiElement.setPath((String) context
 127  
                 .getParameter(UrumaTagHandler.PARAM_PATH));
 128  2820
     }
 129  
 
 130  
     /**
 131  
      * {@link UIElement} へXMLのベースパスを設定します。<br />
 132  
      * 
 133  
      * @param uiElement
 134  
      *            {@link UIElement} オブジェクト
 135  
      * @param context
 136  
      *            コンテクスト情報
 137  
      */
 138  
     protected void setBasePath(final UIElement uiElement,
 139  
             final TagHandlerContext context) {
 140  2820
         uiElement.setBasePath((String) context
 141  
                 .getParameter(UrumaTagHandler.PARAM_BASE_PATH));
 142  2820
     }
 143  
 
 144  
     /**
 145  
      * {@link UIElement} へXML上のロケーション情報を設定します。<br />
 146  
      * 
 147  
      * @param uiElement
 148  
      *            {@link UIElement} オブジェクト
 149  
      * @param context
 150  
      *            コンテクスト情報
 151  
      */
 152  
     protected void setLocation(final UIElement uiElement,
 153  
             final TagHandlerContext context) {
 154  2820
         uiElement.setLocation(context.getDetailPath());
 155  2820
     }
 156  
 
 157  
     /**
 158  
      * {@link UIElement} へ属性の値をセットします。<br />
 159  
      * 
 160  
      * @param uiElement
 161  
      *            {@link UIElement} オブジェクト
 162  
      * @param attributes
 163  
      *            {@link Attributes} オブジェクト
 164  
      */
 165  
     protected void setAttributes(final UIElement uiElement,
 166  
             final Attributes attributes) {
 167  2820
         int length = attributes.getLength();
 168  
 
 169  7588
         for (int i = 0; i < length; i++) {
 170  4768
             String name = attributes.getQName(i);
 171  4768
             String value = attributes.getValue(i);
 172  4768
             setProperty(uiElement, name, value);
 173  
         }
 174  2820
     }
 175  
 
 176  
     /**
 177  
      * {@link UIElement} へプロパティを設定します。<br />
 178  
      * <p>
 179  
      * <code>name</code>に対応したsetterメソッドが存在すればそれを利用して値を設定します。<br />
 180  
      * </p>
 181  
      * 
 182  
      * @param uiElement
 183  
      *            {@link UIElement} オブジェクト
 184  
      * @param name
 185  
      *            プロパティ名
 186  
      * @param value
 187  
      *            値
 188  
      */
 189  
     protected void setProperty(final UIElement uiElement, final String name,
 190  
             final String value) {
 191  4768
         BeanDesc desc = BeanDescFactory.getBeanDesc(uiElement.getClass());
 192  4768
         if (desc.hasPropertyDesc(name)) {
 193  4768
             PropertyDesc pd = desc.getPropertyDesc(name);
 194  4768
             pd.setValue(uiElement, value);
 195  4768
         } else {
 196  0
             throw new ParseException(name, uiElement.getClass().getName());
 197  
         }
 198  4768
     }
 199  
 
 200  
     /**
 201  
      * 生成した {@link UIElement} を {@link TagHandlerContext} 内に存在する親へ設定します。<br />
 202  
      * 
 203  
      * @param uiElement
 204  
      *            {@link UIElement} オブジェクト
 205  
      * @param context
 206  
      *            {@link TagHandlerContext} オブジェクト
 207  
      */
 208  
     protected void setParent(final UIElement uiElement,
 209  
             final TagHandlerContext context) {
 210  1736
         if (!context.isEmpty()) {
 211  1736
             Object parent = context.peek();
 212  1736
             if (UIElementContainer.class.isAssignableFrom(parent.getClass())) {
 213  1712
                 UIElementContainer parentComponent = (UIElementContainer) parent;
 214  1712
                 parentComponent.addChild(uiElement);
 215  
             }
 216  
         }
 217  1736
     }
 218  
 
 219  
     /**
 220  
      * {@link UIComponent} に対応するレンダラをセットします。<br />
 221  
      * 
 222  
      * @param uiComponent
 223  
      *            {@link UIComponent} オブジェクト
 224  
      */
 225  
     protected void setRenderer(final UIComponent uiComponent) {
 226  1852
         Renderer renderer = RendererFactory
 227  
                 .getRenderer(uiComponent.getClass());
 228  1852
         if (renderer != null) {
 229  1852
             uiComponent.setRenderer(renderer);
 230  
         } else {
 231  0
             throw new NotFoundException(UrumaMessageCodes.RENDERER_NOT_FOUND,
 232  
                     uiComponent.getClass().getName());
 233  
         }
 234  1852
     }
 235  
 
 236  
     /*
 237  
      * @see org.seasar.uruma.component.factory.UrumaTagHandler#getElementPath()
 238  
      */
 239  
     @Override
 240  
     public String getElementPath() {
 241  0
         return null;
 242  
     }
 243  
 
 244  
     protected void setupAutoId(final UIElement element) {
 245  116
         if (element instanceof UIComponent) {
 246  116
             UIComponent uiComponent = (UIComponent) element;
 247  116
             if (StringUtil.isEmpty(uiComponent.getId())) {
 248  112
                 String fileName = PathUtil.getFileName(uiComponent.getPath());
 249  112
                 String id = StringUtil.decapitalize(PathUtil
 250  
                         .getBaseName(fileName));
 251  112
                 uiComponent.setId(id);
 252  
             }
 253  
         }
 254  116
     }
 255  
 
 256  
     /**
 257  
      * ID の自動設定を有効にするかどうかを返します。<br />
 258  
      * デフォルトでは <code>false</code> を返します。<br />
 259  
      * 本機能を有効にする場合、サブクラスでオーバーライドして <code>true</code> を返してください。<br />
 260  
      * 
 261  
      * @return ID の自動設定を有効にするかどうか
 262  
      */
 263  
     protected boolean enableAutoId() {
 264  2704
         return false;
 265  
     }
 266  
 
 267  
     protected void setupAutoTitle(final UIElement element) {
 268  116
         if (element instanceof UIComponent) {
 269  116
             UIComponent uiComponent = (UIComponent) element;
 270  116
             BeanDesc desc = BeanDescFactory.getBeanDesc(uiComponent.getClass());
 271  116
             if (desc.hasPropertyDesc("title")) {
 272  116
                 PropertyDesc pd = desc.getPropertyDesc("title");
 273  
 
 274  116
                 if (StringUtil.isEmpty((String) pd.getValue(uiComponent))) {
 275  112
                     String fileName = PathUtil.getFileName(uiComponent
 276  
                             .getPath());
 277  112
                     String title = PathUtil.getBaseName(fileName);
 278  112
                     pd.setValue(uiComponent, title);
 279  
                 }
 280  
             }
 281  
         }
 282  116
     }
 283  
 
 284  
     /**
 285  
      * タイトルの自動設定を有効にするかどうかを返します。<br />
 286  
      * デフォルトでは <code>false</code> を返します。<br />
 287  
      * 本機能を有効にする場合、サブクラスでオーバーライドして <code>true</code> を返してください。<br />
 288  
      * 
 289  
      * @return タイトルの自動設定を有効にするかどうか
 290  
      */
 291  
     protected boolean enableAutoTitle() {
 292  2704
         return false;
 293  
     }
 294  
 }