package ro.nextreports.server.domain; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.jcrom.annotations.JcrChildNode; import org.jcrom.annotations.JcrProperty; import ro.nextreports.engine.querybuilder.sql.Operator; import ro.nextreports.server.util.AnalysisUtil; public class Analysis extends Entity { private static final long serialVersionUID = 1L; @JcrProperty private String reportId; @JcrProperty private String tableName; @JcrProperty(converter = JcrListExpressionConverter.class) private List<String> columns; @JcrProperty(converter = JcrMapExpressionConverter.class) private Map<String, String> columnTypes = new HashMap<String, String>(); @JcrProperty private List<Boolean> selected = new LinkedList<Boolean>(); @JcrProperty private List<String> sortProperty = new LinkedList<String>(); @JcrProperty private List<Boolean> ascending = new LinkedList<Boolean>(); @JcrProperty private int rowsPerPage; @JcrChildNode private List<AnalysisFilter> filters = new ArrayList<AnalysisFilter>(); @JcrChildNode private List<AnalysisDeclaredColumn> declaredColumns = new ArrayList<AnalysisDeclaredColumn>(); @JcrProperty private List<String> groups = new LinkedList<String>(); @JcrProperty private boolean freezed; // business fields unimportant for current Analysis object's state private boolean firstSortRemoved; private boolean changeFirstSortOrder; public Analysis() { } public String getTableName() { return tableName; } public void setTableName(String tableName) { this.tableName = tableName; } public List<String> getColumns() { return columns; } public List<String> getSimpleColumns() { List<String> result = new ArrayList<String>(); for (String name : columns) { result.add(AnalysisUtil.getColumnAlias(name)); } return result; } public void setColumns(List<String> columns) { this.columns = columns; } public List<String> getSortProperty() { return sortProperty; } public void setSortProperty(List<String> sortProperty) { this.sortProperty = sortProperty; } public List<Boolean> getAscending() { return ascending; } public void setAscending(List<Boolean> ascending) { this.ascending = ascending; } public int getRowsPerPage() { return rowsPerPage; } public void setRowsPerPage(int rowsPerPage) { this.rowsPerPage = rowsPerPage; } public List<Boolean> getSelected() { return selected; } public void setSelected(List<Boolean> selected) { this.selected = selected; } public boolean isFirstSortRemoved() { return firstSortRemoved; } public void setFirstSortRemoved(boolean firstSortRemoved) { this.firstSortRemoved = firstSortRemoved; } public boolean isChangeFirstSortOrder() { return changeFirstSortOrder; } public void setChangeFirstSortOrder(boolean changeFirstSortOrder) { this.changeFirstSortOrder = changeFirstSortOrder; } public List<AnalysisFilter> getFilters() { return filters; } public void setFilters(List<AnalysisFilter> filters) { this.filters = filters; } public List<AnalysisDeclaredColumn> getDeclaredColumns() { return declaredColumns; } public void addDeclaredColumn(AnalysisDeclaredColumn col) { if (declaredColumns == null) { declaredColumns = new ArrayList<AnalysisDeclaredColumn>(); } declaredColumns.add(col); String colName = col.getExpression() + AnalysisUtil.AS + col.getColumnName(); columns.add(colName); columnTypes.put(colName, col.getType()); selected.add(true); } public void editDeclaredColumn(int index, int oldColumnIndex, int oldFilterIndex, int oldSortIndex, int oldGroupIndex, AnalysisDeclaredColumn col) { declaredColumns.set(index, col); String colName = col.getExpression() + AnalysisUtil.AS + col.getColumnName(); int foundIndex = oldColumnIndex; columns.set(foundIndex, colName); columnTypes.put(colName, col.getType()); selected.set(foundIndex, true); // modify column name in filters, sorts, groups,.. if (oldFilterIndex != -1) { filters.get(oldFilterIndex).setColumn(col.getColumnName()); } if (oldSortIndex != -1) { sortProperty.set(oldSortIndex, col.getColumnName()); } if (oldGroupIndex != -1) { groups.set(oldGroupIndex, col.getColumnName()); } } public void deleteDeclaredColumn(AnalysisDeclaredColumn col) { declaredColumns.remove(col); String colName = col.getExpression() + AnalysisUtil.AS + col.getColumnName(); int foundIndex = getColumnIndexByName(colName); columns.remove(colName); columnTypes.remove(colName); if (foundIndex != -1) { selected.remove(foundIndex); } // / must also remove declared column from filters, sorts, groups ,.. AnalysisUtil.removeFilterByColumnName(filters, col.getColumnName()); boolean isFirstSort = AnalysisUtil.removeSortByColumnName(sortProperty, ascending, col.getColumnName()); if (isFirstSort) { firstSortRemoved = true; } AnalysisUtil.removeGroupByColumnName(groups, col.getColumnName()); } public int getColumnIndexByName(String name) { if ((columns == null) || columns.isEmpty()) { return -1; } for (int i = 0, size = columns.size(); i < size; i++) { if (columns.get(i).equals(name)) { return i; } } return -1; } public int getFilterIndexByName(String name) { if ((filters == null) || filters.isEmpty()) { return -1; } for (int i = 0, size = filters.size(); i < size; i++) { if (filters.get(i).getColumn().equals(name)) { return i; } } return -1; } public int getSortIndexByName(String name) { if ((sortProperty == null) || sortProperty.isEmpty()) { return -1; } for (int i = 0, size = sortProperty.size(); i < size; i++) { if (sortProperty.get(i).equals(name)) { return i; } } return -1; } public int getGroupIndexByName(String name) { if ((groups == null) || groups.isEmpty()) { return -1; } for (int i = 0, size = groups.size(); i < size; i++) { if (groups.get(i).equals(name)) { return i; } } return -1; } public Map<String, String> getColumnTypes() { return columnTypes; } public void setColumnTypes(Map<String, String> columnTypes) { this.columnTypes = columnTypes; } public List<String> getGroups() { return groups; } public void setGroups(List<String> groups) { this.groups = groups; } public boolean isFreezed() { return freezed; } public void setFreezed(boolean freezed) { this.freezed = freezed; } public String toSql(boolean allColumns) { StringBuilder sb = new StringBuilder("select "); if ((columns == null) || columns.isEmpty() || allColumns) { sb.append("* "); } else { List<String> selColumns = getSelectedColumns(); for (int i = 0, size = selColumns.size(); i < size; i++) { sb.append(selColumns.get(i)); if (i < size - 1) { sb.append(", "); } } } sb.append(" from ").append(tableName); List<AnalysisFilter> nonAggFilters = AnalysisUtil.getFilters(columns, filters, false); if (!nonAggFilters.isEmpty()) { sb.append(" where "); appendFilters(nonAggFilters, sb, false); } if ((groups != null) && !groups.isEmpty()) { sb.append(" group by "); for (int i = 0, size = groups.size(); i < size; i++) { sb.append(groups.get(i)); if (i < size - 1) { sb.append(", "); } } } // orient db does not support having // so we create a subselect at the end // keep this code if we want to change orientdb in the future //List<AnalysisFilter> aggFilters = AnalysisUtil.getFilters(columns, filters, true); //if (!aggFilters.isEmpty()) { // sb.append(" having "); // appendFilters(aggFilters, sb); //} if ((sortProperty != null) && !sortProperty.isEmpty()) { sb.append(" order by "); for (int i = 0, size = sortProperty.size(); i < size; i++) { sb.append(sortProperty.get(i)); if (!ascending.get(i)) { sb.append(" desc"); } else { sb.append(" asc"); } if (i < size - 1) { sb.append(", "); } } } List<AnalysisFilter> aggFilters = AnalysisUtil.getFilters(columns, filters, true); if (!aggFilters.isEmpty()) { // create a subselect because orient db does not support having StringBuilder result = new StringBuilder("select from ( "); result.append(sb.toString()); result.append(" ) where "); appendFilters(aggFilters, result, true); return result.toString(); } else { return sb.toString(); } } public ArrayList<String> getSelectedColumns() { ArrayList<String> result = new ArrayList<String>(); if ((selected == null) || selected.isEmpty()) { return new ArrayList<String>(columns); } else { for (int i = 0, size = selected.size(); i < size; i++) { if (selected.get(i)) { result.add(columns.get(i)); } } return result; } } private void appendFilters(List<AnalysisFilter> filtersList, StringBuilder sb, boolean useAlias) { for (int i = 0, size = filtersList.size(); i < size; i++) { AnalysisFilter fo = filtersList.get(i); String operator = fo.getOperator(); if (useAlias) { sb.append(AnalysisUtil.getColumnAlias(fo.getColumn())); } else { sb.append(AnalysisUtil.getColumnWithoutAlias(columns, fo.getColumn())); } sb.append(" ").append(operator); if (!Operator.isUnar(operator)) { sb.append(" "); boolean in = Operator.IN.equals(operator) || Operator.NOT_IN.equals(operator); boolean needApos = false; boolean isDate = false; if (columnTypes != null) { needApos = "java.lang.String".equals(columnTypes.get(AnalysisUtil.getColumnFullName(columns, fo.getColumn()))); isDate = "java.util.Date".equals(columnTypes.get(AnalysisUtil.getColumnFullName(columns, fo.getColumn()))) || "java.sql.Timestamp".equals(columnTypes.get(AnalysisUtil.getColumnFullName(columns, fo.getColumn()))) || "java.sql.Time".equals(columnTypes.get(AnalysisUtil.getColumnFullName(columns, fo.getColumn()))); } if (in) { sb.append("["); String[] values = fo.getValue().toString().split(";"); for (int j = 0, len = values.length; j < len; j++) { if (needApos && !values[j].startsWith("'")) { sb.append("'"); } else if (isDate) { sb.append("date('"); } sb.append(values[j]); if (needApos && !values[j].endsWith("'")) { sb.append("'"); } else if (isDate) { sb.append("','yyyyMMdd')"); } if (j < len - 1) { sb.append(","); } } sb.append("]"); } else if (Operator.BETWEEN.equals(operator)) { String[] values = fo.getValue().toString().split(";"); for (int j = 0, len = values.length; j < len; j++) { if (needApos && !values[j].startsWith("'")) { sb.append("'"); } else if (isDate) { sb.append("date('"); } sb.append(values[j]); if (needApos && !values[j].endsWith("'")) { sb.append("'"); } else if (isDate) { sb.append("','yyyyMMdd')"); } if (j < len - 1) { sb.append(" and "); } } } else { if (needApos && !fo.getValue().toString().startsWith("'")) { sb.append("'"); } else if (isDate) { sb.append("date('"); } sb.append(fo.getValue()); if (needApos && !fo.getValue().toString().endsWith("'")) { sb.append("'"); } else if (isDate) { sb.append("','yyyyMMdd')"); } } } if (i < size - 1) { sb.append(" and "); } } } @Override public boolean allowPermissions() { return true; } @Override public String toString() { return "Analysis [" + super.toString() + " ,tableName=" + tableName + ", columns=" + columns + ", columnTypes=" + columnTypes + ", selected=" + selected + ", sortProperty=" + sortProperty + ", ascending=" + ascending + ", filters=" + filters + ", declaredColumns=" + declaredColumns + ", groups=" + groups + ", rowsPerPage=" + rowsPerPage + ", freezed=" + freezed + "]"; } }