All Downloads are FREE. Search and download functionalities are using the official Maven repository.

schemacrawler.crawl.MutableCatalog Maven / Gradle / Ivy

Go to download

SchemaCrawler is an open-source Java API that makes working with database metadata as easy as working with plain old Java objects. SchemaCrawler is also a database schema discovery and comprehension, and schema documentation tool. You can search for database schema objects using regular expressions, and output the schema and data in a readable text format. The output is designed to be diff-ed against other database schemas.

There is a newer version: 16.24.2
Show newest version
/*
========================================================================
SchemaCrawler
http://www.schemacrawler.com
Copyright (c) 2000-2024, Sualeh Fatehi .
All rights reserved.
------------------------------------------------------------------------

SchemaCrawler 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.

SchemaCrawler and the accompanying materials are made available under
the terms of the Eclipse Public License v1.0, GNU General Public License
v3 or GNU Lesser General Public License v3.

You may elect to redistribute this code under any of these licenses.

The Eclipse Public License is available at:
http://www.eclipse.org/legal/epl-v10.html

The GNU General Public License v3 and the GNU Lesser General Public
License v3 are available at:
http://www.gnu.org/licenses/

========================================================================
*/

package schemacrawler.crawl;

import static java.util.Objects.requireNonNull;
import static us.fatehi.utility.Utility.isBlank;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Predicate;
import schemacrawler.schema.Catalog;
import schemacrawler.schema.Column;
import schemacrawler.schema.ColumnDataType;
import schemacrawler.schema.CrawlInfo;
import schemacrawler.schema.DatabaseObject;
import schemacrawler.schema.DatabaseUser;
import schemacrawler.schema.NamedObject;
import schemacrawler.schema.NamedObjectKey;
import schemacrawler.schema.Reducer;
import schemacrawler.schema.Routine;
import schemacrawler.schema.Schema;
import schemacrawler.schema.Sequence;
import schemacrawler.schema.Synonym;
import schemacrawler.schema.Table;
import schemacrawler.schemacrawler.SchemaReference;

/**
 * Database and connection information. Created from metadata returned by a JDBC call, and other
 * sources of information.
 */
final class MutableCatalog extends AbstractNamedObjectWithAttributes implements Catalog {

  private static final class FilterBySchema implements Predicate {

    private final Schema schema;

    public FilterBySchema(final Schema schema) {
      this.schema = requireNonNull(schema, "No schema provided");
    }

    @Override
    public boolean test(final DatabaseObject databaseObject) {
      return databaseObject != null && databaseObject.getSchema().equals(schema);
    }
  }

  private static final long serialVersionUID = 4051323422934251828L;

  private final NamedObjectList columnDataTypes = new NamedObjectList<>();
  private final MutableDatabaseInfo databaseInfo;
  private final MutableJdbcDriverInfo jdbcDriverInfo;
  private final NamedObjectList routines = new NamedObjectList<>();
  private final NamedObjectList schemas = new NamedObjectList<>();
  private final NamedObjectList sequences = new NamedObjectList<>();
  private final NamedObjectList synonyms = new NamedObjectList<>();
  private final NamedObjectList tables = new NamedObjectList<>();
  private final NamedObjectList databaseUsers = new NamedObjectList<>();
  private final MutableCrawlInfo crawlInfo;

  MutableCatalog(
      final String name,
      final MutableDatabaseInfo databaseInfo,
      final MutableJdbcDriverInfo jdbcDriverInfo) {
    super(name);

    this.databaseInfo = requireNonNull(databaseInfo, "No database information provided");
    this.jdbcDriverInfo = requireNonNull(jdbcDriverInfo, "No JDBC driver information provided");
    crawlInfo = new MutableCrawlInfo(databaseInfo, jdbcDriverInfo);
  }

  /** {@inheritDoc} */
  @Override
  public Collection getColumnDataTypes() {
    return new ArrayList<>(columnDataTypes.values());
  }

  /** {@inheritDoc} */
  @Override
  public Collection getColumnDataTypes(final Schema schema) {
    final FilterBySchema filter = new FilterBySchema(schema);
    final Collection columnDataTypes = new ArrayList<>();
    for (final ColumnDataType columnDataType : this.columnDataTypes) {
      if (filter.test(columnDataType)) {
        columnDataTypes.add(columnDataType);
      }
    }
    return columnDataTypes;
  }

  @Override
  public CrawlInfo getCrawlInfo() {
    return crawlInfo;
  }

  @Override
  public MutableDatabaseInfo getDatabaseInfo() {
    return databaseInfo;
  }

  /** {@inheritDoc} */
  @Override
  public Collection getDatabaseUsers() {
    return new ArrayList<>(databaseUsers.values());
  }

  /** {@inheritDoc} */
  @Override
  public MutableJdbcDriverInfo getJdbcDriverInfo() {
    return jdbcDriverInfo;
  }

  /** {@inheritDoc} */
  @Override
  public Collection getRoutines() {
    return new ArrayList<>(routines.values());
  }

  /** {@inheritDoc} */
  @Override
  public Collection getRoutines(final Schema schema) {
    return getRoutines(schema, null);
  }

  /** {@inheritDoc} */
  @Override
  public Collection getRoutines(final Schema schema, final String routineName) {
    Predicate filter = new FilterBySchema(schema);
    if (!isBlank(routineName)) {
      filter = filter.and(routine -> routine.getName().equals(routineName));
    }
    final Collection routines = new ArrayList<>();
    for (final Routine routine : this.routines) {
      if (filter.test(routine)) {
        routines.add(routine);
      }
    }
    return routines;
  }

  /** {@inheritDoc} */
  @Override
  public Collection getSchemas() {
    return new ArrayList<>(schemas.values());
  }

  /** {@inheritDoc} */
  @Override
  public Collection getSequences() {
    return new ArrayList<>(sequences.values());
  }

  /** {@inheritDoc} */
  @Override
  public Collection getSequences(final Schema schema) {
    final FilterBySchema filter = new FilterBySchema(schema);
    final Collection sequences = new ArrayList<>();
    for (final Sequence sequence : this.sequences) {
      if (filter.test(sequence)) {
        sequences.add(sequence);
      }
    }
    return sequences;
  }

  /** {@inheritDoc} */
  @Override
  public Collection getSynonyms() {
    return new ArrayList<>(synonyms.values());
  }

  /** {@inheritDoc} */
  @Override
  public Collection getSynonyms(final Schema schema) {
    final FilterBySchema filter = new FilterBySchema(schema);
    final Collection synonyms = new ArrayList<>();
    for (final Synonym synonym : this.synonyms) {
      if (filter.test(synonym)) {
        synonyms.add(synonym);
      }
    }
    return synonyms;
  }

  /** {@inheritDoc} */
  @Override
  public Collection getSystemColumnDataTypes() {
    return getColumnDataTypes(new SchemaReference());
  }

  /** {@inheritDoc} */
  @Override
  public Collection getTables() {
    return new ArrayList<>(tables.values());
  }

  /** {@inheritDoc} */
  @Override
  public Collection
getTables(final Schema schema) { final FilterBySchema filter = new FilterBySchema(schema); final Collection
tables = new ArrayList<>(); for (final Table table : this.tables) { if (filter.test(table)) { tables.add(table); } } return tables; } /** {@inheritDoc} */ @Override public Optional lookupColumn( final Schema schemaRef, final String tableName, final String name) { final Optional tableOptional = lookupTable(schemaRef, tableName); if (tableOptional.isPresent()) { final Table table = tableOptional.get(); return table.lookupColumn(name); } else { return Optional.empty(); } } /** {@inheritDoc} */ @Override public Optional lookupColumnDataType( final Schema schema, final String name) { return columnDataTypes.lookup(schema, name); } /** {@inheritDoc} */ @Override public Optional lookupSchema(final String name) { // Schemas need to be looked up by full name, since either the // catalog or schema may be null, depending on the database if (name == null) { return Optional.empty(); } for (final SchemaReference schema : schemas) { if (name.equals(schema.getFullName())) { return Optional.of(schema); } } return Optional.empty(); } /** {@inheritDoc} */ @Override public Optional lookupSequence(final Schema schemaRef, final String name) { return sequences.lookup(schemaRef, name); } /** {@inheritDoc} */ @Override public Optional lookupSynonym(final Schema schemaRef, final String name) { return synonyms.lookup(schemaRef, name); } /** {@inheritDoc} */ @Override public Optional lookupSystemColumnDataType(final String name) { return lookupColumnDataType(new SchemaReference(), name); } /** {@inheritDoc} */ @Override public Optional lookupTable(final Schema schemaRef, final String name) { return tables.lookup(schemaRef, name); } @Override public void reduce(final Class clazz, final Reducer reducer) { requireNonNull(reducer, "No reducer provided"); requireNonNull(clazz, "No lookup class provided"); if (Schema.class.isAssignableFrom(clazz)) { final Reducer schemaReducer = (Reducer) reducer; schemaReducer.reduce(schemas); } else if (Table.class.isAssignableFrom(clazz)) { // Filter the list of tables based on grep criteria, and // parent-child relationships final Reducer
tableReducer = (Reducer
) reducer; tableReducer.reduce(tables); } else if (Routine.class.isAssignableFrom(clazz)) { // Filter the list of routines based on grep criteria final Reducer routineReducer = (Reducer) reducer; routineReducer.reduce(routines); } else if (Synonym.class.isAssignableFrom(clazz)) { final Reducer synonymReducer = (Reducer) reducer; synonymReducer.reduce(synonyms); } else if (Sequence.class.isAssignableFrom(clazz)) { final Reducer sequenceReducer = (Reducer) reducer; sequenceReducer.reduce(sequences); } } @Override public void undo(final Class clazz, final Reducer reducer) { requireNonNull(reducer, "No reducer provided"); requireNonNull(clazz, "No lookup class provided"); if (Schema.class.isAssignableFrom(clazz)) { final Reducer schemaReducer = (Reducer) reducer; schemaReducer.undo(schemas); } else if (Table.class.isAssignableFrom(clazz)) { // Filter the list of tables based on grep criteria, and // parent-child relationships final Reducer
tableReducer = (Reducer
) reducer; tableReducer.undo(tables); } else if (Routine.class.isAssignableFrom(clazz)) { // Filter the list of routines based on grep criteria final Reducer routineReducer = (Reducer) reducer; routineReducer.undo(routines); } else if (Synonym.class.isAssignableFrom(clazz)) { final Reducer synonymReducer = (Reducer) reducer; synonymReducer.undo(synonyms); } else if (Sequence.class.isAssignableFrom(clazz)) { final Reducer sequenceReducer = (Reducer) reducer; sequenceReducer.undo(sequences); } } void addColumnDataType(final MutableColumnDataType columnDataType) { if (columnDataType != null) { columnDataTypes.add(columnDataType); } } void addDatabaseUser(final ImmutableDatabaseUser databaseUser) { databaseUsers.add(databaseUser); } void addRoutine(final MutableRoutine routine) { routines.add(routine); } Schema addSchema(final SchemaReference schema) { schemas.add(schema); return schema; } void addSequence(final MutableSequence sequence) { sequences.add(sequence); } void addSynonym(final MutableSynonym synonym) { synonyms.add(synonym); } void addTable(final MutableTable table) { tables.add(table); } NamedObjectList getAllRoutines() { return routines; } NamedObjectList getAllSchemas() { return schemas; } NamedObjectList getAllTables() { return tables; } MutableColumnDataType lookupBaseColumnDataTypeByType(final int baseType) { final SchemaReference systemSchema = new SchemaReference(); MutableColumnDataType columnDataType = null; int count = 0; for (final MutableColumnDataType currentColumnDataType : columnDataTypes) { if (baseType == currentColumnDataType.getJavaSqlType().getVendorTypeNumber() && currentColumnDataType.getSchema().equals(systemSchema)) { columnDataType = currentColumnDataType; count = count + 1; } } if (count == 1) { return columnDataType; } else { return null; } } Optional lookupRoutine(final NamedObjectKey routineLookupKey) { return routines.lookup(routineLookupKey); } Optional lookupTable(final NamedObjectKey tableLookupKey) { return tables.lookup(tableLookupKey); } }