package org.sigmah.offline.handler;
/*
* #%L
* Sigmah
* %%
* Copyright (C) 2010 - 2016 URD
* %%
* 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.extjs.gxt.ui.client.data.RpcMap;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.sigmah.client.dispatch.DispatchListener;
import org.sigmah.offline.dao.MonitoredPointAsyncDAO;
import org.sigmah.offline.dao.PersonalCalendarAsyncDAO;
import org.sigmah.offline.dao.ProjectAsyncDAO;
import org.sigmah.offline.dao.ReminderAsyncDAO;
import org.sigmah.offline.dao.RequestManager;
import org.sigmah.offline.dao.RequestManagerCallback;
import org.sigmah.offline.dao.UpdateDiaryAsyncDAO;
import org.sigmah.offline.dispatch.AsyncCommandHandler;
import org.sigmah.offline.dispatch.OfflineExecutionContext;
import org.sigmah.offline.dispatch.UnavailableCommandException;
import org.sigmah.shared.command.CreateEntity;
import org.sigmah.shared.command.result.Authentication;
import org.sigmah.shared.command.result.Calendar;
import org.sigmah.shared.command.result.CreateResult;
import org.sigmah.shared.dto.ProjectDTO;
import org.sigmah.shared.dto.calendar.Event;
import org.sigmah.shared.dto.calendar.PersonalCalendarIdentifier;
import org.sigmah.shared.dto.calendar.PersonalEventDTO;
import org.sigmah.shared.dto.referential.ReminderChangeType;
import org.sigmah.shared.dto.reminder.MonitoredPointDTO;
import org.sigmah.shared.dto.reminder.MonitoredPointHistoryDTO;
import org.sigmah.shared.dto.reminder.ReminderDTO;
import org.sigmah.shared.dto.reminder.ReminderHistoryDTO;
import org.sigmah.shared.dto.report.ProjectReportDTO;
/**
* JavaScript implementation of {@link org.sigmah.server.handler.CreateEntityHandler}.
* Used when the user is offline.
*
* Server-side, this handler is used as a generic handler to create entities.
*
* @author Raphaƫl Calabro (rcalabro@ideia.fr)
*/
@Singleton
public class CreateEntityAsyncHandler implements AsyncCommandHandler<CreateEntity, CreateResult>, DispatchListener<CreateEntity, CreateResult> {
@Inject
private UpdateDiaryAsyncDAO updateDiaryAsyncDAO;
@Inject
private ProjectAsyncDAO projectAsyncDAO;
@Inject
private PersonalCalendarAsyncDAO personalCalendarAsyncDAO;
@Inject
private MonitoredPointAsyncDAO monitoredPointAsyncDAO;
@Inject
private ReminderAsyncDAO reminderAsyncDAO;
@Override
public void execute(CreateEntity command, OfflineExecutionContext executionContext, final AsyncCallback<CreateResult> callback) {
executeCommand(command, null, executionContext.getAuthentication(), callback);
updateDiaryAsyncDAO.saveOrUpdate(command);
}
@Override
public void onSuccess(CreateEntity command, CreateResult result, Authentication authentication) {
executeCommand(command, result, authentication, null);
}
private void executeCommand(CreateEntity command, CreateResult result, Authentication authentication, AsyncCallback<CreateResult> callback) {
if(ProjectDTO.ENTITY_NAME.equals(command.getEntityName())) {
exception(command, callback != null);
} else if(PersonalEventDTO.ENTITY_NAME.equals(command.getEntityName())) {
insertPersonalEvent(command, callback);
} else if(ProjectReportDTO.ENTITY_NAME.equals(command.getEntityName())) {
exception(command, callback != null);
} else if(ReminderDTO.ENTITY_NAME.equals(command.getEntityName())) {
if(result != null) {
reminderAsyncDAO.saveOrUpdate((ReminderDTO)result.getEntity());
} else {
insertReminder(command, authentication, callback);
}
} else if(MonitoredPointDTO.ENTITY_NAME.equals(command.getEntityName())) {
if(result != null) {
monitoredPointAsyncDAO.saveOrUpdate((MonitoredPointDTO)result.getEntity());
} else {
insertMonitoredPoint(command, authentication, callback);
}
} else {
exception(command, callback != null);
}
}
private void exception(CreateEntity command, boolean throwException) throws UnavailableCommandException {
if(throwException) {
throw new UnavailableCommandException("Creation of type '" + command.getEntityName() + "' is not supported yet.");
}
}
private void insertPersonalEvent(CreateEntity command, final AsyncCallback<CreateResult> callback) {
final Event event = buildPersonalEvent(command.getProperties());
final PersonalCalendarIdentifier identifier = (PersonalCalendarIdentifier) event.getParent().getIdentifier();
final Date key = (Date) command.getProperties().get(Event.DATE);
// Loading the parent calendar.
personalCalendarAsyncDAO.get(identifier.getId(), new AsyncCallback<Calendar>() {
@Override
public void onFailure(Throwable caught) {
if(callback != null) {
callback.onFailure(caught);
}
}
@Override
public void onSuccess(Calendar result) {
List<Event> events = result.getEvents().get(key);
if(events == null) {
events = new ArrayList<Event>();
result.getEvents().put(key, events);
}
events.add(event);
// Creating the callback, if necessary.
final AsyncCallback<Calendar> calendarCallback;
if(callback != null) {
calendarCallback = new AsyncCallback<Calendar>() {
@Override
public void onFailure(Throwable caught) {
callback.onFailure(caught);
}
@Override
public void onSuccess(Calendar result) {
callback.onSuccess(new CreateResult(new PersonalEventDTO()));
}
};
} else {
calendarCallback = null;
}
// Persisting the new event.
personalCalendarAsyncDAO.saveOrUpdate(result, calendarCallback);
}
});
}
private Event buildPersonalEvent(RpcMap properties) {
final Event event = new Event();
event.fillValues(properties.getTransientMap());
return event;
}
private void insertReminder(final CreateEntity command, final Authentication authentication, final AsyncCallback<CreateResult> callback) {
final ReminderDTO reminder = buildReminderDTO(command.getProperties(), authentication);
final RequestManager<CreateResult> requestManager = new RequestManager<CreateResult>(new CreateResult(reminder), callback);
final int futureRequest = requestManager.prepareRequest();
final RequestManager<ReminderDTO> objectRequestManager = new RequestManager<ReminderDTO>(reminder, new RequestManagerCallback<CreateResult, ReminderDTO>(requestManager) {
@Override
public void onRequestSuccess(ReminderDTO result) {
reminderAsyncDAO.saveOrUpdate(result, new RequestManagerCallback<CreateResult, ReminderDTO>(requestManager, futureRequest) {
@Override
public void onRequestSuccess(ReminderDTO result) {
// Reminder has been saved successfully.
}
});
}
});
// Retrieves project.
final Integer projectId = (Integer) command.getProperties().get(ReminderDTO.PROJECT_ID);
projectAsyncDAO.get(projectId, new RequestManagerCallback<ReminderDTO, ProjectDTO>(objectRequestManager) {
@Override
public void onRequestSuccess(ProjectDTO result) {
final Integer remindersListId = result.getRemindersList().getId();
reminder.setParentListId(remindersListId);
}
});
// Generates a negative ID
reminderAsyncDAO.generateNegativeId(new RequestManagerCallback<ReminderDTO, Integer>(objectRequestManager) {
@Override
public void onRequestSuccess(Integer result) {
reminder.setId(result);
}
});
objectRequestManager.ready();
requestManager.ready();
}
private ReminderDTO buildReminderDTO(RpcMap properties, Authentication authentication) {
final ReminderDTO reminder = new ReminderDTO();
// Retrieves parameters.
final Long expectedDate = (Long) properties.get(ReminderDTO.EXPECTED_DATE);
final String label = (String) properties.get(ReminderDTO.LABEL);
// Creates point.
reminder.setLabel(label);
reminder.setExpectedDate(new Date(expectedDate));
reminder.setCompletionDate(null);
reminder.setDeleted(false);
final ArrayList<ReminderHistoryDTO> historyList = new ArrayList<ReminderHistoryDTO>();
final ReminderHistoryDTO history = new ReminderHistoryDTO();
history.setDate(new Date());
history.setType(ReminderChangeType.CREATED);
history.setUserId(authentication.getUserId());
history.setValue(authentication.getUserName() + ", " + authentication.getUserFirstName() + " <" + authentication.getUserEmail() + ">");
historyList.add(history);
reminder.setHistory(historyList);
return reminder;
}
private void insertMonitoredPoint(final CreateEntity command, final Authentication authentication, final AsyncCallback<CreateResult> callback) {
final MonitoredPointDTO monitoredPointDTO = buildMonitoredPointDTO(command.getProperties(), authentication);
final RequestManager<CreateResult> requestManager = new RequestManager<CreateResult>(new CreateResult(monitoredPointDTO), callback);
final int futureRequest = requestManager.prepareRequest();
final RequestManager<MonitoredPointDTO> objectRequestManager = new RequestManager<MonitoredPointDTO>(monitoredPointDTO, new RequestManagerCallback<CreateResult, MonitoredPointDTO>(requestManager) {
@Override
public void onRequestSuccess(MonitoredPointDTO result) {
monitoredPointAsyncDAO.saveOrUpdate(result, new RequestManagerCallback<CreateResult, MonitoredPointDTO>(requestManager, futureRequest) {
@Override
public void onRequestSuccess(MonitoredPointDTO result) {
// Monitored Point has been saved successfully.
}
});
}
});
// Retrieves project.
final Integer projectId = (Integer) command.getProperties().get(ReminderDTO.PROJECT_ID);
projectAsyncDAO.get(projectId, new RequestManagerCallback<MonitoredPointDTO, ProjectDTO>(objectRequestManager) {
@Override
public void onRequestSuccess(ProjectDTO result) {
final Integer pointsListId = result.getPointsList().getId();
monitoredPointDTO.setParentListId(pointsListId);
}
});
// Generates a negative ID
monitoredPointAsyncDAO.generateNegativeId(new RequestManagerCallback<MonitoredPointDTO, Integer>(objectRequestManager) {
@Override
public void onRequestSuccess(Integer result) {
monitoredPointDTO.setId(result);
}
});
objectRequestManager.ready();
requestManager.ready();
}
private MonitoredPointDTO buildMonitoredPointDTO(RpcMap properties, Authentication authentication) {
final MonitoredPointDTO monitoredPoint = new MonitoredPointDTO();
// Retrieves parameters.
final Long expectedDate = (Long) properties.get(MonitoredPointDTO.EXPECTED_DATE);
final String label = (String) properties.get(MonitoredPointDTO.LABEL);
// Creates point.
monitoredPoint.setLabel(label);
monitoredPoint.setExpectedDate(new Date(expectedDate));
monitoredPoint.setCompletionDate(null);
monitoredPoint.setDeleted(false);
final ArrayList<MonitoredPointHistoryDTO> historyList = new ArrayList<MonitoredPointHistoryDTO>();
final MonitoredPointHistoryDTO history = new MonitoredPointHistoryDTO();
history.setDate(new Date());
history.setType(ReminderChangeType.CREATED);
history.setUserId(authentication.getUserId());
history.setValue(authentication.getUserName() + ", " + authentication.getUserFirstName() + " <" + authentication.getUserEmail() + ">");
historyList.add(history);
monitoredPoint.setHistory(historyList);
return monitoredPoint;
}
}