@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();
   }
 }
  @Override
  public Activity installApplicationForUsers(Operation operation, List<String> userNameList)
      throws ApplicationManagementException {

    String userName = null;
    try {
      List<Device> deviceList;
      List<DeviceIdentifier> deviceIdentifierList = new ArrayList<>();
      DeviceIdentifier deviceIdentifier;

      for (String user : userNameList) {
        userName = user;
        deviceList =
            DeviceManagementDataHolder.getInstance()
                .getDeviceManagementProvider()
                .getDevicesOfUser(user);
        for (Device device : deviceList) {
          deviceIdentifier = new DeviceIdentifier();
          deviceIdentifier.setId(Integer.toString(device.getId()));
          deviceIdentifier.setType(device.getType());

          deviceIdentifierList.add(deviceIdentifier);
        }
      }
      // TODO: Fix this properly later adding device type to be passed in when the task manage
      // executes "addOperations()"
      String type = null;
      if (deviceIdentifierList.size() > 0) {
        type = deviceIdentifierList.get(0).getType();
      }

      return DeviceManagementDataHolder.getInstance()
          .getDeviceManagementProvider()
          .addOperation(type, operation, deviceIdentifierList);
    } catch (InvalidDeviceException e) {
      throw new ApplicationManagementException("Invalid DeviceIdentifiers found.", e);
    } catch (DeviceManagementException e) {
      throw new ApplicationManagementException(
          "Error in get devices for user: "******" in app installation", e);

    } catch (OperationManagementException e) {
      throw new ApplicationManagementException("Error in add operation at app installation", e);
    }
  }
  @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();
    }
  }
  @Override
  protected Node[] createNodesForKey(DeviceIdentifier model) {
    ArrayList<Node> nodes = new ArrayList<>();
    try {
      Device device = null;
      DeviceIdentifier tmpDM = model;
      String cutted = tmpDM.getName().substring(0, tmpDM.getName().trim().length() - 4).trim();
      switch (cutted) {
        case "Ambient Light Bricklet":
          device = new BrickletAmbientLight(tmpDM.getUid());
          nodes.add(new AmbientLightNode(device));
          break;
        case "AnalogIn Bricklet":
          device = new BrickletAnalogIn(tmpDM.getUid());
          break;
        case "AnalogOut Bricklet":
          device = new BrickletAnalogOut(tmpDM.getUid());
          break;
        case "Buzzer Bricklet":
          device = new BrickletPiezoBuzzer(tmpDM.getUid());
          break;
        case "Current12 Bricklet":
          device = new BrickletCurrent12(tmpDM.getUid());
          break;
        case "Current25 Bricklet":
          device = new BrickletCurrent25(tmpDM.getUid());
          break;
        case "DC Brick":
          device = new BrickDC(tmpDM.getUid());
          break;
        case "Distance IR Bricklet":
          device = new BrickletDistanceIR(tmpDM.getUid());
          nodes.add(new DistanceIRNode(device));
          break;
        case "Humidity Bricklet":
          device = new BrickletHumidity(tmpDM.getUid());
          break;
        case "IMU Brick":
          device = new BrickIMU(tmpDM.getUid());
          break;
        case "IO-16 Bricklet":
          BrickletIO16 io16 = new BrickletIO16(tmpDM.getUid());
          device = io16;
          nodes.add(new IO16Node(io16));
          break;
        case "IO-4 Bricklet":
          device = new BrickletIO4(tmpDM.getUid());
          break;
        case "Joystick Bricklet":
          device = new BrickletJoystick(tmpDM.getUid());
          break;
        case "LCD 16x2 Bricklet":
          device = new BrickletLCD16x2(tmpDM.getUid());
          break;
        case "LCD 20x4 Bricklet":
          device = new BrickletLCD20x4(tmpDM.getUid());
          nodes.add(new LCD2044Node(device));
          break;
        case "Master Brick":
          BrickMaster bm = new BrickMaster(tmpDM.getUid());
          device = bm;
          nodes.add(new BrickMasterNode(bm));
          break;
        case "Linear Poti Bricklet":
          BrickletLinearPoti blp = new BrickletLinearPoti(tmpDM.getUid());
          device = blp;
          nodes.add(new LinearPotiNode(blp));
          break;
        case "Rotary Poti Bricklet":
          device = new BrickletRotaryPoti(tmpDM.getUid());
          break;
        case "Relay Dual Bricklet":
          device = new BrickletDualRelay(tmpDM.getUid());
          break;
        case "Servo Brick":
          device = new BrickServo(tmpDM.getUid());
          break;
        case "Stepper Brick":
          device = new BrickStepper(tmpDM.getUid());
          break;
        case "Temperature AmbientBricklet":
          device = new BrickletTemperature(tmpDM.getUid());
          break;
        case "Temperature IR Bricklet":
          device = new BrickletTemperatureIR(tmpDM.getUid());
          break;
        case "Voltage Bricklet":
          device = new BrickletVoltage(tmpDM.getUid());
          break;
        case "Chibi Extension":
        case "StepDown Brick":
        case "RS485 Extension":
      }

      try {
        if (device != null) {
          ipc.addDevice(device);
        }
      } catch (TimeoutException ex) {
        Exceptions.printStackTrace(ex);
      }

      model.setDeviceType(device);
    } catch (IntrospectionException ex) {
      Exceptions.printStackTrace(ex);
    }
    return (nodes.toArray(new Node[nodes.size()]));
  }