package org.esreport;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
import java.util.regex.Pattern;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.search.SearchHitField;
import org.elasticsearch.search.SearchHits;
import org.json.JSONArray;
import org.json.JSONObject;
public class ESReport {
final ESLogger logger = Loggers.getLogger(ESReport.class);
Vector<String> typeMapping = new Vector<String>();
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sheet;
XSSFRow row;
XSSFCell cell;
XSSFFont font = wb.createFont();
XSSFCellStyle data_style;
XSSFCellStyle double_data_style;
XSSFCellStyle date_data_style;
XSSFCellStyle title_style;
XSSFCellStyle header_style;
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName(GlobalData.engineName);
// INPUT PARAMETERS
String index;
String type;
String config;
String statement;
String reportTitle;
String routing = "";
String nullValue = GlobalData.nullValue;
JSONArray configObj;
JSONObject queryObj;
JSONObject reportAccessType;
JSONObject valueMapping;
Settings settings;
Client esclient;
int k = 0;
long hitscount = 0;
int rows_fetched = 0;
int y = 0;
int doublePrecision = GlobalData.doublePrecision; // default 2
int columnSize = GlobalData.columnSize; // default -1 (i.e., autoSize)
int batchsize = GlobalData.batchsize; // default 5000
int i = 0;
int rownumber = 0;
ESReport() {
logger.info("Initializing Constructor");
setStyles();
}
public ESReport(Client client) {
logger.info("Initializing Constructor");
setStyles();
this.esclient = client;
}
private void setStyles() {
setDataStyle();
setTitleStyle();
setHeaderStyle();
}
private void setHeaderStyle() {
header_style = wb.createCellStyle();
font.setFontHeightInPoints((short) 11);
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
font.setColor(HSSFColor.WHITE.index);
header_style.setFont(font);
header_style.setFillForegroundColor(HSSFColor.LIGHT_BLUE.index);
header_style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
}
private void setTitleStyle() {
title_style = wb.createCellStyle();
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
font.setColor(HSSFColor.WHITE.index);
font.setFontHeightInPoints((short) 14);
title_style.setFont(font);
title_style.setFillForegroundColor(HSSFColor.LIGHT_BLUE.index);
title_style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
}
private void setDataStyle() {
data_style = wb.createCellStyle();
data_style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
data_style.setBorderTop(HSSFCellStyle.BORDER_THIN);
data_style.setBorderRight(HSSFCellStyle.BORDER_THIN);
data_style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
}
private void setDoubleDataStyle() {
double_data_style = wb.createCellStyle();
String doubleFormatString = doubleStringFormatGenerator(doublePrecision);
double_data_style.setDataFormat(wb.createDataFormat().getFormat(doubleFormatString));
}
public void process(String inputStr) {
i = 0;
logger.info("Process Started");
JSONObject input = new JSONObject(inputStr);
initializeParameters(input);
sheet = wb.createSheet(reportTitle);
setTitle();
setHeaders();
logger.info("Building Excel Report");
do {
queryObj.put("from", batchsize * k);
SearchResponse response = null;
logger.debug("Query: " + queryObj.toString());
if (routing.equals("")) {
response = esclient.prepareSearch(index).setTypes(type).setSource(queryObj.toString()).execute()
.actionGet();
} else {
response = esclient.prepareSearch(index).setTypes(type).setRouting(routing)
.setSource(queryObj.toString()).execute().actionGet();
}
SearchHits hits = response.getHits();
hitscount = hits.totalHits();
buildDataLayout(hits);
logger.debug("Processing: " + response.toString());
k++;
rows_fetched = batchsize * k;
} while (rows_fetched < hitscount);
logger.info("Finished processing data");
formatExcelSheet();
reportAccess(wb, reportAccessType);
esclient.close();
}
private void initializeParameters(JSONObject input) {
logger.info("Initializing Input Parameters");
index = input.getString(GlobalData.indexStr);
type = input.getString(GlobalData.typeStr);
config = input.get(GlobalData.configStr).toString();
statement = input.get(GlobalData.statementStr).toString();
reportTitle = input.getString(GlobalData.reportTitleStr);
if (input.has(GlobalData.valueMappingStr)) {
valueMapping = input.getJSONObject(GlobalData.valueMappingStr);
}
if (input.has(GlobalData.routingStr)) {
routing = input.getString(GlobalData.routingStr);
}
if (input.has(GlobalData.batchSizeStr)) {
batchsize = input.getInt(GlobalData.batchSizeStr);
}
if (input.has(GlobalData.nullValueStr)) {
nullValue = input.getString(GlobalData.nullValueStr);
}
configObj = new JSONArray(config);
queryObj = new JSONObject(statement);
queryObj.put("size", batchsize);
reportAccessType = input.getJSONObject(GlobalData.reportAccessStr);
if (input.has(GlobalData.columnSizeStr))
columnSize = input.getInt(GlobalData.columnSizeStr);
if (input.has(GlobalData.decimalStr))
doublePrecision = input.getInt(GlobalData.decimalStr);
setDoubleDataStyle();
// Read data format from JSON file
readTypeConfig();
k = 0;
hitscount = 0;
rows_fetched = 0;
}
private void setTitle() {
logger.info("Setting Title and Headers");
row = sheet.createRow(rownumber);
rownumber++;
cell = row.createCell(0);
cell.setCellValue(reportTitle);
cell.setCellStyle(title_style);
for (int i = 1; i < configObj.length(); i++) {
cell = row.createCell(i);
cell.setCellStyle(title_style);
}
}
private void setHeaders() {
for (int i = 1; i < configObj.length(); i++) {
cell = row.createCell(i);
cell.setCellStyle(title_style);
}
row = sheet.createRow(rownumber);
for (int i = 0; i < configObj.length(); i++) {
cell = row.createCell(i);
JSONObject headerJSON = (JSONObject) configObj.get(i);
cell.setCellValue(headerJSON.getString("title"));
cell.setCellStyle(header_style);
}
rownumber++;
}
private void buildDataLayout(SearchHits hits) {
logger.info("buildDataLayout");
// For each row
for (int i = 0; i < hits.getHits().length; i++) {
// Row n
Map<String, SearchHitField> responseFields = hits.getAt(i).getFields();
row = sheet.createRow(rownumber);
for (int j = 0; j < configObj.length(); j++) {
cell = row.createCell(j);
JSONObject headerJSON = (JSONObject) configObj.get(j);
String content = null;
content = headerJSON.getString(GlobalData.formatStr).trim();
content = getExprValue(responseFields, content);
writeToCell(j, content, cell);
}
rownumber++;
}
}
// 0 getValue
// 1 getDerivedValue
// 2 Length
// 3 Format Number Length
// 4 Sub String
// 5 Character at index
// 6 Calculate
// 7 Range
// 8 Array indexOf(int value)
// 9 Array indexOf(String value)
// 10 Array valueAt(index)
private String getExprValue(Map<String, SearchHitField> responseFields, String format) {
String exprTemp = format;
int exprIndexSize = 0;
int startIndexCount = StringUtils.countMatches(exprTemp, "[");
int endIndexCount = StringUtils.countMatches(exprTemp, "]");
if (startIndexCount == endIndexCount) {
exprIndexSize = startIndexCount;
}
for (int i = 0; i < exprIndexSize; i++) {
JSONObject exprIndex = getExprIndex(exprTemp);
String elementeryExpr = exprTemp.substring(exprIndex.getInt(GlobalData.startIndexStr) + 1,
exprIndex.getInt(GlobalData.endIndexStr));
String[] elementeryExprArray = elementeryExpr.split(",");
if (elementeryExprArray[0].equals("0")) {
String t = getValue(responseFields, elementeryExprArray[1]);
t = getExprValue(responseFields, t);
exprTemp = exprTemp
.replaceFirst(Pattern.quote(exprTemp.substring(exprIndex.getInt(GlobalData.startIndexStr),
exprIndex.getInt(GlobalData.endIndexStr) + 1)), t);
}
if (elementeryExprArray[0].equals("1")) {
String t = getDerivedValue(responseFields, elementeryExprArray[1], elementeryExprArray[2]);
t = getExprValue(responseFields, t);
exprTemp = exprTemp
.replaceFirst(Pattern.quote(exprTemp.substring(exprIndex.getInt(GlobalData.startIndexStr),
exprIndex.getInt(GlobalData.endIndexStr) + 1)), t);
}
if (elementeryExprArray[0].equals("2")) {
String t = getStringLength(elementeryExprArray[1]);
exprTemp = exprTemp
.replaceFirst(Pattern.quote(exprTemp.substring(exprIndex.getInt(GlobalData.startIndexStr),
exprIndex.getInt(GlobalData.endIndexStr) + 1)), t);
}
if (elementeryExprArray[0].equals("3")) {
String t = getFormatNumberLength(elementeryExprArray[1], Integer.valueOf(elementeryExprArray[2]));
exprTemp = exprTemp
.replaceFirst(Pattern.quote(exprTemp.substring(exprIndex.getInt(GlobalData.startIndexStr),
exprIndex.getInt(GlobalData.endIndexStr) + 1)), t);
}
if (elementeryExprArray[0].equals("4")) {
String t = getSubString(elementeryExprArray[1], Integer.valueOf(elementeryExprArray[2]),
Integer.valueOf(elementeryExprArray[3]));
exprTemp = exprTemp
.replaceFirst(Pattern.quote(exprTemp.substring(exprIndex.getInt(GlobalData.startIndexStr),
exprIndex.getInt(GlobalData.endIndexStr) + 1)), t);
}
if (elementeryExprArray[0].equals("5")) {
String t = getCharacter(elementeryExprArray[1], Integer.valueOf(elementeryExprArray[2]));
exprTemp = exprTemp
.replaceFirst(Pattern.quote(exprTemp.substring(exprIndex.getInt(GlobalData.startIndexStr),
exprIndex.getInt(GlobalData.endIndexStr) + 1)), t);
}
if (elementeryExprArray[0].equals("6")) {
String t = getComputedString(elementeryExprArray[1]);
exprTemp = exprTemp
.replaceFirst(Pattern.quote(exprTemp.substring(exprIndex.getInt(GlobalData.startIndexStr),
exprIndex.getInt(GlobalData.endIndexStr) + 1)), t);
}
if (elementeryExprArray[0].equals("7")) {
String t = getRange(elementeryExprArray[1], elementeryExprArray[2]);
t = getExprValue(responseFields, t);
exprTemp = exprTemp
.replaceFirst(Pattern.quote(exprTemp.substring(exprIndex.getInt(GlobalData.startIndexStr),
exprIndex.getInt(GlobalData.endIndexStr) + 1)), t);
}
if (elementeryExprArray[0].equals("8")) {
String t = getArrayIndexOf(responseFields, elementeryExprArray[1],
Integer.valueOf(elementeryExprArray[2]));
exprTemp = exprTemp
.replaceFirst(Pattern.quote(exprTemp.substring(exprIndex.getInt(GlobalData.startIndexStr),
exprIndex.getInt(GlobalData.endIndexStr) + 1)), String.valueOf(t));
}
if (elementeryExprArray[0].equals("9")) {
String t = getArrayIndexOf(responseFields, elementeryExprArray[1], elementeryExprArray[2]);
exprTemp = exprTemp
.replaceFirst(Pattern.quote(exprTemp.substring(exprIndex.getInt(GlobalData.startIndexStr),
exprIndex.getInt(GlobalData.endIndexStr) + 1)), String.valueOf(t));
}
if (elementeryExprArray[0].equals("10")) {
String t = getArrayValueAt(responseFields, elementeryExprArray[1],
Integer.valueOf(elementeryExprArray[2]));
exprTemp = exprTemp
.replaceFirst(Pattern.quote(exprTemp.substring(exprIndex.getInt(GlobalData.startIndexStr),
exprIndex.getInt(GlobalData.endIndexStr) + 1)), t);
}
}
return exprTemp;
}
// ProcessType: 0
private String getValue(Map<String, SearchHitField> responseFields, String fieldName) {
if (responseFields.containsKey(fieldName)) {
SearchHitField fieldValueObj = responseFields.get(fieldName);
return fieldValueObj.getValue().toString();
} else {
return nullValue;
}
}
// ProcessType: 1
private String getDerivedValue(Map<String, SearchHitField> responseFields, String valueMappingKey, String value) {
String trimValue = value.trim();
JSONObject tempMapping = valueMapping.getJSONObject(valueMappingKey);
if (tempMapping.has(trimValue)) {
return tempMapping.getString(trimValue);
} else if (tempMapping.has(GlobalData.defaultStr)) {
return tempMapping.getString(GlobalData.defaultStr);
} else {
return nullValue;
}
}
// ProcessType: 2
private String getStringLength(String fieldValue) {
if (!fieldValue.equals(nullValue)) {
return String.valueOf(fieldValue.length());
} else {
return nullValue;
}
}
// ProcessType: 3
private String getFormatNumberLength(String fieldValue, Integer formatNumberLength) {
String format = StringUtils.repeat("0", formatNumberLength);
DecimalFormat mFormat = new DecimalFormat(format);
if (StringUtils.isNumeric(fieldValue)) {
return mFormat.format(Integer.valueOf(fieldValue));
} else {
return nullValue;
}
}
// ProcessType: 4
private String getSubString(String fieldValue, int from, int end) {
if (!fieldValue.equals("-")) {
return fieldValue.substring(from, end);
} else {
return fieldValue;
}
}
// ProcessType: 5
private String getCharacter(String fieldValue, int index) {
if (index < fieldValue.length() && !fieldValue.equals(nullValue)) {
return String.valueOf(fieldValue.charAt(index));
} else {
return nullValue;
}
}
// ProcessType: 6
private String getComputedString(String fieldValue) {
if (!fieldValue.equals(nullValue) && !fieldValue.equals("")) {
try {
return String.valueOf(engine.eval(fieldValue));
} catch (ScriptException e) {
return nullValue;
}
}
return nullValue;
}
// ProcessType: 7
@SuppressWarnings("unchecked")
private String getRange(String valueMappingKey, String fieldValue) {
JSONObject tempMapping = valueMapping.getJSONObject(valueMappingKey);
if (!fieldValue.equals(nullValue) && !fieldValue.equals("")) {
Iterator<String> keys = tempMapping.keys();
while (keys.hasNext()) {
String key = keys.next();
String keyTemp = key;
key = key.replace("x", fieldValue);
try {
if ((Boolean) engine.eval(key)) {
return tempMapping.getString(keyTemp);
}
} catch (ScriptException e) {
return nullValue;
}
}
}
if (tempMapping.has(GlobalData.defaultStr)) {
return tempMapping.getString(GlobalData.defaultStr);
}
return nullValue;
}
// ProcessType: 8
private String getArrayIndexOf(Map<String, SearchHitField> responseFields, String fieldName, int value) {
try {
return String.valueOf(responseFields.get(fieldName).getValues().indexOf(value));
} catch (Exception e) {
return nullValue;
}
}
// ProcessType: 9
private String getArrayIndexOf(Map<String, SearchHitField> responseFields, String fieldName, String value) {
try {
return String.valueOf(responseFields.get(fieldName).getValues().indexOf(value));
} catch (Exception e) {
return nullValue;
}
}
// ProcessType 10
private String getArrayValueAt(Map<String, SearchHitField> responseFields, String fieldName, int arrayIndex) {
try {
return String.valueOf(responseFields.get(fieldName).getValues().get(arrayIndex));
} catch (Exception e) {
return nullValue;
}
}
private JSONObject getExprIndex(String exprTemp) {
int startIndex = 0;
int endIndex = 0;
for (int i = 0; i < exprTemp.length(); i++) {
if (exprTemp.substring(i, i + 1).equals("[")) {
startIndex = i;
continue;
}
if (exprTemp.substring(i, i + 1).equals("]")) {
endIndex = i;
break;
}
}
JSONObject exprIndex = new JSONObject();
exprIndex.put(GlobalData.startIndexStr, startIndex);
exprIndex.put(GlobalData.endIndexStr, endIndex);
return exprIndex;
}
public void reportAccess(XSSFWorkbook wb2, JSONObject reportAccess) {
DecimalFormat mFormat = new DecimalFormat("00");
Calendar date = new GregorianCalendar();
String fileName = reportAccess.getString("fileName");
fileName += "_" + date.get(Calendar.YEAR) + mFormat.format(Integer.valueOf(date.get(Calendar.MONTH) + 1))
+ date.get(Calendar.DAY_OF_MONTH) + "_" + mFormat.format(date.get(Calendar.HOUR_OF_DAY))
+ mFormat.format(date.get(Calendar.MINUTE));
JSONObject reportAccessType = null;
if (reportAccess.has(GlobalData.reportFileConfigStr)) {
logger.info("Saving file for FTP access");
reportAccessType = reportAccess.getJSONObject(GlobalData.reportFileConfigStr);
reportAccessTypeFile(wb, reportAccessType, fileName);
logger.info("Saving file for FTP access done");
} else
logger.info("Save path null!");
if (reportAccess.has(GlobalData.emailStr)) {
logger.info("Sending E-Mail...");
reportAccessType = reportAccess.getJSONObject(GlobalData.emailStr);
reportAccessTypeEMail(wb, reportAccessType, fileName);
} else
logger.info("No email will be sent!!");
}
public void reportAccessTypeEMail(XSSFWorkbook localwb, JSONObject reportAccessTypeEMail, String fileName) {
String ftpUrl = "ftp://user:psw@" + GlobalData.ftpServerName + "/" + fileName + ".xlsx";
JSONArray eMailList = reportAccessTypeEMail.getJSONArray(GlobalData.deliverToStr);
MailAPI mailAPI = new MailAPI();
if (reportAccessTypeEMail.has(GlobalData.subjectStr)) {
mailAPI.setSubject(reportAccessTypeEMail.getString(GlobalData.subjectStr));
}
if (reportAccessTypeEMail.has(GlobalData.descriptionStr)) {
mailAPI.setText(reportAccessTypeEMail.getString(GlobalData.descriptionStr));
}
mailAPI.addRecipients(eMailList);
mailAPI.setText(ftpUrl);
mailAPI.send();
logger.info("E-Mail Sent");
}
public void reportAccessTypeFile(XSSFWorkbook localWB, JSONObject reportAccessTypeFile, String fileName) {
FileOutputStream out;
try {
out = new FileOutputStream(
reportAccessTypeFile.getString(GlobalData.filePathStr) + "//" + fileName + ".xlsx");
localWB.write(out);
out.close();
} catch (FileNotFoundException e) {
logger.info("Save path write error!!");
e.printStackTrace();
} catch (IOException e) {
logger.info("Save path write error!!");
e.printStackTrace();
}
}
private void formatExcelSheet() {
if (columnSize != -1) {
for (int i = 0; i < configObj.length(); i++) {
try {
// Char size
sheet.setColumnWidth(i, columnSize * 256);
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
for (int i = 0; i < configObj.length(); i++) {
try {
sheet.autoSizeColumn(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private void readTypeConfig() {
for (int i = 0; i < configObj.length(); i++) {
JSONObject headerJSON = (JSONObject) configObj.get(i);
String type = headerJSON.getString(GlobalData.typeStr);
if (type.equals(GlobalData.doubleStr)) {
typeMapping.addElement(GlobalData.doubleStr);
} else if (type.equals(GlobalData.longStr)) {
typeMapping.addElement(GlobalData.longStr);
} else if (type.equals(GlobalData.stringStr)) {
typeMapping.addElement(GlobalData.stringStr);
} else
logger.error("Error parsing config data type!");
}
}
private void writeToCell(int colIndex, String contentValue, XSSFCell cell) {
try {
String dataType = typeMapping.get(colIndex);
switch (dataType) {
case GlobalData.doubleStr: {
if (contentValue == null || contentValue.equals(nullValue.toLowerCase())
|| contentValue.equals(nullValue.toUpperCase()) || contentValue.equals(""))
contentValue = "0";
double tempValue = Double.parseDouble(contentValue);
cell.setCellValue(tempValue);
cell.setCellType(XSSFCell.CELL_TYPE_NUMERIC);
cell.setCellStyle(double_data_style);
cell = null;
break;
}
case GlobalData.longStr: {
if (contentValue == null || contentValue.equals(nullValue.toLowerCase())
|| contentValue.equals(nullValue.toUpperCase()) || contentValue.equals(""))
contentValue = "0";
long tempValue = Long.parseLong(contentValue);
cell.setCellValue(tempValue);
cell.setCellType(XSSFCell.CELL_TYPE_NUMERIC);
cell = null;
break;
}
case GlobalData.stringStr: {
if (contentValue == null)
contentValue = "";
cell.setCellValue(contentValue);
cell = null;
break;
}
default:
logger.error("Error parsing data type!");
cell = null;
break;
}
} catch (Exception e) {
e.printStackTrace();
logger.error(e.getMessage());
}
}
private String doubleStringFormatGenerator(int precision) {
String ret = "0.";
for (int i = 0; i < precision; i++)
ret += "0";
return ret;
}
}