Package org.hibernate.tool.hbmlint.detector

Source Code of org.hibernate.tool.hbmlint.detector.SchemaByMetaDataDetector

package org.hibernate.tool.hbmlint.detector;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;

import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.JDBCReaderFactory;
import org.hibernate.cfg.Settings;
import org.hibernate.cfg.reveng.DatabaseCollector;
import org.hibernate.cfg.reveng.DefaultDatabaseCollector;
import org.hibernate.cfg.reveng.DefaultReverseEngineeringStrategy;
import org.hibernate.cfg.reveng.JDBCReader;
import org.hibernate.cfg.reveng.JDBCToHibernateTypeHelper;
import org.hibernate.cfg.reveng.SchemaSelection;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.Mapping;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.IdentifierCollection;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.RootClass;
import org.hibernate.mapping.Table;
import org.hibernate.tool.hbmlint.Issue;
import org.hibernate.tool.hbmlint.IssueCollector;
import org.hibernate.util.StringHelper;

public class SchemaByMetaDataDetector extends RelationalModelDetector {

  public String getName() {
    return "schema";
  }
 
  JDBCReader reader;

  private TableSelectorStrategy tableSelector;

  private DatabaseCollector dbc;

  private Dialect dialect;

  private Mapping mapping;

  /** current table as read from the database */
  Table currentDbTable = null;

  public SchemaByMetaDataDetector() {

  }

  public void initialize(Configuration cfg, Settings settings) {
    super.initialize( cfg, settings );
    dialect = settings.getDialect();

    tableSelector = new TableSelectorStrategy(
        new DefaultReverseEngineeringStrategy() );
    reader = JDBCReaderFactory.newJDBCReader( cfg.getProperties(),
        settings, tableSelector );
    dbc = new DefaultDatabaseCollector(reader.getMetaDataDialect());
    mapping = cfg.buildMapping();
  }

  public void visit(Configuration cfg, IssueCollector collector) {
    super.visit( cfg, collector );
   
    visitGenerators(cfg, collector);
       
  }
 
  public void visitGenerators(Configuration cfg, IssueCollector collector) {
    Iterator iter = iterateGenerators(cfg);
   
    Set sequences = Collections.EMPTY_SET;
    if(dialect.supportsSequences()) {
      sequences = reader.readSequences(dialect.getQuerySequencesString());
    }

    // TODO: move this check into something that could check per class or collection instead.
    while ( iter.hasNext() ) {
      PersistentIdentifierGenerator generator = (PersistentIdentifierGenerator) iter.next();
      Object key = generator.generatorKey();
      if ( !isSequence(key, sequences) && !isTable( key ) ) {
        collector.reportIssue( new Issue( "MISSING_ID_GENERATOR", Issue.HIGH_PRIORITY, "Missing sequence or table: " + key));
      }
    }

   
  }

  private boolean isSequence(Object key, Set sequences) {
    if(key instanceof String) {
      if ( sequences.contains( key ) ) {
        return true;
      } else {
        String[] strings = StringHelper.split(".", (String) key);
        if(strings.length==3) {
          return sequences.contains(strings[2]);
        } else if (strings.length==2) {
          return sequences.contains(strings[1]);
        }
      }
    }
    return false;
  }

  private boolean isTable(Object key) throws HibernateException {
    // BIG HACK - should probably utilize the table cache before going to the jdbcreader :(
    if(key instanceof String) {
      String[] strings = StringHelper.split(".", (String) key);
      if(strings.length==1) {
        tableSelector.clearSchemaSelections();
        tableSelector.addSchemaSelection( new SchemaSelection(null,null, strings[0]) );
        List list = reader.readDatabaseSchema( dbc, null, null );
        return !list.isEmpty();
      } else if(strings.length==3) {
        tableSelector.clearSchemaSelections();
        tableSelector.addSchemaSelection( new SchemaSelection(strings[0],strings[1], strings[2]) );
        List list = reader.readDatabaseSchema( dbc, null, null );
        return !list.isEmpty();
      } else if (strings.length==2) {
        tableSelector.clearSchemaSelections();
        tableSelector.addSchemaSelection( new SchemaSelection(null,strings[0], strings[1]) );
        List list = reader.readDatabaseSchema( dbc, null, null );
        return !list.isEmpty();
      }
    }
    return false;
  }
 
  public void visit(Configuration cfg, Table table, IssueCollector pc) {

    if ( table.isPhysicalTable() ) {
      setSchemaSelection( table );

      List list = reader.readDatabaseSchema( dbc, null, null );

      if ( list.isEmpty() ) {
        pc.reportIssue( new Issue( "SCHEMA_TABLE_MISSING",
            Issue.HIGH_PRIORITY, "Missing table "
                + Table.qualify( table.getCatalog(), table
                    .getSchema(), table.getName() ) ) );
        return;
      }
      else if ( list.size() > 1 ) {
        pc.reportIssue( new Issue( "SCHEMA_TABLE_MISSING",
            Issue.NORMAL_PRIORITY, "Found "
                + list.size()
                + " tables for "
                + Table.qualify( table.getCatalog(), table
                    .getSchema(), table.getName() ) ) );
        return;
      }
      else {
        currentDbTable = (Table) list.get( 0 );
        visitColumns(cfg,table,pc);       
      }
    }
    else {
      // log?     
    }
  }

  String table(Table t) {
    return Table.qualify( t.getCatalog(), t.getSchema(), t.getName() );
  }
 
  public void visit(Configuration cfg, Table table, Column col,
      IssueCollector pc) {
    if ( currentDbTable == null ) {
      return;
    }

    Column dbColumn = currentDbTable
        .getColumn( new Column( col.getName() ) );

    if ( dbColumn == null ) {
      pc.reportIssue( new Issue( "SCHEMA_COLUMN_MISSING",
          Issue.HIGH_PRIORITY, table(table) + " is missing column: " + col.getName() ) );
    }
    else {
      //TODO: this needs to be able to know if a type is truly compatible or not. Right now it requires an exact match.
      //String sqlType = col.getSqlType( dialect, mapping );
      int dbTypeCode = dbColumn.getSqlTypeCode().intValue();
      int modelTypeCode = col
                .getSqlTypeCode( mapping );
      // TODO: sqltype name string
      if ( !(dbTypeCode == modelTypeCode ) ) {
        pc.reportIssue( new Issue( "SCHEMA_COLUMN_TYPE_MISMATCH",
            Issue.NORMAL_PRIORITY, table(table) + " has a wrong column type for "
                + col.getName() + ", expected: "
                + JDBCToHibernateTypeHelper.getJDBCTypeName(modelTypeCode) + " but was " + JDBCToHibernateTypeHelper.getJDBCTypeName(dbTypeCode) + " in db") );
      }
    }
  }

  private void setSchemaSelection(Table table) {
    tableSelector.clearSchemaSelections();
    tableSelector.addSchemaSelection( new SchemaSelection( table
        .getCatalog(), table.getSchema(), table.getName() ) );

  }

  /**
   *
   * @param cfg
   * @return iterator over all the IdentifierGenerator's found in the entitymodel and return a list of unique IdentifierGenerators
   * @throws MappingException
   */
  private Iterator iterateGenerators(Configuration cfg) throws MappingException {

    TreeMap generators = new TreeMap();
    String defaultCatalog = getSettings().getDefaultCatalogName();
    String defaultSchema = getSettings().getDefaultSchemaName();

    Iterator iter = cfg.getClassMappings();
    while ( iter.hasNext() ) {
      PersistentClass pc = (PersistentClass) iter.next();

      if ( !pc.isInherited() ) {

        IdentifierGenerator ig = pc.getIdentifier()
            .createIdentifierGenerator(
                cfg.getIdentifierGeneratorFactory(),
                dialect,
                defaultCatalog,
                defaultSchema,
                (RootClass) pc
              );

        if ( ig instanceof PersistentIdentifierGenerator ) {
          generators.put( ( (PersistentIdentifierGenerator) ig ).generatorKey(), ig );
        }

      }
    }

    iter = getConfiguration().getCollectionMappings();
    while ( iter.hasNext() ) {
      Collection collection = (Collection) iter.next();

      if ( collection.isIdentified() ) {

        IdentifierGenerator ig = ( (IdentifierCollection) collection ).getIdentifier()
            .createIdentifierGenerator(
                getConfiguration().getIdentifierGeneratorFactory(),
                dialect,
                defaultCatalog,
                defaultSchema,
                null
              );

        if ( ig instanceof PersistentIdentifierGenerator ) {
          generators.put( ( (PersistentIdentifierGenerator) ig ).generatorKey(), ig );
        }

      }
    }

    return generators.values().iterator();
  }

}
TOP

Related Classes of org.hibernate.tool.hbmlint.detector.SchemaByMetaDataDetector

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.