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 java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.sigmah.server.dao.ContactDAO;
import org.sigmah.server.dao.CountryDAO;
import org.sigmah.server.dao.FlexibleElementDAO;
import org.sigmah.server.dao.HistoryTokenDAO;
import org.sigmah.server.dao.OrgUnitDAO;
import org.sigmah.server.dao.ValueDAO;
import org.sigmah.server.dispatch.impl.UserDispatch;
import org.sigmah.server.domain.Contact;
import org.sigmah.server.domain.HistoryToken;
import org.sigmah.server.domain.OrgUnit;
import org.sigmah.server.domain.User;
import org.sigmah.server.domain.element.DefaultContactFlexibleElement;
import org.sigmah.server.domain.element.FlexibleElement;
import org.sigmah.server.domain.value.Value;
import org.sigmah.server.handler.base.AbstractCommandHandler;
import org.sigmah.shared.command.DedupeContact;
import org.sigmah.shared.command.result.ContactDuplicatedProperty;
import org.sigmah.shared.dispatch.CommandException;
import org.sigmah.shared.dto.ContactDTO;
import org.sigmah.shared.dto.referential.ValueEventChangeType;
import org.sigmah.shared.util.ValueResultUtils;
public class DedupeContactHandler extends AbstractCommandHandler<DedupeContact, ContactDTO> {
private final ContactDAO contactDAO;
private final CountryDAO countryDAO;
private final FlexibleElementDAO flexibleElementDAO;
private final HistoryTokenDAO historyTokenDAO;
private final OrgUnitDAO orgUnitDAO;
private final ValueDAO valueDAO;
@Inject
public DedupeContactHandler(ContactDAO contactDAO, CountryDAO countryDAO, FlexibleElementDAO flexibleElementDAO, HistoryTokenDAO historyTokenDAO, OrgUnitDAO orgUnitDAO, ValueDAO valueDAO) {
this.contactDAO = contactDAO;
this.countryDAO = countryDAO;
this.flexibleElementDAO = flexibleElementDAO;
this.historyTokenDAO = historyTokenDAO;
this.orgUnitDAO = orgUnitDAO;
this.valueDAO = valueDAO;
}
@Override
protected ContactDTO execute(DedupeContact command, UserDispatch.UserExecutionContext context) throws CommandException {
Contact targetedContact = contactDAO.findById(command.getTargetedContactId());
if (command.getOriginContactId() != null) {
Contact originContact = contactDAO.findById(command.getOriginContactId());
mergeContacts(originContact, targetedContact, command.getContactDuplicatedProperties(), context.getUser());
} else {
applyProperties(command.getContactDuplicatedProperties(), targetedContact, context.getUser());
}
return mapper().map(targetedContact, new ContactDTO());
}
private void mergeContacts(Contact originContact, Contact targetedContact, List<ContactDuplicatedProperty> properties, User user) {
for (ContactDuplicatedProperty property : properties) {
FlexibleElement flexibleElement = flexibleElementDAO.findById(property.getFlexibleElementId());
if (flexibleElement instanceof DefaultContactFlexibleElement) {
applyDefaultValue(originContact, targetedContact, (DefaultContactFlexibleElement) flexibleElement);
continue;
}
Value oldValue = valueDAO.getValueByElementAndContainer(property.getFlexibleElementId(), targetedContact.getId());
HistoryToken historyToken = valueToHistoryToken(oldValue, user);
historyTokenDAO.persist(historyToken, user);
Value newValue = valueDAO.getValueByElementAndContainer(property.getFlexibleElementId(), originContact.getId());
oldValue.setValue(newValue.getValue());
valueDAO.persist(oldValue, user);
}
originContact.delete();
contactDAO.persist(originContact, user);
}
private HistoryToken valueToHistoryToken(Value value, User user) {
HistoryToken historyToken = new HistoryToken();
// XXX: Set comment?
historyToken.setDate(new Date());
historyToken.setElementId(value.getElement().getId());
historyToken.setProjectId(value.getContainerId());
historyToken.setType(ValueEventChangeType.EDIT);
historyToken.setValue(value.getValue());
historyToken.setUser(user);
return historyToken;
}
private void applyDefaultValue(Contact originContact, Contact targetedContact, DefaultContactFlexibleElement flexibleElement) {
switch (flexibleElement.getType()) {
case FIRST_NAME:
targetedContact.setFirstname(originContact.getFirstname());
break;
case ORGANIZATION_NAME: // Fall through
case FAMILY_NAME:
targetedContact.setName(originContact.getName());
break;
case MAIN_ORG_UNIT:
targetedContact.setMainOrgUnit(originContact.getMainOrgUnit());
break;
case SECONDARY_ORG_UNITS:
targetedContact.setSecondaryOrgUnits(originContact.getSecondaryOrgUnits());
break;
case LOGIN:
targetedContact.setLogin(originContact.getLogin());
break;
case EMAIL_ADDRESS:
targetedContact.setEmail(originContact.getEmail());
break;
case PHONE_NUMBER:
targetedContact.setPhoneNumber(originContact.getPhoneNumber());
break;
case POSTAL_ADDRESS:
targetedContact.setPostalAddress(originContact.getPostalAddress());
break;
case PHOTO:
targetedContact.setPhoto(originContact.getPhoto());
break;
case COUNTRY:
targetedContact.setCountry(originContact.getCountry());
break;
case DIRECT_MEMBERSHIP:
targetedContact.setParent(originContact.getParent());
break;
case CREATION_DATE: // Fall through
case TOP_MEMBERSHIP:
// NOOP, shouldn't be possible
break;
default:
throw new IllegalStateException("Unknown DefaultContactFlexibleElementType : " + flexibleElement.getType());
}
}
private void applyProperties(List<ContactDuplicatedProperty> properties, Contact contact, User user) {
// This function is always called when the new contact was in creation
// So only default values are concerned by the properties
for (ContactDuplicatedProperty property : properties) {
DefaultContactFlexibleElement flexibleElement = (DefaultContactFlexibleElement) flexibleElementDAO.findById(property.getFlexibleElementId());
switch (flexibleElement.getType()) {
case FIRST_NAME:
contact.setFirstname(property.getSerializedNewValue());
break;
case ORGANIZATION_NAME: // Fall through
case FAMILY_NAME:
contact.setName(property.getSerializedNewValue());
break;
case MAIN_ORG_UNIT:
if (property.getSerializedNewValue() == null) {
contact.setMainOrgUnit(null);
continue;
}
int mainOrgUnitId = Integer.parseInt(property.getSerializedNewValue());
contact.setMainOrgUnit(orgUnitDAO.findById(mainOrgUnitId));
break;
case SECONDARY_ORG_UNITS:
if (property.getSerializedNewValue() == null) {
contact.setSecondaryOrgUnits(null);
continue;
}
ArrayList<OrgUnit> orgUnits = new ArrayList<>();
for (String serializedId : property.getSerializedNewValue().split(ValueResultUtils.DEFAULT_VALUE_SEPARATOR)) {
int secondaryOrgUnitId = Integer.parseInt(serializedId);
orgUnits.add(orgUnitDAO.findById(secondaryOrgUnitId));
}
contact.setSecondaryOrgUnits(orgUnits);
break;
case LOGIN:
contact.setLogin(property.getSerializedNewValue());
break;
case EMAIL_ADDRESS:
contact.setEmail(property.getSerializedNewValue());
break;
case PHONE_NUMBER:
contact.setPhoneNumber(property.getSerializedNewValue());
break;
case POSTAL_ADDRESS:
contact.setPostalAddress(property.getSerializedNewValue());
break;
case PHOTO:
contact.setPhoto(property.getSerializedNewValue());
break;
case COUNTRY:
if (property.getSerializedNewValue() == null) {
contact.setCountry(null);
continue;
}
int countryId = Integer.parseInt(property.getSerializedNewValue());
contact.setCountry(countryDAO.findById(countryId));
break;
case DIRECT_MEMBERSHIP:
if (property.getSerializedNewValue() == null) {
contact.setParent(null);
continue;
}
int parentId = Integer.parseInt(property.getSerializedNewValue());
contact.setParent(contactDAO.findById(parentId));
break;
case CREATION_DATE: // Fall through
case TOP_MEMBERSHIP:
// NOOP, shouldn't be possible
break;
default:
throw new IllegalStateException("Unknown DefaultContactFlexibleElementType : " + flexibleElement.getType());
}
}
contactDAO.persist(contact, user);
}
}