package org.sigmah.server.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.google.inject.Inject;
import com.google.inject.persist.Transactional;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
import org.sigmah.server.dao.ContactDAO;
import org.sigmah.server.dispatch.impl.UserDispatch.UserExecutionContext;
import org.sigmah.server.domain.Contact;
import org.sigmah.server.domain.User;
import org.sigmah.server.domain.element.DefaultContactFlexibleElement;
import org.sigmah.server.domain.element.FlexibleElement;
import org.sigmah.server.handler.base.AbstractCommandHandler;
import org.sigmah.server.i18n.I18nServer;
import org.sigmah.server.service.ValueService;
import org.sigmah.shared.Language;
import org.sigmah.shared.command.UpdateContact;
import org.sigmah.shared.command.result.VoidResult;
import org.sigmah.shared.dispatch.CommandException;
import org.sigmah.shared.dispatch.FunctionalException;
import org.sigmah.shared.dispatch.UpdateConflictException;
import org.sigmah.shared.dto.element.DefaultContactFlexibleElementDTO;
import org.sigmah.shared.dto.element.FlexibleElementDTO;
import org.sigmah.shared.dto.element.event.ValueEventWrapper;
import org.sigmah.shared.dto.value.TripletValueDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UpdateContactHandler extends AbstractCommandHandler<UpdateContact, VoidResult> {
private static final Logger LOGGER = LoggerFactory.getLogger(UpdateContactHandler.class);
private final I18nServer i18nServer;
private final ContactDAO contactDAO;
private final ValueService valueService;
@Inject
public UpdateContactHandler(final I18nServer i18nServer, final ContactDAO contactDAO, final ValueService valueService) {
this.i18nServer = i18nServer;
this.contactDAO = contactDAO;
this.valueService = valueService;
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public VoidResult execute(UpdateContact cmd, UserExecutionContext context) throws CommandException {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("[execute] Updates contact #" + cmd.getContactId() + " with following values #" + cmd.getValues().size() + " : " + cmd.getValues());
}
updateContact(cmd.getValues(), cmd.getContactId(), context, cmd.getComment());
return null;
}
@Transactional(rollbackOn = CommandException.class)
protected void updateContact(List<ValueEventWrapper> values, Integer contactId, UserExecutionContext context, String comment) throws CommandException {
// This date must be the same for all the saved values !
final Date historyDate = new Date();
final User user = context.getUser();
final Contact contact = contactDAO.findById(contactId);
// Verify if the modifications conflicts with the contact state.
final List<String> conflicts = searchForConflicts(contact, context);
// Iterating over the value change events
for (final ValueEventWrapper valueEvent : values) {
// Event parameters.
final FlexibleElementDTO source = valueEvent.getSourceElement();
final FlexibleElement element = em().find(FlexibleElement.class, source.getId());
final TripletValueDTO updateListValue = valueEvent.getTripletValue();
final String updateSingleValue = valueEvent.getSingleValue();
final Set<Integer> multivaluedIdsValue = valueEvent.getMultivaluedIdsValue();
final Integer iterationId = valueEvent.getIterationId();
LOGGER.debug("[execute] Updates value of element #{} ({})", source.getId(), source.getEntityName());
LOGGER.debug("[execute] Event of type {} with value {} and list value {} (iteration : {}).", valueEvent.getChangeType(), updateSingleValue, updateListValue, iterationId);
if (source instanceof DefaultContactFlexibleElementDTO) {
// Case of the default flexible element which values arent't stored
// like other values. These values impact directly the contact.
valueService.saveValue(updateSingleValue, historyDate, (DefaultContactFlexibleElement)element, contact, iterationId, user, comment);
}
else if (updateSingleValue != null) {
valueService.saveValue(updateSingleValue, historyDate, element, contactId, iterationId, user, comment);
}
else if (multivaluedIdsValue != null) {
valueService.saveValue(multivaluedIdsValue, valueEvent, historyDate, element, contactId, iterationId, user, comment);
}
else if (updateListValue != null) {
// Special case : this value is a part of a list which is the true value of the flexible element. (only used for
// the TripletValue class for the moment)
valueService.saveValue(updateListValue, valueEvent.getChangeType(), historyDate, element, contactId, iterationId, user, comment);
}
else {
LOGGER.warn("Empty value event received for element #{} ({}) of container #{}.", source.getId(), source.getEntityName(), contactId);
}
}
if (!conflicts.isEmpty()) {
// A conflict was found.
throw new UpdateConflictException(contact.toContainerInformation(), conflicts.toArray(new String[0]));
}
}
// Check if the targeted contact can be updated
private List<String> searchForConflicts(Contact contact, UserExecutionContext context) throws FunctionalException {
Language language = context.getLanguage();
if (contact == null) {
return Collections.singletonList(i18nServer.t(language, "contactNotFoundError"));
}
List<String> conflicts = new ArrayList<>();
if (contact.getContactModel().isUnderMaintenance()) {
conflicts.add(i18nServer.t(language, "conflictEditingUnderMaintenanceContact", contact.getFullName()));
}
// TODO: check computation values
// TODO: check permissions
return conflicts;
}
}