package org.activityinfo.legacy.shared.impl; /* * #%L * ActivityInfo Server * %% * Copyright (C) 2009 - 2013 UNICEF * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import com.bedatadriven.rebar.sql.client.SqlTransaction; import com.bedatadriven.rebar.sql.client.query.SqlInsert; import com.bedatadriven.rebar.sql.client.query.SqlUpdate; import com.bedatadriven.rebar.time.calendar.LocalDate; import com.extjs.gxt.ui.client.data.RpcMap; import com.google.gwt.user.client.rpc.AsyncCallback; import org.activityinfo.legacy.shared.command.CreateSite; import org.activityinfo.legacy.shared.command.result.CreateResult; import org.activityinfo.legacy.shared.command.result.VoidResult; import org.activityinfo.legacy.shared.exception.CommandException; import org.activityinfo.legacy.shared.model.AttributeDTO; import org.activityinfo.legacy.shared.model.IndicatorDTO; import java.util.Date; import java.util.Map.Entry; /** * Handles the creation of a new entity on the client side, and queues the * command for later transmission to the server. * <p/> * Currently only supports updates to the SiteDTO view. */ public class CreateSiteHandler implements CommandHandlerAsync<CreateSite, CreateResult> { @Override public void execute(final CreateSite cmd, final ExecutionContext context, final AsyncCallback<CreateResult> callback) { if (cmd.hasNestedCommand()) { executeNestedCommand(cmd, context); } insertSite(context.getTransaction(), cmd); // we only create a reporting period if this is a one-off activity Integer reportingPeriodId = cmd.getReportingPeriodId(); if (reportingPeriodId != null) { insertReportingPeriod(context.getTransaction(), cmd); } callback.onSuccess(new CreateResult(cmd.getSiteId())); } private void insertSite(SqlTransaction tx, CreateSite cmd) { RpcMap properties = cmd.getProperties(); // deal with the possibility that we've already received this command // but its completion was not acknowledged because of network problems tx.executeSql("delete from indicatorvalue Where ReportingPeriodId in " + "(select reportingperiodid from reportingperiod where siteid=" + cmd.getSiteId() + ")"); SqlUpdate.delete(Tables.REPORTING_PERIOD).where("SiteId", cmd.getSiteId()).execute(tx); SqlUpdate.delete(Tables.SITE_HISTORY).where("siteid", cmd.getSiteId()).execute(tx); SqlUpdate.delete(Tables.SITE).where("SiteId", cmd.getSiteId()).execute(tx); SqlInsert.insertInto(Tables.SITE) .value("SiteId", cmd.getSiteId()) .value("LocationId", cmd.getLocationId()) .value("ActivityId", cmd.getActivityId()) .value("Date1", properties.get("date1")) .value("Date2", properties.get("date2")) .value("Comments", properties.get("comments")) .value("PartnerId", properties.get("partnerId")) .value("ProjectId", properties.get("projectId")) .value("DateCreated", new Date()) .value("DateEdited", new Date()) .value("timeEdited", new Date().getTime()) .execute(tx); insertAttributeValues(tx, cmd); } private void insertAttributeValues(SqlTransaction tx, CreateSite cmd) { for (Entry<String, Object> property : cmd.getProperties().getTransientMap().entrySet()) { if (property.getKey().startsWith(AttributeDTO.PROPERTY_PREFIX) && property.getValue() != null) { SqlInsert.insertInto(Tables.ATTRIBUTE_VALUE) .value("AttributeId", AttributeDTO.idForPropertyName(property.getKey())) .value("SiteId", cmd.getSiteId()) .value("Value", property.getValue()) .execute(tx); } } } private int insertReportingPeriod(SqlTransaction tx, CreateSite cmd) { int reportingPeriodId = cmd.getReportingPeriodId(); SqlInsert.insertInto(Tables.REPORTING_PERIOD) .value("ReportingPeriodId", reportingPeriodId) .value("SiteId", cmd.getSiteId()) .value("Date1", cmd.getProperties().get("date1")) .value("Date2", cmd.getProperties().get("date2")) .value("DateCreated", new Date()) .value("DateEdited", new Date()) .execute(tx); insertIndicatorValues(tx, cmd); return reportingPeriodId; } private void insertIndicatorValues(SqlTransaction tx, CreateSite cmd) { for (Entry<String, Object> property : cmd.getProperties().getTransientMap().entrySet()) { if (property.getKey().startsWith(IndicatorDTO.PROPERTY_PREFIX) && property.getValue() != null) { Object value = property.getValue(); SqlInsert sqlInsert = SqlInsert.insertInto(Tables.INDICATOR_VALUE) .value("IndicatorId", IndicatorDTO.indicatorIdForPropertyName(property.getKey())) .value("ReportingPeriodId", cmd.getReportingPeriodId()); if (value instanceof Integer) { value = Double.valueOf(((Integer)value).doubleValue()); } if (value instanceof Double) { sqlInsert.value("Value", value).execute(tx); } else if (value instanceof String) { sqlInsert.value("TextValue", value).execute(tx); } else if (value instanceof Date) { sqlInsert.value("DateValue", value).execute(tx); } else if (value instanceof LocalDate) { sqlInsert.value("DateValue", value).execute(tx); } else if (value instanceof Boolean) { sqlInsert.value("BooleanValue", value).execute(tx); } } } } private void executeNestedCommand(final CreateSite cmd, final ExecutionContext context) { context.execute(cmd.getNestedCommand(), new AsyncCallback<VoidResult>() { @Override public void onSuccess(VoidResult result) { // continue creating the site } @Override public void onFailure(Throwable caught) { throw new CommandException("can't execute nested command while creating site", caught); } }); } }