かとじゅんの技術日誌

技術の話をするところ

BuriをS2JDBC対応にしてみる その1

BuriS2DaoもしくはDBFluteを前提としているのですが、S2JDBCも対応できんじゃね?というid:imai78せんせからアドバイス受けたのでいろいろ調べてみた。とりあえず、BuriDataFieldProcRuleインターフェイスの実装をS2JDBC用に作ればよいのかな。

S2DaoToDataAccessRuleクラスをS2JDBCのサービスクラス用に多少書き換えただけの、S2JDBCToDataAccessRuleを作った。

package org.escafe.buri.compiler.util.impl.rules;

import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;

import org.escafe.buri.common.util.BuriConfiguration;
import org.escafe.buri.common.util.ClassDefUtil;
import org.escafe.buri.common.util.ClassDefUtilImpl;
import org.escafe.buri.event.util.caller.DataAccessRuleEventCaller;
import org.escafe.buri.oouo.internal.structure.BuriDataFieldType;
import org.seasar.extension.jdbc.EntityMeta;
import org.seasar.extension.jdbc.PropertyMeta;
import org.seasar.extension.jdbc.manager.JdbcManagerImplementor;
import org.seasar.framework.beans.BeanDesc;
import org.seasar.framework.beans.factory.BeanDescFactory;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.log.Logger;
import org.seasar.framework.util.ClassUtil;
import org.seasar.framework.util.StringUtil;

public class S2JDBCToDataAccessRule extends AbstractBuriDataFieldProcRule {
	private static Logger logger = Logger
			.getLogger(S2JDBCToDataAccessRule.class);

	protected String serviceKeyName = "service";
	public final String SERVICEKEY = "service";

	private BuriConfiguration configuration;
	private S2Container container;
	private ClassDefUtil classDefUtil;
	private DataAccessRuleEventCaller dataAccessRuleEventCaller;

	private JdbcManagerImplementor jdbcManagerImplementor;

	@Override
	public boolean getRequiredRule(BuriDataFieldType src) {
		if (hasName(src, "preprocess")) {
			return false;
		}
		return true;
	}

	public boolean isRequiredNegotiate(BuriDataFieldType src) {
		if (src.getKeys().size() == 0) {
			return true;
		}
		if (!hasName(src, "select")) {
			return true;
		}
		if (!hasName(src, "insert")) {
			return true;
		}
		if (!hasName(src, "update")) {
			return true;
		}
		if (!hasName(src, "delete")) {
			return true;
		}
		if (!hasName(src, "tableName")) {
			return true;
		}
		return false;
	}

	@Override
	public boolean fstCheckProcess(BuriDataFieldType src) {
		if (!isRequiredNegotiate(src)) {
			return false;
		}
		if (src.getCache().containsKey(serviceKeyName)) {

		} else if (hasName(src, SERVICEKEY)) {
			src.getCache().put(serviceKeyName, getNameVal(src, SERVICEKEY));
		}
		dataAccessRuleEventCaller.determinedRule(this, src);
		return true;
	}

	@Override
	public boolean process(BuriDataFieldType src) {
		// if( ! src.getCache().containsKey(serviceKeyName) ) {
		// return false;
		// }
		if (src.getCache().containsKey(serviceKeyName + "_end")) {
			return false;
		}
		negotiateService(src);

		dataAccessRuleEventCaller.endNegotiateDao(this, src);

		src.getCache().put(serviceKeyName + "_end", Boolean.TRUE);
		return false;
	}

	protected void negotiateService(BuriDataFieldType src) {
		String dtoClassName = src.getId();
		String serviceName = getServiceName(src, dtoClassName);
		if (serviceName != null) {
			src.getCache().put(serviceKeyName, serviceName);
			Class daoClass = container.getRoot().getComponentDef(serviceName)
					.getComponentClass();
			pkeySetup(src);

			if (src.getKeys().size() == 1) {
				String keyName = src.getKeys().keySet().toArray()[0].toString();
				BeanDesc beanDesc = BeanDescFactory.getBeanDesc(ClassUtil
						.forName(dtoClassName));
				Class tgtClass = beanDesc.getPropertyDesc(keyName)
						.getPropertyType();
				src.getCache().put(serviceKeyName + "_KeyType", tgtClass);
				src.getCache().put(serviceKeyName + "_KeyName", keyName);
				findAndSetupAllMethod(src, beanDesc, daoClass);
			}
		}

	}

	protected void findAndSetupAllMethod(BuriDataFieldType src,
			BeanDesc beanDesc, Class serviceClass) {
		Method methods[] = serviceClass.getMethods();
		for (Method method : methods) {
			String methodName = method.getName();
			selectSetup(src, method, methodName, beanDesc);
			updateSetup(src, method, methodName, beanDesc);
			deleteSetup(src, method, methodName, beanDesc);
			selectManySetup(src, method, methodName, beanDesc);
			insertSetup(src, method, methodName, beanDesc);
			tableNameSetup(src, method, methodName, beanDesc);
		}
	}

	protected void tableNameSetup(BuriDataFieldType src, Method method,
			String methodName, BeanDesc beanDesc) {
		if (!StringUtil.isEmpty(src.getTableName())) {
			return;
		}
		Class tgt = ClassUtil.forName(src.getId());

		EntityMeta entityMeta = jdbcManagerImplementor.getEntityMetaFactory()
				.getEntityMeta(tgt);
		String tableName = entityMeta.getTableMeta().getName();
		if (!StringUtil.isEmpty(tableName)) {
			src.setTableName(tableName);
		}
	}

	protected void selectManySetup(BuriDataFieldType src, Method method,
			String methodName, BeanDesc beanDesc) {
		if (!StringUtil.isEmpty(src.getSelectMany())) {
			return;
		}

		if (isSelectManyMethod(src, method, methodName)) {
			String serviceName = src.getCache().get(serviceKeyName).toString();
			src.setSelectMany(serviceName + "." + methodName + "(#data)");
		}
	}

	protected boolean isSelectManyMethod(BuriDataFieldType src, Method method,
			String methodName) {
		if (methodName.startsWith("get") || methodName.startsWith("select")) {
			if (method.getParameterTypes().length == 1) {
				if (method.getParameterTypes()[0].isAssignableFrom(List.class)) {
					return true;
				}
			}
		}
		return false;
	}

	protected void deleteSetup(BuriDataFieldType src, Method method,
			String methodName, BeanDesc beanDesc) {
		if (!StringUtil.isEmpty(src.getDelete())) {
			return;
		}

		if (isDeleteMethod(src, method, methodName)) {
			String serviceName = src.getCache().get(serviceKeyName).toString();
			src.setDelete(serviceName + "." + methodName + "(#data)");
		}
	}

	protected boolean isDeleteMethod(BuriDataFieldType src, Method method,
			String methodName) {
		if (methodName.startsWith("del")) {
			if (method.getParameterTypes().length == 1) {
				String clazzName = classDefUtil.getClassName(method
						.getParameterTypes()[0]);
				if (clazzName.equals(src.getId())) {
					return true;
				}
			}
		}
		return false;
	}

	protected void updateSetup(BuriDataFieldType src, Method method,
			String methodName, BeanDesc beanDesc) {
		if (!StringUtil.isEmpty(src.getUpdate())) {
			return;
		}

		if (isUpdateMethod(src, method, methodName)) {
			String serviceName = src.getCache().get(serviceKeyName).toString();
			src.setUpdate(serviceName + "." + methodName + "(#data)");
		}
	}

	protected boolean isUpdateMethod(BuriDataFieldType src, Method method,
			String methodName) {
		if (methodName.startsWith("update")) {
			if (method.getParameterTypes().length == 1) {
				String clazzName = classDefUtil.getClassName(method
						.getParameterTypes()[0]);
				if (clazzName.equals(src.getId())) {
					return true;
				}
			}
		}
		return false;
	}

	protected void insertSetup(BuriDataFieldType src, Method method,
			String methodName, BeanDesc beanDesc) {
		if (!StringUtil.isEmpty(src.getInsert())) {
			return;
		}

		if (isInsertMethod(src, method, methodName)) {
			String serviceName = src.getCache().get(serviceKeyName).toString();
			src.setInsert(serviceName + "." + methodName + "(#data)");
		}
	}

	protected boolean isInsertMethod(BuriDataFieldType src, Method method,
			String methodName) {
		if (methodName.startsWith("insert")) {
			if (method.getParameterTypes().length == 1) {
				String clazzName = classDefUtil.getClassName(method
						.getParameterTypes()[0]);
				if (clazzName.equals(src.getId())) {
					return true;
				}
			}
		}
		return false;
	}

	protected void selectSetup(BuriDataFieldType src, Method method,
			String methodName, BeanDesc beanDesc) {
		if (!StringUtil.isEmpty(src.getSelect())) {
			return;
		}

		if (isSelectMethod(src, method, methodName)) {
			String keyName = src.getCache().get(serviceKeyName + "_KeyName")
					.toString();
			String serviceName = src.getCache().get(serviceKeyName).toString();
			src.setSelect(serviceName + "." + methodName + "(#data." + keyName
					+ ")");
		}
	}

	protected boolean isSelectMethod(BuriDataFieldType src, Method method,
			String methodName) {
		if (methodName.startsWith("get") || methodName.startsWith("select")) {
			if (method.getParameterTypes().length == 1) {
				Class tgtClass = (Class) src.getCache().get(
						serviceKeyName + "_KeyType");
				if (method.getParameterTypes()[0].equals(tgtClass)) {
					return true;
				}
			}
		}
		return false;
	}

	protected void pkeySetup(BuriDataFieldType src) {
		if ((src.getKeys().size() > 0) || hasName(src, "pkey")) {
			return;
		}
		Class tgt = ClassUtil.forName(src.getId());

		EntityMeta entityMeta = jdbcManagerImplementor.getEntityMetaFactory()
				.getEntityMeta(tgt);
		for (PropertyMeta pm : entityMeta.getIdPropertyMetaList()) {
			String condition = createPkeyCondition(pm);
			src.getKeys().put(pm.getName(), condition);

		}
	}

	protected String createPkeyCondition(PropertyMeta pm) {
		String condition = null;
		String pkeyName = pm.getName();
		Class propType = pm.getPropertyClass();
		if (propType.equals(Long.TYPE)) {
			condition = pkeyName + " != 0";
		} else if (propType.isAssignableFrom(Number.class)) {
			condition = pkeyName + " != 0";
		} else {
			condition = pkeyName + " != null";
		}
		return condition;
	}

	protected String getServiceName(BuriDataFieldType src, String dtoClassName) {
		String dao = null;
		String shtName = createServiceName(src, dtoClassName);
		String shtName2 = shtName.substring(0, 1).toLowerCase()
				+ shtName.substring(1);
		if (container.getRoot().hasComponentDef(shtName)) {
			dao = shtName;
		} else if (container.getRoot().hasComponentDef(shtName2)) {
			dao = shtName2;
		} else {
			dao = findServiceClass(shtName, dtoClassName);
		}
		if (dao == null) {
			dao = findServiceClassFromNamespace(shtName, dtoClassName);
		}
		return dao;
	}

	protected String findServiceClassFromNamespace(String shtName,
			String dtoClassName) {
		String service = null;
		List serviceNamespace = configuration.getValList("Namespace");
		Iterator ite = serviceNamespace.iterator();
		while (ite.hasNext()) {
			String nameSpace = ite.next().toString();
			String componentName = nameSpace + "." + shtName;
			if (container.getRoot().hasComponentDef(componentName)) {
				return componentName;
			}
		}
		return service;
	}

	protected String findServiceClass(String shtName, String dtoClassName) {
		String service = null;
		List servicePackageName = configuration
				.getValList("ServicePackageName");
		Iterator ite = servicePackageName.iterator();
		while (ite.hasNext()) {
			String pacName = ite.next().toString();
			String fullName = pacName + "." + shtName;
			service = classNameToService(fullName);
			if (service != null) {
				break;
			}
		}
		/*
		 * if(dao == null) { dao = genarateDaoClass(shtName,dtoClassName); }
		 */
		return service;
	}

	/*
	 * protected String genarateDaoClass(String shtName,String dtoClassName) {
	 * Class tgtClass = ClassUtil.forName(dtoClassName); String packageName =
	 * tgtClass.getPackage().getName(); packageName =
	 * packageName.replaceAll("dto","dao") + "." + shtName; packageName =
	 * classNameToDao(packageName); return packageName; }
	 */

	protected String classNameToService(String fullName) {
		String service = null;
		if (ClassDefUtilImpl.isClassName(fullName)) {
			Class serviceClass = ClassUtil.forName(fullName);
			if (container.getRoot().hasComponentDef(serviceClass)) {
				service = container.getRoot().getComponentDef(serviceClass)
						.getComponentName();
			}
		}
		return service;
	}

	protected String createServiceName(BuriDataFieldType src,
			String dtoClassName) {
		if (hasName(src, SERVICEKEY)) {
			return getNameVal(src, SERVICEKEY);
		}
		if (dtoClassName.indexOf("$$") > -1) {
			int enhansPos = dtoClassName.indexOf("$$");
			dtoClassName = dtoClassName.substring(0, enhansPos);
		}
		Class tgtClass = ClassUtil.forName(dtoClassName);
		String shtName = ClassUtil.getShortClassName(tgtClass);
		if (shtName.length() > 3) {
			if (shtName.substring(shtName.length() - 3).equalsIgnoreCase("Dto")) {
				shtName = shtName.substring(0, shtName.length() - 3);
			}
		}
		if (shtName.length() > 6) {
			if (shtName.substring(shtName.length() - 6).equalsIgnoreCase(
					"Entity")) {
				shtName = shtName.substring(0, shtName.length() - 6);
			}
		}
		shtName = shtName + "Service";
		return shtName;
	}

	public S2Container getContainer() {
		return container;
	}

	public void setContainer(S2Container container) {
		this.container = container;
	}

	public BuriConfiguration getConfiguration() {
		return configuration;
	}

	public void setConfiguration(BuriConfiguration configuration) {
		this.configuration = configuration;
	}

	public ClassDefUtil getClassDefUtil() {
		return classDefUtil;
	}

	public void setClassDefUtil(ClassDefUtil classDefUtil) {
		this.classDefUtil = classDefUtil;
	}

	public DataAccessRuleEventCaller getDataAccessRuleEventCaller() {
		return dataAccessRuleEventCaller;
	}

	public void setDataAccessRuleEventCaller(
			DataAccessRuleEventCaller dataAccessRuleEventCaller) {
		this.dataAccessRuleEventCaller = dataAccessRuleEventCaller;
	}

	public JdbcManagerImplementor getJdbcManagerImplementor() {
		return jdbcManagerImplementor;
	}

	public void setJdbcManagerImplementor(
			JdbcManagerImplementor jdbcManagerImplementor) {
		this.jdbcManagerImplementor = jdbcManagerImplementor;
	}
}

そして、buri-share.dicon上に以下のようにすればよいのかなと。思ったりしたりしなかったりというわけで、まだデバッグもしてないのでした。まこたんせんせから、なにか指摘があることを期待して、そろそろ寝る〜w

	<component name="s2JdbcToDataAccessRule" class="org.escafe.buri.compiler.util.impl.rules.S2JDBCToDataAccessRule">
	</component>

	<component class="org.escafe.buri.compiler.util.impl.BuriDataFieldCompilePreprocessorImpl">
		<!-- snip -->
		<initMethod name="addDataAccessRules">
			<arg>s2JdbcToDataAccessRule</arg>
		</initMethod>
		<!-- snip -->
	</component>