martedì 9 settembre 2008

Hibernate Tools: Custom Reverse Engineering/2

Gli Hibernate Tools fanno un discreto lavoro per il reverse Engineering del database, e già personalizzare i modelli usati per la generazione automatica del codice permette di incrementare la produttività.

Si può anche personalizzare la naming convention. Di default infatti una tabella t_utenti verrebbe mappata come TUtenti; se volessimo modificare questo comportamento (magari per togliere il prefisso "T" convenzionale nel database ma abbastanza inutile nel contesto OOP) dovremmo creare una nostra classe che faccia l'override del metodo tableToClassName:

package reveng;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import org.hibernate.cfg.reveng.DelegatingReverseEngineeringStrategy;
import org.hibernate.cfg.reveng.ReverseEngineeringStrategy;
import org.hibernate.cfg.reveng.TableIdentifier;

public class CustomReverseEngineeringStrategy extends DelegatingReverseEngineeringStrategy
{

  private static final String TABLE_PREFIX = "t_";

  private Properties properties = null;
  
  public CustomReverseEngineeringStrategy(ReverseEngineeringStrategy delegate)
  {
    super(delegate);
    try
    {
      properties = getPropertiesFromClasspath("reveng.properties");
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }

  public static Properties getPropertiesFromClasspath(String propFileName) throws IOException
  {
    
    if (propFileName==null || "".equals(propFileName)) return null;
    
    Properties props = new Properties();
    InputStream inputStream = getInputStreamFromClasspath(propFileName);

    if (inputStream != null)
    {
      props.load(inputStream);
      return props;     
    }

    else
    {
      return null;
    }
  }

  public static InputStream getInputStreamFromClasspath(String resourceFileName)
  {
    return CustomReverseEngineeringStrategy.class.getResourceAsStream(resourceFileName);
  }
  
  @Override
  /**
   * Genera il nome della classe a partire dal nome della tabella, ignorando il prefisso "t_"
   */
  public String tableToClassName(TableIdentifier tableIdentifier)
  {
    String tableName = tableIdentifier.getName();
    
    String className = super.tableToClassName(tableIdentifier);
    String qualifiedName = getPackageName(className);
    
    // default
    String result = className;
    
    // proprietà mappata
    String mappedProperty = (String) properties.get("table."+tableName);
    if (mappedProperty != null && mappedProperty.length()>0)
    {
      result = qualifiedName + "." + mappedProperty;
    }
    // proprietà non mappata, rimuovo il prefisso delle tabelle - se presente
    else if (tableName.startsWith(TABLE_PREFIX))
    {
      String cleanClassName = getClassName(className).substring(1);
      result = qualifiedName + "." + cleanClassName;  
    }
    
    return result;
  }
  
  public String getPackageName(String fullyQualifiedName)
  {
    int dotIndex = fullyQualifiedName.lastIndexOf('.');
    return fullyQualifiedName.substring(0, dotIndex);
  }

  public String getClassName(String fullyQualifiedName)
  {
    int dotIndex = fullyQualifiedName.lastIndexOf('.');
    return fullyQualifiedName.substring(dotIndex+1);
  }
  
  public static void main(String[] args)
  {
    CustomReverseEngineeringStrategy cres = new   CustomReverseEngineeringStrategy(null);
    System.out.println(cres.getPackageName("it.package.test.Class1"));
    System.out.println(cres.getClassName("it.package.test.Class1"));
  }
  
}
NOTA: questa classe tra l'altro cerca un file .properties nel quale siano definite le chiavi table.t_nome_tabella=NomeClasse per un ulteriore livello di personalizzazione.
NOTA2: il metodo main serve solo per effettuare un test

Nessun commento: