package demo.processors;
import com.force.api.ForceApi;
import com.force.api.QueryResult;
import demo.BatchTemplate;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.amqp.core.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreatorFactory;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.sql.Types;
import java.util.*;
@Component
public class LeadProcessor extends AbstractBatchProcessor {
private Logger logger = Logger.getLogger(getClass());
private ForceApi forceApi;
private RestUtils sfdcRestUtils;
private JdbcTemplate jdbcTemplate;
@Autowired
public LeadProcessor(RestUtils sfdcRestUtils, BatchTemplate batchTemplate, JdbcTemplate jdbcTemplate, ForceApi forceApi) {
super(batchTemplate);
this.sfdcRestUtils = sfdcRestUtils;
this.jdbcTemplate = jdbcTemplate;
this.forceApi = forceApi;
}
private void log(String msg, Object... a) {
logger.info(String.format(msg, a));
}
private String camelCaseToTableCol(String x) {
String col = "";
int index = 0;
for (char c : x.toCharArray()) {
if (Character.isUpperCase(c)) {
col = col + (index == 0 ? "" : "_") + c;
} else {
col = col + c;
}
index = index + 1;
}
return col.toLowerCase();
}
private int type(Object o) {
if (o instanceof String) return Types.VARCHAR;
if (o instanceof Number) return Types.BIGINT;
if (o instanceof Date) return Types.DATE;
return Types.OTHER;
}
@Transactional
@Override
public void doProcessMessage(String batchId, Message msg) {
String q = new String(msg.getBody());
if (!org.springframework.util.StringUtils.hasText(q)) {
return;
}
String[] sooqlColNames = (" AnnualRevenue,City,Company,ConvertedAccountId,ConvertedContactId,ConvertedDate,ConvertedOpportunityId,Country,CreatedById,CreatedDate, Description,Email,EmailBouncedDate,EmailBouncedReason, " +
"FirstName,Id,Industry,IsConverted,IsDeleted,IsUnreadByOwner,Jigsaw,JigsawContactId,LastActivityDate,LastModifiedById,LastModifiedDate,LastName, LeadSource, " +
"MasterRecordId, OwnerId,Phone,PostalCode, Rating,Salutation, State,Status,Street,SystemModstamp,Title,Website ")
.trim()
.split(",");
String[] tableColNames = new String[sooqlColNames.length];
for (int i = 0; i < sooqlColNames.length; i++) {
sooqlColNames[i] = sooqlColNames[i].trim();
tableColNames[i] = camelCaseToTableCol(sooqlColNames[i]);
}
String qMarks = StringUtils.repeat("?,", 1 + tableColNames.length); //1 more because we have a batch_id column
qMarks = qMarks.substring(0, qMarks.length() - 1);
String query =
String.format("SELECT %s FROM Lead ", StringUtils.join(sooqlColNames, ",")) +
" WHERE (Company LIKE '%" + q + "%' or Email LIKE '%@%" + q +
"%') and ( City <> '') and (City <>',') and (State <> '') and (Country <> '') ";
QueryResult<Map> res = this.forceApi.query(query);
String insertIntoLeadTableSql = String.format(" insert ignore into sfdc_lead( sfdc_id, %s ) " +
" values ( %s )", StringUtils.join(tableColNames, ","), qMarks);
Set<String> sfdcIdsToAssignToBatch = new HashSet<>();
Set<Number> numbers = new HashSet<>();
for (Map<String, Object> row : res.getRecords()) {
PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(insertIntoLeadTableSql);
pscf.setReturnGeneratedKeys(true);
String sfdcId = (String) row.get("Id");
Object[] parameters = new Object[]{
// batchId,
sfdcId,
row.get("AnnualRevenue"),
row.get("City"),
row.get("Company"),
row.get("ConvertedAccountId"),
row.get("ConvertedContactId"),
sfdcRestUtils.parseDate(row.get("ConvertedDate")),
row.get("ConvertedOpportunityId"),
row.get("Country"),
row.get("CreatedById"),
sfdcRestUtils.parseDate(row.get("CreatedDate")),
row.get("Description"),
row.get("Email"),
sfdcRestUtils.parseDate(row.get("EmailBouncedDate")),
row.get("EmailBouncedReason"),
row.get("FirstName"),
row.get("Id"),
row.get("Industry"),
row.get("IsConverted"),
row.get("IsDeleted"),
row.get("IsUnreadByOwner"),
row.get("Jigsaw"),
row.get("JigsawContactId"),
sfdcRestUtils.parseDate(row.get("LastActivityDate")),
sfdcRestUtils.parseDate(row.get("LastModifiedById")),
sfdcRestUtils.parseDate(row.get("LastModifiedDate")),
row.get("LastName"),
row.get("LeadSource"),
row.get("MasterRecordId"),
row.get("OwnerId"),
row.get("Phone"),
row.get("PostalCode"),
row.get("Rating"),
row.get("Salutation"),
row.get("State"),
row.get("Status"),
row.get("Street"),
row.get("SystemModstamp"),
row.get("Title"),
row.get("Website")
};
for (Object p : parameters) {
pscf.addParameter(new SqlParameter(type(p)));
}
KeyHolder keyHolder = new GeneratedKeyHolder();
int updatedRows = this.jdbcTemplate.update(pscf.newPreparedStatementCreator(parameters), keyHolder);
Number generatedKey = keyHolder.getKey();
if (updatedRows == 0 && generatedKey == null) {
// then it already existed in the DB (insert ignore)
sfdcIdsToAssignToBatch.add(sfdcId);
} else {
// otherwise accumulate it
numbers.add(generatedKey);
}
}
// account for the batch data
List<Object[]> objects = new ArrayList<>();
for (Number k : numbers) {
objects.add(new Object[]{batchId, k});
}
log("there are " + numbers.size() + " values accumulated for the batch table");
int[] updatedRows = jdbcTemplate.batchUpdate("insert into sfdc_batch_lead( batch_id, lead_id) values(?,?)", objects);
List<String> inClause = new ArrayList<>();
for (String x : sfdcIdsToAssignToBatch) {
inClause.add(String.format("'%s'", x));
}
String insertTheRest = String.format(
"insert into sfdc_batch_lead ( batch_id, lead_id) select ?, " +
" sl._id from sfdc_lead sl where sl.sfdc_id IN ( %s )", StringUtils.join(inClause, ","));
if (sfdcIdsToAssignToBatch.size() > 0) {
int restOfUpdatedRows = jdbcTemplate.update(insertTheRest, batchId);
log("insertTheRest=" + insertTheRest);
log("restOfUpdatedRows=" + restOfUpdatedRows);
}
}
}