/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2005-2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2007-2012, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.coverage.sql;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.geotoolkit.internal.sql.table.Database;
import org.geotoolkit.internal.sql.table.LocalCache;
import org.geotoolkit.internal.sql.table.QueryType;
import org.geotoolkit.internal.sql.table.SingletonTable;
import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
/**
* Connection to a table of {@linkplain Layer layers}.
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @version 3.15
*
* @since 3.10 (derived from Seagis)
* @module
*/
final class LayerTable extends SingletonTable<LayerEntry> {
/**
* Creates a layer table.
*
* @param database Connection to the database.
*/
public LayerTable(final Database database) {
this(new LayerQuery(database));
}
/**
* Constructs a new {@code LayerTable} from the specified query.
*/
private LayerTable(final LayerQuery query) {
super(query, query.byName);
}
/**
* Creates a new instance having the same configuration than the given table.
* This is a copy constructor used for obtaining a new instance to be used
* concurrently with the original instance.
*
* @param table The table to use as a template.
*/
private LayerTable(final LayerTable table) {
super(table);
}
/**
* Returns a copy of this table. This is a copy constructor used for obtaining
* a new instance to be used concurrently with the original instance.
*/
@Override
protected LayerTable clone() {
return new LayerTable(this);
}
/**
* Creates a layer from the current row in the specified result set.
*
* @param results The result set to read.
* @param identifier The identifier of the layer to create.
* @return The entry for current row in the specified result set.
* @throws SQLException if an error occurred while reading the database.
*/
@Override
protected LayerEntry createEntry(final LocalCache lc, final ResultSet results, final Comparable<?> identifier)
throws SQLException
{
final LayerQuery query = (LayerQuery) super.query;
double period = results.getDouble(indexOf(query.period));
if (results.wasNull()) {
period = Double.NaN;
}
final String fallback = results.getString(indexOf(query.fallback));
final String comments = results.getString(indexOf(query.comments));
return new LayerEntry(identifier, period, fallback, comments, (TableFactory) getDatabase());
}
/**
* Creates a new layer if none exist for the given name.
*
* @param name The name of the layer.
* @return {@code true} if a new layer has been created, or {@code false} if it already exists.
* @throws SQLException if an error occurred while reading or writing the database.
*/
final boolean createIfAbsent(final String name) throws SQLException {
ensureNonNull("name", name);
if (exists(name)) {
return false;
}
final LayerQuery query = (LayerQuery) super.query;
final LocalCache lc = getLocalCache();
synchronized (lc) {
boolean success = false;
transactionBegin(lc);
try {
final LocalCache.Stmt ce = getStatement(lc, QueryType.INSERT);
final PreparedStatement statement = ce.statement;
statement.setString(indexOf(query.name), name);
success = updateSingleton(statement);
release(lc, ce);
} finally {
transactionEnd(lc, success);
}
}
return true;
}
/**
* Searches for a layer name not already in use. If the given string is not in use, then
* it is returned as-is. Otherwise this method appends a unused decimal number to the
* specified name.
*
* @since 3.11
*/
public String searchFreeIdentifier(final String base) throws SQLException {
final LocalCache lc = getLocalCache();
synchronized (lc) {
return searchFreeIdentifier(lc, base);
}
}
}