Java tutorial
/* * Copyright 2014 Lorenzo. * * 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 es.logongas.ix3.util; import es.logongas.ix3.core.EntityType; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import org.springframework.context.ApplicationContext; /** * clase que ayuda a crear factorias facilmente para las clase de negocio. * * @author Lorenzo * @param <T> */ public class FactoryHelper<T> { private final String domainBasePackageName; private final String interfaceBasePackageName; private final String implBasePackageName; private final String interfaceSufix; private final String implSufix; private final Class<? extends T> defaultImplClass; private final ApplicationContext context; private final String implSubPackageName; public FactoryHelper(String domainBasePackageName, String interfaceBasePackageName, String implBasePackageName, String implSubPackageName, String interfaceSufix, String implSufix, Class<? extends T> defaultImplClass, ApplicationContext context) { this.domainBasePackageName = domainBasePackageName; this.interfaceBasePackageName = interfaceBasePackageName; this.implBasePackageName = implBasePackageName; this.implSubPackageName = implSubPackageName; this.interfaceSufix = interfaceSufix; this.implSufix = implSufix; this.defaultImplClass = defaultImplClass; this.context = context; } /** * Obtiene la Implementacin de un objeto asociado a una clase de negocio. * El DAO debe tener el nombre siguiente DAONombreEntidad<<ImplSufi>>. Si no * existe una clase especfica con ese nombre se retornar * GenericDAOImplHibernate. Hay ncamente 3 paquetes donde debe estar la * clase DAONombreEntidadImplHibernate En el paquete * 'interfaceBasePackageName' , en el paquete interfaceBasePackageName y un * subpaquete igual a subtituir domainBasePackageName por * interfaceBasePackageName o en un subpaquete del interfaz llamado * "implSubPackageName" * * @param entityClass * @return El DAO de la entidad */ public T getImpl(Class entityClass) { //Hay 3 formas de encontrar el DAO String fqcn; T t; Class tClass; try { fqcn = getFQCNImplInSpecificPackage(entityClass, domainBasePackageName, implBasePackageName); tClass = Class.forName(fqcn); t = (T) context.getAutowireCapableBeanFactory().createBean(tClass); } catch (Exception ex) { //Si no existe probamos con la siguiente try { fqcn = getFQCNImplInSamePackage(entityClass, implBasePackageName); tClass = Class.forName(fqcn); t = (T) context.getAutowireCapableBeanFactory().createBean(tClass); } catch (Exception ex1) { try { fqcn = getFQCNImplInSubPackage(entityClass, domainBasePackageName, implBasePackageName); tClass = Class.forName(fqcn); t = (T) context.getAutowireCapableBeanFactory().createBean(tClass); } catch (Exception ex2) { Object bean; try { bean = context.getAutowireCapableBeanFactory().createBean(defaultImplClass); Object noProxyBean = unProxyObject(bean); if (noProxyBean instanceof EntityType) { EntityType entityType = (EntityType) noProxyBean; entityType.setEntityType(entityClass); } } catch (Exception ex3) { throw new RuntimeException(ex3); } //Pero como es generico deberemos ver si existe el interfaz Class<? extends T> interfaceClass = getInterface(entityClass); if (interfaceClass == null) { //Si no existe el interfaz no hace falta crear el Proxy pq //sera perder rendimiento. t = (T) bean; } else { t = (T) Proxy.newProxyInstance(InvocationHandlerImpl.class.getClassLoader(), new Class[] { interfaceClass }, new InvocationHandlerImpl(bean)); } } } } return t; } /** * Busca el interfaz del objeto que estamos fabricando relativo a la clase * de negocio. Si ste no existe retorna <code>null</code> * * @param entityClass La clase Java de una "Clase de negocio" * @return El interfaz */ private Class<? extends T> getInterface(Class entityClass) { //Hay 3 formas de encontrar el interface String fqcn; Class interfaceClass; try { fqcn = getFQCNInterfaceInSpecificPackage(entityClass, domainBasePackageName, interfaceBasePackageName); interfaceClass = Class.forName(fqcn); } catch (Exception ex) { //Si no existe probamos con la siguiente try { fqcn = getFQCNInterfaceInSamePackage(entityClass, interfaceBasePackageName); interfaceClass = Class.forName(fqcn); } catch (Exception ex1) { //No existe es uqe no hay un interfaz concreto interfaceClass = null; } } return interfaceClass; } private String getFQCNInterfaceInSamePackage(Class entityClass, String implBasePackageName) { if (implBasePackageName != null) { String packageName = implBasePackageName; return packageName + "." + getInterfaceClassName(entityClass); } else { return null; } } private String getFQCNInterfaceInSpecificPackage(Class entityClass, String domainBasePackageName, String interfaceBasePackageName) { if ((domainBasePackageName != null) && (interfaceBasePackageName != null)) { String packageName = entityClass.getPackage().getName().replace(domainBasePackageName, interfaceBasePackageName); return packageName + "." + getInterfaceClassName(entityClass); } else { return null; } } private String getFQCNImplInSamePackage(Class entityClass, String implBasePackageName) { if (implBasePackageName != null) { String packageName = implBasePackageName; return packageName + "." + getImplClassName(entityClass); } else { return null; } } private String getFQCNImplInSpecificPackage(Class entityClass, String domainBasePackageName, String implBasePackageName) { if ((domainBasePackageName != null) && (implBasePackageName != null)) { String packageName = entityClass.getPackage().getName().replace(domainBasePackageName, implBasePackageName); return packageName + "." + getImplClassName(entityClass); } else { return null; } } private String getFQCNImplInSubPackage(Class entityClass, String domainBasePackageName, String implBasePackageName) { if ((domainBasePackageName != null) && (implBasePackageName != null)) { String packageName = entityClass.getPackage().getName().replace(domainBasePackageName, implBasePackageName) + "." + implSubPackageName; return packageName + "." + getImplClassName(entityClass); } else { return null; } } private String getInterfaceClassName(Class entityClass) { return entityClass.getSimpleName() + interfaceSufix; } private String getImplClassName(Class entityClass) { return entityClass.getSimpleName() + implSufix; } /** * Obtiene el objeto original de un objeto si este es un proxy. Si el objeto no est en un proxy retorna el mismo objeto. * @param proxyObject El proxy * @return El objeto que contiene el proxy */ private Object unProxyObject(Object proxyObject) { try { if (proxyObject == null) { return null; } Method methodGetTargetSource = ReflectionUtil.getMethod(proxyObject.getClass(), "getTargetSource"); if (methodGetTargetSource != null) { Object targetSource = methodGetTargetSource.invoke(proxyObject); if (targetSource == null) { return proxyObject; } Method methodGetTarget = ReflectionUtil.getMethod(targetSource.getClass(), "getTarget"); if (methodGetTarget != null) { return unProxyObject(methodGetTarget.invoke(targetSource)); } else { return proxyObject; } } else { return proxyObject; } } catch (Exception ex) { throw new RuntimeException(ex); } } }