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"; } }