Package org.byteliberi.easydriver.generator.model

Source Code of org.byteliberi.easydriver.generator.model.MetaEasyDriverFactory

/*
* EasyDriver is a library that let a programmer build queries easier
* than using plain JDBC.
* Copyright (C) 2011 Paolo Proni
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package org.byteliberi.easydriver.generator.model;

import java.io.File;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import org.byteliberi.easydriver.generator.FieldPropertyAssociation;
import org.byteliberi.easydriver.generator.GenerationException;
import org.byteliberi.easydriver.generator.Utils;


/**
* This factory class creates the directories and reads the metadata from the database.
* @author Paolo Proni
*/
public class MetaEasyDriverFactory {
  private final static String PUBLIC = "public";
     
  /**
   * Creates the directories which match the package name
   * @param basePath Directory where to start to write down the other directories.
   * @param packageName Package name that the generated class will belong to.
   * @return String with the complete path for creating the source names.
   * @throws GenerationException It was not possible to create the directories
   */
  public static String createDir(final String basePath, final String packageName) throws GenerationException {
    final StringBuilder sb = new StringBuilder(basePath);
    if (sb.charAt(sb.length() - 1) != File.separatorChar)
      sb.append(File.separatorChar);
    sb.append(packageName.replace('.', File.separatorChar));
   
    String path = sb.toString();
   
    final File dir = new File(path);
    if (!dir.exists()) {
      final boolean ok = dir.mkdirs();
      if (!ok)
        throw new GenerationException("Not created");
    }
   
    if (path.charAt(path.length() - 1) != File.separatorChar)
      path = path + File.separatorChar;
   
    return path;
  }
 
  /**
   * Reads the metadata from the database
   * @param con Database connection
   * @return List where every item contains the metadata about a single table or a view.
   * @throws SQLException A problem occurred with the query or the database itself.
   */
  public static List<MetaEasyDriver> readMetaData(final Connection con) throws SQLException {
    final LinkedList<MetaEasyDriver> entities = new LinkedList<MetaEasyDriver>();
    final DatabaseMetaData dbMeta = con.getMetaData();
    ResultSet rsTables = null;
    try {
      rsTables = dbMeta.getTables(null, PUBLIC, null, new String[] {"TABLE","VIEW"});     
      while (rsTables.next()) {
        final String tableName = rsTables.getString(3);
        final MetaEasyDriver metaEasyDriver = new MetaEasyDriver(tableName);
        metaEasyDriver.setSchema(PUBLIC);
       
        final List<PropertyModel> props = findProperties(dbMeta, PUBLIC, tableName);       
        final HashMap<String, String> propMap = new HashMap<String, String>(props.size());
        for (PropertyModel prop : props) {
          propMap.put(prop.getName(), prop.getPropertyClass());
        }
       
        final List<FieldPropertyAssociation> fieldAssoc = Utils.findFields(dbMeta, PUBLIC, tableName);
       
        metaEasyDriver.setFields(fieldAssoc);           
        metaEasyDriver.setProperties(props);
               
       
        /* Let's look for the primary key fields. The metadata do not read easily the type of the columns,
           so we look for the already found fields ! */
        final List<PropertyModel> pks = findPrimaryKeys(dbMeta, PUBLIC, tableName);               
        for (PropertyModel pm : pks) {
          pm.setPropertyClass(propMap.get(Utils.getCamelName(pm.getName())));
        }
        metaEasyDriver.setPrimaryKey(pks);       
        metaEasyDriver.setRelationships(findRelations(dbMeta, PUBLIC, tableName))
               
        entities.add(metaEasyDriver);
      }
    }
    finally {
      if (rsTables != null)
        rsTables.close();
    }
    return entities;
  }
 
  /**
   * Finds the fields which compose a primary key.
   * @param dbMeta Database metadata.
   * @param schemaName Name of the schema.
   * @param tableName Name of the table.
   * @return List properties made by a name and a type.
   * @throws SQLException A problem occurred with the query or the database itself.
   */
  private static List<PropertyModel> findPrimaryKeys(final DatabaseMetaData dbMeta,
                            final String schemaName,
                            final String tableName) throws SQLException {
   
    final LinkedList<PropertyModel> result = new LinkedList<PropertyModel>();
    ResultSet rs = null;
    try {
      rs = dbMeta.getPrimaryKeys(null, schemaName, tableName);
      while (rs.next()) {
        final String pkName = rs.getString(4);
        final PropertyModel prop = new PropertyModel(Visibility.PRIVATE, "", Utils.getCamelName( pkName ));
       
        result.add(prop);
      }
    }
    finally {
      if (rs != null)
        rs.close();
    }
    return result;
  }
 
  /**
   * Read the fields of a table and creates the model for some Java properties
   * which match those fields.
   *
   * @param dbMeta Database meta data
   * @param schemaName Name of the database schema.
   * @param tableName Name of the table
   * @return List of property which match the columns
   * @throws SQLException A problem occurred with the query or the database itself.
   */
  private static List<PropertyModel> findProperties(final DatabaseMetaData dbMeta,
                             final String schemaName,
                             final String tableName) throws SQLException {
   
    final LinkedList<PropertyModel> found = new LinkedList<PropertyModel>();
    ResultSet rs = null;
    try {
      rs = dbMeta.getColumns(null, schemaName, tableName, null);     
      while (rs.next()) {
        final String columnName = Utils.getCamelName( rs.getString(4) );
        final int columnType = rs.getInt(5);
        final String className = Utils.getJavaType(columnType);
        found.add(new PropertyModel(Visibility.PRIVATE, className, columnName));
      }
    }
    finally {
      if (rs != null)
        rs.close();
    }
    return found; 
  }
 
 
 
  /**
   * This method returns the Java class name which best matches with given column.
   * @param dbMeta Database metadata.
   * @param schemaName Name of the schema.
   * @param table Name of the table.
   * @param column Column name
   * @return Java class name which matches the column type
   * @throws SQLException A problem occurred with the query or the database itself.
   */
  private static String getJavaTypeForColumn(final DatabaseMetaData dbMeta, final String schemaName, final String table, final String column) throws SQLException {
    String javaType="";
    ResultSet rs = null;
    try {
      rs = dbMeta.getColumns(null, schemaName, table, column);
      while (rs.next()) {
        javaType = Utils.getJavaType(rs.getInt(5));
      }
    }
    finally {
      if (rs != null)
        rs.close();
    }
    return javaType;
  }
 
  /**
   * Creates a collection where each item is a list of relations with related tables and fields.
   * @param dbMeta Database metadata.
   * @param schemaName Name of the schema.
   * @param table Name of the table.
   * @return Each item is a relationship between two tables, but every relationship is made by
   * on or more fields. Each field couple is an element of the list.
   * @throws SQLException A problem occurred with the query or the database itself.
   */
  private static Collection<List<RelationModel>> findRelations(final DatabaseMetaData dbMeta, final String schemaName, final String table) throws SQLException {         
    final HashMap<String, List<RelationModel>> foundRel = new HashMap<String, List<RelationModel>>();
   
    ResultSet rs = null;
    try {
      rs = dbMeta.getImportedKeys(null, schemaName, table);
     
      while (rs.next()) {
        final String oneTable = rs.getString(3);
        final String pkOneTable = rs.getString(4);
//        final String manyTable = rs.getString(7);
        final String rfManyTable = rs.getString(8);
       
        List<RelationModel> rels;
        if (foundRel.containsKey(oneTable))
          rels = foundRel.get(oneTable);
        else {
          rels = new LinkedList<RelationModel>();
          foundRel.put(oneTable, rels);
        }
       
        rels.add(new RelationModel(oneTable, pkOneTable, rfManyTable, getJavaTypeForColumn(dbMeta, schemaName, oneTable, pkOneTable)));
      }
    }
    finally {
      if (rs != null)
        rs.close();
    }
   
    return foundRel.values();
  }
}
TOP

Related Classes of org.byteliberi.easydriver.generator.model.MetaEasyDriverFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.