package com.cadrlife.devsearch.agent.service;
import com.cadrlife.devsearch.agent.UpdateScope;
import com.cadrlife.devsearch.agent.action.ProjectHandler;
import com.cadrlife.devsearch.domain.Project;
import com.google.common.base.*;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.io.Files;
import com.google.common.util.concurrent.AbstractFuture;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
public class TableDumpService extends RepoService{
private final String sqlQuery;
private final DataSource dataSource;
private final QueryRunner queryRunner;
public TableDumpService(String sqlQuery, DataSource dataSource) {
this.sqlQuery = sqlQuery;
this.dataSource = dataSource;
// QueryRunner true param is "PmdKnownBroken" - workaround for dbutils/sqlserver issue. - RM
queryRunner = new QueryRunner(dataSource, true);
}
@Override
public Iterable<ListenableFuture<Project>> pullRepo(UpdateScope updateScope) {
final Set<String> projectNames = new HashSet<>();
final Path repoCheckoutDir = checkoutRootPath.resolve(updateScope.getRepoName());
if (!updateScope.isAllProjects()) {
throw new UnsupportedOperationException("All or nothing for table dump");
}
try {
queryRunner.query(sqlQuery, new ResultSetHandler<Void>() {
@Override
public Void handle(ResultSet rs) throws SQLException {
while(rs.next()) {
List<String> emptyFields = new ArrayList<>();
StringBuilder stringBuilder = new StringBuilder();
String project = rs.getString("dev_search_project");
String path = rs.getString("dev_search_path");
projectNames.add(project);
// System.out.println(project + " - " + path);
for (int i=1; i<=rs.getMetaData().getColumnCount(); i++) {
String label = rs.getMetaData().getColumnLabel(i);
String val = rs.getString(i);
if (!label.toLowerCase().startsWith("dev_search")) {
if (CharMatcher.WHITESPACE.matchesAllOf(Strings.nullToEmpty(val))) {
emptyFields.add(label);
} else {
stringBuilder.append(label).append(": ").append(val).append("\n");
}
}
}
stringBuilder.append("\n").append("Empty fields: ").append(Joiner.on(", ").join(emptyFields)).append("\n");
Path filePath = repoCheckoutDir.resolve(project).resolve(path);
filePath.getParent().toFile().mkdirs();
try {
Files.write(stringBuilder.toString(), filePath.toFile(), Charset.defaultCharset());
} catch (IOException e) {
Throwables.propagate(e);
}
}
return null;
}
});
} catch (SQLException e) {
throw new RuntimeException("Problem dumping table", e);
}
return Iterables.transform(findProjectsByAnyName(projectNames), new Function<Project,ListenableFuture<Project>>(){
@Override
public ListenableFuture<Project> apply(final Project project) {
return Futures.immediateFuture(project);
}
});
}
@Override
public List<Project> findAllProjects() {
throw new UnsupportedOperationException("All or nothing for table dump");
}
@Override
public void updateProject(File file, Project projectName) {
throw new UnsupportedOperationException("All or nothing for table dump");
}
@Override
public String getSourceType() {
return "tabledump";
}
}