
rapture.repo.postgres.PostgresFolderHandler Maven / Gradle / Ivy
/**
* Copyright (C) 2011-2015 Incapture Technologies LLC
*
* This is an autogenerated license statement. When copyright notices appear below
* this one that copyright supercedes this statement.
*
* Unless required by applicable law or agreed to in writing, software is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied.
*
* Unless explicit permission obtained in writing this software cannot be distributed.
*/
package rapture.repo.postgres;
import rapture.common.RaptureFolderInfo;
import rapture.common.exception.ExceptionToString;
import rapture.postgres.PostgresException;
import rapture.postgres.PostgresFactory;
import rapture.postgres.PostgresHelper;
import rapture.postgres.TemplateLoader;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.sql.DataSource;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
/**
*
* @author alanmoore
*/
public class PostgresFolderHandler {
private static Logger log = Logger.getLogger(PostgresFolderHandler.class);
private String tableName;
private String folderTable;
private Cache seriesCache = CacheBuilder.newBuilder().initialCapacity(1000).maximumSize(20000).expireAfterAccess(1,
TimeUnit.MINUTES).build();
private NamedParameterJdbcTemplate namedJdbcTemplate;
public PostgresFolderHandler(String instanceName, String tableName) {
PostgresSanitizer sanitizer = PostgresFactory.getSanitizer(instanceName);
this.tableName = sanitizer.sanitizeTableName(tableName);
this.folderTable = sanitizer.sanitizeTableName(tableName + "_folder");
}
public void setDataSource(DataSource dataSource) {
this.namedJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}
private void setupEnum() {
try {
Boolean exists = namedJdbcTemplate.getJdbcOperations()
.queryForObject("SELECT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'foldertype')", Boolean.class);
if (!exists) {
log.debug("folderType enum does not exist, creating");
namedJdbcTemplate.getJdbcOperations().execute("CREATE TYPE folderType as ENUM ('folder', 'doc');");
}
} catch (DataAccessException e) {
log.error("Could not create folder type enum: " + ExceptionToString.format(e));
}
}
public void initialize() {
// Check to see if the tables exist. If they don't, create them
setupEnum();
log.debug("Checking that " + folderTable + " exists");
boolean exists = false;
boolean skip = false;
try {
exists = PostgresHelper.tableExists(namedJdbcTemplate, folderTable);
} catch (PostgresException e) {
log.error(ExceptionToString.format(e));
skip = true; //skip, stuff is broken!
}
if (!skip) {
if (!exists) {
log.info("Table " + folderTable + " does not exist, creating");
namedJdbcTemplate.getJdbcOperations().execute(String.format("CREATE TABLE %s (\n"
+ " ID VARCHAR(1024) NOT NULL,\n"
+ " SUB VARCHAR(1024) NOT NULL,\n"
+ " N folderType NOT NULL,\n"
+ " PRIMARY KEY(ID, SUB)\n"
+ ");\n", folderTable));
}
String sql = String.format(TemplateLoader.getResourceAsString("/sqltemplates/insertFolderFunc.sql"), tableName, folderTable);
namedJdbcTemplate.update(sql, new MapSqlParameterSource());
}
}
public void removeKey(String key) {
if (key.contains("/")) {
int lastIndex = key.lastIndexOf("/");
if (lastIndex > 0) {
String parent = StringUtils.prependIfMissing(key.substring(0, lastIndex), "/");
if (lastIndex < key.length() - 1) {
String child = key.substring(lastIndex + 1, key.length());
delete(parent, child);
if (getChildren(parent).size() == 0){
lastIndex = parent.lastIndexOf("/");
String parentFolder = parent.substring(lastIndex+1);
String grandParent = StringUtils.prependIfMissing(parent.substring(0, lastIndex), "/");
delete(grandParent, parentFolder);
}
} else {
log.error(String.format("Cannot delete key ending in slash, bad input: [%s]", key));
}
} else {
delete("/", key);
}
}
}
private void delete(String parent, String child) {
String sql = String.format("DELETE FROM %s\n"
+ "WHERE id=:parent AND sub=:child", folderTable);
MapSqlParameterSource parameterSource = new MapSqlParameterSource().addValue("parent", parent, Types.VARCHAR).addValue("child", child, Types.VARCHAR);
namedJdbcTemplate.update(sql, parameterSource);
}
public List getChildren(String prefix) {
if (!prefix.startsWith("/")) {
prefix = "/" + prefix;
}
String sql = String.format("SELECT SUB, N FROM %s WHERE ID=:prefix;", folderTable);
SqlParameterSource paramSource = new MapSqlParameterSource("prefix", prefix);
RowMapper rowMapper = new RowMapper() {
@Override
public RaptureFolderInfo mapRow(ResultSet rs, int rowNum) throws SQLException {
String value = rs.getString(1);
String nature = rs.getObject(2).toString();
RaptureFolderInfo info = new RaptureFolderInfo();
info.setName(value);
info.setFolder(nature.equals("folder"));
return info;
}
};
return namedJdbcTemplate.query(sql, paramSource, rowMapper);
}
public boolean drop() {
String sql = String.format("DROP TABLE %2$s;\n"
+ "DROP FUNCTION IF EXISTS rap_insertf_%1$s(character, character, text);\n", tableName, folderTable);
namedJdbcTemplate.getJdbcOperations().execute(sql);
return true;
}
public void addKey(String key) {
boolean isPresent = seriesCache.getIfPresent(key) != null;
if (!isPresent) {
// A key is x/y/z
// We need to add / - x
// Then x -> y
// y -> z (doc)
log.debug("Key is " + key);
String[] parts = key.split("/");
String parent = "/";
for (int i = 0; i < parts.length; i++) {
String sub = parts[i];
String nature = (i < parts.length - 1) ? "folder" : "doc";
log.debug(String.format("Would add %s -> %s as %s", parent, sub, nature));
String sql = String.format("SELECT rap_insertF_%s(:parent, :sub, :nature);", tableName);
log.debug("SQL is " + sql);
SqlParameterSource paramSource = new MapSqlParameterSource("parent", parent).addValue("sub", sub).addValue("nature", nature);
RowMapper rowMapper = new RowMapper() {
@Override
public Boolean mapRow(ResultSet rs, int rowNum) throws SQLException {
return true;
}
};
namedJdbcTemplate.query(sql, paramSource, rowMapper);
parent = parent + (parent.endsWith("/") ? "" : "/") + sub;
}
seriesCache.put(key, true);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy