package org.jooq.impl;
import static org.jooq.impl.Tools.EMPTY_CHECK;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.jooq.Catalog;
import org.jooq.Check;
import org.jooq.Domain;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Index;
import org.jooq.Meta;
import org.jooq.Record;
import org.jooq.Schema;
import org.jooq.Sequence;
import org.jooq.SortField;
import org.jooq.Table;
import org.jooq.TableField;
import org.jooq.UDT;
import org.jooq.UDTRecord;
import org.jooq.UniqueKey;
import org.jooq.exception.DataAccessException;
final class Snapshot extends AbstractMeta {
private static final long serialVersionUID = 5561057000510740144L;
private Meta delegate;
Snapshot(Meta meta) {
super(meta.configuration());
delegate = meta;
getCatalogs();
delegate = null;
resolveReferences();
}
private final void resolveReferences() {
for (Catalog catalog : getCatalogs())
((SnapshotCatalog) catalog).resolveReferences();
}
@Override
final List<Catalog> getCatalogs0() throws DataAccessException {
List<Catalog> result = new ArrayList<>();
for (Catalog catalog : delegate.getCatalogs())
result.add(new SnapshotCatalog(catalog));
return result;
}
private class SnapshotCatalog extends CatalogImpl {
private static final long serialVersionUID = 7979890261252183486L;
private final List<SnapshotSchema> schemas;
SnapshotCatalog(Catalog catalog) {
super(catalog.getQualifiedName(), catalog.getCommentPart());
schemas = new ArrayList<>();
for (Schema schema : catalog.getSchemas())
schemas.add(new SnapshotSchema(this, schema));
}
private final void resolveReferences() {
for (SnapshotSchema schema : schemas)
schema.resolveReferences();
}
@Override
public final List<Schema> getSchemas() {
return Collections.<Schema>unmodifiableList(schemas);
}
}
private class SnapshotSchema extends SchemaImpl {
private static final long serialVersionUID = -95755926444275258L;
private final List<SnapshotDomain<?>> domains;
private final List<SnapshotTable<?>> tables;
private final List<SnapshotSequence<?>> sequences;
private final List<SnapshotUDT<?>> udts;
SnapshotSchema(SnapshotCatalog catalog, Schema schema) {
super(schema.getQualifiedName(), catalog, schema.getCommentPart());
domains = new ArrayList<>();
tables = new ArrayList<>();
sequences = new ArrayList<>();
udts = new ArrayList<>();
for (Domain<?> domain : schema.getDomains())
domains.add(new SnapshotDomain<>(this, domain));
for (Table<?> table : schema.getTables())
tables.add(new SnapshotTable<>(this, table));
for (Sequence<?> sequence : schema.getSequences())
sequences.add(new SnapshotSequence<>(this, sequence));
for (UDT<?> udt : schema.getUDTs())
udts.add(new SnapshotUDT<>(this, udt));
}
final void resolveReferences() {
for (SnapshotTable<?> table : tables)
table.resolveReferences();
}
@Override
public final List<Domain<?>> getDomains() {
return Collections.<Domain<?>>unmodifiableList(domains);
}
@Override
public final List<Table<?>> getTables() {
return Collections.<Table<?>>unmodifiableList(tables);
}
@Override
public final List<Sequence<?>> getSequences() {
return Collections.<Sequence<?>>unmodifiableList(sequences);
}
@Override
public final List<UDT<?>> getUDTs() {
return Collections.<UDT<?>>unmodifiableList(udts);
}
}
private class SnapshotDomain<T> extends DomainImpl<T> {
private static final long serialVersionUID = -1607062195966296849L;
SnapshotDomain(SnapshotSchema schema, Domain<T> domain) {
super(schema, domain.getQualifiedName(), domain.getDataType(), domain.getChecks().toArray(EMPTY_CHECK));
}
}
private class SnapshotTable<R extends Record> extends TableImpl<R> {
private static final long serialVersionUID = -6070726881709997500L;
private final List<Index> indexes;
private final List<UniqueKey<R>> uniqueKeys;
private UniqueKey<R> primaryKey;
private final List<ForeignKey<R, ?>> foreignKeys;
private final List<Check<R>> checks;
SnapshotTable(SnapshotSchema schema, Table<R> table) {
super(table.getQualifiedName(), schema, null, null, table.getCommentPart(), table.getOptions());
indexes = new ArrayList<>();
uniqueKeys = new ArrayList<>();
foreignKeys = new ArrayList<>();
checks = new ArrayList<>();
for (Field<?> field : table.fields())
createField(field.getUnqualifiedName(), field.getDataType(), this, field.getComment());
for (Index index : table.getIndexes()) {
List<SortField<?>> indexFields = index.getFields();
SortField<?>[] copiedFields = new SortField[indexFields.size()];
for (int i = 0; i < indexFields.size(); i++) {
SortField<?> field = indexFields.get(i);
Field<?> f = field(field.getName());
copiedFields[i] = f != null ? f.sort(field.getOrder()) : field;
}
indexes.add(Internal.createIndex(index.getQualifiedName(), this, copiedFields, index.getUnique()));
}
for (UniqueKey<R> uk : table.getKeys())
uniqueKeys.add(Internal.createUniqueKey(this, uk.getQualifiedName(), fields(uk.getFieldsArray()), uk.enforced()));
UniqueKey<R> pk = table.getPrimaryKey();
for (UniqueKey<R> uk : uniqueKeys)
if (uk.equals(pk))
primaryKey = uk;
foreignKeys.addAll(table.getReferences());
checks.addAll(table.getChecks());
}
@SuppressWarnings("unchecked")
@Deprecated
private final TableField<R, ?>[] fields(TableField<R, ?>[] tableFields) {
TableField<R, ?>[] result = new TableField[tableFields.length];
for (int i = 0; i < tableFields.length; i++)
result[i] = (TableField<R, ?>) field(tableFields[i].getName());
return result;
}
final void resolveReferences() {
for (int i = 0; i < foreignKeys.size(); i++) {
ForeignKey<R, ?> fk = foreignKeys.get(i);
UniqueKey<?> uk = lookupUniqueKey(fk);
if (uk == null)
foreignKeys.remove(i);
else
foreignKeys.set(i, copyFK(this, uk, fk));
}
}
@Override
public final List<Index> getIndexes() {
return Collections.unmodifiableList(indexes);
}
@Override
public final List<UniqueKey<R>> getKeys() {
return Collections.unmodifiableList(uniqueKeys);
}
@Override
public final UniqueKey<R> getPrimaryKey() {
return primaryKey;
}
@Override
public final List<ForeignKey<R, ?>> getReferences() {
return Collections.unmodifiableList(foreignKeys);
}
@Override
public final List<Check<R>> getChecks() {
return Collections.unmodifiableList(checks);
}
}
private class SnapshotSequence<T extends Number> extends SequenceImpl<T> {
private static final long serialVersionUID = -1607062195966296849L;
SnapshotSequence(SnapshotSchema schema, Sequence<T> sequence) {
super(
sequence.getQualifiedName(),
schema,
sequence.getDataType(),
false,
sequence.getStartWith(),
sequence.getIncrementBy(),
sequence.getMinvalue(),
sequence.getMaxvalue(),
sequence.getCycle(),
sequence.getCache()
);
}
}
private class SnapshotUDT<R extends UDTRecord<R>> extends UDTImpl<R> {
private static final long serialVersionUID = -5732449514562314202L;
SnapshotUDT(SnapshotSchema schema, UDT<R> udt) {
super(udt.getName(), schema, udt.getPackage(), udt.isSynthetic());
}
}
}