private void generateHeader() {
    SyncmlHeader sourceHeader = syncmlDocument.getHeader();
    SyncmlHeader header = new SyncmlHeader();
    header.setMsgID(sourceHeader.getMsgID());
    header.setSessionId(sourceHeader.getSessionId());
    Target target = new Target();
    target.setLocURI(sourceHeader.getSource().getLocURI());
    header.setTarget(target);

    Source source = new Source();
    source.setLocURI(sourceHeader.getTarget().getLocURI());
    header.setSource(source);
    replySyncmlDocument.setHeader(header);
  }
  /**
   * Update Status of the lock operation.
   *
   * @param status Status of the operation.
   * @param syncmlDocument parsed syncml payload.
   * @param deviceIdentifier Device Id.
   * @throws OperationManagementException
   * @throws DeviceManagementException
   * @throws NotificationManagementException
   */
  public void lockOperationUpdate(
      StatusTag status, SyncmlDocument syncmlDocument, DeviceIdentifier deviceIdentifier)
      throws OperationManagementException, DeviceManagementException,
          NotificationManagementException {

    pendingDataOperations =
        WindowsAPIUtils.getDeviceManagementService()
            .getOperationsByDeviceAndStatus(deviceIdentifier, Operation.Status.PENDING);
    if (Constants.SyncMLResponseCodes.ACCEPTED.equals(status.getData())) {
      for (Operation operation : pendingDataOperations) {
        if ((OperationCode.Command.DEVICE_LOCK.getCode().equals(operation.getCode()))
            && operation.getId() == status.getCommandReference()) {
          operation.setStatus(Operation.Status.COMPLETED);
          new OperationUtils()
              .updateOperations(
                  syncmlDocument.getHeader().getSource().getLocURI(), pendingDataOperations);
        }
      }
    }
    if (Constants.SyncMLResponseCodes.PIN_NOTFOUND.equals(status.getData())) {
      for (Operation operation : pendingDataOperations) {

        if ((OperationCode.Command.DEVICE_LOCK.getCode().equals(operation.getCode())
            && operation.getId() == status.getCommandReference())) {
          operation.setStatus(Operation.Status.ERROR);
          new OperationUtils()
              .updateOperations(
                  syncmlDocument.getHeader().getSource().getLocURI(), pendingDataOperations);
          try {
            NotificationManagementService nmService =
                WindowsAPIUtils.getNotificationManagementService();
            Notification lockResetNotification = new Notification();
            lockResetNotification.setOperationId(status.getCommandReference());
            lockResetNotification.setStatus(String.valueOf(Notification.Status.NEW));
            lockResetNotification.setDeviceIdentifier(deviceIdentifier);
            lockResetNotification.setDescription(
                Constants.SyncMLResponseCodes.LOCKRESET_NOTIFICATION);

            nmService.addNotification(lockResetNotification);
          } catch (NotificationManagementException e) {
            String msg = "Failure occurred in getting notification service";
            log.error(msg, e);
            throw new NotificationManagementException(msg, e);
          }
        }
      }
    }
  }
 private void generateBody() throws WindowsOperationException {
   SyncmlBody syncmlBody = generateStatuses();
   try {
     appendOperations(syncmlBody);
   } catch (WindowsOperationException e) {
     String message = "Error while generating operation of the syncml message.";
     log.error(message);
     throw new WindowsOperationException(message);
   }
   replySyncmlDocument.setBody(syncmlBody);
 }
  /**
   * Get pending operations.
   *
   * @param syncmlDocument SyncmlDocument object which creates from the syncml engine using syncml
   *     payload
   * @return Return list of pending operations.
   * @throws OperationManagementException
   * @throws DeviceManagementException
   * @throws FeatureManagementException
   * @throws PolicyComplianceException
   * @throws NotificationManagementException
   */
  public List<? extends Operation> getPendingOperations(SyncmlDocument syncmlDocument)
      throws OperationManagementException, DeviceManagementException, FeatureManagementException,
          PolicyComplianceException, NotificationManagementException,
          WindowsDeviceEnrolmentException, WindowsOperationException {

    List<? extends Operation> pendingOperations;
    DeviceIdentifier deviceIdentifier =
        convertToDeviceIdentifierObject(syncmlDocument.getHeader().getSource().getLocURI());
    UpdateUriOperations(syncmlDocument);
    generateComplianceFeatureStatus(syncmlDocument);

    pendingOperations =
        WindowsAPIUtils.getDeviceManagementService().getPendingOperations(deviceIdentifier);
    return pendingOperations;
  }
  /**
   * * Update the status of the DataWipe operation.
   *
   * @param status Status of the data wipe.
   * @param syncmlDocument Parsed syncml payload from the syncml engine.
   * @param deviceIdentifier specific device id to be wiped.
   * @throws OperationManagementException
   * @throws DeviceManagementException
   */
  public void dataWipe(
      StatusTag status, SyncmlDocument syncmlDocument, DeviceIdentifier deviceIdentifier)
      throws OperationManagementException, DeviceManagementException {

    if ((Constants.SyncMLResponseCodes.ACCEPTED.equals(status.getData()))) {
      pendingDataOperations =
          WindowsAPIUtils.getDeviceManagementService()
              .getOperationsByDeviceAndStatus(deviceIdentifier, Operation.Status.PENDING);
      for (Operation operation : pendingDataOperations) {

        if ((OperationCode.Command.WIPE_DATA.equals(operation.getCode()))
            && (operation.getId() == status.getCommandReference())) {
          operation.setStatus(Operation.Status.COMPLETED);
          updateOperations(
              syncmlDocument.getHeader().getSource().getLocURI(), pendingDataOperations);
        }
      }
    }
  }
  /**
   * Generate Compliance Features.
   *
   * @param syncmlDocument syncmlDocument object parsed from the syncml engine.
   * @throws NotificationManagementException
   * @throws FeatureManagementException
   * @throws PolicyComplianceException
   */
  public void generateComplianceFeatureStatus(SyncmlDocument syncmlDocument)
      throws NotificationManagementException, FeatureManagementException, PolicyComplianceException,
          WindowsDeviceEnrolmentException, WindowsOperationException {
    List<Profile> profiles = generateDeviceOperationStatusObject(syncmlDocument);
    DeviceIdentifier deviceIdentifier =
        convertToDeviceIdentifierObject(syncmlDocument.getHeader().getSource().getLocURI());
    boolean isCompliance = false;
    if (profiles.size() != Constants.EMPTY) {
      try {
        if (WindowsAPIUtils.getPolicyManagerService()
                .getAppliedPolicyToDevice(deviceIdentifier)
                .getProfile()
                .getProfileFeaturesList()
            != null) {
          List<ProfileFeature> profileFeatures =
              WindowsAPIUtils.getPolicyManagerService()
                  .getAppliedPolicyToDevice(deviceIdentifier)
                  .getProfile()
                  .getProfileFeaturesList();
          List<ComplianceFeature> complianceFeatures = new ArrayList<>();
          for (ProfileFeature activeFeature : profileFeatures) {
            JSONObject policyContent = new JSONObject(activeFeature.getContent().toString());

            for (Profile deviceFeature : profiles) {
              if (deviceFeature.getFeatureCode().equals(activeFeature.getFeatureCode())
                  && (PluginConstants.OperationCodes.CAMERA.equals(
                      deviceFeature.getFeatureCode()))) {
                if (policyContent.getBoolean(PluginConstants.PolicyConfigProperties.POLICY_ENABLE)
                    == (deviceFeature.isEnable())) {
                  isCompliance = true;
                  deviceFeature.setCompliance(isCompliance);
                } else {
                  deviceFeature.setCompliance(isCompliance);
                }
                ComplianceFeature complianceFeature =
                    setComplianceFeatures(activeFeature, deviceFeature);
                complianceFeatures.add(complianceFeature);
              }
              if (deviceFeature.getFeatureCode().equals(activeFeature.getFeatureCode())
                  && (PluginConstants.OperationCodes.ENCRYPT_STORAGE.equals(
                      deviceFeature.getFeatureCode()))) {
                if (policyContent.getBoolean(
                        PluginConstants.PolicyConfigProperties.ENCRYPTED_ENABLE)
                    == (deviceFeature.isEnable())) {
                  isCompliance = true;
                  deviceFeature.setCompliance(isCompliance);
                } else {
                  deviceFeature.setCompliance(isCompliance);
                }
                ComplianceFeature complianceFeature =
                    setComplianceFeatures(activeFeature, deviceFeature);
                complianceFeatures.add(complianceFeature);
              }
              if (deviceFeature.getFeatureCode().equals(activeFeature.getFeatureCode())
                  && (PluginConstants.OperationCodes.PASSCODE_POLICY.equals(
                      deviceFeature.getFeatureCode()))) {
                if (policyContent.getBoolean(PluginConstants.PolicyConfigProperties.ENABLE_PASSWORD)
                    == (deviceFeature.isEnable())) {
                  isCompliance = true;
                  deviceFeature.setCompliance(isCompliance);
                } else {
                  deviceFeature.setCompliance(isCompliance);
                }
                ComplianceFeature complianceFeature =
                    setComplianceFeatures(activeFeature, deviceFeature);
                complianceFeatures.add(complianceFeature);
              }
            }
          }
          WindowsAPIUtils.getPolicyManagerService()
              .checkPolicyCompliance(deviceIdentifier, complianceFeatures);
        }
      } catch (JSONException e) {
        String msg = "Error occurred while parsing json object.";
        log.error(msg);
        throw new WindowsDeviceEnrolmentException(msg, e);
      } catch (PolicyComplianceException e) {
        String msg = "Error occurred while setting up policy compliance.";
        log.error(msg, e);
        throw new PolicyComplianceException(msg, e);
      } catch (PolicyManagementException e) {
        String msg = "Error occurred while getting effective policy.";
        log.error(msg, e);
        throw new PolicyComplianceException(msg, e);
      }
    }
  }
  /**
   * Generate status of the features that have been activated on the device.
   *
   * @param syncmlDocument syncmlDocument object pasrsed from the syncml engine.
   * @return device statuses for the activated features
   * @throws NotificationManagementException
   */
  public List<Profile> generateDeviceOperationStatusObject(SyncmlDocument syncmlDocument)
      throws NotificationManagementException, WindowsOperationException {

    DeviceIdentifier deviceIdentifier =
        convertToDeviceIdentifierObject(syncmlDocument.getHeader().getSource().getLocURI());
    String lockUri = null;
    ResultsTag result = syncmlDocument.getBody().getResults();

    List<Profile> profiles = new ArrayList<>();
    if (result != null) {
      List<ItemTag> results = result.getItem();
      for (OperationCode.Info info : OperationCode.Info.values()) {
        if (PluginConstants.OperationCodes.PIN_CODE.equals(info.name())) {
          lockUri = info.getCode();
        }
      }
      for (ItemTag item : results) {
        for (OperationCode.Info info : OperationCode.Info.values()) {
          if (item.getSource().getLocURI().equals(info.getCode())
              && PluginConstants.OperationCodes.CAMERA_STATUS.equals(info.name())) {
            Profile cameraProfile = new Profile();
            cameraProfile.setFeatureCode(PluginConstants.OperationCodes.CAMERA);
            cameraProfile.setData(item.getData());
            if ((PluginConstants.SyncML.SYNCML_DATA_ONE.equals(item.getData()))) {
              cameraProfile.setEnable(true);
            } else {
              cameraProfile.setEnable(false);
            }
            profiles.add(cameraProfile);
          }
          if (item.getSource().getLocURI().equals(info.getCode())
              && PluginConstants.OperationCodes.ENCRYPT_STORAGE_STATUS.equals(info.name())) {
            Profile encryptStorage = new Profile();
            encryptStorage.setFeatureCode(PluginConstants.OperationCodes.ENCRYPT_STORAGE);
            encryptStorage.setData(item.getData());
            if ((PluginConstants.SyncML.SYNCML_DATA_ONE.equals(item.getData()))) {
              encryptStorage.setEnable(true);
            } else {
              encryptStorage.setEnable(false);
            }
            profiles.add(encryptStorage);
          }
          if (item.getSource().getLocURI().equals(info.getCode())
              && PluginConstants.OperationCodes.DEVICE_PASSWORD_STATUS.equals(info.name())) {
            Profile encryptStorage = new Profile();
            encryptStorage.setFeatureCode(PluginConstants.OperationCodes.PASSCODE_POLICY);
            encryptStorage.setData(item.getData());
            if ((PluginConstants.SyncML.SYNCML_DATA_ZERO.equals(item.getData()))) {
              encryptStorage.setEnable(true);
            } else {
              encryptStorage.setEnable(false);
            }
            profiles.add(encryptStorage);
          }
          if (!item.getData().isEmpty() && item.getSource().getLocURI().equals(lockUri)) {
            String pinValue = item.getData();
            NotificationManagementService nmService =
                WindowsAPIUtils.getNotificationManagementService();
            Notification notification = new Notification();
            notification.setDescription("Auto generated DevicePin : " + pinValue);
            notification.setOperationId(result.getCommandReference());
            notification.setDeviceIdentifier(deviceIdentifier);
            notification.setStatus(String.valueOf(Notification.Status.NEW));
            try {
              nmService.addNotification(notification);
            } catch (NotificationManagementException e) {
              String msg = "Failure Occurred in getting notification service.";
              log.error(msg, e);
              throw new WindowsOperationException(msg, e);
            }
            break;
          }
        }
      }
    }
    return profiles;
  }
  /**
   * Update the completed/Error status of the operation which have the URI of the operation code in
   * the syncml payload.
   *
   * @param syncmlDocument SyncmlDocument object generated from the the syncml engine.
   * @throws DeviceManagementException
   * @throws NotificationManagementException
   * @throws OperationManagementException
   */
  public void UpdateUriOperations(SyncmlDocument syncmlDocument)
      throws DeviceManagementException, NotificationManagementException,
          OperationManagementException, WindowsOperationException {
    DeviceIdentifier deviceIdentifier =
        convertToDeviceIdentifierObject(syncmlDocument.getHeader().getSource().getLocURI());
    List<StatusTag> statuses = syncmlDocument.getBody().getStatus();
    OperationUtils operationUtils = new OperationUtils();

    for (StatusTag status : statuses) {

      if ((Constants.EXECUTE.equals(status.getCommand()))) {
        if (status.getTargetReference() == null) {
          operationUtils.updateDeviceOperations(status, syncmlDocument, deviceIdentifier);
        } else {
          if ((OperationCode.Command.DEVICE_LOCK.equals(status.getTargetReference()))) {
            operationUtils.lockOperationUpdate(status, syncmlDocument, deviceIdentifier);
          }
          if ((OperationCode.Command.DEVICE_RING.equals(status.getTargetReference()))) {
            operationUtils.ring(status, syncmlDocument, deviceIdentifier);
          }
          if (equals(OperationCode.Command.WIPE_DATA.equals(status.getTargetReference()))) {
            operationUtils.dataWipe(status, syncmlDocument, deviceIdentifier);
          }
        }
      }
      if ((Constants.SEQUENCE.equals(status.getCommand()))) {
        if ((Constants.SyncMLResponseCodes.ACCEPTED.equals(status.getData()))) {

          pendingDataOperations =
              WindowsAPIUtils.getDeviceManagementService()
                  .getOperationsByDeviceAndStatus(deviceIdentifier, Operation.Status.PENDING);
          for (Operation operation : pendingDataOperations) {
            if ((PluginConstants.OperationCodes.POLICY_BUNDLE.equals(operation.getCode()))
                && operation.getId() == status.getCommandReference()) {
              operation.setStatus(Operation.Status.COMPLETED);
            }
            if ((PluginConstants.OperationCodes.MONITOR.equals(operation.getCode()))
                && operation.getId() == status.getCommandReference()) {
              operation.setStatus(Operation.Status.COMPLETED);
            }
          }
          operationUtils.updateOperations(
              syncmlDocument.getHeader().getSource().getLocURI(), pendingDataOperations);
        } else {
          pendingDataOperations =
              WindowsAPIUtils.getDeviceManagementService()
                  .getOperationsByDeviceAndStatus(deviceIdentifier, Operation.Status.PENDING);
          for (Operation operation : pendingDataOperations) {

            if ((PluginConstants.OperationCodes.POLICY_BUNDLE.equals(operation.getCode()))
                && operation.getId() == status.getCommandReference()) {
              operation.setStatus(Operation.Status.ERROR);
            }
            if ((PluginConstants.OperationCodes.MONITOR.equals(operation.getCode()))
                && operation.getId() == status.getCommandReference()) {
              operation.setStatus(Operation.Status.ERROR);
            }
          }
          operationUtils.updateOperations(
              syncmlDocument.getHeader().getSource().getLocURI(), pendingDataOperations);
        }
      }
    }
  }
  private SyncmlBody generateStatuses() {
    SyncmlBody sourceSyncmlBody = syncmlDocument.getBody();
    SyncmlHeader sourceHeader = syncmlDocument.getHeader();
    SyncmlBody syncmlBodyReply = new SyncmlBody();
    List<Status> status = new ArrayList<Status>();
    Status headerStatus =
        new Status(
            HEADER_COMMAND_REFERENCE_ID,
            sourceHeader.getMsgID(),
            HEADER_STATUS_ID,
            HEADER_COMMAND_TEXT,
            sourceHeader.getSource().getLocURI(),
            String.valueOf(Constants.SyncMLResponseCodes.AUTHENTICATION_ACCEPTED));
    status.add(headerStatus);
    if (sourceSyncmlBody.getAlert() != null) {
      Status alertStatus =
          new Status(
              sourceSyncmlBody.getAlert().getCommandId(),
              HEADER_COMMAND_REFERENCE_ID,
              sourceSyncmlBody.getAlert().getCommandId(),
              ALERT_COMMAND_TEXT,
              null,
              String.valueOf(Constants.SyncMLResponseCodes.ACCEPTED));
      status.add(alertStatus);
    }
    if (sourceSyncmlBody.getReplace() != null) {
      Status replaceStatus =
          new Status(
              sourceSyncmlBody.getReplace().getCommandId(),
              HEADER_COMMAND_REFERENCE_ID,
              sourceSyncmlBody.getReplace().getCommandId(),
              REPLACE_COMMAND_TEXT,
              null,
              String.valueOf(Constants.SyncMLResponseCodes.ACCEPTED));
      status.add(replaceStatus);
    }
    if (sourceSyncmlBody.getExec() != null) {
      Status replaceStatus =
          new Status(
              sourceSyncmlBody.getExec().getCommandId(),
              HEADER_COMMAND_REFERENCE_ID,
              sourceSyncmlBody.getExec().getCommandId(),
              GET_COMMAND_TEXT,
              null,
              String.valueOf(Constants.SyncMLResponseCodes.ACCEPTED));
      status.add(replaceStatus);
    }
    if (sourceSyncmlBody.getGet() != null) {
      Status execStatus =
          new Status(
              sourceSyncmlBody.getGet().getCommandId(),
              HEADER_COMMAND_REFERENCE_ID,
              sourceSyncmlBody.getGet().getCommandId(),
              EXEC_COMMAND_TEXT,
              null,
              String.valueOf(Constants.SyncMLResponseCodes.ACCEPTED));
      status.add(execStatus);
    }

    syncmlBodyReply.setStatus(status);
    return syncmlBodyReply;
  }