class DemandResponseEventService {

	@Transactional(readOnly = false)
	public DemandResponseEvent update(DemandResponseEvent event, DemandResponseEventUpdateDto dto) {

		List<DemandResponseEventTarget> toKeep = new ArrayList<>();
		List<DemandResponseEventTargetDto> toAdd = new ArrayList<>();
		for (DemandResponseEventTargetDto updateTarget : dto.getTargets()) {
			boolean found = false;
			for (DemandResponseEventTarget target : event.getTargets()) {
				if (target.getTargetType().equals(updateTarget.getTargetType())
						&& target.getTargetId().equals(updateTarget.getTargetId())) {
					found = true;
					toKeep.add(target);
				}
			}
			if (!found) {
				toAdd.add(updateTarget);
			}

		}

		if (!toAdd.isEmpty()) {
			List<VenDemandResponseEvent> list = new ArrayList<>();
			List<Ven> findVenForTarget = findVenForTarget(event, toAdd);
			for (Ven ven : findVenForTarget) {
				list.add(new VenDemandResponseEvent(event, ven));
			}
			if (!list.isEmpty()) {
				venDemandResponseEventDao.saveAll(list);
			}

		}

		Set<DemandResponseEventTarget> actualSet = new HashSet<DemandResponseEventTarget>(event.getTargets());
		actualSet.removeAll(toKeep);
		// unlink removed target
		if (!actualSet.isEmpty()) {
			List<Ven> vens = findVenForTarget(event, new ArrayList<>(actualSet));
			venDemandResponseEventDao.deleteByEventIdAndVenIn(event.getId(), vens);
		}

		// update modification number if event is published
		if (dto.getPublished()) {
			event.getDescriptor().setModificationNumber(event.getDescriptor().getModificationNumber() + 1);
		}

		DemandResponseEvent partialUpdate = dtoMapper.map(dto, DemandResponseEvent.class);
		// link signals
		demandResponseEventSignalDao.deleteAll(event.getSignals());
		partialUpdate.getSignals().forEach(sig -> sig.setEvent(event));
		demandResponseEventSignalDao.saveAll(partialUpdate.getSignals());

		// update event
		event.getSignals().clear();
		event.getTargets().clear();
		event.getSignals().addAll(partialUpdate.getSignals());
		event.getTargets().addAll(partialUpdate.getTargets());
		event.setLastUpdateTimestamp(System.currentTimeMillis());
		event.setPublished(partialUpdate.isPublished());
		DemandResponseEvent save = demandResponseEventDao.save(event);

		if (dto.getPublished()) {
			this.distributeEventToPushVen(event);
		}

		return save;
	}

}