public void onEventAsync(PleaseLoadPoisToUpdateEvent event) {
    List<Poi> updatedPois = poiDao.queryForAllUpdated();
    List<Poi> newPois = poiDao.queryForAllNew();
    List<Poi> toDeletePois = poiDao.queryToDelete();
    List<PoiNodeRef> wayPoiNodeRef = poiNodeRefDao.queryAllToUpdate();
    List<PoiUpdateWrapper> allPois = new ArrayList<>();

    for (Poi p : updatedPois) {
      allPois.add(
          new PoiUpdateWrapper(
              true,
              p,
              poiDao.queryForId(p.getOldPoiId()),
              null,
              PoiUpdateWrapper.PoiAction.UPDATE));
    }
    for (Poi p : newPois) {
      allPois.add(new PoiUpdateWrapper(true, p, null, null, PoiUpdateWrapper.PoiAction.CREATE));
    }
    for (Poi p : toDeletePois) {
      allPois.add(
          new PoiUpdateWrapper(
              true,
              p,
              poiDao.queryForId(p.getOldPoiId()),
              null,
              PoiUpdateWrapper.PoiAction.DELETED));
    }
    for (PoiNodeRef p : wayPoiNodeRef) {
      allPois.add(new PoiUpdateWrapper(false, null, null, p, PoiUpdateWrapper.PoiAction.UPDATE));
    }

    bus.post(new PoisToUpdateLoadedEvent(allPois));
  }
 public void deleteOldPoiAssociated(Poi poi) {
   Long oldId = poi.getOldPoiId();
   if (oldId != null) {
     Poi old = poiDao.queryForId(oldId);
     if (old != null) {
       deletePoi(old);
     }
     poi.setOldPoiId(null);
   }
 }
  /**
   * Method saving a poi and all the associated foreign collections without transaction management.
   *
   * <p>Do not call the DAO directly to save a poi, use this method.
   *
   * @param poi The poi to save
   * @return The saved poi
   * @see #savePoi(Poi)
   */
  private Poi savePoiNoTransaction(Poi poi) {
    List<PoiTag> poiTagsToRemove = poiTagDao.queryByPoiId(poi.getId());
    poiTagsToRemove.removeAll(poi.getTags());
    for (PoiTag poiTag : poiTagsToRemove) {
      poiTagDao.delete(poiTag);
    }

    List<PoiNodeRef> poiNodeRefsToRemove = poiNodeRefDao.queryByPoiId(poi.getId());
    poiNodeRefsToRemove.removeAll(poi.getNodeRefs());
    for (PoiNodeRef poiNodeRef : poiNodeRefsToRemove) {
      poiNodeRefDao.delete(poiNodeRef);
    }

    poiDao.createOrUpdate(poi);

    if (poi.getTags() != null) {
      for (PoiTag poiTag : poi.getTags()) {
        poiTag.setPoi(poi);
        poiTagDao.createOrUpdate(poiTag);
      }
    }

    if (poi.getNodeRefs() != null) {
      for (PoiNodeRef poiNodeRef : poi.getNodeRefs()) {
        poiNodeRef.setPoi(poi);
        poiNodeRefDao.createOrUpdate(poiNodeRef);
      }
    }

    return poi;
  }
 /**
  * Query for a Poi with a given id eagerly.
  *
  * @param id The id of the Poi to load.
  * @return The queried Poi.
  */
 public Poi queryForId(Long id) {
   Poi poi = poiDao.queryForId(id);
   if (poi == null) {
     return null;
   }
   poiTypeDao.refresh(poi.getType());
   poi.setTags(loadLazyForeignCollection(poi.getTags()));
   poi.getType().setTags(loadLazyForeignCollection(poi.getType().getTags()));
   return poi;
 }
  /**
   * Send a {@link io.mapsquare.osmcontributor.core.events.PoiForEditionLoadedEvent} containing the
   * suggestions for the PoiTypeTags and a new Poi to complete.
   *
   * @param event Event containing the position, level and PoiType of the Poi to create.
   */
  private void loadPoiForCreation(PleaseLoadPoiForCreationEvent event) {
    Poi poi = new Poi();
    Set<Double> level = new HashSet<>();
    level.add(event.getLevel());
    poi.setLevel(level);
    poi.setLatitude(event.getLat());
    poi.setLongitude(event.getLng());
    poi.setType(poiTypeDao.queryForId(event.getPoiType()));

    Map<String, String> defaultTags = new HashMap<>();
    for (PoiTypeTag poiTypeTag : poi.getType().getTags()) {
      if (poiTypeTag.getValue() != null) { // default tags should be set in the corresponding POI
        defaultTags.put(poiTypeTag.getKey(), poiTypeTag.getValue());
      }
    }
    poi.applyChanges(defaultTags);

    bus.post(new PoiForEditionLoadedEvent(poi, suggestionsForTagsValue(poi.getType().getTags())));
  }
  /**
   * Get the backup data and put it back in the active Poi, at the end the backup Poi is deleted.
   *
   * @param poiId The Id of the Poi to revert.
   */
  private void revertPoi(Long poiId) {
    Poi poi = poiDao.queryForId(poiId);
    Poi backup;
    Long oldPoiId = poi.getOldPoiId();

    if (oldPoiId != null) {
      backup = poiDao.queryForId(oldPoiId);

      // we retrieve the backup data and put it back
      backup.setOld(false);
      backup.setId(poi.getId());
      savePoi(backup);

      // we prepare to delete the modifications
      poi.setId(oldPoiId);
    }

    deletePoi(poi);
  }
  /**
   * Send a {@link io.mapsquare.osmcontributor.core.events.PoiForEditionLoadedEvent} containing the
   * Poi to edit and the suggestions for the PoiTypeTags.
   *
   * @param id The id of the Poi to edit.
   */
  private void loadPoiForEdition(Long id) {
    Poi poi = queryForId(id);

    bus.post(new PoiForEditionLoadedEvent(poi, suggestionsForTagsValue(poi.getType().getTags())));
  }
  /**
   * Merge POIs in parameters to those already in the database.
   *
   * @param remotePois The POIs to merge.
   */
  public void mergeFromOsmPois(List<Poi> remotePois) {
    List<Poi> toMergePois = new ArrayList<>();

    Map<String, Poi> remotePoisMap = new HashMap<>();
    // Map remote Poi backend Ids
    for (Poi poi : remotePois) {
      remotePoisMap.put(poi.getBackendId(), poi);
    }

    // List matching Pois
    List<Poi> localPois = poiDao.queryForBackendIds(remotePoisMap.keySet());

    Map<String, Poi> localPoisMap = new HashMap<>();
    // Map matching local Pois
    for (Poi localPoi : localPois) {
      localPoisMap.put(localPoi.getBackendId(), localPoi);
    }

    // Browse remote pois
    for (Poi remotePoi : remotePois) {
      Poi localPoi = localPoisMap.get(remotePoi.getBackendId());
      Long localVersion = -1L;
      // If localPoi is versioned
      if (localPoi != null && localPoi.getVersion() != null) {
        localVersion = Long.valueOf(localPoi.getVersion());
      }
      // Compute version delta
      if (Long.valueOf(remotePoi.getVersion()) > localVersion) {
        // Remote version is newer, override existing one
        if (localPoi != null) {
          remotePoi.setId(localPoi.getId());
        }
        // This Poi should be updated
        toMergePois.add(remotePoi);
      }
    }

    // savePois of either new or existing Pois
    savePois(toMergePois);
  }