package com.supaham.commons.jdbc.sql;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.supaham.commons.utils.StringUtils.checkNotNullOrEmpty;
import com.supaham.commons.utils.MapUtils;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Represents a Map implementation that is meant to store {@link Table}s to ids. This class is
* completely independent from anything SQL-related.
*/
public class TableMap {
private final Map<String, Table> tables;
public TableMap() {
this(new HashMap<String, Table>());
}
public TableMap(@Nonnull Map<String, Table> tables) {
checkNotNull(tables, "tables cannot be null.");
this.tables = tables;
}
/**
* Checks if this {@link TableMap} contains a table id.
*
* @param tableId table id to check for
*
* @return true if this {@link TableMap} contains the {@code tableId}
*
* @see #hasTable(Table)
* @see #hasTableByName(String)
*/
public boolean hasTable(@Nonnull String tableId) {
checkNotNullOrEmpty(tableId, "tableId");
return this.tables.containsKey(tableId);
}
/**
* Checks if this {@link TableMap} contains a table. This is not to be confused with the actual
* database, the {@link TableMap} can contain a table, along side a display name and a schema.
*
* @param table table to check for
*
* @return true if this {@link TableMap} contains the {@code tableName}
*/
public boolean hasTable(@Nonnull Table table) {
checkNotNull(table, "table");
return this.tables.containsValue(table);
}
/**
* Checks if this {@link TableMap} contains a table by its name.
*
* @param tableName table name to check for
*
* @return true if this {@link TableMap} contains a table with the name as {@code tableName}
*
* @throws NullPointerException thrown if {@code tableName} is null
* @throws IllegalArgumentException thrown if {@code tableName} is empty
* @see #getTableIdByName(String)
*/
public boolean hasTableByName(@Nonnull String tableName) {
checkNotNullOrEmpty(tableName, "tableName");
return getTableIdByName(tableName) != null;
}
/**
* Gracefully gets a table id by a {@link Table}'s name.
*
* @param tableName table name to check for. If null or empty, null is returned.
*
* @return the table id the the {@code tableName} belongs to
*/
@Nullable
public String getTableIdByName(@Nullable String tableName) {
if (tableName == null || tableName.isEmpty()) {
return null;
}
for (Entry<String, Table> entry : tables.entrySet()) {
if (entry.getValue().getName().equals(tableName)) {
return entry.getKey();
}
}
return null;
}
/**
* Gracefully gets a {@link Table}'s name from this {@link TableMap}.
*
* @param tableId id of the table to get the name for. If null or empty, null is returned.
*
* @return the name assigned to table {@code id}, nullable
*/
@Nullable
public Table getTable(@Nullable String tableId) {
if (tableId == null || tableId.isEmpty()) {
return null;
}
return this.tables.get(tableId);
}
/**
* Gracefully gets a {@link Table}'s name from this {@link TableMap} by table id.
*
* @param tableId id of the table to get the name for. If null or empty, null is returned.
*
* @return the name assigned to table {@code id}, nullable
*
* @see #getTable(String)
*/
@Nullable
public String getTableName(@Nullable String tableId) {
Table table = getTable(tableId);
return table == null ? null : table.getName();
}
/**
* Adds a table to this display name
*
* @param id id of the table to add
* @param name name of the table to add
* @param schema the schema of the table to add, nullable
*/
public void addTable(@Nonnull String id, @Nonnull String name, @Nullable String schema)
throws IllegalArgumentException {
checkNotNullOrEmpty(id, "id");
Table table = new Table(name, schema == null ? Table.NO_SCHEMA : schema);
addTable(id, table);
}
/**
* Adds a {@link Table} to this {@link TableMap}.
*
* @param id id to give to the table.
* @param table table to add
*
* @throws IllegalArgumentException thrown if the {@code id} already exists in this table
*/
public void addTable(@Nonnull String id, @Nonnull Table table) throws IllegalArgumentException {
checkNotNullOrEmpty(id, "id");
checkArgument(!this.tables.containsKey(id), "table already exists in this database.");
this.tables.put(id, table);
}
/**
* Removes a {@link Table} from this {@link TableMap}.
*
* @param table table to remove
*
* @return true if the {@code table} was found and removed
*/
public boolean removeTable(@Nonnull Table table) {
return MapUtils.removeValue(this.tables, table) != null;
}
/**
* Removes a {@link Table} by id from this {@link TableMap}.
*
* @param id id of the table to remove
*
* @return removed table, nullable
*/
@Nullable
public Table removeTable(@Nonnull String id) {
checkNotNullOrEmpty(id, "id");
return this.tables.remove(id);
}
/**
* Gets a {@link Map} of the table ids and their {@link Table} instances from this {@link
* TableMap}.
*
* @return map of tables
*/
public Map<String, Table> getTables() {
return Collections.unmodifiableMap(this.tables);
}
/* ================================
* >> DELEGATE METHODS
* ================================ */
/**
* @see Map#clear()
*/
public void clear() {
this.tables.clear();
}
/**
* @see Map#keySet()
*/
public Set<String> keySet() {
return tables.keySet();
}
/**
* @see Map#values()
*/
public Collection<Table> values() {
return tables.values();
}
/**
* @see Map#entrySet()
*/
public Set<Entry<String, Table>> entrySet() {
return tables.entrySet();
}
}