/* * codjo.net * * Common Apache License 2.0 */ package net.codjo.persistent.sql; import net.codjo.persistent.Persistent; import net.codjo.persistent.Reference; import net.codjo.utils.QueryHelper; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.math.BigDecimal; // Java Class import java.sql.SQLException; import java.util.Map; import java.util.ResourceBundle; /** * Class de fabrique de clef primaire (cad d'identifiant d'une reference). * * @author $Author: blazart $ * @version $Revision: 1.3 $ */ class SimpleHomePKFactory extends SimpleHomeFactory { private boolean pkAutomatic; /** * Constructeur. * * @param resb ResourceBundle contenant la description * * @exception ClassNotFoundException Description of Exception * @exception NoSuchMethodException Description of Exception */ protected SimpleHomePKFactory(ResourceBundle resb) throws ClassNotFoundException, NoSuchMethodException { pkAutomatic = "AUTOMATIC".equals(resb.getString("primaryKey")); init(resb, "primaryKey."); } /** * Rempli la clause where du QueryHelper. * * @param qh Description of Parameter * @param ref Description of Parameter * * @exception NoSuchFieldException Description of Exception * @exception IllegalAccessException Description of Exception */ public void fillSelectorValue(QueryHelper qh, Reference ref) throws NoSuchFieldException, IllegalAccessException { Object pk = ref.getId(); if (isPkAutomatic()) { qh.setSelectorValue((String)getConstructorArgs().get(0), pk); } else if (getObjectClass() == String.class) { qh.setSelectorValue((String)getConstructorArgs().get(0), pk); } else { // @ugly : pas clair du tout a la relecture. for (int i = 0; i < getConstructorArgs().size(); i++) { debug(" selector " + i + " - " + getConstructorArgs().get(i)); String propertyName = getPropertyMapping().columnToProperty((String)getConstructorArgs() .get(i)); Field field = getObjectClass().getField(propertyName); qh.setSelectorValue((String)getConstructorArgs().get(i), field.get(pk)); } } } /** * Construit l'id (primary key) de la reference. Lorsque la clef primaire est en mode * automatique, elle est construite a l'aide du <code>QueryHelper </code>et de sa * methode <code>getUniqueId</code> . En mode manuelle, elle est construite a partir * de l'obj reference. * * @param ref Une reference ne possedant pas de clef primaire. * @param qh Description of Parameter * * @exception SQLException En mode automatique, impossible de creer un id * @exception InvocationTargetException Description of Exception * @exception IllegalAccessException Description of Exception * @exception InstantiationException Description of Exception * * @see net.codjo.utils.sql.QueryHelper#getUniqueID() */ public void buildId(Reference ref, QueryHelper qh) throws SQLException, InvocationTargetException, IllegalAccessException, InstantiationException { Object pk; if (isPkAutomatic()) { pk = new Integer(qh.getUniqueID()); } else { Persistent obj = ref.getLoadedObject(); // Init Arg Object[] constructorVals = newConstructorVals(); for (int i = 0; i < constructorVals.length; i++) { Object dbName = getConstructorArgs().get(i); int idx = getPropertyMapping().columnIndex((String)dbName); Object v = getPropertyMapping().getPropertyValue(idx, obj); if (v != null && v instanceof Persistent) { v = ((Persistent)v).getId(); } constructorVals[i] = v; } // Call constructor pk = newInstance(constructorVals); } debug("Creation d'un nouvel ID = " + pk); ref.setId(pk); } /** * Description of the Method * * @param args Description of Parameter * * @return Description of the Returned Value * * @exception InstantiationException Description of Exception * @exception IllegalAccessException Description of Exception * @exception InvocationTargetException Description of Exception */ public Object newInstance(Object[] args) throws InstantiationException, IllegalAccessException, InvocationTargetException { if (getObjectClass() == BigDecimal.class) { return args[0]; } else { return super.newInstance(args); } } /** * Rempli le tableau des valeurs . * * @param vals Description of Parameter * * @return Description of the Returned Value * * @todo a descendre dans PK */ protected Object[] fillConstructorVals(Map vals) { Object[] constructorVals = newConstructorVals(); for (int i = 0; i < getConstructorArgs().size(); i++) { constructorVals[i] = vals.get((String)getConstructorArgs().get(i)); } return constructorVals; } /** * Recherche de la classe de la Clef Primaire. * * @param resb Description of Parameter * @param classProperty Description of Parameter * * @return Description of the Returned Value * * @exception ClassNotFoundException Description of Exception */ protected Class findClass(ResourceBundle resb, String classProperty) throws ClassNotFoundException { if (isPkAutomatic()) { return Integer.class; } else { return Class.forName(resb.getString(classProperty)); } } /** * Recherche du constructeur. * * @param c Description of Parameter * * @return Description of the Returned Value * * @exception NoSuchMethodException Description of Exception */ protected Constructor findConstructor(Class c) throws NoSuchMethodException { if (isPkAutomatic() || c == Integer.class) { Class[] args = {int.class}; return c.getDeclaredConstructor(args); } else if (c == String.class) { Class[] args = {String.class}; return c.getDeclaredConstructor(args); } else if (c == BigDecimal.class) { Class[] args = {String.class}; return c.getDeclaredConstructor(args); } else { return super.findConstructor(c); } } /** * Indique si la clef primaire est automatique ou non. Lorsqu'une clef primaire est * automatique, c'est un Entier a auto-increment. * * @return <code>true</code> si la clef est gere par le Home. */ private final boolean isPkAutomatic() { return pkAutomatic; } }