package net.techreadiness.plugin.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.ClientErrorException;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.SecurityContext;
import net.techreadiness.persistence.criteriaquery.QueryResult;
import net.techreadiness.persistence.dao.OrgDAO;
import net.techreadiness.persistence.dao.UserDAO;
import net.techreadiness.persistence.domain.OrgDO;
import net.techreadiness.persistence.domain.UserDO;
import net.techreadiness.plugin.persistence.dao.SnapshotWindowDao;
import net.techreadiness.plugin.persistence.domain.SnapshotWindowDO;
import net.techreadiness.plugin.persistence.report.BaseDataRetriever;
import net.techreadiness.plugin.service.object.SnapshotDevice;
import net.techreadiness.plugin.service.object.SnapshotOrg;
import net.techreadiness.plugin.service.reports.MinimumRecommendedFlag;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.MessageSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.transaction.annotation.Transactional;
import com.google.common.collect.Iterables;
@Named
@Path("snapshots")
@Produces(MediaType.APPLICATION_JSON)
@Transactional
public class SnapshotRestServiceImpl implements SnapshotRestService {
@Inject
private UserDAO userDAO;
@Inject
private OrgDAO orgDAO;
@Inject
private SnapshotWindowDao snapshotDAO;
@Inject
@Named("BaseDataRetriever")
private BaseDataRetriever dataRetriever;
@Inject
private JdbcTemplate template;
@Inject
private MessageSource messageSource;
@GET
@Path("{snapshotWindowId}/{orgId}")
@Override
@Produces(MediaType.APPLICATION_JSON)
public SnapshotOrg getSnapshotDataForOrg(@Context SecurityContext context,
@PathParam("snapshotWindowId") Long snapshotWindowId, @PathParam("orgId") Long orgId,
@QueryParam("flag") @DefaultValue("MINIMUM") MinimumRecommendedFlag flag) {
UserDO user = userDAO.findByUsername(context.getUserPrincipal().getName(), false);
if (!userDAO.hasAccessToOrg(user.getUserId(), orgId)) {
String message = messageSource.getMessage("validation.org.access.denied", new Object[] { user.getUsername(),
orgId }, java.util.Locale.getDefault());
throw new ClientErrorException(Response.status(Status.FORBIDDEN).entity(message).build());
}
try {
QueryResult<Map<String, String>> reportData = dataRetriever.getSnapshotReportDataForOrg(snapshotWindowId, orgId,
flag);
Collection<Map<String, String>> rows = reportData.getRows();
if (CollectionUtils.isEmpty(rows)) {
String message = messageSource.getMessage("ready.no.snapshot.data.for.org", null, Locale.getDefault());
throw new NotFoundException(Response.status(Status.NOT_FOUND).entity(message).build());
}
Map<String, String> first = Iterables.getFirst(rows, Collections.<String, String> emptyMap());
SnapshotOrg org = new SnapshotOrg();
for (Entry<String, String> entry : first.entrySet()) {
try {
BeanUtils.setProperty(org, entry.getKey(), entry.getValue());
} catch (Exception e) {
throw new InternalServerErrorException(e);
}
}
return org;
} catch (SQLException e) {
throw new InternalServerErrorException(e);
}
}
@Override
@GET
@Produces("text/csv")
@Path("{snapshotId}/{orgId}/non-compliant-devices")
public Response exportNonCompliantDevices(@Context SecurityContext context, @Context Request request,
@PathParam("snapshotId") Long snapshotId, @PathParam("orgId") Long orgId,
@QueryParam("flag") @DefaultValue("MINIMUM") MinimumRecommendedFlag flag) {
UserDO user = userDAO.findByUsername(context.getUserPrincipal().getName(), false);
if (!userDAO.hasAccessToOrg(user.getUserId(), orgId)) {
String message = messageSource.getMessage("validation.org.access.denied", new Object[] { user.getUsername(),
orgId }, java.util.Locale.getDefault());
throw new ClientErrorException(Response.status(Status.FORBIDDEN).entity(message).build());
}
OrgDO org = orgDAO.getById(orgId);
if (!org.getOrgType().isAllowDevice()) {
String message = messageSource.getMessage("ready.no.snapshot.data.for.org", new Object[] { user.getUsername(),
orgId }, java.util.Locale.getDefault());
throw new InternalServerErrorException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(message).build());
}
SnapshotWindowDO snapshot = snapshotDAO.getById(snapshotId);
ResponseBuilder response = request.evaluatePreconditions(snapshot.getExecuteDate());
if (response != null) {
return response.build();
}
List<SnapshotDevice> devices = template.query(buildNonCompliantQuery(flag), new Object[] { snapshotId, orgId },
new SnapshotDeviceRowMapper());
String header = "Organization,Device Name,# of Devices,Operating System,Memory,Monitor / Display Size,Screen Resolution,Environment";
StringBuilder sb = new StringBuilder(header.length() + devices.size() * 150);
sb.append(header);
sb.append("\n");
for (SnapshotDevice device : devices) {
sb.append(device.getOrgName());
sb.append(" (");
sb.append(device.getLocalOrgCode());
sb.append("),");
sb.append(device.getName());
sb.append(",");
sb.append(device.getCount());
sb.append(",");
if (device.getOperatingSystem() != null) {
sb.append(buildExportValue(device.getOperatingSystem()));
}
sb.append(",");
if (device.getMemory() != null) {
sb.append(buildExportValue(device.getMemory()));
}
sb.append(",");
if (device.getMonitorDisplaySize() != null) {
sb.append(buildExportValue(device.getMonitorDisplaySize()));
}
sb.append(",");
if (device.getScreenResolution() != null) {
sb.append(buildExportValue(device.getScreenResolution()));
}
sb.append(",");
if (device.getEnvironment() != null) {
sb.append(buildExportValue(device.getEnvironment()));
}
sb.append("\n");
}
CacheControl cache = new CacheControl();
cache.setMaxAge(3600);
cache.setMustRevalidate(true);
cache.setNoCache(false);
return Response.ok().type("text/csv").entity(sb.toString()).lastModified(snapshot.getExecuteDate())
.cacheControl(cache).build();
}
private static String buildExportValue(String value) {
if (value.contains(",")) {
String newValue = value.replaceAll(",", "");
value = newValue;
}
return StringUtils.defaultIfBlank(value, "(missing)");
}
private static String buildNonCompliantQuery(MinimumRecommendedFlag flag) {
StringBuilder sb = new StringBuilder();
sb.append("select ");
sb.append(" o.name orgName, ");
sb.append(" o.code orgCode, ");
sb.append(" o.local_code localOrgCode,");
sb.append(" concat(po.name,' (',po.local_code,')') parentOrgName, ");
sb.append(" po.code parentOrgCode, ");
sb.append(" po.local_code parentLocalOrgCode, ");
sb.append(" sd.name,");
sb.append(" sd.count count,");
sb.append(" sc_operating_system.name operatingSystem,");
sb.append(" sc_memory.name memory,");
sb.append(" sc_display_size.name monitorDisplaySize,");
sb.append(" sc_screen_resolution.name screenResolution,");
sb.append(" sc_environment.name environment,");
sb.append(" sd.environment_compliant environmentCompliance,");
if (flag.equals(MinimumRecommendedFlag.MINIMUM)) {
sb.append(" sd.min_compliant_operating_system operatingSystemCompliance,");
sb.append(" sd.min_compliant_memory memoryCompliance,");
sb.append(" sd.min_compliant_screen_resolution screenResolutionCompliance,");
sb.append(" sd.min_compliant_display_size monitorDisplaySizeCompliance");
} else {
sb.append(" sd.rec_compliant_operating_system operatingSystemCompliance,");
sb.append(" sd.rec_compliant_memory memoryCompliance,");
sb.append(" sd.rec_compliant_screen_resolution screenResolutionCompliance,");
sb.append(" sd.rec_compliant_display_size monitorDisplaySizeCompliance");
}
sb.append(" from readiness.snapshot_device sd");
sb.append(" join org o on o.org_id = sd.org_id");
sb.append(" join org po on po.org_id = o.parent_org_id");
sb.append(" left join readiness.snapshot_config sc_operating_system on sc_operating_system.snapshot_window_id = sd.snapshot_window_id ");
sb.append(" and sc_operating_system.code ='operatingSystems' ");
sb.append(" and sc_operating_system.value = sd.operating_system");
sb.append(" left join readiness.snapshot_config sc_memory on sc_memory.snapshot_window_id = sd.snapshot_window_id ");
sb.append(" and sc_memory.code ='memory' ");
sb.append(" and sc_memory.value = sd.memory");
sb.append(" left join readiness.snapshot_config sc_display_size on sc_display_size.snapshot_window_id = sd.snapshot_window_id ");
sb.append(" and sc_display_size.code ='displaySize' ");
sb.append(" and sc_display_size.value = sd.display_size");
sb.append(" left join readiness.snapshot_config sc_screen_resolution on sc_screen_resolution.snapshot_window_id = sd.snapshot_window_id ");
sb.append(" and sc_screen_resolution.code ='screenResolutions' ");
sb.append(" and sc_screen_resolution.value = sd.screen_resolution");
sb.append(" left join readiness.snapshot_config sc_environment on sc_environment.snapshot_window_id = sd.snapshot_window_id ");
sb.append(" and sc_environment.code ='environment' ");
sb.append(" and sc_environment.value = sd.environment");
sb.append(" where ");
sb.append(" sd.snapshot_window_id = ? ");
sb.append(" and sd.org_id = ? ");
if (flag.equals(MinimumRecommendedFlag.MINIMUM)) {
sb.append(" and min_compliant = 'no'");
} else {
sb.append(" and rec_compliant = 'no'");
}
return sb.toString();
}
private static final class SnapshotDeviceRowMapper implements RowMapper<SnapshotDevice> {
@Override
public SnapshotDevice mapRow(ResultSet rs, int rowNum) throws SQLException {
String orgName = rs.getString("orgName");
String orgCode = rs.getString("orgCode");
String localOrgCode = rs.getString("localOrgCode");
String parentOrgName = rs.getString("parentOrgName");
String parentOrgCode = rs.getString("parentOrgCode");
String parentLocalOrgCode = rs.getString("parentLocalOrgCode");
String name = rs.getString("name");
Long count = rs.getLong("count");
String operatingSystem = rs.getString("operatingSystem");
String memory = rs.getString("memory");
String monitorDisplaySize = rs.getString("monitorDisplaySize");
String screenResolution = rs.getString("screenResolution");
String environment = rs.getString("environment");
SnapshotDevice device = new SnapshotDevice();
device.setOrgName(orgName);
device.setOrgCode(orgCode);
device.setLocalOrgCode(localOrgCode);
device.setParentOrgName(parentOrgName);
device.setParentOrgCode(parentOrgCode);
device.setParentLocalOrgCode(parentLocalOrgCode);
device.setName(name);
device.setCount(count);
device.setOperatingSystem(operatingSystem);
device.setMemory(memory);
device.setMonitorDisplaySize(monitorDisplaySize);
device.setScreenResolution(screenResolution);
device.setEnvironment(environment);
return device;
}
}
}