com.agiletec.aps.system.common.entity.AbstractEntitySearcherDAO Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of entando-engine Show documentation
Show all versions of entando-engine Show documentation
Entando Engine: an agile, modern and user-centric open source Portal platform.
/*
* Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.agiletec.aps.system.common.entity;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.agiletec.aps.system.common.AbstractSearcherDAO;
import com.agiletec.aps.system.common.FieldSearchFilter;
import com.agiletec.aps.system.common.entity.model.ApsEntityRecord;
import com.agiletec.aps.system.common.entity.model.EntitySearchFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Abstract class extended by those DAO that perform searches on entities.
* @author E.Santoboni
*/
@SuppressWarnings(value = {"serial", "rawtypes"})
public abstract class AbstractEntitySearcherDAO extends AbstractSearcherDAO implements IEntitySearcherDAO {
private static final Logger _logger = LoggerFactory.getLogger(AbstractEntitySearcherDAO.class);
@Override
public List searchRecords(EntitySearchFilter[] filters) {
Connection conn = null;
List records = new ArrayList<>();
PreparedStatement stat = null;
ResultSet result = null;
try {
conn = this.getConnection();
stat = this.buildStatement(filters, false, true, conn);
result = stat.executeQuery();
while (result.next()) {
ApsEntityRecord record = this.createRecord(result);
if (!records.contains(record)) {
records.add(record);
}
}
} catch (Throwable t) {
_logger.error("Error while loading records list", t);
throw new RuntimeException("Error while loading records list", t);
} finally {
closeDaoResources(result, stat, conn);
}
return records;
}
protected abstract ApsEntityRecord createRecord(ResultSet result) throws Throwable;
protected Integer countId(EntitySearchFilter[] filters) {
Connection conn = null;
int count = 0;
PreparedStatement stat = null;
ResultSet result = null;
try {
conn = this.getConnection();
stat = this.buildStatement(filters, true, false, conn);
result = stat.executeQuery();
if (result.next()) {
count = result.getInt(1);
}
} catch (Throwable t) {
_logger.error("Error while loading the count of IDs", t);
throw new RuntimeException("Error while loading the count of IDs", t);
} finally {
closeDaoResources(result, stat, conn);
}
return count;
}
@Override
public List searchId(String typeCode, EntitySearchFilter[] filters) {
if (typeCode != null && typeCode.trim().length() > 0) {
EntitySearchFilter filter = new EntitySearchFilter(IEntityManager.ENTITY_TYPE_CODE_FILTER_KEY, false, typeCode, false);
EntitySearchFilter[] newFilters = this.addFilter(filters, filter);
return this.searchId(newFilters);
}
return this.searchId(filters);
}
@Override
public List searchId(EntitySearchFilter[] filters) {
Connection conn = null;
List idList = new ArrayList<>();
PreparedStatement stat = null;
ResultSet result = null;
try {
conn = this.getConnection();
stat = this.buildStatement(filters, false, false, conn);
result = stat.executeQuery();
while (result.next()) {
String id = result.getString(this.getMasterTableIdFieldName());
if (!idList.contains(id)) {
idList.add(id);
}
}
} catch (Throwable t) {
_logger.error("Error while loading the list of IDs", t);
throw new RuntimeException("Error while loading the list of IDs", t);
} finally {
closeDaoResources(result, stat, conn);
}
return idList;
}
protected EntitySearchFilter[] addFilter(EntitySearchFilter[] filters, EntitySearchFilter filterToAdd) {
int len = 0;
if (filters != null) {
len = filters.length;
}
EntitySearchFilter[] newFilters = new EntitySearchFilter[len + 1];
for (int i = 0; i < len; i++) {
newFilters[i] = filters[i];
}
newFilters[len] = filterToAdd;
return newFilters;
}
private PreparedStatement buildStatement(EntitySearchFilter[] filters, boolean isCount, boolean selectAll, Connection conn) {
String query = this.createQueryString(filters, isCount, selectAll);
PreparedStatement stat = null;
try {
stat = conn.prepareStatement(query);
int index = 0;
index = this.addAttributeFilterStatementBlock(filters, index, stat);
index = this.addMetadataFieldFilterStatementBlock(filters, index, stat);
} catch (Throwable t) {
_logger.error("Error while creating the statement", t);
throw new RuntimeException("Error while creating the statement", t);
}
return stat;
}
/**
* Add to the statement the filters on the entity metadata.
* @param filters the filters to add to the statement.
* @param index The current index of the statement.
* @param stat The statement.
* @return The current statement index, eventually incremented by filters.
* @throws Throwable In case of error.
*/
protected int addMetadataFieldFilterStatementBlock(EntitySearchFilter[] filters, int index, PreparedStatement stat) throws Throwable {
if (filters == null) {
return index;
}
for (int i = 0; i < filters.length; i++) {
EntitySearchFilter filter = filters[i];
if (filter.getKey() != null && !filter.isAttributeFilter()) {
index = this.addObjectSearchStatementBlock(filter, index, stat);
}
}
return index;
}
/**
* Add the attribute filters to the statement.
* @param filters The filters on the entity filters to insert in the statement.
* @param index The last index used to associate the elements to the statement.
* @param stat The statement where the filters are applied.
* @return The last used index.
* @throws SQLException In case of error.
*/
protected int addAttributeFilterStatementBlock(EntitySearchFilter[] filters,
int index, PreparedStatement stat) throws SQLException {
if (filters == null) {
return index;
}
for (int i = 0; i < filters.length; i++) {
EntitySearchFilter filter = filters[i];
if ((null != filter.getKey() || null != filter.getRoleName()) && filter.isAttributeFilter()) {
if (null != filter.getKey()) {
stat.setString(++index, filter.getKey());
} else {
stat.setString(++index, filter.getRoleName().toUpperCase());
}
index = this.addObjectSearchStatementBlock(filter, index, stat);
}
}
return index;
}
/**
* Add to the statement a filter on a attribute.
* @param filter The filter on the attribute to apply in the statement.
* @param index The last index used to associate the elements to the statement.
* @param stat The statement where the filters are applied.
* @return The last used index.
* @throws SQLException In case of error.
*/
protected int addObjectSearchStatementBlock(EntitySearchFilter filter, int index, PreparedStatement stat) throws SQLException {
if (filter.isAttributeFilter() && null != filter.getLangCode()) {
stat.setString(++index, filter.getLangCode());
}
return super.addObjectSearchStatementBlock(filter, index, stat);
}
protected String createQueryString(EntitySearchFilter[] filters, boolean isCount, boolean selectAll) {
StringBuffer query = this.createBaseQueryBlock(filters, isCount, selectAll);
boolean hasAppendWhereClause = this.appendFullAttributeFilterQueryBlocks(filters, query, false);
this.appendMetadataFieldFilterQueryBlocks(filters, query, hasAppendWhereClause);
if (!isCount) {
boolean ordered = this.appendOrderQueryBlocks(filters, query, false);
this.appendLimitQueryBlock(filters, query);
}
return query.toString();
}
/**
* Create the 'base block' of the query with the eventual references to the support table.
* @param filters The filters defined.
* @param isCount
* @param selectAll When true, this will insert all the fields in the master table in the select
* of the master query.
* When true we select all the available fields; when false only the field addressed by the filter
* is selected.
* @return The base block of the query.
*/
protected StringBuffer createBaseQueryBlock(EntitySearchFilter[] filters, boolean isCount, boolean selectAll) {
StringBuffer query = null;
if (isCount) {
query = this.createMasterCountQueryBlock();
} else {
query = this.createMasterSelectQueryBlock(filters, selectAll);
}
this.appendJoinSearchTableQueryBlock(filters, query);
return query;
}
protected StringBuffer createMasterSelectQueryBlock(EntitySearchFilter[] filters, boolean selectAll) {
String masterTableName = this.getEntityMasterTableName();
StringBuffer query = new StringBuffer("SELECT ").append(masterTableName).append(".");
if (selectAll) {
query.append("* ");
} else {
query.append(this.getEntityMasterTableIdFieldName());
}
if (filters != null) {
String searchTableName = this.getEntitySearchTableName();
for (int i = 0; i < filters.length; i++) {
EntitySearchFilter filter = filters[i];
if (!filter.isAttributeFilter() && filter.isLikeOption()) {
String tableFieldName = this.getTableFieldName(filter.getKey());
//check for id column already present
if (!tableFieldName.equals(this.getMasterTableIdFieldName())) {
query.append(", ").append(masterTableName).append(".").append(tableFieldName);
}
} else if (filter.isAttributeFilter() && filter.isLikeOption()) {
String columnName = this.getAttributeFieldColunm(filter);
query.append(", ").append(searchTableName).append(i).append(".").append(columnName);
query.append(" AS ").append(columnName).append(i).append(" ");
}
}
}
query.append(" FROM ").append(masterTableName).append(" ");
return query;
}
protected void appendJoinSearchTableQueryBlock(EntitySearchFilter[] filters, StringBuffer query) {
if (filters == null) {
return;
}
String masterTableName = this.getEntityMasterTableName();
String masterTableIdFieldName = this.getEntityMasterTableIdFieldName();
String searchTableName = this.getEntitySearchTableName();
String searchTableIdFieldName = this.getEntitySearchTableIdFieldName();
String attributeRoleTableName = this.getEntityAttributeRoleTableName();
String attributeRoleTableIdFieldName = this.getEntityAttributeRoleTableIdFieldName();
for (int i = 0; i < filters.length; i++) {
EntitySearchFilter filter = filters[i];
if ((null != filter.getKey() || null != filter.getRoleName()) && filter.isAttributeFilter() && !filter.isNullOption()) {
query.append("INNER JOIN ");
query.append(searchTableName).append(" ").append(searchTableName).append(i).append(" ON ")
.append(masterTableName).append(".").append(masterTableIdFieldName).append(" = ")
.append(searchTableName).append(i).append(".").append(searchTableIdFieldName).append(" ");
if (null != filter.getRoleName()) {
query.append("INNER JOIN ");
query.append(attributeRoleTableName).append(" ").append(attributeRoleTableName).append(i).append(" ON ")
.append(masterTableName).append(".").append(masterTableIdFieldName).append(" = ")
.append(attributeRoleTableName).append(i).append(".").append(attributeRoleTableIdFieldName).append(" ");
}
}
}
}
protected boolean appendFullAttributeFilterQueryBlocks(EntitySearchFilter[] filters, StringBuffer query, boolean hasAppendWhereClause) {
if (filters != null) {
for (int i = 0; i < filters.length; i++) {
EntitySearchFilter filter = filters[i];
if (!filter.isAttributeFilter()) {
continue;
}
if (filter.isNullOption() && filter.getKey() != null) {
hasAppendWhereClause = this.appendNullAttributeFilterQueryBlocks(filter, query, hasAppendWhereClause);
} else if (!filter.isNullOption() && (filter.getKey() != null || filter.getRoleName() != null)) {
hasAppendWhereClause = this.appendValuedAttributeFilterQueryBlocks(filter, i, query, hasAppendWhereClause);
}
}
}
return hasAppendWhereClause;
}
private boolean appendNullAttributeFilterQueryBlocks(EntitySearchFilter filter, StringBuffer query, boolean hasAppendWhereClause) {
hasAppendWhereClause = this.verifyWhereClauseAppend(query, hasAppendWhereClause);
query.append(this.getEntityMasterTableName()).append(".").append(this.getEntityMasterTableIdFieldName());
query.append(" NOT IN (");
String searchTableName = this.getEntitySearchTableName();
query.append("SELECT ").append(searchTableName).append(".").append(this.getEntitySearchTableIdFieldName());
query.append(" FROM ").append(searchTableName).append(" WHERE ").append(searchTableName).append(".attrname = ? ");
this.addAttributeLangQueryBlock(searchTableName, query, filter, true);
query.append(" AND (").append(searchTableName).append(".datevalue IS NOT NULL OR ").append(searchTableName).append(".textvalue IS NOT NULL OR ").append(searchTableName).append(".numvalue IS NOT NULL) ");
query.append(" ) ");
return hasAppendWhereClause;
}
private boolean appendValuedAttributeFilterQueryBlocks(EntitySearchFilter filter, int index, StringBuffer query, boolean hasAppendWhereClause) {
String searchTableNameAlias = this.getEntitySearchTableName() + index;
String attributeRoleTableNameAlias = this.getEntityAttributeRoleTableName() + index;
hasAppendWhereClause = this.verifyWhereClauseAppend(query, hasAppendWhereClause);
if (null != filter.getKey()) {
query.append(searchTableNameAlias).append(".attrname = ? ");
} else {
query.append("UPPER(").append(attributeRoleTableNameAlias).append(".rolename) = ? ");
query.append(" AND ").append(searchTableNameAlias).append(".attrname = ").append(attributeRoleTableNameAlias).append(".attrname ");
}
hasAppendWhereClause = this.addAttributeLangQueryBlock(searchTableNameAlias, query, filter, hasAppendWhereClause);
if (filter.getAllowedValues() != null && filter.getAllowedValues().size() > 0) {
hasAppendWhereClause = this.verifyWhereClauseAppend(query, hasAppendWhereClause);
List