/* * Copyright 2008 Pavel Syrtsov * * 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 com.sf.ddao.crud.param; import com.sf.ddao.chain.CtxHelper; import com.sf.ddao.chain.MethodCallCtx; import com.sf.ddao.crud.CRUDDao; import com.sf.ddao.crud.CRUDIgnore; import com.sf.ddao.crud.DirtyPropertyAware; import com.sf.ddao.factory.param.DefaultParameter; import com.sf.ddao.factory.param.ParameterHandler; import com.sf.ddao.factory.param.ParameterHelper; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.chain.Context; import java.beans.PropertyDescriptor; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.sql.PreparedStatement; import java.sql.SQLException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; /** * Date: Oct 27, 2009 * Time: 3:36:12 PM */ public class CRUDBeanPropsParameter implements ParameterHandler { public static final String CRUD_BEAN_PROPS = "crudBeanProps"; private volatile List<PropertyDescriptor> descriptors; private int argNum; private String fmt; public void init(AnnotatedElement element, String param, boolean isRef) { int commaIdx = param.indexOf(","); if (commaIdx < 0) { throw new IllegalArgumentException("Expected 2 arguments for parameter function CRUD_BEAN_PROPS:" + param); } fmt = param.substring(commaIdx + 1); param = param.substring(0, commaIdx); argNum = Integer.parseInt(param); } public String extractParam(Context context) throws SQLException { throw new UnsupportedOperationException(); } public void appendParam(Context ctx, StringBuilder sb) throws SQLException { if (descriptors == null) { init(ctx); } int c = 0; final Object bean = getBean(ctx); DirtyPropertyAware dirtyPropertyAware = null; if (bean instanceof DirtyPropertyAware) { dirtyPropertyAware = (DirtyPropertyAware) bean; } for (PropertyDescriptor descriptor : descriptors) { if (dirtyPropertyAware != null && !dirtyPropertyAware.isDirty(descriptor.getName())) { continue; } if (c > 0) { sb.append(","); } final String fieldName = mapPropName2Field(descriptor); sb.append(MessageFormat.format(fmt, fieldName)); c++; } } public static String mapPropName2Field(PropertyDescriptor descriptor) { final String s = descriptor.getName(); StringBuilder sb = new StringBuilder(s.length()); for (char ch : s.toCharArray()) { if (Character.isUpperCase(ch)) { ch = Character.toLowerCase(ch); sb.append("_").append(ch); } else { sb.append(ch); } } return sb.toString(); } public int bindParam(PreparedStatement preparedStatement, int idx, Context ctx) throws SQLException { if (descriptors == null) { init(ctx); } int c = 0; final Object bean = getBean(ctx); DirtyPropertyAware dirtyPropertyAware = null; if (bean instanceof DirtyPropertyAware) { dirtyPropertyAware = (DirtyPropertyAware) bean; } for (PropertyDescriptor descriptor : descriptors) { try { if (dirtyPropertyAware != null && !dirtyPropertyAware.isDirty(descriptor.getName())) { continue; } Object v = descriptor.getReadMethod().invoke(bean); ParameterHelper.bind(preparedStatement, idx++, v, descriptor.getPropertyType(), ctx); c++; } catch (Exception e) { throw new SQLException(descriptor.getName(), e); } } if (dirtyPropertyAware != null) { dirtyPropertyAware.cleanDirtyBean(); } return c; } private Object getBean(Context context) { final MethodCallCtx callCtx = CtxHelper.get(context, MethodCallCtx.class); Object[] args = callCtx.getArgs(); final Object bean; if (argNum == DefaultParameter.RETURN_ARG_IDX) { bean = callCtx.getLastReturn(); } else { bean = args[argNum]; } return bean; } private synchronized void init(Context ctx) { if (descriptors != null) { return; } Class<?> beanClass = CRUDParameterService.getCRUDDaoBean(ctx, argNum); final PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(beanClass); List<PropertyDescriptor> res = new ArrayList<PropertyDescriptor>(descriptors.length); for (PropertyDescriptor descriptor : descriptors) { if (CRUDDao.IGNORED_PROPS.contains(descriptor.getName())) { continue; } final Method readMethod = descriptor.getReadMethod(); if (readMethod == null) { continue; } if (readMethod.getAnnotation(CRUDIgnore.class) != null) { continue; } res.add(descriptor); } this.descriptors = res; } }