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 extends R> 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;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy