/**
   * Delete all the POIs who are ways and have no PoiType except the POIs in parameters. Delete also
   * the PoiNodeRefs associated.
   *
   * <p>Do not call the DAO directly to delete a way, use this method.
   *
   * @param exceptions The POIs who shouldn't be deleted.
   */
  public void deleteAllWaysExcept(final List<Poi> exceptions) {
    databaseHelper.callInTransaction(
        new Callable<Void>() {
          @Override
          public Void call() throws Exception {
            List<Poi> pois = poiDao.queryForAllWaysNoType();
            pois.removeAll(exceptions);
            List<Poi> poisToDelete = new ArrayList<>();

            for (Poi poi : pois) {
              boolean delete = true;
              for (PoiNodeRef poiNodeRef : poi.getNodeRefs()) {
                if (poiNodeRef.getUpdated()) {
                  delete = false;
                }
              }
              if (delete) {
                poisToDelete.add(poi);
                poiNodeRefDao.delete(poi.getNodeRefs());
              }
            }

            poiDao.delete(poisToDelete);
            return null;
          }
        });
  }
 /**
  * Method saving a poi and all the associated foreign collections.
  *
  * <p>Do not call the DAO directly to save a poi, use this method.
  *
  * @param poi The poi to save.
  * @return The saved poi.
  */
 public Poi savePoi(final Poi poi) {
   return databaseHelper.callInTransaction(
       new Callable<Poi>() {
         @Override
         public Poi call() throws Exception {
           return savePoiNoTransaction(poi);
         }
       });
 }
 /**
  * Reset the database : delete all the Pois, PoiTags and PoiNodeRefs of the database.
  *
  * @return Whether the reset was successful.
  */
 public Boolean resetDatabase() {
   return databaseHelper.callInTransaction(
       new Callable<Boolean>() {
         @Override
         public Boolean call() throws Exception {
           poiDao.deleteAll();
           poiNodeRefDao.deleteAll();
           poiTagDao.deleteAll();
           return true;
         }
       });
 }
 /**
  * Method saving a List of POIs and all the associated foreign collections. The saving is done in
  * a transaction.
  *
  * <p>Do not call the DAO directly to save a List of POIs, use this method.
  *
  * @param pois The List of POIs to save.
  * @return The saved List.
  */
 public List<Poi> savePois(final List<Poi> pois) {
   return databaseHelper.callInTransaction(
       new Callable<List<Poi>>() {
         @Override
         public List<Poi> call() throws Exception {
           List<Poi> result = new ArrayList<>(pois.size());
           for (Poi poi : pois) {
             result.add(savePoiNoTransaction(poi));
           }
           return result;
         }
       });
 }
 /**
  * Method saving a List of PoiNodeRefs.
  *
  * @param poiNodeRefs The List of PoiNodeReds to save.
  * @return The saved List.
  */
 public List<PoiNodeRef> savePoiNodeRefs(final List<PoiNodeRef> poiNodeRefs) {
   return databaseHelper.callInTransaction(
       new Callable<List<PoiNodeRef>>() {
         @Override
         public List<PoiNodeRef> call() throws Exception {
           List<PoiNodeRef> result = new ArrayList<>(poiNodeRefs.size());
           for (PoiNodeRef poiNodeRef : poiNodeRefs) {
             poiNodeRefDao.createOrUpdate(poiNodeRef);
             result.add(poiNodeRef);
           }
           return result;
         }
       });
 }
 /**
  * Reset the PoiTypes of the database : delete all the Pois, PoiTags, PoiNodeRefs, PoiTypes and
  * PoiTypeTags of the database then reload and save the PoiTypes from the assets.
  *
  * @return Whether the reset was successful.
  */
 public Boolean resetTypes() {
   return databaseHelper.callInTransaction(
       new Callable<Boolean>() {
         @Override
         public Boolean call() throws Exception {
           Timber.d("Resetting the PoiTypes of the database");
           poiDao.deleteAll();
           poiNodeRefDao.deleteAll();
           poiTagDao.deleteAll();
           poiTypeDao.deleteAll();
           poiTypeTagDao.deleteAll();
           Timber.d("All Pois en PoiTypes deleted from database");
           savePoiTypesFromAssets();
           Timber.d("Finished reloading and saving PoiTypes from assets");
           return true;
         }
       });
 }
 /**
  * Method saving a PoiType and all the associated foreign collections.
  *
  * <p>Do not call the DAO directly to save a PoiType, use this method.
  *
  * @param poiType The PoiType to save.
  * @return The saved PoiType.
  */
 public PoiType savePoiType(final PoiType poiType) {
   return databaseHelper.callInTransaction(
       new Callable<PoiType>() {
         @Override
         public PoiType call() throws Exception {
           poiTypeDao.createOrUpdate(poiType);
           List<PoiTypeTag> poiTypeTagsToDelete = poiTypeTagDao.queryByPoiTypeId(poiType.getId());
           poiTypeTagsToDelete.removeAll(poiType.getTags());
           poiTypeTagDao.delete(poiTypeTagsToDelete);
           // Save the PoiTypeTags
           for (PoiTypeTag poiTypeTag : poiType.getTags()) {
             poiTypeTag.setPoiType(poiType);
             poiTypeTagDao.createOrUpdate(poiTypeTag);
           }
           return poiType;
         }
       });
 }
  /**
   * Delete a PoiType and all the PoiTypeTags and POIs associated.
   *
   * <p>Do not call the DAO directly to delete a PoiType, use this method.
   *
   * @param poiType The PoiType to delete.
   */
  public void deletePoiType(PoiType poiType) {
    final Long id = poiType.getId();
    databaseHelper.callInTransaction(
        new Callable<PoiType>() {
          @Override
          public PoiType call() throws Exception {
            List<Long> poiIdsToDelete = poiDao.queryAllIdsByPoiTypeId(id);

            Timber.d("PoiTags deleted : %d", poiTagDao.deleteByPoiIds(poiIdsToDelete));
            Timber.d("PoiNodeRefs deleted : %d", poiNodeRefDao.deleteByPoiIds(poiIdsToDelete));
            Timber.d("POIs deleted : %d", poiDao.deleteIds(poiIdsToDelete));

            Timber.d("PoiTypeTags deleted : %d", poiTypeTagDao.deleteByPoiTypeId(id));
            poiTypeDao.deleteById(id);
            Timber.i("Deleted PoiType id=%d", id);
            return null;
          }
        });
  }
  /**
   * Delete a Poi and all PoiTags and PoiNodeRefs associated.
   *
   * <p>Do not call the DAO directly to delete a Poi, use this method.
   *
   * @param poi The Poi to delete.
   */
  public void deletePoi(final Poi poi) {
    databaseHelper.callInTransaction(
        new Callable<Void>() {
          @Override
          public Void call() throws Exception {
            Poi poiToDelete = poiDao.queryForId(poi.getId());
            if (poiToDelete == null) {
              return null;
            }
            List<PoiNodeRef> poiNodeRefsToDelete = poiNodeRefDao.queryByPoiId(poiToDelete.getId());
            List<PoiTag> poiTagsToDelete = poiTagDao.queryByPoiId(poiToDelete.getId());

            Timber.d("NodeRefs to delete : %d", poiNodeRefsToDelete.size());
            Timber.d("NodeTags to delete : %d", poiTagsToDelete.size());

            poiTagDao.delete(poiTagsToDelete);
            poiNodeRefDao.delete(poiNodeRefsToDelete);
            poiDao.delete(poiToDelete);

            Timber.i("Deleted Poi %d", poiToDelete.getId());
            return null;
          }
        });
  }