/* * Copyright 2004-2015 the Seasar Foundation and the Others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ package org.seasar.extension.dxo.annotation.impl; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.seasar.extension.dxo.DxoConstants; import org.seasar.extension.dxo.annotation.AnnotationReader; import org.seasar.extension.dxo.converter.Converter; import org.seasar.framework.beans.BeanDesc; import org.seasar.framework.beans.factory.BeanDescFactory; import org.seasar.framework.beans.util.BeanUtil; import org.seasar.framework.container.S2Container; import org.seasar.framework.container.util.ConstantAnnotationUtil; import org.seasar.framework.util.ClassUtil; import org.seasar.framework.util.FieldUtil; import org.seasar.framework.util.MapUtil; /** * Dxoから定数アノテーションを読み取る{@link AnnotationReader}の実装クラスです。 * * @author Satoshi Kimura * @author koichik */ public class ConstantAnnotationReader implements AnnotationReader { /** S2コンテナ */ protected S2Container container; /** 変換先クラスに指定されたコンバータのキャッシュです */ protected Map convertersCache = MapUtil.createHashMap(); /** * インスタンスを構築します。 * * @param container * S2コンテナ */ public ConstantAnnotationReader(final S2Container container) { this.container = container.getRoot(); } public String getDatePattern(final Class dxoClass, final Method method) { return getDatePattern(dxoClass, method, DxoConstants.DATE_PATTERN); } public String getTimePattern(final Class dxoClass, final Method method) { return getDatePattern(dxoClass, method, DxoConstants.TIME_PATTERN); } public String getTimestampPattern(final Class dxoClass, final Method method) { return getDatePattern(dxoClass, method, DxoConstants.TIMESTAMP_PATTERN); } public String getConversionRule(final Class dxoClass, final Method method) { final BeanDesc dxoBeanDesc = BeanDescFactory.getBeanDesc(dxoClass); String fieldName = getConstantAnnotationName(method, DxoConstants.CONVERSION_RULE); if (dxoBeanDesc.hasField(fieldName)) { return (String) dxoBeanDesc.getFieldValue(fieldName, null); } fieldName = method.getName() + "_" + DxoConstants.CONVERSION_RULE; if (dxoBeanDesc.hasField(fieldName)) { return (String) dxoBeanDesc.getFieldValue(fieldName, null); } return null; } public boolean isExcludeNull(final Class dxoClass, final Method method) { final BeanDesc dxoBeanDesc = BeanDescFactory.getBeanDesc(dxoClass); String fieldName = getConstantAnnotationName(method, DxoConstants.EXCLUDE_NULL); if (dxoBeanDesc.hasField(fieldName)) { return true; } fieldName = method.getName() + "_" + DxoConstants.EXCLUDE_NULL; if (dxoBeanDesc.hasField(fieldName)) { return true; } return false; } public boolean isExcludeWhitespace(final Class dxoClass, final Method method) { final BeanDesc dxoBeanDesc = BeanDescFactory.getBeanDesc(dxoClass); String fieldName = getConstantAnnotationName(method, DxoConstants.EXCLUDE_WHITESPACE); if (dxoBeanDesc.hasField(fieldName)) { return true; } fieldName = method.getName() + "_" + DxoConstants.EXCLUDE_WHITESPACE; if (dxoBeanDesc.hasField(fieldName)) { return true; } return false; } public String getSourcePrefix(final Class dxoClass, final Method method) { final BeanDesc dxoBeanDesc = BeanDescFactory.getBeanDesc(dxoClass); String fieldName = getConstantAnnotationName(method, DxoConstants.SOURCE_PREFIX); if (dxoBeanDesc.hasField(fieldName)) { return (String) dxoBeanDesc.getFieldValue(fieldName, null); } fieldName = method.getName() + "_" + DxoConstants.SOURCE_PREFIX; if (dxoBeanDesc.hasField(fieldName)) { return (String) dxoBeanDesc.getFieldValue(fieldName, null); } return null; } public String getDestPrefix(final Class dxoClass, final Method method) { final BeanDesc dxoBeanDesc = BeanDescFactory.getBeanDesc(dxoClass); String fieldName = getConstantAnnotationName(method, DxoConstants.DEST_PREFIX); if (dxoBeanDesc.hasField(fieldName)) { return (String) dxoBeanDesc.getFieldValue(fieldName, null); } fieldName = method.getName() + "_" + DxoConstants.DEST_PREFIX; if (dxoBeanDesc.hasField(fieldName)) { return (String) dxoBeanDesc.getFieldValue(fieldName, null); } return null; } public Map getConverters(final Class destClass) { final Map converters = (Map) convertersCache.get(destClass); if (converters != null) { return converters; } return createConverters(destClass); } /** * 日付(<code>Date, Time, Timestamp</code>)と<code>String</code>の変換フォーマットを返します。 * * @param dxoClass * Dxoクラスまたはインタフェース * @param method * Dxoメソッド * @param annotation * 定数アノテーション名 * @return 変換フォーマット */ protected String getDatePattern(final Class dxoClass, final Method method, final String annotation) { final BeanDesc dxoBeanDesc = BeanDescFactory.getBeanDesc(dxoClass); String fieldName = getConstantAnnotationName(method, annotation); if (dxoBeanDesc.hasField(fieldName)) { return (String) dxoBeanDesc.getFieldValue(fieldName, null); } fieldName = method.getName() + "_" + annotation; if (dxoBeanDesc.hasField(fieldName)) { return (String) dxoBeanDesc.getFieldValue(fieldName, null); } fieldName = annotation; if (dxoBeanDesc.hasField(fieldName)) { return (String) dxoBeanDesc.getFieldValue(fieldName, null); } return null; } /** * 変換先クラスに指定されたコンバータの{@link Map}を作成して返します。 * * @param destClass * 変換先クラス * @return 変換先クラスに指定されたコンバータの{@link Map} */ protected Map createConverters(final Class destClass) { final Map converters = new HashMap(); final BeanDesc beanDesc = BeanDescFactory.getBeanDesc(destClass); for (int i = 0; i < beanDesc.getFieldSize(); ++i) { final Field field = beanDesc.getField(i); if (!ConstantAnnotationUtil.isConstantAnnotation(field)) { continue; } if (!field.getName().endsWith("DxoConverter")) { continue; } final String fieldName = field.getName(); final int index = fieldName.lastIndexOf("_"); final String propertyName = fieldName.substring(0, index); if (!beanDesc.hasPropertyDesc(propertyName)) { continue; } final String converterName = fieldName.substring(index + 1); if (!container.hasComponentDef(converterName)) { continue; } final Converter converter = (Converter) container .getComponent(converterName); final String s = (String) FieldUtil.get(field, null); final Map props = ConstantAnnotationUtil.convertExpressionToMap(s); BeanUtil.copyProperties(props, converter); converters.put(propertyName, converter); } convertersCache.put(destClass, converters); return converters; } /** * 指定されたメソッド固有の定数アノテーション名を返します。 * * @param method * メソッド * @param suffix * 定数アノテーションのsuffix * @return 指定されたメソッド固有の定数アノテーション名 */ protected String getConstantAnnotationName(final Method method, final String suffix) { final StringBuffer buf = new StringBuffer(100).append(method.getName()); final Class[] parameterTypes = method.getParameterTypes(); for (int i = 0; i < parameterTypes.length; i++) { buf.append("_").append(getShortClassName(parameterTypes[i])); } buf.append("_").append(suffix); return new String(buf); } /** * クラスを表す単純な名前を返します。 * * @param clazz * クラス * @return クラスを表す単純な名前 */ protected String getShortClassName(final Class clazz) { if (clazz.isArray()) { return ClassUtil.getShortClassName(clazz.getComponentType()) + "$"; } return ClassUtil.getShortClassName(clazz); } }