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.renderer;
17  
18  import java.lang.reflect.Field;
19  import java.util.StringTokenizer;
20  
21  import org.eclipse.jface.action.LegacyActionTools;
22  import org.eclipse.jface.resource.ImageDescriptor;
23  import org.eclipse.swt.SWT;
24  import org.eclipse.swt.graphics.Color;
25  import org.eclipse.swt.graphics.Font;
26  import org.eclipse.swt.graphics.FontData;
27  import org.eclipse.swt.graphics.Image;
28  import org.seasar.eclipse.common.util.FontManager;
29  import org.seasar.eclipse.common.util.ImageManager;
30  import org.seasar.eclipse.common.util.SWTUtil;
31  import org.seasar.framework.beans.BeanDesc;
32  import org.seasar.framework.beans.PropertyDesc;
33  import org.seasar.framework.beans.factory.BeanDescFactory;
34  import org.seasar.uruma.annotation.RenderingPolicy;
35  import org.seasar.uruma.annotation.RenderingPolicy.ConversionType;
36  import org.seasar.uruma.annotation.RenderingPolicy.SetTiming;
37  import org.seasar.uruma.annotation.RenderingPolicy.TargetType;
38  import org.seasar.uruma.component.UIElement;
39  import org.seasar.uruma.core.UrumaConstants;
40  import org.seasar.uruma.core.UrumaMessageCodes;
41  import org.seasar.uruma.exception.RenderException;
42  import org.seasar.uruma.log.UrumaLogger;
43  import org.seasar.uruma.util.PathUtil;
44  
45  /**
46   * レンダリングのサポートを行うユーティリティクラスです。<br />
47   * 
48   * @author y-komori
49   */
50  public class RendererSupportUtil implements UrumaConstants {
51      private static final UrumaLogger logger = UrumaLogger
52              .getLogger(RendererSupportUtil.class);
53  
54      /**
55       * <code>src</code> でアノテートされたフィールドを <code>dest</code> へコピーします。<br />
56       * <p>
57       * src オブジェクトの持つフィールドのうち、 {@link RenderingPolicy}
58       * アノテーションが指定されたフィールドで、現在のタイミングと同じタイミングが指定されたフィールドを、 アノテーションの示す方法で変換して
59       * <code>dest</code> の同名フィールドへコピーします。<br />
60       * コピー方法の詳細は、 {@link RenderingPolicy} のドキュメントを参照してください。<br />
61       * </p>
62       * 
63       * @param src
64       *            転送元オブジェクト
65       * @param dest
66       *            転送先オブジェクト
67       * @param nowTiming
68       *            現在のタイミング
69       */
70      public static void setAttributes(final UIElement src, final Object dest,
71              final SetTiming nowTiming) {
72          BeanDesc beanDesc = BeanDescFactory.getBeanDesc(src.getClass());
73          int pdSize = beanDesc.getPropertyDescSize();
74  
75          for (int i = 0; i < pdSize; i++) {
76              PropertyDesc pd = beanDesc.getPropertyDesc(i);
77              Field field = pd.getField();
78  
79              if (field != null) {
80                  RenderingPolicy policy = field
81                          .getAnnotation(RenderingPolicy.class);
82                  if ((policy != null) && (policy.setTiming() == nowTiming)
83                          && (policy.targetType() != TargetType.NONE)) {
84                      String value = getSrcValue(src, pd);
85                      if (value != null) {
86                          setValue(src, dest, pd, policy, value);
87                      }
88                  }
89              }
90          }
91      }
92  
93      private static String getSrcValue(final UIElement src, final PropertyDesc pd) {
94          if (String.class.isAssignableFrom(pd.getPropertyType())) {
95              return (String) pd.getValue(src);
96          } else {
97              logger.log(UrumaMessageCodes.COMPONENT_PROPERTY_IS_NOT_STRING, pd
98                      .getBeanDesc().getBeanClass().getName(), pd
99                      .getPropertyName());
100             return null;
101         }
102     }
103 
104     private static void setValue(final UIElement src, final Object dest,
105             final PropertyDesc srcPd, final RenderingPolicy policy,
106             final String value) {
107         BeanDesc desc = BeanDescFactory.getBeanDesc(dest.getClass());
108 
109         // RenderingPolicy#name が設定されていない場合は
110         // 転送元のプロパティ名をそのまま利用する
111         String propertyName = policy.name();
112         if (NULL_STRING.equals(propertyName)) {
113             propertyName = srcPd.getPropertyName();
114         }
115 
116         try {
117             if (desc.hasPropertyDesc(propertyName)) {
118                 PropertyDesc destPd = desc.getPropertyDesc(propertyName);
119                 if (destPd.isWritable()) {
120                     destPd.setValue(dest, convertValue(src, value, policy
121                             .conversionType()));
122                 } else {
123                     logger.log(UrumaMessageCodes.PROPERTY_IS_NOT_WRITABLE, dest
124                             .getClass().getName(), destPd.getPropertyName());
125                 }
126             } else {
127                 logger.log(UrumaMessageCodes.WIDGET_PROPERTY_NOT_FOUND, dest
128                         .getClass().getName(), propertyName);
129             }
130         } catch (Exception ex) {
131             throw new RenderException(UrumaMessageCodes.RENDER_MAPPING_FAILED,
132                     ex, propertyName, dest.getClass().getName(), value);
133         }
134     }
135 
136     /**
137      * {@link ConversionType} にしたがって値を変換します。<br />
138      * 
139      * @param src
140      *            変換元の値を保持する {@link UIElement} オブジェクト
141      * @param value
142      *            変換元の値
143      * @param conversionType
144      *            変換方式を指定する {@link ConversionType} オブジェクト
145      * @return 変換結果オブジェクト
146      */
147     public static Object convertValue(final UIElement src, final String value,
148             final ConversionType conversionType) {
149 
150         if (conversionType == ConversionType.STRING) {
151             return value;
152         } else if (conversionType == ConversionType.TEXT) {
153             return convertText(value);
154         } else if (conversionType == ConversionType.BOOLEAN) {
155             return convertBoolean(value);
156         } else if (conversionType == ConversionType.INT) {
157             return convertInt(value);
158         } else if (conversionType == ConversionType.INT_ARRAY) {
159             return convertIntArray(value);
160         } else if (conversionType == ConversionType.CHAR) {
161             return convertCharacter(value);
162         } else if (conversionType == ConversionType.SWT_CONST) {
163             return convertSwtConst(value);
164         } else if (conversionType == ConversionType.COLOR) {
165             return convertColor(value);
166         } else if (conversionType == ConversionType.IMAGE) {
167             return convertImage(value, src.getBasePath());
168         } else if (conversionType == ConversionType.ACCELERATOR) {
169             return convertAccelerator(value);
170         }
171         return null;
172     }
173 
174     /**
175      * テキストの変換を行います。<br />
176      * 
177      * @param value
178      *            変換対象
179      * @return 変換結果
180      */
181     public static String convertText(final String value) {
182         String text = value.replace("\\n", "\n");
183         text = text.replace("\\t", "\t");
184         if (text.startsWith("\"") && text.endsWith("\"")) {
185             text = text.substring(1, text.length() - 1);
186         }
187         return text;
188     }
189 
190     /**
191      * <code>boolean</code> 型への変換を行います。<br />
192      * 
193      * @param value
194      *            変換対象
195      * @return 変換結果
196      */
197     public static boolean convertBoolean(final String value) {
198         return Boolean.valueOf(value).booleanValue();
199     }
200 
201     /**
202      * <code>int</code> 型への変換を行います。<br />
203      * 
204      * @param value
205      *            変換対象
206      * @return 変換結果
207      */
208     public static int convertInt(final String value) {
209         return Integer.valueOf(value).intValue();
210     }
211 
212     /**
213      * カンマ区切りの数値を <code>int</code> 型配列へ変換します。<br />
214      * 
215      * @param value
216      *            変換対象
217      * @return 変換結果
218      */
219     public static int[] convertIntArray(final String value) {
220         StringTokenizer tokenizer = new StringTokenizer(value, ",");
221         int[] result = new int[tokenizer.countTokens()];
222         for (int i = 0; tokenizer.hasMoreTokens(); i++) {
223             String token = tokenizer.nextToken();
224             result[i] = convertInt(token.trim());
225         }
226         return result;
227     }
228 
229     /**
230      * {@link Character} 型への変換を行います。<br />
231      * 
232      * @param value
233      *            変換対象
234      * @return 変換結果
235      */
236     public static Character convertCharacter(final String value) {
237         if (value.length() > 0) {
238             return Character.valueOf(value.charAt(0));
239         } else {
240             return null;
241         }
242     }
243 
244     /**
245      * {@link SWT} 定数への変換を行います。<br />
246      * 
247      * @param value
248      *            変換対象
249      * @return 変換結果
250      * @see SWTUtil#getStyle(String)
251      */
252     public static int convertSwtConst(final String value) {
253         return SWTUtil.getStyle(value);
254     }
255 
256     /**
257      * {@link Color} オブジェクトへの変換を行います。<br />
258      * 
259      * @param value
260      *            変換対象
261      * @return 変換結果
262      * @see SWTUtil#getColor(String)
263      */
264     public static Color convertColor(final String value) {
265         return SWTUtil.getColor(value);
266     }
267 
268     /**
269      * <code>value</code> の示すパスからイメージを読み込みます。<br />
270      * 
271      * @param value
272      *            パス
273      * @param basePath
274      *            ベースパス
275      * @return 変換結果
276      * @see ImageManager
277      */
278     public static Image convertImage(final String value, final String basePath) {
279         Image image = ImageManager.getImage(value);
280         if (image == null) {
281             String path = PathUtil.createPath(basePath, value);
282             image = ImageManager.loadImage(path);
283         }
284         return image;
285     }
286 
287     /**
288      * <code>value</code> の示すパスからイメージを読み込みます。<br />
289      * 
290      * @param value
291      *            パス
292      * @return 変換結果
293      * @see ImageManager
294      */
295     public static Image convertImage(final String value) {
296         return convertImage(value, "");
297     }
298 
299     /**
300      * <code>value</code> のパスの指すイメージを表す {@link ImageDescriptor} を返します。<br />
301      * 
302      * @param value
303      *            パス
304      * @param basePath
305      *            ベースパス
306      * @return 変換結果
307      * @see ImageManager
308      */
309     public static ImageDescriptor convertImageDescriptor(final String value,
310             final String basePath) {
311         ImageDescriptor image = ImageManager.getImageDescriptor(value);
312         if (image == null) {
313             String path = PathUtil.createPath(basePath, value);
314             image = ImageManager.loadImageDescriptor(path);
315         }
316         return image;
317     }
318 
319     /**
320      * <code>value</code> のパスの指すイメージを表す {@link ImageDescriptor} を返します。<br />
321      * 
322      * @param value
323      *            パス
324      * @return 変換結果
325      * @see ImageManager
326      */
327     public static ImageDescriptor convertImageDescriptor(final String value) {
328         return convertImageDescriptor(value, "");
329     }
330 
331     /**
332      * キーアクセラレータの <code>int</code> 値への変換を行います<br />。
333      * 
334      * @param value
335      *            変換対象
336      * @return 変換結果
337      */
338     public static int convertAccelerator(final String value) {
339         return LegacyActionTools.convertAccelerator(value);
340     }
341 
342     /**
343      * {@link Font} オブジェクトを取得します。<br />
344      * 
345      * @param defaultFont
346      *            見つからなかった場合のデフォルト {@link Font} オブジェクト
347      * @param fontName
348      *            フォント名称
349      * @param fontStyle
350      *            フォントスタイル
351      * @param fontHeight
352      *            フォント高さ
353      * @return {@link Font} オブジェクト
354      */
355     public static Font getFont(final Font defaultFont, String fontName,
356             final String fontStyle, final String fontHeight) {
357         FontData fontData = defaultFont.getFontData()[0];
358 
359         if (fontName == null) {
360             fontName = fontData.getName();
361         }
362 
363         int style;
364         if (fontStyle != null) {
365             style = SWTUtil.getStyle(fontStyle);
366             style = (style == SWT.NONE) ? SWT.NORMAL : style;
367         } else {
368             style = fontData.getStyle();
369         }
370 
371         int height;
372         if (fontHeight != null) {
373             height = Integer.parseInt(fontHeight);
374         } else {
375             height = fontData.getHeight();
376         }
377 
378         return FontManager.get(fontName, height, style);
379     }
380 }