/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.infrastructure.entityaccess.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Date;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.infrastructure.dataqueries.service.GenericDataServiceImpl;
import org.mifosplatform.infrastructure.entityaccess.MifosEntityAccessConstants;
import org.mifosplatform.infrastructure.entityaccess.data.MifosEntityAccessData;
import org.mifosplatform.infrastructure.entityaccess.data.MifosEntityRelationData;
import org.mifosplatform.infrastructure.entityaccess.data.MifosEntityToEntityMappingData;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntity;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityAccessType;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityType;
import org.mifosplatform.infrastructure.entityaccess.exception.MifosEntityAccessConfigurationException;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.useradministration.domain.AppUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
public class MifosEntityAccessReadServiceImpl implements MifosEntityAccessReadService {
private final PlatformSecurityContext context;
private final JdbcTemplate jdbcTemplate;
private final static Logger logger = LoggerFactory.getLogger(GenericDataServiceImpl.class);
@Autowired
public MifosEntityAccessReadServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource) {
this.context = context;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
/*
* (non-Javadoc)
*
* @see org.mifosplatform.infrastructure.entityaccess.service.
* MifosEntityAccessReadService#getSQLQueryWithListOfIDsForEntityAccess
* (Long,
* org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityType,
* org.mifosplatform.infrastructure.entityaccess.domain.
* MifosEntityAccessType,
* org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityType,
* boolean)
*
* This method returns the list of entity IDs as a comma separated list Or
* null if there is no entity restrictions or if there
*/
@Override
public String getSQLQueryInClause_WithListOfIDsForEntityAccess(Long firstEntityId, MifosEntityType firstEntityType,
MifosEntityAccessType accessType, MifosEntityType secondEntityType, boolean includeAllOffices) {
Collection<MifosEntityAccessData> accesslist = retrieveEntityAccessFor(firstEntityId, firstEntityType, accessType, secondEntityType,
includeAllOffices);
String returnIdListStr = null;
StringBuffer accessListCSVStrBuf = null;
if ((accesslist != null) && (accesslist.size() > 0)) {
logger.debug("Found " + accesslist.size() + " access type restrictions while getting entity access configuration for "
+ firstEntityType.getType() + ":" + firstEntityId + " with type " + accessType.toStr() + " against "
+ secondEntityType.getType());
accessListCSVStrBuf = new StringBuffer(" ");
for (int i = 0; i < accesslist.size(); i++) {
MifosEntityAccessData accessData = (MifosEntityAccessData) accesslist.toArray()[i];
if (accessData == null) { throw new MifosEntityAccessConfigurationException(firstEntityId, firstEntityType, accessType,
secondEntityType); }
if (accessData.getSecondEntity().getId() == 0) { // If there is
// any ID that
// zero, then
// allow access
// to all
accessListCSVStrBuf = null;
break;
}
if (i > 0) {
accessListCSVStrBuf.append(',');
}
accessListCSVStrBuf.append(accessData.getSecondEntity().getId());
}
} else {
logger.debug("Found zero access type restrictions while getting entity access configuration for " + firstEntityType.getType()
+ ":" + firstEntityId + " with type " + accessType.toStr() + " against " + secondEntityType.getType());
accessListCSVStrBuf = new StringBuffer();
accessListCSVStrBuf.append("false"); // Append false so that no rows
// will be returned
}
if (accessListCSVStrBuf != null) {
returnIdListStr = accessListCSVStrBuf.toString();
}
logger.debug("List of IDs applicable:" + returnIdListStr);
return returnIdListStr;
}
@Override
public Collection<MifosEntityAccessData> retrieveEntityAccessFor(Long firstEntityId, MifosEntityType firstEntityType,
MifosEntityAccessType accessType, MifosEntityType secondEntityType, boolean includeAllSubOffices) {
final AppUser currentUser = this.context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
String hierarchySearchString = null;
if (includeAllSubOffices) {
hierarchySearchString = "." + "%";
} else {
hierarchySearchString = hierarchy + "%";
}
String sql = getSQLForRetriveEntityAccessFor(firstEntityType, accessType, secondEntityType);
Collection<MifosEntityAccessData> entityAccessData = null;
MifosEntityAccessDataMapper mapper = new MifosEntityAccessDataMapper();
if (includeAllSubOffices && (firstEntityType.getTable().equals("m_office"))) {
sql += " where firstentity.hierarchy like ? order by firstEntity.hierarchy";
entityAccessData = this.jdbcTemplate.query(sql, mapper, new Object[] { firstEntityId, hierarchySearchString });
} else {
entityAccessData = this.jdbcTemplate.query(sql, mapper, new Object[] { firstEntityId });
}
return entityAccessData;
}
private String getSQLForRetriveEntityAccessFor(MifosEntityType firstEntityType, MifosEntityAccessType accessType,
MifosEntityType secondEntityType) {
StringBuffer str = new StringBuffer("select eea.entity_id as entity_id, entity_type as entity_type, ");
str.append("access_type_code_value_id as access_id, cv.code_value as access_type_desc, c.code_name as code, ");
str.append("firstentity.id as first_entity_id, firstentity.name as entity_name, ");
str.append("otherentity.id as second_entity_id, otherentity.name as second_entity_name, ");
str.append("eea.second_entity_type as second_entity_type ");
str.append("from m_entity_to_entity_access eea ");
str.append("left join m_code_value cv on (cv.code_value = ");
str.append("'");
str.append(accessType.toStr());
str.append("' ");
str.append("and eea.access_type_code_value_id = cv.id) ");
str.append("left join m_code c on (c.code_name = '");
str.append(MifosEntityAccessConstants.ENTITY_ACCESS_CODENAME);
str.append("' and cv.code_id = c.id) ");
str.append("left join ");
str.append(firstEntityType.getTable());
str.append(" firstentity on (eea.entity_type = ");
str.append("'");
str.append(firstEntityType.getType());
str.append("'");
str.append(" and eea.entity_id = firstentity.id) left join ");
str.append(secondEntityType.getTable());
str.append(" otherentity on (eea.second_entity_type = ");
str.append("'");
str.append(secondEntityType.getType());
str.append("' ");
str.append("and eea.second_entity_id = otherentity.id) ");
str.append("where eea.access_type_code_value_id = cv.id ");
str.append("and eea.entity_id = ? ");
logger.debug(str.toString());
return str.toString();
}
private static final class MifosEntityAccessDataMapper implements RowMapper<MifosEntityAccessData> {
@Override
public MifosEntityAccessData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final String entityType = rs.getString("entity_type");
final Long entityId = rs.getLong("entity_id");
// final String entityName = rs.getString("entity_name");
// final Long accessId = rs.getLong("access_id");
final String accessTypeDesc = rs.getString("access_type_desc");
// final String code = rs.getString("code");
final Long secondEntityId = rs.getLong("second_entity_id");
// final String secondEntityName =
// rs.getString("second_entity_name");
final String secondEntityType = rs.getString("second_entity_type");
MifosEntity firstEntity = null;
MifosEntityType etype = MifosEntityType.get(entityType);
if (etype != null) {
firstEntity = new MifosEntity(entityId, etype);
}
MifosEntity secondEntity = null;
MifosEntityType secondetype = MifosEntityType.get(secondEntityType);
if (etype != null) {
secondEntity = new MifosEntity(secondEntityId, secondetype);
}
MifosEntityAccessType accessType = null;
if (accessTypeDesc != null) {
accessType = MifosEntityAccessType.get(accessTypeDesc);
}
MifosEntityAccessData returnMifosEntityAccessData = null;
if (firstEntity != null && secondEntity != null && accessType != null) {
returnMifosEntityAccessData = new MifosEntityAccessData(firstEntity, accessType, secondEntity);
}
return returnMifosEntityAccessData;
}
}
@Override
public String getSQLQueryInClauseIDList_ForLoanProductsForOffice(Long officeId, boolean includeAllOffices) {
MifosEntityType firstEntityType = MifosEntityType.OFFICE;
MifosEntityAccessType accessType = MifosEntityAccessType.OFFICE_ACCESS_TO_LOAN_PRODUCTS;
MifosEntityType secondEntityType = MifosEntityType.LOAN_PRODUCT;
return getSQLQueryInClause_WithListOfIDsForEntityAccess(officeId, firstEntityType, accessType, secondEntityType, includeAllOffices);
}
@Override
public String getSQLQueryInClauseIDList_ForSavingsProductsForOffice(Long officeId, boolean includeAllOffices) {
MifosEntityType firstEntityType = MifosEntityType.OFFICE;
MifosEntityAccessType accessType = MifosEntityAccessType.OFFICE_ACCESS_TO_SAVINGS_PRODUCTS;
MifosEntityType secondEntityType = MifosEntityType.SAVINGS_PRODUCT;
return getSQLQueryInClause_WithListOfIDsForEntityAccess(officeId, firstEntityType, accessType, secondEntityType, includeAllOffices);
}
@Override
public String getSQLQueryInClauseIDList_ForChargesForOffice(Long officeId, boolean includeAllOffices) {
MifosEntityType firstEntityType = MifosEntityType.OFFICE;
MifosEntityAccessType accessType = MifosEntityAccessType.OFFICE_ACCESS_TO_CHARGES;
MifosEntityType secondEntityType = MifosEntityType.CHARGE;
return getSQLQueryInClause_WithListOfIDsForEntityAccess(officeId, firstEntityType, accessType, secondEntityType, includeAllOffices);
}
@Override
public Collection<MifosEntityRelationData> retrieveAllSupportedMappingTypes() {
EntityRelationMapper entityMapper = new EntityRelationMapper();
final String sql = entityMapper.schema();
final Collection<MifosEntityRelationData> mapTypes = this.jdbcTemplate.query(sql, entityMapper, new Object[] {});
return mapTypes;
}
private static final class EntityRelationMapper implements RowMapper<MifosEntityRelationData> {
private final StringBuilder sqlBuilder = new StringBuilder("select id as id,code_name as mapping_Types from m_entity_relation ");
public String schema() {
return this.sqlBuilder.toString();
}
@Override
public MifosEntityRelationData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long mappingTypesId = rs.getLong("id");
final String mappingTypes = rs.getString("mapping_Types");
return MifosEntityRelationData.getMappingTypes(mappingTypesId, mappingTypes);
}
}
@Override
public Collection<MifosEntityToEntityMappingData> retrieveEntityToEntityMappings(Long mapId, Long fromId, Long toId) {
EntityToEntityMapper entityToEntityMapper = new EntityToEntityMapper();
String sql = entityToEntityMapper.schema();
final Collection<MifosEntityToEntityMappingData> mapTypes = this.jdbcTemplate.query(sql, entityToEntityMapper,
new Object[] { mapId, fromId, fromId, toId, toId });
return mapTypes;
}
@Override
public Collection<MifosEntityToEntityMappingData> retrieveOneMapping(Long mapId) {
GetOneEntityMapper entityMapper = new GetOneEntityMapper();
String sql = entityMapper.schema();
final Collection<MifosEntityToEntityMappingData> mapTypes = this.jdbcTemplate.query(sql, entityMapper, new Object[] { mapId });
return mapTypes;
}
private static final class GetOneEntityMapper implements RowMapper<MifosEntityToEntityMappingData> {
private final String schema;
public GetOneEntityMapper() {
StringBuffer str = new StringBuffer("select eem.rel_id as relId, ");
str.append("eem.from_id as fromId,eem.to_Id as toId,eem.start_date as startDate,eem.end_date as endDate ");
str.append("from m_entity_to_entity_mapping eem ");
str.append("where eem.id= ? ");
this.schema = str.toString();
}
public String schema() {
return this.schema;
}
@Override
public MifosEntityToEntityMappingData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long relId = rs.getLong("relId");
final Long fromId = rs.getLong("fromId");
final Long toId = rs.getLong("toId");
final Date startDate = rs.getDate("startDate");
final Date endDate = rs.getDate("endDate");
return MifosEntityToEntityMappingData.getRelatedEntities(relId, fromId, toId, startDate, endDate);
}
}
private static final class EntityToEntityMapper implements RowMapper<MifosEntityToEntityMappingData> {
private final String schema;
public EntityToEntityMapper() {
StringBuffer str = new StringBuffer("select eem.id as mapId, ");
str.append("eem.rel_id as relId, ");
str.append("eem.from_id as from_id, ");
str.append("eem.to_id as to_id, ");
str.append("eem.start_date as startDate, ");
str.append("eem.end_date as endDate, ");
str.append("case er.code_name ");
str.append("when 'office_access_to_loan_products' then ");
str.append("o.name ");
str.append("when 'office_access_to_savings_products' then ");
str.append("o.name ");
str.append("when 'office_access_to_fees/charges' then ");
str.append("o.name ");
str.append("when 'role_access_to_loan_products' then ");
str.append("r.name ");
str.append("when 'role_access_to_savings_products' then ");
str.append("r.name ");
str.append("end as from_name, ");
str.append("case er.code_name ");
str.append("when 'office_access_to_loan_products' then ");
str.append("lp.name ");
str.append("when 'office_access_to_savings_products' then ");
str.append("sp.name ");
str.append("when 'office_access_to_fees/charges' then ");
str.append("charge.name ");
str.append("when 'role_access_to_loan_products' then ");
str.append("lp.name ");
str.append("when 'role_access_to_savings_products' then ");
str.append("sp.name ");
str.append("end as to_name, ");
str.append("er.code_name ");
str.append("from m_entity_to_entity_mapping eem ");
str.append("join m_entity_relation er on eem.rel_id = er.id ");
str.append("left join m_office o on er.from_entity_type = 1 and eem.from_id = o.id ");
str.append("left join m_role r on er.from_entity_type = 5 and eem.from_id = r.id ");
str.append("left join m_product_loan lp on er.to_entity_type = 2 and eem.to_id = lp.id ");
str.append("left join m_savings_product sp on er.to_entity_type = 3 and eem.to_id = sp.id ");
str.append("left join m_charge charge on er.to_entity_type = 4 and eem.to_id = charge.id ");
str.append("where ");
str.append("er.id = ? and ");
str.append("( ? = 0 or from_id = ? ) and ");
str.append("( ? = 0 or to_id = ? ) ");
this.schema = str.toString();
}
public String schema() {
return this.schema;
}
@Override
public MifosEntityToEntityMappingData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long mapId = rs.getLong("mapId");
final Long relId = rs.getLong("relId");
final Long fromId = rs.getLong("from_id");
final Long toId = rs.getLong("to_id");
final String fromEntity = rs.getString("from_name");
final String toEntity = rs.getString("to_name");
final Date startDate = rs.getDate("startDate");
final Date endDate = rs.getDate("endDate");
return MifosEntityToEntityMappingData.getRelatedEntities(mapId, relId, fromId, toId, startDate, endDate, fromEntity, toEntity);
}
}
}