blob: 2d7a62ca70144768e5a038c86fae9383e824c0e9 [file] [log] [blame]
package org.eclipse.openk.elogbook.persistence.util;
import org.apache.log4j.Logger;
import org.eclipse.openk.elogbook.common.Globals;
import org.eclipse.openk.elogbook.common.NotificationStatus;
import org.eclipse.openk.elogbook.persistence.model.HTblResponsibility;
import org.eclipse.openk.elogbook.persistence.model.TblNotification;
import org.eclipse.openk.elogbook.persistence.model.TblResponsibility;
import org.eclipse.openk.elogbook.viewmodel.GlobalSearchFilter;
import org.eclipse.openk.elogbook.viewmodel.Notification.ListType;
import org.eclipse.openk.elogbook.viewmodel.NotificationSearchFilter;
import org.eclipse.openk.elogbook.viewmodel.ReminderSearchFilter;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class NotificationQueryCreator {
private static final String AND_LIT = " AND ";
private static final String OR_LIT = " OR ";
private static final String ORDER_LIT = " ORDER BY ";
private static final String FK_BRANCH_EQUAL = "fk_ref_branch = ";
private static final String FK_GRID_TERRITORY_EQUAL = "fk_ref_grid_territory = ";
private static final String FK_BRANCH_NULL = "fk_ref_branch IS NULL";
private static final String FK_GRID_TERRITORY_NULL = "fk_ref_grid_territory IS NULL";
private static final String DUMMY_FALSE_VALUE_ORCLAUSE = " false ";
private static final Logger LOGGER = Logger.getLogger(NotificationQueryCreator.class.getName());
private EntityManager em;
private String tablePrefix = "";
private Map<Integer, Object> latebindParamMap = new HashMap<>();
private int iCounter = 1;
public NotificationQueryCreator(EntityManager em, String tablePrefix) {
this.em = em;
if (tablePrefix != null && !tablePrefix.isEmpty()) {
this.tablePrefix = tablePrefix + ".";
}
}
/**
* Generate the Query by processing the informations from the notification search-filter.
*
* @param notificationSearchFilter
* The Object obtained from view viewmodel
* @param baseWhereClause
* the base where clause to be completed using the notification search filter
* @param listType
* the listType (where clause creation depends from it)
* @param tblResponsibilities
* the list with the {@link TblResponsibility} objects
* @return the generated query
*/
public Query generateNotificationQuery(NotificationSearchFilter notificationSearchFilter, String baseWhereClause,
ListType listType, List<TblResponsibility> tblResponsibilities) {
StringBuilder sql = new StringBuilder("select * from view_active_notification v where 1=1 ");
if (baseWhereClause != null && !baseWhereClause.isEmpty()) {
sql.append(AND_LIT).append(baseWhereClause);
}
if (notificationSearchFilter != null) {
sql.append(extendWhereClauseApplyingSearchFilter(notificationSearchFilter, listType, tblResponsibilities));
}
sql.append(getNotificationOrder());
// _fd: No String comes unescaped from outside the program -> So SONAR
// is wrong with it error
Query q = em.createNativeQuery(sql.toString(), TblNotification.class); // NOSONAR
latebindParamMap.forEach(q::setParameter);
return q;
}
public Query generateNotificationQueryWithReminder(ReminderSearchFilter rsf, String baseWhereClause,
List<TblResponsibility> tblResponsibilities) {
StringBuilder sql = new StringBuilder("select * from view_active_notification v where 1=1 ");
if (baseWhereClause != null && !baseWhereClause.isEmpty()) {
sql.append(AND_LIT).append(baseWhereClause);
}
if (rsf != null) {
sql.append(extendWhereClauseApplyingSearchFilterWithReminder(rsf, tblResponsibilities));
}
sql.append(getNotificationOrder());
// _fd: No String comes unescaped from outside the program -> So SONAR
// is wrong with it error
Query q = em.createNativeQuery(sql.toString(), TblNotification.class); // NOSONAR
latebindParamMap.forEach(q::setParameter);
return q;
}
/**
* Create a query to get historical notifications relevant for the responsibility belonging to a specific
* transaction id .
*
* @param hTblResponsibilities
* the list of historical responsibilities at shift change date
* @param listType
* the {@link ListType}
* @return the generated query.
*/
public Query generateFindHistoricalNotificationsByResponsibilityQuery(List<HTblResponsibility> hTblResponsibilities,
ListType listType) {
StringBuilder sqlSB = new StringBuilder("select * from " + " tbl_notification t1 join ( "
+ " select incident_id, max(version) as version FROM tbl_notification t " + " WHERE ");
sqlSB.append("(");
sqlSB.append(" mod_Date < ? ").append(OR_LIT).append(" mod_Date IS NULL").append(AND_LIT)
.append("create_Date < ? ");
sqlSB.append(")");
sqlSB.append(" GROUP BY incident_id");
sqlSB.append(" ) t2 ON ( t1.incident_id = t2.incident_id AND t1.version = t2.version) where ");
sqlSB.append("(").append(DUMMY_FALSE_VALUE_ORCLAUSE);
for (HTblResponsibility hTblResponsibility : hTblResponsibilities) {
sqlSB.append(OR_LIT);
sqlSB.append(FK_BRANCH_EQUAL).append(hTblResponsibility.getRefBranch().getId()).append(AND_LIT)
.append(FK_GRID_TERRITORY_EQUAL).append(hTblResponsibility.getRefGridTerritory().getId());
}
extendFindHistoricalNotificationsByResponsibilityQueryListTypeSpecific(sqlSB, listType,
hTblResponsibilities.get(0).getTransferDate());
sqlSB.append(")").append(getNotificationOrder());
Query query = em.createNativeQuery(sqlSB.toString(), TblNotification.class);
query.setParameter(1, hTblResponsibilities.get(0).getTransferDate());
query.setParameter(2, hTblResponsibilities.get(0).getTransferDate());
return query;
}
/**
* Create a query by evaluating the search filter criteria.
*
* @param gsf
* the search filter containing the search criteria.
* @return the generated query.
*/
public Query generateFindNotificationsMatchingSearchCriteriaQuery(GlobalSearchFilter gsf) {
String sql = createSearchCriteriaSelectString(gsf);
Query query = em.createQuery(sql, TblNotification.class);
substituteSearchCriteriaParameters(gsf, query);
return query;
}
/**
* Helper method generating SQL SELECT for search.
* @param gsf the search filter containing search criteria
* @return The generated query string
*/
private String createSearchCriteriaSelectString(GlobalSearchFilter gsf) {
StringBuilder sqlSB = new StringBuilder("SELECT t FROM");
if (gsf.isFastSearchSelected()) {
sqlSB.append(" ViewNotification t WHERE 1 = 1 AND ");
sqlSB.append("(t.modDate > :timestamp or t.modDate IS NULL AND t.createDate > :timestamp) AND ");
}
else {
sqlSB.append(" TblNotification t WHERE 1 = 1 AND ");
}
if (gsf.getSearchString() != null) {
sqlSB.append("( UPPER(t.notificationText) LIKE :notificationText OR")
.append(" UPPER(t.freeText) LIKE :freeText OR")
.append(" UPPER(t.freeTextExtended) LIKE :freeTextExtended)");
}
if (gsf.getResponsibilityForwarding() != null && !gsf.getResponsibilityForwarding().isEmpty()) {
sqlSB.append(" AND t.responsibilityForwarding LIKE :responsibilityForwarding ");
}
if (gsf.isBranchSelected()) {
sqlSB.append(" AND t.refBranch.id = :refBranch ");
}
if (gsf.isGridTerritorySelected()) {
sqlSB.append(" AND t.refGridTerritory.id = :refGridTerritory ");
}
List<Integer> statusIds = gsf.getSelectedStatusMappedToIds();
if (!statusIds.isEmpty()) {
sqlSB.append(" AND t.refNotificationStatus.id IN ( ");
for (Integer status : statusIds) {
sqlSB.append(status.toString()).append(", ");
}
replaceLastCommaWithParanthese(sqlSB);
}
sqlSB.append(" ORDER BY t.refBranch, t.incidentId DESC, t.version DESC, t.refGridTerritory, t.beginDate ");
return sqlSB.toString();
}
/**
* Helper method setting parameters to the generated search query.
* @param gsf the search filter where the parameter values are taken from
* @param query the generated query.
*/
private void substituteSearchCriteriaParameters(GlobalSearchFilter gsf, Query query) {
if (gsf.isFastSearchSelected()) {
query.setParameter("timestamp", createSearchIntervalParameter());
}
if (gsf.getSearchString() != null) {
query.setParameter("notificationText", "%" + gsf.getSearchString().toUpperCase() + "%");
query.setParameter("freeText", "%" + gsf.getSearchString().toUpperCase() + "%");
query.setParameter("freeTextExtended", "%" + gsf.getSearchString().toUpperCase() + "%");
}
if (gsf.getResponsibilityForwarding() != null && !gsf.getResponsibilityForwarding().isEmpty()) {
query.setParameter("responsibilityForwarding", "%" + gsf.getResponsibilityForwarding() + "%");
}
if (gsf.isBranchSelected()) {
query.setParameter("refBranch", gsf.getFkRefBranch());
}
if (gsf.isGridTerritorySelected()) {
query.setParameter("refGridTerritory", gsf.getFkRefGridTerritory());
}
}
/**
* Helper method computing the search interval. The (negative) number of days actually is taken from Globals.
*
* @return the search interval.
*/
private Timestamp createSearchIntervalParameter() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
calendar.add(Calendar.DAY_OF_YEAR, Globals.FAST_SEARCH_NUMBER_OF_DAYS_BACK);
long searchDateFromInms = calendar.getTime().getTime();
Timestamp searchDateFrom = new Timestamp(searchDateFromInms);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Folgenden Timestamp für das Schnellsucheintervall ermittelt: " + searchDateFrom.toString());
}
return searchDateFrom;
}
/**
* Helper method removing last (= wrong) comma by inserting paranthese instead.
*
* @param sqlSB
* the String Builderwhere the comma is to replace.
*/
private void replaceLastCommaWithParanthese(StringBuilder sqlSB) {
int posFinished = sqlSB.length() - 2;
sqlSB.replace(posFinished, posFinished + 1, ")");
}
/**
* Helper method to extend the Where-Clause of generateFindHistoricalNotificationsByResponsibilityQuery method list
* type specific
*
* Note: Past notifications are picked only if their begin date is between transferDate and one week before transfer
* date.
*
* @param sqlSB
* the query string builder to be extended
* @param listType
* the list type
*/
private void extendFindHistoricalNotificationsByResponsibilityQueryListTypeSpecific(StringBuilder sqlSB,
ListType listType, Timestamp transferDate) {
sqlSB.append(AND_LIT).append("fk_ref_notification_status ");
switch (listType) {
case PAST:
sqlSB.append("IN ").append("(").append(NotificationStatus.CLOSED.id).append(", ")
.append(NotificationStatus.FINISHED.id).append(")").append(AND_LIT).append("begin_date <= '")
.append(transferDate).append("'").append(AND_LIT).append("begin_date > TIMESTAMP '")
.append(transferDate).append("' - INTERVAL '7 days'");
break;
case OPEN:
sqlSB.append("IN ").append("(").append(NotificationStatus.OPEN.id).append(", ")
.append(NotificationStatus.INPROGRESS.id).append(", ").append(NotificationStatus.FINISHED.id)
.append(")").append(AND_LIT).append("begin_date < TIMESTAMP '").append(transferDate)
.append("' + INTERVAL '1 day '");
break;
case FUTURE:
sqlSB.append("NOT IN ").append("(").append(NotificationStatus.CLOSED.id).append(", ")
.append(NotificationStatus.FINISHED.id).append(")");
break;
default:
break;
}
}
/**
* Create the where clause.
*
* @param nsf
* The Object obtained from view viewmodel
* @param listType
* the listType (where clause creation depends from it)
* @param tblResponsibilities
* the list with the {@link TblResponsibility} objects
* @return he appropriate String to extend the where-clause
*/
private String extendWhereClauseApplyingSearchFilter(NotificationSearchFilter nsf, ListType listType,
List<TblResponsibility> tblResponsibilities) {
StringBuilder ret = new StringBuilder();
if (listType == ListType.PAST || listType == ListType.FUTURE) {
ret.append(extendWhereClauseByDates(nsf));
}
ret.append(extendWhereClauseByResponsibility(tblResponsibilities));
return ret.toString();
}
private String extendWhereClauseApplyingSearchFilterWithReminder(ReminderSearchFilter rsf,
List<TblResponsibility> tblResponsibilities) {
StringBuilder ret = new StringBuilder();
ret.append(extendWhereClauseByReminderDate(rsf));
ret.append(extendWhereClauseByResponsibility(tblResponsibilities));
return ret.toString();
}
/**
* Use DateFrom and DateTo in where clause.
*
* @param nsf
* the notification search filter
* @return the appropriate String to extend the where-clause
*/
private String extendWhereClauseByDates(NotificationSearchFilter nsf) {
StringBuilder ret = new StringBuilder();
if (nsf.getDateFrom() != null) {
ret.append(AND_LIT).append(tablePrefix).append("begin_date >= ?");
latebindParamMap.put(iCounter, nsf.getDateFrom());
iCounter++;
}
if (nsf.getDateTo() != null) {
ret.append(AND_LIT).append(tablePrefix).append("begin_date <= ?");
latebindParamMap.put(iCounter, nsf.getDateTo());
}
return ret.toString();
}
private String extendWhereClauseByReminderDate(ReminderSearchFilter rsf) {
StringBuilder ret = new StringBuilder();
if (rsf.getReminderDate() != null) {
ret.append(AND_LIT).append(tablePrefix).append("reminder_date <= ?");
latebindParamMap.put(iCounter, rsf.getReminderDate());
}
return ret.toString();
}
/**
* Use TblResponsibilities in where clause. The foreign key constraints for branches and grid territories are used
* for matching. Null value matches all branches/grid territories. In case of empty responsibilities entity only the
* notifications for all branches and grid territories are returned.
*
* @param tblResponsibilities
* the list with the {@link TblResponsibility} objects
* @return the appropriate String to extend the where-clause
*/
private String extendWhereClauseByResponsibility(List<TblResponsibility> tblResponsibilities) {
StringBuilder stringBuilder = new StringBuilder(AND_LIT).append("(").append(FK_BRANCH_NULL).append(AND_LIT)
.append(FK_GRID_TERRITORY_NULL);
if (tblResponsibilities.isEmpty()) {
stringBuilder.append(")");
return stringBuilder.toString();
}
stringBuilder.append(OR_LIT).append("(");
int actualListPos = 0;
for (TblResponsibility tblResponsibility : tblResponsibilities) {
stringBuilder.append(appendForeignKeyNullOrMatching(tblResponsibility));
actualListPos++;
if (actualListPos < tblResponsibilities.size()) {
stringBuilder.append(OR_LIT);
}
}
stringBuilder.append(")").append(")");
return stringBuilder.toString();
}
/**
* Helper Method: Extend the where clause by foreign keys null or matching.
*
* Append to where clause: (fk_ref_branch IS NULL OR fk_ref_branch = x) AND (fk_grid_territory IS NULL OR
* fk_ref_grid_territory = y)
*
* @param tblResponsibility
* the responsibility with the foreign keys to check matching
* @return the extended where clause
*/
private String appendForeignKeyNullOrMatching(TblResponsibility tblResponsibility) {
StringBuilder stringBuilder = new StringBuilder("(");
stringBuilder.append(FK_BRANCH_NULL).append(OR_LIT).append(FK_BRANCH_EQUAL)
.append(tblResponsibility.getRefBranch().getId()).append(")").append(AND_LIT).append("(")
.append(FK_GRID_TERRITORY_NULL).append(OR_LIT).append(FK_GRID_TERRITORY_EQUAL)
.append(tblResponsibility.getRefGridTerritory().getFkRefMaster()).append(")");
return stringBuilder.toString();
}
private String getNotificationOrder() {
return ORDER_LIT + tablePrefix + "fk_ref_branch ASC, fk_ref_grid_territory ASC, " + tablePrefix + "begin_date";
}
}