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

schemacrawler.crawl.MutableTable Maven / Gradle / Ivy

/*
========================================================================
SchemaCrawler
http://www.schemacrawler.com
Copyright (c) 2000-2021, 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.Comparator.naturalOrder;
import static java.util.Comparator.nullsLast;
import static schemacrawler.utility.NamedObjectSort.alphabetical;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import schemacrawler.schema.Column;
import schemacrawler.schema.ColumnReference;
import schemacrawler.schema.ForeignKey;
import schemacrawler.schema.Index;
import schemacrawler.schema.NamedObject;
import schemacrawler.schema.PrimaryKey;
import schemacrawler.schema.Privilege;
import schemacrawler.schema.Schema;
import schemacrawler.schema.Table;
import schemacrawler.schema.TableConstraint;
import schemacrawler.schema.TableReference;
import schemacrawler.schema.TableRelationshipType;
import schemacrawler.schema.TableType;
import schemacrawler.schema.Trigger;
import schemacrawler.schema.WeakAssociation;

class MutableTable extends AbstractDatabaseObject implements Table {

  private enum TableAssociationType {
    all,
    exported,
    imported
  }

  private static final long serialVersionUID = 3257290248802284852L;

  private final NamedObjectList columns = new NamedObjectList<>();
  private final NamedObjectList constraints = new NamedObjectList<>();
  private final StringBuilder definition;
  private final NamedObjectList foreignKeys = new NamedObjectList<>();
  private final NamedObjectList weakAssociations = new NamedObjectList<>();
  private final NamedObjectList hiddenColumns = new NamedObjectList<>();
  private final NamedObjectList alternateKeys = new NamedObjectList<>();
  private final NamedObjectList indexes = new NamedObjectList<>();
  private final NamedObjectList> privileges = new NamedObjectList<>();
  private final NamedObjectList triggers = new NamedObjectList<>();
  private MutablePrimaryKey primaryKey;
  private int sortIndex;
  private TableType tableType = TableType.UNKNOWN; // Default value

  MutableTable(final Schema schema, final String name) {
    super(schema, name);
    definition = new StringBuilder();
  }

  /** {@inheritDoc} */
  @Override
  public int compareTo(final NamedObject obj) {
    if (obj == null) {
      return -1;
    }

    int comparison = 0;

    if (comparison == 0 && obj instanceof MutableTable) {
      comparison = sortIndex - ((MutableTable) obj).sortIndex;
    }
    if (comparison == 0) {
      comparison = super.compareTo(obj);
    }

    return comparison;
  }

  /** {@inheritDoc} */
  @Override
  public Collection getAlternateKeys() {
    return new HashSet<>(alternateKeys.values());
  }

  /** {@inheritDoc} */
  @Override
  public List getColumns() {
    return new ArrayList<>(columns.values());
  }

  /** {@inheritDoc} */
  @Override
  public String getDefinition() {
    return definition.toString();
  }

  /** {@inheritDoc} */
  @Override
  public Collection getExportedForeignKeys() {
    return getTableReferences(foreignKeys, TableAssociationType.exported);
  }

  /** {@inheritDoc} */
  @Override
  public Collection getForeignKeys() {
    return getTableReferences(foreignKeys, TableAssociationType.all);
  }

  /** {@inheritDoc} */
  @Override
  public Collection getHiddenColumns() {
    return new HashSet<>(hiddenColumns.values());
  }

  @Override
  public Collection getImportedForeignKeys() {
    return getTableReferences(foreignKeys, TableAssociationType.imported);
  }

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

  /** {@inheritDoc} */
  @Override
  public MutablePrimaryKey getPrimaryKey() {
    return primaryKey;
  }

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

  /** {@inheritDoc} */
  @Override
  public Collection getRelatedTables(final TableRelationshipType tableRelationshipType) {
    final Set
relatedTables = new HashSet<>(); if (tableRelationshipType != null && tableRelationshipType != TableRelationshipType.none) { final List foreignKeysList = new ArrayList<>(foreignKeys.values()); for (final ForeignKey foreignKey : foreignKeysList) { for (final ColumnReference columnReference : foreignKey) { final Table parentTable = columnReference.getPrimaryKeyColumn().getParent(); final Table childTable = columnReference.getForeignKeyColumn().getParent(); switch (tableRelationshipType) { case parent: if (equals(childTable)) { relatedTables.add(parentTable); } break; case child: if (equals(parentTable)) { relatedTables.add(childTable); } break; default: break; } } } } final List
relatedTablesList = new ArrayList<>(relatedTables); relatedTablesList.sort(alphabetical); return relatedTablesList; } /** {@inheritDoc} */ @Override public Collection getTableConstraints() { return new ArrayList<>(constraints.values()); } /** {@inheritDoc} */ @Override public TableType getTableType() { return tableType; } /** {@inheritDoc} */ @Override public Collection getTriggers() { return new ArrayList<>(triggers.values()); } /** {@inheritDoc} */ @Override public final TableType getType() { return getTableType(); } /** {@inheritDoc} */ @Override public Collection getWeakAssociations() { return getTableReferences(weakAssociations, TableAssociationType.all); } @Override public boolean hasDefinition() { return definition.length() > 0; } /** {@inheritDoc} */ @Override public final boolean hasForeignKeys() { return !foreignKeys.isEmpty(); } /** {@inheritDoc} */ @Override public final boolean hasPrimaryKey() { return getPrimaryKey() != null; } /** {@inheritDoc} */ @Override public Optional lookupAlternateKey(final String name) { return alternateKeys.lookup(this, name); } /** {@inheritDoc} */ @Override public Optional lookupColumn(final String name) { Optional optionalColumn = columns.lookup(this, name); if (!optionalColumn.isPresent()) { optionalColumn = hiddenColumns.lookup(this, name); } return optionalColumn; } /** {@inheritDoc} */ @Override public Optional lookupForeignKey(final String name) { return foreignKeys.lookup(this, name); } /** {@inheritDoc} */ @Override public Optional lookupIndex(final String name) { return indexes.lookup(this, name); } /** {@inheritDoc} */ @Override public Optional> lookupPrivilege(final String name) { return privileges.lookup(this, name); } /** {@inheritDoc} */ @Override public Optional lookupTableConstraint(final String name) { return constraints.lookup(this, name); } /** * Looks up a trigger by name. * * @param triggerName Trigger name * @return Trigger, if found, or null */ @Override public Optional lookupTrigger(final String triggerName) { return triggers.lookup(this, triggerName); } final void addAlternateKey(final MutablePrimaryKey alternateKey) { alternateKeys.add(alternateKey); } final void addColumn(final MutableColumn column) { columns.add(column); } final void addForeignKey(final MutableForeignKey foreignKey) { foreignKeys.add(foreignKey); } final void addHiddenColumn(final MutableColumn column) { hiddenColumns.add(column); } final void addIndex(final MutableIndex index) { indexes.add(index); } final void addPrivilege(final MutablePrivilege
privilege) { privileges.add(privilege); } final void addTableConstraint(final TableConstraint tableConstraint) { constraints.add(tableConstraint); } final void addTrigger(final MutableTrigger trigger) { triggers.add(trigger); } final void addWeakAssociation(final MutableWeakAssociation weakAssociation) { weakAssociations.add(weakAssociation); } final void appendDefinition(final String definition) { if (definition != null) { this.definition.append(definition); } } NamedObjectList getAllColumns() { return columns; } void removeTableConstraint(final TableConstraint tableConstraint) { constraints.remove(tableConstraint); } final void setPrimaryKey(final MutablePrimaryKey primaryKey) { if (primaryKey == null) { return; } else { this.primaryKey = primaryKey; } } final void setSortIndex(final int sortIndex) { this.sortIndex = sortIndex; } final void setTableType(final TableType tableType) { if (tableType == null) { this.tableType = TableType.UNKNOWN; } else { this.tableType = tableType; } } private Collection getTableReferences( final NamedObjectList tableReferences, final TableAssociationType tableAssociationType) { final List foreignKeysList = new ArrayList<>(tableReferences.values()); if (tableAssociationType != null && tableAssociationType != TableAssociationType.all) { for (final Iterator iterator = foreignKeysList.iterator(); iterator.hasNext(); ) { final R foreignKey = iterator.next(); final boolean isExportedKey = foreignKey.getReferencedTable().equals(this); if (tableAssociationType == TableAssociationType.exported && !isExportedKey) { iterator.remove(); continue; } final boolean isImportedKey = foreignKey.getReferencingTable().equals(this); if (tableAssociationType == TableAssociationType.imported && !isImportedKey) { iterator.remove(); continue; } } } // Sort imported keys (constrained columns) first and then exported keys // Note: This comparator assumes the all the foreign keys belong to this table - either imported // or exported, and no explicit checks for this are done final Comparator fkComparator = nullsLast( ((Comparator) (final R one, final R two) -> { final boolean isOneImportedKey = one.getReferencingTable().equals(this); final boolean isTwoImportedKey = two.getReferencingTable().equals(this); if (isOneImportedKey == isTwoImportedKey) { return 0; } else if (isOneImportedKey) { return -1; } else { return 1; } }) .thenComparing(naturalOrder())); Collections.sort(foreignKeysList, fkComparator); return foreignKeysList; } }