blob: 6484d02ae40abe9a1fd7246c807e6777c54cd4af [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.jdbc.schema;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.identifier.QualifiedDBIdentifier;
/**
* Represents a grouping of schemas used in a database.
*
* @author Abe White
*/
public class SchemaGroup
extends NameSet
implements Cloneable {
private static final long serialVersionUID = 1L;
private Map<DBIdentifier, Schema> _schemaMap = null;
// cache
private Schema[] _schemas = null;
/**
* Return all schemas.
*/
public Schema[] getSchemas() {
if (_schemas == null)
_schemas = (_schemaMap == null) ? new Schema[0] : (Schema[])
_schemaMap.values().toArray(new Schema[_schemaMap.size()]);
return _schemas;
}
/**
* Return the schema with the given name, or null if none.
* @deprecated
*/
@Deprecated
public Schema getSchema(String name) {
if (_schemaMap == null)
return null;
return getSchema(DBIdentifier.toUpper(DBIdentifier.newSchema(name)));
}
public Schema getSchema(DBIdentifier name) {
if (_schemaMap == null)
return null;
DBIdentifier sName = DBIdentifier.toUpper(name);
Schema schema = _schemaMap.get(sName);
return schema;
}
/**
* Add a schema to the group.
*/
public Schema addSchema() {
return addSchema(DBIdentifier.NULL);
}
/**
* Add a schema to the group.
*/
public Schema addSchema(DBIdentifier name) {
addName(name, false);
Schema schema = newSchema(name);
DBIdentifier sName = DBIdentifier.toUpper(name);
if (_schemaMap == null)
_schemaMap = new HashMap<>();
_schemaMap.put(sName, schema);
_schemas = null;
return schema;
}
/**
* @deprecated
* @param name
*/
@Deprecated
public Schema addSchema(String name) {
return addSchema(DBIdentifier.newSchema(name));
}
/**
* Remove the given schema from the group.
*
* @return true if the schema was removed, false if not in the group
*/
public boolean removeSchema(Schema schema) {
if (schema == null)
return false;
DBIdentifier name = DBIdentifier.toUpper(schema.getIdentifier());
Schema rem = _schemaMap.get(name);
if (schema.equals(rem)) {
_schemaMap.remove(name);
removeName(schema.getIdentifier());
_schemas = null;
schema.remove();
return true;
}
return false;
}
/**
* Import a schema from another group. Foreign keys are not imported.
*/
public Schema importSchema(Schema schema) {
if (schema == null)
return null;
Schema copy = addSchema(schema.getIdentifier());
Sequence[] seqs = schema.getSequences();
for (Sequence seq : seqs) {
copy.importSequence(seq);
}
Table[] tables = schema.getTables();
Index[] idxs;
Unique[] unqs;
Table tab;
for (Table table : tables) {
tab = copy.importTable(table);
idxs = table.getIndexes();
for (Index idx : idxs) {
tab.importIndex(idx);
}
unqs = table.getUniques();
for (Unique unq : unqs) {
tab.importUnique(unq);
}
}
return copy;
}
/**
* Return true if the given table is known to exist. While
* {@link #findTable} may exhibit dynamic behavior in some schema group
* implementations, this method only returns true if the table has been
* added to this group or is known to exist in the database.
*/
public boolean isKnownTable(Table table) {
return findTable(table) != null;
}
/**
* Return true if the given table is known to exist. While
* {@link #findTable} may exhibit dynamic behavior in some schema group
* implementations, this method only returns true if the table has been
* added to this group or is known to exist in the database.
* @deprecated
*/
@Deprecated
public boolean isKnownTable(String name) {
return findTable(name) != null;
}
public boolean isKnownTable(QualifiedDBIdentifier path) {
return findTable(path) != null;
}
/**
* Find the equivalent of the given table in this schema group. The
* given table that may have come from another schema group.
*/
public Table findTable(Table table) {
return findTable(table.getQualifiedPath());
}
/**
* Find the table with the given name in the group, using '.' as the
* catalog separator. Returns null if no table found.
* @deprecated
*/
@Deprecated
public Table findTable(String name) {
if (name == null)
return null;
return findTable(QualifiedDBIdentifier.getPath(DBIdentifier.newTable(name)));
}
public Table findTable(QualifiedDBIdentifier path) {
if (DBIdentifier.isNull(path)) {
return null;
}
if (!DBIdentifier.isNull(path.getSchemaName())) {
Schema schema = getSchema(path.getSchemaName());
if (schema != null)
return schema.getTable(path.getUnqualifiedName());
} else {
Schema[] schemas = getSchemas();
Table tab;
for (Schema schema : schemas) {
tab = schema.getTable(path.getIdentifier());
if (tab != null)
return tab;
}
}
return null;
}
/**
* Find the table with the given name in the group, using '.' as the catalog
* separator. Returns null if no table found.
* @deprecated
*/
@Deprecated
public Table findTable(Schema inSchema, String name) {
if (name == null)
return null;
return findTable(inSchema, DBIdentifier.newTable(name), DBIdentifier.NULL);
}
public Table findTable(Schema inSchema, DBIdentifier name) {
if (DBIdentifier.isNull(name))
return null;
return findTable(inSchema, QualifiedDBIdentifier.getPath(name), DBIdentifier.NULL);
}
public Table findTable(Schema inSchema, DBIdentifier name, DBIdentifier defaultSchemaName) {
if (DBIdentifier.isNull(name))
return null;
return findTable(inSchema, QualifiedDBIdentifier.getPath(name), defaultSchemaName);
}
public Table findTable(Schema inSchema, QualifiedDBIdentifier path, DBIdentifier defaultSchemaName) {
if (path == null)
return null;
if (!DBIdentifier.isNull(path.getSchemaName())) {
Schema schema = getSchema(path.getSchemaName());
if (schema != null)
return schema.getTable(path.getIdentifier());
} else {
Schema[] schemas = getSchemas();
for (Schema schema : schemas) {
Table tab = schema.getTable(path.getIdentifier());
// if a table is found and it has the same schema
// as the input schema , it means that the table
// exists. However, if the input schema is null,
// then we assume that there is only one table for the
// db default schema, in this case, table exists..
// We can't handle the case that one entity has schema name
// and other entity does not have schema name but both entities
// map to the same table.
boolean isDefaultSchema = DBIdentifier.isNull(inSchema.getIdentifier()) &&
!DBIdentifier.isNull(defaultSchemaName) &&
DBIdentifier.equalsIgnoreCase(defaultSchemaName, schema.getIdentifier());
boolean hasNoDefaultSchema = DBIdentifier.isNull(inSchema.getIdentifier()) &&
DBIdentifier.isNull(defaultSchemaName);
if (tab != null &&
(schema == inSchema || isDefaultSchema || hasNoDefaultSchema))
return tab;
}
}
return null;
}
/**
* Return true if the given sequence is known to exist. While
* {@link #findSequence} may exhibit dynamic behavior in some schema group
* implementations, this method only returns true if the sequence has been
* added to this group or is known to exist in the database.
*/
public boolean isKnownSequence(Sequence seq) {
return findSequence(seq) != null;
}
/**
* Return true if the given sequence is known to exist. While
* {@link #findSequence} may exhibit dynamic behavior in some schema group
* implementations, this method only returns true if the sequence has been
* added to this group or is known to exist in the database.
* @deprecated
*/
@Deprecated
public boolean isKnownSequence(String name) {
return findSequence(name) != null;
}
public boolean isKnownSequence(DBIdentifier name) {
return findSequence(QualifiedDBIdentifier.getPath(name)) != null;
}
public boolean isKnownSequence(QualifiedDBIdentifier path) {
return findSequence(path) != null;
}
/**
* Find the equivalent of the given sequence in this schema group. The
* given sequence that may have come from another schema group.
*/
public Sequence findSequence(Sequence seq) {
return findSequence(seq.getQualifiedPath());
}
/**
* Find the sequence with the given name in the group, using '.' as the
* catalog separator. Returns null if no sequence found.
* @deprecated
*/
@Deprecated
public Sequence findSequence(String name) {
if (name == null)
return null;
return findSequence(DBIdentifier.newSequence(name));
}
public Sequence findSequence(DBIdentifier name) {
if (DBIdentifier.isNull(name))
return null;
return findSequence(QualifiedDBIdentifier.getPath(name));
}
public Sequence findSequence(QualifiedDBIdentifier path) {
if (path == null)
return null;
if (!DBIdentifier.isNull(path.getSchemaName())) {
Schema schema = getSchema(path.getSchemaName());
if (schema != null)
return schema.getSequence(path.getIdentifier());
} else {
Schema[] schemas = getSchemas();
Sequence seq;
for (Schema schema : schemas) {
seq = schema.getSequence(path.getIdentifier());
if (seq != null)
return seq;
}
}
return null;
}
/**
* Find the sequence with the given name in the group, using '.' as the
* catalog separator. Returns null if no sequence found.
* @deprecated
*/
@Deprecated
public Sequence findSequence(Schema inSchema, String name) {
if (name == null)
return null;
return findSequence(inSchema, QualifiedDBIdentifier.getPath(DBIdentifier.newSequence(name)));
}
public Sequence findSequence(Schema inSchema, QualifiedDBIdentifier path) {
if (path == null)
return null;
if (!DBIdentifier.isNull(path.getSchemaName())) {
Schema schema = getSchema(path.getSchemaName());
if (schema != null)
return schema.getSequence(path.getIdentifier());
} else {
Schema[] schemas = getSchemas();
Sequence seq;
for (Schema schema : schemas) {
seq = schema.getSequence(path.getIdentifier());
if ((seq != null) &&
(schema == inSchema || DBIdentifier.isNull(inSchema.getIdentifier())))
return seq;
}
}
return null;
}
/**
* Find all foreign keys exported by a given primary key (all foreign keys
* that link to the primary key).
*/
public ForeignKey[] findExportedForeignKeys(PrimaryKey pk) {
if (pk == null)
return new ForeignKey[0];
Schema[] schemas = getSchemas();
Table[] tabs;
ForeignKey[] fks;
Collection<ForeignKey> exports = new LinkedList<>();
for (Schema schema : schemas) {
tabs = schema.getTables();
for (Table tab : tabs) {
fks = tab.getForeignKeys();
for (ForeignKey fk : fks) {
if (fk.getPrimaryKeyTable() != null
&& pk.equals(fk.getPrimaryKeyTable().
getPrimaryKey()))
exports.add(fk);
}
}
}
return exports.toArray(new ForeignKey[exports.size()]);
}
/**
* Remove unreferenced or emtpy components from the schema.
*/
public void removeUnusedComponents() {
Schema[] schemas = getSchemas();
Table[] tabs;
Column[] cols;
Sequence[] seqs;
PrimaryKey pk;
ForeignKey[] fks;
for (Schema schema : schemas) {
seqs = schema.getSequences();
for (Sequence seq : seqs)
if (seq.getRefCount() == 0)
schema.removeSequence(seq);
tabs = schema.getTables();
for (Table tab : tabs) {
pk = tab.getPrimaryKey();
fks = tab.getForeignKeys();
cols = tab.getColumns();
if (pk != null && pk.getRefCount() == 0)
tab.removePrimaryKey();
for (ForeignKey fk : fks)
if (fk.getRefCount() == 0)
tab.removeForeignKey(fk);
for (Column col : cols)
if (col.getRefCount() == 0)
tab.removeColumn(col);
if (tab.getColumns().length == 0)
schema.removeTable(tab);
}
if (schema.getTables().length == 0)
removeSchema(schema);
}
}
@Override
public Object clone() {
SchemaGroup clone = newInstance();
clone.copy(this);
return clone;
}
/**
* Create a new instance of this class.
*/
protected SchemaGroup newInstance() {
return new SchemaGroup();
}
/**
* Copy cloneable state from the given instance.
*/
protected void copy(SchemaGroup group) {
Schema[] schemas = group.getSchemas();
for (Schema value : schemas) {
importSchema(value);
}
// have to do fks after all schemas are imported
Table[] tabs;
ForeignKey[] fks;
for (Schema schema : schemas) {
tabs = schema.getTables();
for (Table tab : tabs) {
fks = tab.getForeignKeys();
for (ForeignKey fk : fks)
getSchema(schema.getIdentifier()).getTable
(tab.getIdentifier()).importForeignKey(fk);
}
}
}
/**
* Return a new schema with the given name.
* @deprecated
*/
@Deprecated
protected Schema newSchema(String name) {
return new Schema(name, this);
}
protected Schema newSchema(DBIdentifier name) {
return new Schema(name, this);
}
/**
* Return a new sequence with the given name and owner schema.
* @deprecated
*/
@Deprecated
protected Sequence newSequence(String name, Schema schema) {
return new Sequence(name, schema);
}
protected Sequence newSequence(DBIdentifier name, Schema schema) {
return new Sequence(name, schema);
}
/**
* Return a new table with the given name and owner schema.
* @deprecated
*/
@Deprecated
protected Table newTable(String name, Schema schema) {
return new Table(name, schema);
}
protected Table newTable(DBIdentifier name, Schema schema) {
return new Table(name, schema);
}
/**
* Return a new column with the given name and owner table.
* @deprecated
*/
@Deprecated
protected Column newColumn(String name, Table table) {
return new Column(name, table);
}
protected Column newColumn(DBIdentifier name, Table table) {
return new Column(name, table);
}
/**
* Return a new primary key with the given name and owner table.
* @deprecated
*/
@Deprecated
protected PrimaryKey newPrimaryKey(String name, Table table) {
return new PrimaryKey(name, table);
}
protected PrimaryKey newPrimaryKey(DBIdentifier name, Table table) {
return new PrimaryKey(name, table);
}
/**
* Return a new index with the given name and owner table.
* @deprecated
*/
@Deprecated
protected Index newIndex(String name, Table table) {
return new Index(name, table);
}
protected Index newIndex(DBIdentifier name, Table table) {
return new Index(name, table);
}
/**
* Return a new unique constraint with the given name and owner table.
* @deprecated
*/
@Deprecated
protected Unique newUnique(String name, Table table) {
return new Unique(name, table);
}
protected Unique newUnique(DBIdentifier name, Table table) {
return new Unique(name, table);
}
/**
* Return a new foreign key with the given name and owner table.
* @deprecated
*/
@Deprecated
protected ForeignKey newForeignKey(String name, Table table) {
return new ForeignKey(name, table);
}
protected ForeignKey newForeignKey(DBIdentifier name, Table table) {
return new ForeignKey(name, table);
}
}