@Path("{id}")
 @PUT
 public Response update(Geofence entity) throws SQLException {
   Context.getPermissionsManager().checkReadonly(getUserId());
   Context.getPermissionsManager().checkGeofence(getUserId(), entity.getId());
   Context.getGeofenceManager().updateGeofence(entity);
   return Response.ok(entity).build();
 }
 @POST
 public Response add(Geofence entity) throws SQLException {
   Context.getPermissionsManager().checkReadonly(getUserId());
   Context.getDataManager().addGeofence(entity);
   Context.getDataManager().linkGeofence(getUserId(), entity.getId());
   Context.getGeofenceManager().refreshGeofences();
   return Response.ok(entity).build();
 }
 public final void refreshGeofences() {
   if (dataManager != null) {
     try {
       geofencesLock.writeLock().lock();
       try {
         geofences.clear();
         for (Geofence geofence : dataManager.getGeofences()) {
           geofences.put(geofence.getId(), geofence);
         }
       } finally {
         geofencesLock.writeLock().unlock();
       }
     } catch (SQLException error) {
       Log.warning(error);
     }
   }
   refreshUserGeofences();
   refresh();
 }
 public final void updateGeofence(Geofence geofence) {
   geofencesLock.writeLock().lock();
   try {
     geofences.put(geofence.getId(), geofence);
   } finally {
     geofencesLock.writeLock().unlock();
   }
   try {
     dataManager.updateGeofence(geofence);
   } catch (SQLException error) {
     Log.warning(error);
   }
 }
  public final void refresh() {
    if (dataManager != null) {
      try {
        groupGeofencesLock.writeLock().lock();
        deviceGeofencesLock.writeLock().lock();
        try {
          groupGeofences.clear();
          for (GroupGeofence groupGeofence : dataManager.getGroupGeofences()) {
            getGroupGeofences(groupGeofence.getGroupId()).add(groupGeofence.getGeofenceId());
          }

          deviceGeofences.clear();
          deviceGeofencesWithGroups.clear();

          for (DeviceGeofence deviceGeofence : dataManager.getDeviceGeofences()) {
            getDeviceGeofences(deviceGeofences, deviceGeofence.getDeviceId())
                .add(deviceGeofence.getGeofenceId());
            getDeviceGeofences(deviceGeofencesWithGroups, deviceGeofence.getDeviceId())
                .add(deviceGeofence.getGeofenceId());
          }

          for (Device device : dataManager.getAllDevicesCached()) {
            long groupId = device.getGroupId();
            while (groupId != 0) {
              getDeviceGeofences(deviceGeofencesWithGroups, device.getId())
                  .addAll(getGroupGeofences(groupId));
              if (dataManager.getGroupById(groupId) != null) {
                groupId = dataManager.getGroupById(groupId).getGroupId();
              } else {
                groupId = 0;
              }
            }
            List<Long> deviceGeofenceIds = device.getGeofenceIds();
            if (deviceGeofenceIds == null) {
              deviceGeofenceIds = new ArrayList<>();
            } else {
              deviceGeofenceIds.clear();
            }
            Position lastPosition = Context.getConnectionManager().getLastPosition(device.getId());
            if (lastPosition != null && deviceGeofencesWithGroups.containsKey(device.getId())) {
              for (long geofenceId : deviceGeofencesWithGroups.get(device.getId())) {
                Geofence geofence = getGeofence(geofenceId);
                if (geofence != null
                    && geofence
                        .getGeometry()
                        .containsPoint(lastPosition.getLatitude(), lastPosition.getLongitude())) {
                  deviceGeofenceIds.add(geofenceId);
                }
              }
            }
            device.setGeofenceIds(deviceGeofenceIds);
          }

        } finally {
          groupGeofencesLock.writeLock().unlock();
          deviceGeofencesLock.writeLock().unlock();
        }

      } catch (SQLException error) {
        Log.warning(error);
      }
    }
  }