Package org.restsql.tools.impl

Source Code of org.restsql.tools.impl.AbstractResourceDefinitionGenerator

/* Copyright (c) restSQL Project Contributors. Licensed under MIT. */
package org.restsql.tools.impl;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.restsql.core.Config;
import org.restsql.core.Factory;
import org.restsql.core.sqlresource.Database;
import org.restsql.core.sqlresource.MetaData;
import org.restsql.core.sqlresource.ObjectFactory;
import org.restsql.core.sqlresource.Query;
import org.restsql.core.sqlresource.SqlResourceDefinition;
import org.restsql.core.sqlresource.Table;
import org.restsql.tools.ResourceDefinitionGenerator;

/**
* Base implemenation for generator.
*
* @author Mark Sawers
*/
public abstract class AbstractResourceDefinitionGenerator implements ResourceDefinitionGenerator {

  @Override
  public int generate(final String relativeSubDir, final String databaseName, final String exclusionPattern) throws GenerationException {
    if (relativeSubDir == null || relativeSubDir.length() == 0) {
      throw new GenerationException("relativeSubDir required");
    } else if (databaseName == null || databaseName.length() == 0) {
      throw new GenerationException("databaseName required");
    }
    final String sqlResourcesDir = Config.properties.getProperty(Config.KEY_SQLRESOURCES_DIR,
        Config.DEFAULT_SQLRESOURCES_DIR);
    Config.logger.info("Attempting to generate resource definitions in subdirectory " + relativeSubDir
        + " for database " + databaseName);

    try {
      final File subdirObj = createSubDir(relativeSubDir, sqlResourcesDir);
      return createDefs(subdirObj, databaseName, exclusionPattern);
    } catch (final GenerationException exception) {
      Config.logger.error(exception.toString());
      throw exception;
    }
  }

  /**
   * Creates resource definitions.
   *
   * @param subDirObj subdir file object
   * @param databaseName database name
   * @return number of definitions created
   * @throws GenerationException if a database access or file write error occurs
   */
  protected int createDefs(final File subDirObj, final String databaseName, final String exclusionPattern) throws GenerationException {
    // Create definition object
    final ObjectFactory objectFactory = new ObjectFactory();
    final SqlResourceDefinition def = objectFactory.createSqlResourceDefinition();
    final Query query = objectFactory.createQuery();
    def.setQuery(query);
    final MetaData metaData = objectFactory.createMetaData();
    final Database database = objectFactory.createDatabase();
    database.setDefault(databaseName);
    metaData.setDatabase(database);
    final Table table = objectFactory.createTable();
    table.setRole("Parent");
    metaData.getTable().add(table);
    def.setMetadata(metaData);

    StringBuilder queryString = null;
    int defsCreated = 0;

    // Now inspect the information schema for columns and tables, build definition and write the files
    Connection connection = null;
    try {
      connection = Factory.getConnection(databaseName);
 
      // Build SQL query, prepare statement and execute
      String sql = getColumnsQuery();
      if (exclusionPattern != null) {
        sql += getTableExclusionQueryClause();
      }
      final PreparedStatement statement = connection.prepareStatement(sql);
      statement.setString(1, databaseName);
      if (exclusionPattern != null) {
        statement.setString(2, exclusionPattern);
      }
      Config.logger.info(sql);
      final ResultSet resultSet = statement.executeQuery();
     
      // Iterate through results, create build def and write the files
      while (resultSet.next()) {
        final String columnName = resultSet.getString(1);
        final String tableName = resultSet.getString(2);

        if (!tableName.equals(table.getName())) {
          if (defsCreated > 0) {
            // Complete previous def and write it
            queryString.append("\n\t\tFROM ");
            queryString.append(table.getName());
            queryString.append("\n\t");
            query.setValue(queryString.toString());
            writeDef(subDirObj, def, table.getName());
            table.setName(tableName);
          } else {
            table.setName(tableName);
          }

          // Start new def
          defsCreated++;
          queryString = new StringBuilder();
          queryString.append("\n\t\tSELECT ");
          queryString.append(columnName);
        } else {
          queryString.append(", ");
          queryString.append(columnName);
        }
      }
      // Finish up the last one
      if (defsCreated > 0) {
        queryString.append(" FROM ");
        queryString.append(table.getName());
        query.setValue(queryString.toString());
        writeDef(subDirObj, def, table.getName());
      }
    } catch (final SQLException exception) {
      throw new GenerationException(exception.toString());
    } finally {
      if (connection != null) {
        try {
          connection.close();
        } catch (final SQLException e) {
        }
      }
    }

    Config.logger.info("Generated " + defsCreated + " resource definitions in "
        + subDirObj.getAbsolutePath());
    return defsCreated;
  }

  /**
   * Hook method for implementation by db-specific classes. Must be preparable statement with single query param of
   * the database name. Columns returned must be column name and then table name.
   */
  protected abstract String getColumnsQuery();

  /** Returns query clause for a table name exclusion pattern. */
  protected String getTableExclusionQueryClause() {
    return " AND table_name NOT LIKE ?";
  }

  /**
   * Creates sub directory if it does not exist.
   *
   * @param relativeSubDir directory path relative to sql resources directory to create
   * @param sqlResourcesDir absolute sql resources directory
   * @throws GenerationException if subdir could not be created, or it exists and is not writable or empty
   */
  private File createSubDir(final String relativeSubDir, final String sqlResourcesDir)
      throws GenerationException {
    final File dir = new File(sqlResourcesDir + "/" + relativeSubDir);
    if (!dir.exists()) {
      if (!dir.mkdir()) {
        throw new GenerationException("Could not create subdir " + dir.getAbsolutePath());
      }
    } else {
      if (!dir.canWrite()) {
        throw new GenerationException("Cannot write to subdir " + dir.getAbsolutePath());
      } else if (dir.list().length > 0) {
        throw new GenerationException("Subdir " + dir.getAbsolutePath() + " exists and is not empty");
      }
    }
    return dir;
  }

  /**
   * Writes definition to file in provided subdirectory.
   *
   * @param subDirObj subdir file object
   * @param def sql resource definition
   * @param resourceName table name
   * @throws GenerationException if a serialization or write error occurs
   */
  private void writeDef(final File subDirObj, final SqlResourceDefinition def, final String resourceName)
      throws GenerationException {
    final String defFileName = subDirObj + "/" + resourceName + ".xml";
    try {
      final JAXBContext context = JAXBContext.newInstance(ObjectFactory.class);
      final Marshaller marshaller = context.createMarshaller();
      marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
      final FileWriter writer = new FileWriter(defFileName);
      marshaller.marshal(def, writer);
    } catch (final JAXBException exception) {
      throw new GenerationException(exception.toString());
    } catch (final IOException exception) {
      throw new GenerationException(exception.toString());
    }

    Config.logger.info("Wrote resource definition " + defFileName);
  }
}
TOP

Related Classes of org.restsql.tools.impl.AbstractResourceDefinitionGenerator

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.