@Path("devices/{deviceLibraryIdentifier}/registrations/{passTypeIdentifier}/{serialNumber}")
  @DELETE
  public Response unregisterDevice(
      @PathParam("deviceLibraryIdentifier") String deviceLibraryIdentifier,
      @PathParam("passTypeIdentifier") String passTypeIdentifier,
      @PathParam("serialNumber") String serialNumber,
      @HeaderParam("Authorization") @DefaultValue("") String authorization) {

    PassDAO pass = new PassDAO(passTypeIdentifier, serialNumber);
    if (!pass.retrieve()) {
      // pass not found
      // response is UNAUTHORIZED in order to prevent trial/error/guessing for passes
      log.warn("pass does not exist: {}", serialNumber);
      return Response.status(Response.Status.UNAUTHORIZED).build();
    }

    if (!AuthUtil.isAuthorized(authorization, pass.getAuthenticationToken())) {
      log.warn("invalid authorization: {}", authorization);
      return Response.status(Response.Status.UNAUTHORIZED).build();
    }

    DeviceDAO device = new DeviceDAO(deviceLibraryIdentifier);
    if (device.retrieve()) {
      device.removeRegistration(passTypeIdentifier, serialNumber);
      if (device.store()) {
        return Response.status(Response.Status.OK).build();
      } else {
        return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
      }
    }
    return Response.status(Response.Status.NOT_FOUND).build();
  }
 @Override
 public List<Application> getApplicationListForDevice(DeviceIdentifier deviceId)
     throws ApplicationManagementException {
   Device device;
   try {
     int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
     DeviceManagementDAOFactory.openConnection();
     device = deviceDAO.getDevice(deviceId, tenantId);
     if (device == null) {
       if (log.isDebugEnabled()) {
         log.debug(
             "No device is found upon the device identifier '"
                 + deviceId.getId()
                 + "' and type '"
                 + deviceId.getType()
                 + "'. Therefore returning null");
       }
       return null;
     }
     return applicationDAO.getInstalledApplications(device.getId());
   } catch (DeviceManagementDAOException e) {
     throw new ApplicationManagementException(
         "Error occurred while fetching the Application List of '"
             + deviceId.getType()
             + "' device carrying the identifier'"
             + deviceId.getId(),
         e);
   } catch (SQLException e) {
     throw new ApplicationManagementException(
         "Error occurred while opening a connection to the data source", e);
   } finally {
     DeviceManagementDAOFactory.closeConnection();
   }
 }
 @Path("devices/{deviceLibraryIdentifier}/registrations/{passTypeIdentifier}")
 @GET
 public Response getSerialNumbersOfPassesAssociatedWithDevice(
     @PathParam("deviceLibraryIdentifier") String deviceLibraryIdentifier,
     @PathParam("passTypeIdentifier") String passTypeIdentifier,
     @QueryParam("passesUpdatedSince") @DefaultValue("") String passesUpdatedSince) {
   DeviceDAO device = new DeviceDAO(deviceLibraryIdentifier);
   ListOfPasses passes = new ListOfPasses();
   passes.setLastUpdated(DateUtil.getTimeStamp());
   if (device.retrieve()) {
     for (Registration reg : device.getRegistrations()) {
       if (passTypeIdentifier.equals(reg.getPassTypeIdentifier())) {
         passes.addSerialNumber(reg.getSerialNumber());
       }
     }
   }
   if (passes.getSerialNumbers().size() > 0) {
     return Response.status(Response.Status.OK).entity(passes.toJson(Pass.PRETTY)).build();
   }
   return Response.status(Response.Status.NO_CONTENT).build();
 }
  @Path("/devices/{deviceLibraryIdentifier}/registrations/{passTypeIdentifier}/{serialNumber}")
  @POST
  public Response registerDeviceForPassPushNotifications(
      @PathParam("deviceLibraryIdentifier") String deviceLibraryIdentifier,
      @PathParam("passTypeIdentifier") String passTypeIdentifier,
      @PathParam("serialNumber") String serialNumber,
      @HeaderParam("Authorization") @DefaultValue("") String authorization,
      String jsonDictionaryWithPushToken) {

    PassDAO pass = new PassDAO(serialNumber);
    if (!pass.retrieve()) {
      // pass not found
      // response is UNAUTHORIZED in order to prevent trial/error/guessing for passes
      log.warn("pass does not exist: {}", serialNumber);
      return Response.status(Response.Status.UNAUTHORIZED).build();
    }

    if (!AuthUtil.isAuthorized(authorization, pass.getAuthenticationToken())) {
      log.warn("invalid authorization: {}", authorization);
      return Response.status(Response.Status.UNAUTHORIZED).build();
    }

    String pushToken = ServiceUtil.getPushTokenFromBody(jsonDictionaryWithPushToken);

    DeviceDAO device = new DeviceDAO(deviceLibraryIdentifier);
    device.retrieve();
    if (device.addRegistration(passTypeIdentifier, serialNumber, pushToken) == 1) {
      // really added a new record
      if (device.store()) {
        return Response.status(Response.Status.CREATED).build();
      }
    } else {
      // nothing added, was already in list
      return Response.status(Response.Status.OK).build();
    }
    return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
  }
  @Override
  public void updateApplicationListInstalledInDevice(
      DeviceIdentifier deviceIdentifier, List<Application> applications)
      throws ApplicationManagementException {
    List<Application> installedAppList = getApplicationListForDevice(deviceIdentifier);
    try {
      int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
      DeviceManagementDAOFactory.beginTransaction();
      Device device = deviceDAO.getDevice(deviceIdentifier, tenantId);

      if (log.isDebugEnabled()) {
        log.debug("Device:" + device.getId() + ":identifier:" + deviceIdentifier.getId());
      }

      if (log.isDebugEnabled()) {
        log.debug("num of apps installed:" + installedAppList.size());
      }
      List<Application> appsToAdd = new ArrayList<>();
      List<Integer> appIdsToRemove = new ArrayList<>(installedAppList.size());

      for (Application installedApp : installedAppList) {
        if (!applications.contains(installedApp)) {
          if (log.isDebugEnabled()) {
            log.debug("Remove app Id:" + installedApp.getId());
          }
          appIdsToRemove.add(installedApp.getId());
        }
      }
      applicationMappingDAO.removeApplicationMapping(device.getId(), appIdsToRemove, tenantId);
      Application installedApp;
      List<Integer> applicationIds = new ArrayList<>();

      for (Application application : applications) {
        if (!installedAppList.contains(application)) {
          installedApp =
              applicationDAO.getApplication(
                  application.getApplicationIdentifier(), application.getVersion(), tenantId);
          if (installedApp == null) {
            appsToAdd.add(application);
          } else {
            applicationIds.add(installedApp.getId());
          }
        }
      }
      if (log.isDebugEnabled()) {
        log.debug("num of apps add:" + appsToAdd.size());
      }
      applicationIds.addAll(applicationDAO.addApplications(appsToAdd, tenantId));

      if (log.isDebugEnabled()) {
        log.debug("num of app Ids:" + applicationIds.size());
      }
      applicationMappingDAO.addApplicationMappings(device.getId(), applicationIds, tenantId);

      if (log.isDebugEnabled()) {
        log.debug("num of remove app Ids:" + appIdsToRemove.size());
      }

      DeviceManagementDAOFactory.commitTransaction();
    } catch (DeviceManagementDAOException e) {
      DeviceManagementDAOFactory.rollbackTransaction();
      throw new ApplicationManagementException(
          "Error occurred saving application list to the device", e);
    } catch (TransactionManagementException e) {
      throw new ApplicationManagementException("Error occurred while initializing transaction", e);
    } finally {
      DeviceManagementDAOFactory.closeConnection();
    }
  }