Name

sn_agent.PolicyDraftUtils

Description

No description available

Script

var PolicyDraftUtils = Class.create();
PolicyDraftUtils.prototype = {

  CRITICAL_POLICY_FIELD_TO_BOOLEAN_FIELD: {
      "monitored_ci_type_filter": "",
      "filter": "",
      "table": "",
      "monitored_ci_type_script": "",
      "monitored_ci_script": "",
      "monitored_ci_type_group": "",
      "monitored_ci_group": "",
      "proxy_agent": "single_proxy_agent",
      "proxy_filter": "proxy_advanced",
      "proxy_script": "proxy_script_advanced",
      "single_proxy_agent": "",
      "proxy_advanced": "",
      "proxy_script_advanced": "",
      "proxy_cluster": "",
      "agent_cluster_name": "proxy_cluster",
      "run_checks_on_all_proxyagents": "",
      "is_service_filter": "",
      "service_filter": "",
  },

  POLICY_EXCLUDED_COMPARISON_FIELDS: ['is_draft', 'publish_status', 'published_parent', 'related_policy', 'publish_error', 'checks_str'],
  CHECK_EXCLUDED_COMPARISON_FIELDS: ['monitoring_policy', 'is_draft', 'published_parent', 'published_check', 'check_json', 'prev_command'],
  PARAMS_EXCLUDED_COMPARISON_FIELDS: ['check', 'is_draft', 'published_parent', 'published_param', 'published_secure_param'],

  initialize: function() {
      this.policyStateUtil = new PolicyStateUtil();
  },

  getPublishedParent: function(policyDraftSysID) {
      var policyGr = new GlideRecord("sn_agent_policy");
      policyGr.setLimit(1);
      var hasSucceed = policyGr.get(policyDraftSysID);
      if (hasSucceed)
          return policyGr.related_policy;
      return "";
  },

  getRelatedPolicy: function(policySysID) {
      var policyGr = new GlideRecord("sn_agent_policy");
      policyGr.setLimit(1);
      var hasSucceed = policyGr.get("related_policy", policySysID);
      if (hasSucceed) {
          return policyGr;
      }
      return null;
  },

  saveDraft: function(draftPolicyGr) {
      var publishedValue = draftPolicyGr.getValue("publish_status");
      var publishedPolicyId = draftPolicyGr.getValue("related_policy");

      //if status was published and we have parent, change it to published*
      var isPublished = (publishedValue != '0' && publishedValue != '2');
      var changeStatusToPublishStar = isPublished && publishedPolicyId;

      //change the status to published* on the draft copy if needed
      if (changeStatusToPublishStar) {
          draftPolicyGr.setValue("publish_status", "2");
      }

      var updatedId = draftPolicyGr.update();
      // draft policy pubish status was just updated, so synchronize the publish status down to the policy state records
      this.policyStateUtil.synchronizePolicyStatePublishStatus(draftPolicyGr);

      if (changeStatusToPublishStar) {
          //only if we were able to save the draft and we need to change the status to Published*
          if (updatedId != null) {
              var publishedRecord = new GlideRecord("sn_agent_policy");
              if (publishedRecord.get(publishedPolicyId)) {
                  publishedRecord.setValue("publish_status", "2");
                  //don't change the update time of the published policy upon the change of this status, so it will not be downloaded to mid again
                  publishedRecord.setWorkflow(false);
                  publishedRecord.update();
                  this.policyStateUtil.synchronizePolicyStatePublishStatus(publishedRecord);
              }
          } else {
              // we are here since we failed to update the draft, so that current draft form will not present Published*, restore it to Published
              draftPolicyGr.setValue("publish_status", "1");
              draftPolicyGr.update();
              this.policyStateUtil.synchronizePolicyStatePublishStatus(draftPolicyGr);
          }

      }
  },

  /*
  Clone a Policy Tree to draft or public depending on the isClonePublish value
  sourcePolicyGr = the source policy to clone from
  isClonePublish = Is the clone record publish or draft
  clonePolicyGr = the clone policy to clone to
  isDraftChild = is the tree created will be a child
  */
  clonePolicyTree: function(sourcePolicyGr, isClonePublish, clonePolicyGr, isDraftChild) {


      var sourcePolicyId = sourcePolicyGr.getValue("sys_id");
      var createNewPolicyRecord = true;

      if (!clonePolicyGr) {
          clonePolicyGr = this.cloneRecord(sourcePolicyGr);
      } else {
          this.cloneRecord(sourcePolicyGr, clonePolicyGr);
          createNewPolicyRecord = false;
      }

      if (isDraftChild) {
          clonePolicyGr.setValue("relationship_state", "2");
          clonePolicyGr.setValue("publish_status", "0");
          clonePolicyGr.setValue("published_parent", sourcePolicyId);
          clonePolicyGr.setValue("order", this.getMaximumOrderOfSiblings(sourcePolicyId) + 100);
          var gdt = new GlideDateTime();
          var childPolicyName = sourcePolicyGr.name + " " + gdt.getDisplayValue();
          clonePolicyGr.setValue("name", childPolicyName);
      }

      if (!isClonePublish && !isDraftChild) {
          clonePolicyGr.setValue("related_policy", sourcePolicyId);
          //I don't want check instances to be recreated by business rule
          clonePolicyGr.setWorkflow(false);
      } else if (isDraftChild) {
          // DEF0367389: Prevent BR from creating dupe check instances
          clonePolicyGr.setWorkflow(false);
      }

      if (createNewPolicyRecord) {
          if (isClonePublish)
              clonePolicyGr.setValue('publish_status', '3'); // Mark queue for reaclc.
          var clonePolicyId = clonePolicyGr.insert();
          // clone policy was just created, so synchronize the publish status down to the policy state record
          this.policyStateUtil.synchronizePolicyStatePublishStatus(clonePolicyGr);
      } else {
          clonePolicyGr.update();
          clonePolicyId = clonePolicyGr.getValue("sys_id");
          // clone policy was just updated, so synchronize the publish status down to the policy state record
          this.policyStateUtil.synchronizePolicyStatePublishStatus(clonePolicyGr);
      }

      if (isClonePublish) { //Not relvant for child policy since it allways created in draft mode
          sourcePolicyGr.setValue("related_policy", clonePolicyId);
          sourcePolicyGr.setWorkflow(false);
          sourcePolicyGr.update();
      }

      //copy all check instances
      var sourceCheckGr = new GlideRecord("sn_agent_check");
      sourceCheckGr.addQuery("monitoring_policy", sourcePolicyId);
      sourceCheckGr.query();

      while (sourceCheckGr.next()) {
          var cloneCheckGr = this.cloneRecord(sourceCheckGr);
          cloneCheckGr.setValue("monitoring_policy", clonePolicyId);
          if (!isClonePublish && !isDraftChild) {
              cloneCheckGr.setValue("published_check", sourceCheckGr.getValue("sys_id"));
          } else if (isDraftChild) {
              cloneCheckGr.setValue("published_parent", sourceCheckGr.getValue("sys_id"));
          }
          cloneCheckGr.setWorkflow(false); // DEF0361960 prevent BR from creating duplicate check instances
          var cloneCheckId = cloneCheckGr.insert();

          if (isClonePublish) { //Not relvant for child policy since it allways created in draft mode
              sourceCheckGr.setValue("published_check", cloneCheckId);
              //don't invoke draft busness rules
              sourceCheckGr.setWorkflow(false);
              sourceCheckGr.update();
          }

          this.createNewPublishNewCheckParams(sourceCheckGr.getValue("sys_id"), cloneCheckId, isClonePublish, isDraftChild);
          this.createNewPublishNewCheckSecureParams(sourceCheckGr.getValue("sys_id"), cloneCheckId, isClonePublish, isDraftChild);
      }

      return clonePolicyId;

  },

  getMaximumOrderOfSiblings: function(parentPolicyId) {
      var siblingsGr = new GlideAggregate("sn_agent_policy");
      siblingsGr.addQuery("published_parent", parentPolicyId);
      siblingsGr.groupBy("published_parent");
      siblingsGr.addAggregate("MAX", "order");
      siblingsGr.query();
      if (siblingsGr.next()) {
          return parseInt(siblingsGr.getAggregate("MAX", "order"));
      }
      return 0;
  },

  cloneRecord: function(sourceRecord, cloneRecord) {
      if (!cloneRecord) {
          cloneRecord = new GlideRecord(sourceRecord.getTableName());
          cloneRecord.initialize();
      }
      for (var field in cloneRecord) {
          if (!field.startsWith("sys")) {
              var sourceValue = sourceRecord.getValue(field);
              //null doesn't update the record in DB
              if (sourceValue == null)
                  sourceValue = "";
              cloneRecord.setValue(field, sourceValue);
          }
      }

      //the copy always switches the draft mode
      if (cloneRecord.getValue("is_draft") == 0)
          cloneRecord.setValue("is_draft", "1");
      else
          cloneRecord.setValue("is_draft", "0");
      return cloneRecord;
  },

  republishParentPolicy: function(draftParentPolicyGr, funcName) {
      this.createDraftChildIfDoesNotExist(draftParentPolicyGr);
      if (funcName == 'republishDraftParentAndChildren')
          this.republishDraftParentAndChildren(draftParentPolicyGr);
      else
          this.publishDraft(draftParentPolicyGr);
  },

  createDraftChildIfDoesNotExist: function(draftParentPolicyGr) {
      var publishedParentPolicyId = draftParentPolicyGr.getValue("related_policy");
      var publishedChildPolicyGr = new GlideRecord("sn_agent_policy");
      publishedChildPolicyGr.addQuery("published_parent", publishedParentPolicyId);
      publishedChildPolicyGr.addQuery("is_draft", "false");
      publishedChildPolicyGr.query();
      while (publishedChildPolicyGr.next()) {
          if (!this.doesPublishedPolicyHasDraftCopy(publishedChildPolicyGr))
              this.createDraftFromPublished(publishedChildPolicyGr, false);
      }
  },

  doesPublishedPolicyHasDraftCopy: function(publishedPolicyGr) {
      var draftPolicyGr = new GlideRecord("sn_agent_policy");
      if (draftPolicyGr.get("related_policy", publishedPolicyGr.getUniqueValue()))
          return true;
      return false;
  },

  republishDraftParentAndChildren: function(draftParentPolicyGr) {
      // Publish draft parent policy
      this.publishDraft(draftParentPolicyGr);

      // Publish draft child policies
      var publishedParentPolicyId = draftParentPolicyGr.getValue("related_policy");
      if (!publishedParentPolicyId)
          return;
      var draftChildPolicyGr = new GlideRecord("sn_agent_policy");
      draftChildPolicyGr.addQuery("published_parent", publishedParentPolicyId);
      draftChildPolicyGr.addQuery("is_draft", "true");
      draftChildPolicyGr.addQuery("inherit_from_parent", "true");
      draftChildPolicyGr.query();
      while (draftChildPolicyGr.next())
          this.publishDraft(draftChildPolicyGr);
  },

  markSiblingsAndParentAsQueued: function(parentSysId) {
      var publishedKidsGr = new GlideRecord('sn_agent_policy');
      publishedKidsGr.addQuery('published_parent', parentSysId);
      publishedKidsGr.addActiveQuery();
      publishedKidsGr.addQuery('is_draft', '0');
      publishedKidsGr.addQuery('inherit_from_parent', '1');
      publishedKidsGr.query();
      while (publishedKidsGr.next()) {
          publishedKidsGr.setValue('publish_status', '3');
          publishedKidsGr.update();
          // published kid policy just had its publish_status updated, so synchronize it down to the policy state
          this.policyStateUtil.synchronizePolicyStatePublishStatus(publishedKidsGr);
      }

      var parentPolicy = new GlideRecord('sn_agent_policy');
      if (!parentPolicy.get('sys_id', parentSysId))
          return;

      // do not set parent to processing if it is inactive
      if (!global.JSUtil.getBooleanValue(parentPolicy, 'active'))
          return;

      parentPolicy.setValue('publish_status', '3');
      parentPolicy.update();
      // parent policy just had its publish_status updated, so synchronize it down to the policy state
      this.policyStateUtil.synchronizePolicyStatePublishStatus(parentPolicy);
  },

  publishDraft: function(draftPolicyGr) {
      var publishStatus = "1"; // published

      if (this.isDraftCriticallyDifferentFromPublished(draftPolicyGr)) {
          // If this is a child policy and we need full recalc - publish the entire hierarchy
          if (draftPolicyGr.getValue('relationship_state') == '2')
              this.markSiblingsAndParentAsQueued(draftPolicyGr.getValue('published_parent'));
          // For all other policies
          publishStatus = "3"; // Queued = full policy calculation
      } else if (this.isDraftDifferentFromPublished(draftPolicyGr))
          publishStatus = "5"; // No need to calculate the policy, just publish it to MID servers.

      // Create DB view for agent-ci relationship
      var view = new AgentPolicyDBView();
      if (!view) {
          // We will continue to publish despite no view
          gs.warn("Could not find AgentPolicyDBView class. Unable to create DB View.");
      } else {
          view.generateDBView(draftPolicyGr);
      }

      var draftPolicyId = draftPolicyGr.getValue("sys_id");
      //set publish status to "Published"
      draftPolicyGr.setValue("publish_status", "1");
      //set active value to "Active"
      draftPolicyGr.setValue("active", "1");

      var publishedPolicyId = draftPolicyGr.getValue("related_policy");

      //draft was never published
      if (!publishedPolicyId) {
          this.clonePolicyTree(draftPolicyGr, true);
      } else {
          //only update the published status on the draft
          draftPolicyGr.update();
          // draft policy publish status was updated, so synchronize it down to the policy state record
          this.policyStateUtil.synchronizePolicyStatePublishStatus(draftPolicyGr);
          var publishedPolicyGr = new GlideRecord("sn_agent_policy");
          if (!publishedPolicyGr.get(publishedPolicyId))
              return;
          this.cloneRecord(draftPolicyGr, publishedPolicyGr);

          //clear related policy field
          publishedPolicyGr.setValue("related_policy", "");
          publishedPolicyGr.setValue("publish_status", publishStatus);

          publishedPolicyGr.update();
          // published policy publish status was updated, so synchronize it down to all of the policy's policy state records
          this.policyStateUtil.synchronizePolicyStatePublishStatus(publishedPolicyGr);

          var newPublishedCheckIds = {};
          var draftCheckGr = new GlideRecord("sn_agent_check");
          draftCheckGr.addQuery("monitoring_policy", draftPolicyId);
          draftCheckGr.query();
          while (draftCheckGr.next()) {
              var publishedCheckId = draftCheckGr.getValue("published_check");
              if (publishedCheckId) {
                  var publishedCheckGr = new GlideRecord("sn_agent_check");
                  if (!publishedCheckGr.get(publishedCheckId))
                      continue;
                  this.cloneRecord(draftCheckGr, publishedCheckGr);
                  publishedCheckGr.setValue("monitoring_policy", publishedPolicyId);
                  //clear the published check
                  publishedCheckGr.setValue("published_check", "");
                  publishedCheckGr.update();

                  this.updateExistingPublishedCheckWithCheckParams(draftCheckGr.getValue("sys_id"), publishedCheckId);
                  this.updateExistingPublishedCheckWithSecureParams(draftCheckGr.getValue("sys_id"), publishedCheckId);

              } else {
                  //check doesn't exist for published record
                  publishedCheckGr = this.cloneRecord(draftCheckGr);
                  publishedCheckGr.setValue("monitoring_policy", publishedPolicyId);
                  publishedCheckId = publishedCheckGr.insert();
                  //don't invoke draft business rules
                  draftCheckGr.setWorkflow(false);
                  draftCheckGr.setValue("published_check", publishedCheckId);
                  draftCheckGr.update();

                  //copy all params that belong to current check instance
                  this.createNewPublishNewCheckParams(draftCheckGr.getValue("sys_id"), publishedCheckId, true);
                  this.createNewPublishNewCheckSecureParams(draftCheckGr.getValue("sys_id"), publishedCheckId, true);

                  // If publishedCheckGr is related to a parent policy, it should be copied to all child policies that inherit from it
                  if (publishedCheckGr.monitoring_policy.relationship_state == "1")
                      this.copyCheckInstanceToChildPolicies(publishedCheckGr);
              }
              newPublishedCheckIds[publishedCheckId] = true;
          }

          //delete all previouse checks that didn't come from last publish
          var arrCheckIdsToKeep = Object.keys(newPublishedCheckIds)
          publishedCheckGr = new GlideRecord("sn_agent_check");
          publishedCheckGr.addQuery("monitoring_policy", publishedPolicyId);
          publishedCheckGr.addQuery("sys_id", "NOT IN", Object.keys(newPublishedCheckIds));
          publishedCheckGr.deleteMultiple();
          if (publishedCheckGr.monitoring_policy.relationship_state == "1")
              this.deleteDraftChildPoliciesCheckInstancesBasedOnParentDelete(publishedPolicyId, arrCheckIdsToKeep);
      }
  },

  deleteDraftChildPoliciesCheckInstancesBasedOnParentDelete: function(publishedParentSysId, arrParentCheckIdsToKeep) {
      if (!arrParentCheckIdsToKeep || arrParentCheckIdsToKeep.length < 1)
          return;

      var draftChildPolicyGr = new GlideRecord("sn_agent_policy");
      draftChildPolicyGr.addQuery("published_parent", publishedParentSysId);
      draftChildPolicyGr.addQuery("is_draft", "true");
      draftChildPolicyGr.addQuery("inherit_from_parent", "true");
      draftChildPolicyGr.query();
      while (draftChildPolicyGr.next()) {
          cloneCheckGr = new GlideRecord('sn_agent_check');
          cloneCheckGr.addQuery("monitoring_policy", draftChildPolicyGr.getUniqueValue());
          cloneCheckGr.addQuery("published_parent", "NOT IN", arrParentCheckIdsToKeep);
          cloneCheckGr.deleteMultiple();
      }
  },

  copyCheckInstanceToChildPolicies: function(publishedParentCheckInstanceGr) {
      var draftChildPolicyGr = new GlideRecord("sn_agent_policy");
      draftChildPolicyGr.addQuery("published_parent", publishedParentCheckInstanceGr.getValue("monitoring_policy"));
      draftChildPolicyGr.addQuery("is_draft", "true");
      draftChildPolicyGr.addQuery("inherit_from_parent", "true");
      draftChildPolicyGr.query();
      while (draftChildPolicyGr.next()) {
          this.copyCurrentCheckInstanceToChildPolicy(draftChildPolicyGr.getUniqueValue(), publishedParentCheckInstanceGr);
          this.updateChildPolicyChecksStr(draftChildPolicyGr, publishedParentCheckInstanceGr);
          this.updatePublishStatusToEditedChildPolicy(draftChildPolicyGr);
          draftChildPolicyGr.update();
          this.policyStateUtil.synchronizePolicyStatePublishStatus(draftChildPolicyGr);
      }
  },

  copyCurrentCheckInstanceToChildPolicy: function(childePolicyId, publishedParentCheckGr) {
      var publishedParentCheckId = publishedParentCheckGr.getUniqueValue();
      var cloneCheckGr = undefined;

      cloneCheckGr = new GlideRecord('sn_agent_check');
      cloneCheckGr.addQuery("monitoring_policy", childePolicyId);
      cloneCheckGr.addQuery("published_parent", publishedParentCheckId);
      cloneCheckGr.query();
      if (!cloneCheckGr.next())
          cloneCheckGr = this.cloneRecord(publishedParentCheckGr);
      else
          this.cloneRecord(publishedParentCheckGr, cloneCheckGr);

      // A business rule prevents us form inserting a new check: we want to keep the business rule and insert here
      cloneCheckGr.setWorkflow(false);
      cloneCheckGr.setValue("monitoring_policy", childePolicyId);
      cloneCheckGr.setValue("published_parent", publishedParentCheckId);
      cloneCheckGr.update();

      var cloneCheckId = cloneCheckGr.getUniqueValue();

      this.copyCheckParams(cloneCheckId, publishedParentCheckId, "sn_agent_check_param");
      this.copyCheckParams(cloneCheckId, publishedParentCheckId, "sn_agent_check_secure_param");
  },

  copyCheckParams: function(cloneCheckId, publishedParentCheckId, checkParamsTable) {
      var publishedCheckParamGr = new GlideRecord(checkParamsTable);
      publishedCheckParamGr.addQuery("check", publishedParentCheckId);
      publishedCheckParamGr.addQuery("is_draft", false);
      publishedCheckParamGr.query();
      while (publishedCheckParamGr.next()) {
          var cloneCheckParamGr = undefined;
          cloneCheckParamGr = new GlideRecord(checkParamsTable);
          cloneCheckParamGr.addQuery("check", cloneCheckId);
          cloneCheckParamGr.addQuery("published_parent", publishedCheckParamGr.getUniqueValue());
          cloneCheckParamGr.query();

          if (!cloneCheckParamGr.next())
              cloneCheckParamGr = this.cloneRecord(publishedCheckParamGr);
          else
              this.cloneRecord(publishedCheckParamGr, cloneCheckParamGr);

          cloneCheckParamGr.setWorkflow(false);
          cloneCheckParamGr.setValue("check", cloneCheckId);
          cloneCheckParamGr.setValue("published_parent", publishedCheckParamGr.getUniqueValue());
          cloneCheckParamGr.update();
      }
  },

  updateChildPolicyChecksStr: function(draftChildPolicyGr, publishedParentCheckInstanceGr) {
      var updatedChecksStr = draftChildPolicyGr.getValue("checks_str") + "," + publishedParentCheckInstanceGr.getValue("check_def");
      draftChildPolicyGr.setValue("checks_str", updatedChecksStr);
  },

  updatePublishStatusToEditedChildPolicy: function(draftChildPolicyGr) {
      // If the child's publish_status field is 'Published', change it to 'Published*'
      if (draftChildPolicyGr.getValue("publish_status") == "1") {
          this.updatePublishedChildPolicyStatus(draftChildPolicyGr.getValue("related_policy"), "2");
          draftChildPolicyGr.setValue("publish_status", "2");
      }
  },

  updatePublishedChildPolicyStatus: function(publishedChildPolicyId, statusValue) {
      var policyGr = new GlideRecord("sn_agent_policy");
      if (policyGr.get(publishedChildPolicyId)) {
          policyGr.setValue("publish_status", statusValue);
          policyGr.update();
          this.policyStateUtil.synchronizePolicyStatePublishStatus(policyGr);
      }
  },

  createDraftFromPublished: function(publishedRecord, isDraftChild) {
      var currentDomain = new sn_agent.DomainInfo().getCurrentDomain();
      var publishedRecordDomain = publishedRecord.getValue("sys_domain");
      if (currentDomain != publishedRecordDomain) {
          publishedRecord = this.copyPolicyTreeToCurrentDomain(publishedRecord);
      }
      var isDraftShouldBeOverride = false;
      var parentDomainDraftSysID = "";
      if (publishedRecord.sys_overrides) {
          parentDomainDraftSysID = this.getParentDomainDraftSysID(publishedRecord.sys_overrides);
          if (parentDomainDraftSysID != "")
              isDraftShouldBeOverride = true;
      }

      var clonePolicyId = this.clonePolicyTree(publishedRecord, false, null, isDraftChild);
      if (isDraftShouldBeOverride && !isDraftChild) {
          this.setOverrideForDraft(clonePolicyId, parentDomainDraftSysID);
      }
      return clonePolicyId;
  },

  createDraftChildFromPublished: function(publishedPolicy) {
      var publishedParentPolicyInCurrentDomain = publishedPolicy;
      var childPolicyID = this.createDraftFromPublished(publishedPolicy, true);
      var currentDomain = new sn_agent.DomainInfo().getCurrentDomain();
      var publishedPolicyDomain = publishedPolicy.getValue("sys_domain");

      if (currentDomain != publishedPolicyDomain) {
          // publishedPolicy has already been copied to the current domain in the createDraftFromPublished() function
          publishedParentPolicyInCurrentDomain = this.getRecordInCurrentDomain(publishedPolicy.getValue("sys_id"), "sn_agent_policy");
      }

      this.updateRelationshipStateToPublishAndDraftParent(publishedParentPolicyInCurrentDomain);

      return childPolicyID;
  },

  getRecordInCurrentDomain: function(recordId, table) {
      var gr = new GlideRecord(table);
      if (gr.get("sys_overrides", recordId))
          return gr;
      return null;
  },

  updateRelationshipStateToPublishAndDraftParent: function(publishedPolicy) {
      publishedPolicy.setValue("relationship_state", "1");
      publishedPolicy.update();

      var draftPolicyGR = this.getRelatedPolicy(publishedPolicy.sys_id);
      if (draftPolicyGR != null) {
          draftPolicyGR.setValue("relationship_state", "1");
          draftPolicyGR.setWorkflow(false);
          draftPolicyGR.update();
      }
  },

  createDraft: function(publishedPolicy) {
      var clonePolicyId = this.createDraftFromPublished(publishedPolicy, false);

      if (!publishedPolicy.relationship_state) { //OOB need to fix that field
          publishedPolicy.setValue("relationship_state", "0");
          publishedPolicy.setWorkflow(false);
          publishedPolicy.update();
      }

      return clonePolicyId;
  },


  getParentDomainDraftSysID: function(sourceParentDomainSysID) {
      var policyPublishedForParentDomain = new GlideRecord("sn_agent_policy");
      policyPublishedForParentDomain.addQuery("related_policy", sourceParentDomainSysID);
      policyPublishedForParentDomain.query();
      if (policyPublishedForParentDomain.next()) {
          return policyPublishedForParentDomain.sys_id;
      }
      return "";
  },

  setOverrideForDraft: function(clonePolicyId, parentDomainDraftSysID) {
      var cloneDraftCurrentDomain = new GlideRecord("sn_agent_policy");
      var found = cloneDraftCurrentDomain.get(clonePolicyId);
      if (found) {
          cloneDraftCurrentDomain.sys_overrides = parentDomainDraftSysID;
          cloneDraftCurrentDomain.update();
      }
  },

  copyPolicyTreeToCurrentDomain: function(sourcePolicyOldDomainGr) {
      var sourcePolicyNewDomainGr;

      // If there is a policy hierarchy of parent policy and child policies, copy the entire tree
      var parentPolicySysId = sourcePolicyOldDomainGr.getValue("sys_id");
      if (sourcePolicyOldDomainGr.getValue("relationship_state") == "2") {
          // sourcePolicyOldDomainGr is a child policy
          parentPolicySysId = sourcePolicyOldDomainGr.getValue("published_parent");
      }

      var policyGr = new GlideRecord("sn_agent_policy");
      var qc1 = policyGr.addQuery("is_draft", false);
      qc1.addOrCondition("publish_status", "0");
      var qc2 = policyGr.addQuery("published_parent", parentPolicySysId);
      qc2.addOrCondition("sys_id", parentPolicySysId);
      policyGr.orderBy("published_parent"); // The orderBy("published_parent") ensures that we copy the parent policy first and then the child policies
      policyGr.query();
      while (policyGr.next()) {
          var currentIsTheSourcePolicy = sourcePolicyOldDomainGr.getValue("sys_id") == policyGr.getValue("sys_id");
          var currentPolicyNewDomainGr = this.copyPolicyEntitiesToCurrentDomain(policyGr);
          if (policyGr.getValue("relationship_state") == "1") {
              // policyGr is a parent policy, save the parent policy sys_id in the current domain
              parentPolicySysId = currentPolicyNewDomainGr.getValue("sys_id");
          }
          if (policyGr.getValue("relationship_state") == "2") {
              // policyGr is a child policy, update its parent policy in the current domain
              currentPolicyNewDomainGr.setValue("published_parent", parentPolicySysId);
              currentPolicyNewDomainGr.update();
          }
          if (currentIsTheSourcePolicy) {
              sourcePolicyNewDomainGr = currentPolicyNewDomainGr;
          }
      }
      return sourcePolicyNewDomainGr;
  },

  copyPolicyEntitiesToCurrentDomain: function(sourcePolicyOldDomainGr) {
      var oldDomainPolicyID = sourcePolicyOldDomainGr.getValue("sys_id");
      sourcePolicyOldDomainGr.setWorkflow(false);
      sourcePolicyOldDomainGr.update();
      var newDomainPolicyID = sourcePolicyOldDomainGr.getValue("sys_id");
      this.copyChecksTreeToCurrentDomain(oldDomainPolicyID, newDomainPolicyID);
      var sourcePolicyNewDomainGr = new GlideRecord("sn_agent_policy");
      sourcePolicyNewDomainGr.get(newDomainPolicyID);
      return sourcePolicyNewDomainGr;
  },

  copyChecksTreeToCurrentDomain: function(oldDomainPolicyID, newDomainPolicyID) {
      //copy all check instances from domain father to domain child
      var sourceCheckOldDomainGr = new GlideRecord("sn_agent_check");
      sourceCheckOldDomainGr.addQuery("monitoring_policy", oldDomainPolicyID);
      sourceCheckOldDomainGr.query();
      var newDomainCheckID, oldDomainCheckID;
      while (sourceCheckOldDomainGr.next()) {

          oldDomainCheckID = sourceCheckOldDomainGr.getValue("sys_id");
          sourceCheckOldDomainGr.setWorkflow(false);
          sourceCheckOldDomainGr.setValue("monitoring_policy", newDomainPolicyID);
          if (sourceCheckOldDomainGr.getValue("published_parent")) {
              var checkPublishedParentGr = this.getRecordInCurrentDomain(sourceCheckOldDomainGr.getValue("published_parent"), "sn_agent_check");
              sourceCheckOldDomainGr.setValue("published_parent", checkPublishedParentGr.getUniqueValue());
          }
          sourceCheckOldDomainGr.update();
          newDomainCheckID = sourceCheckOldDomainGr.getValue("sys_id");

          this.copyAllCheckParamsInstanceToCurrentDomain(oldDomainCheckID, newDomainCheckID);
      }
  },

  copyAllCheckParamsInstanceToCurrentDomain: function(oldDomainCheckID, newDomainCheckID) {

      this.copyCheckParamsToCurrentDomain(oldDomainCheckID, newDomainCheckID, "sn_agent_check_param", "check");
      this.copyCheckParamsToCurrentDomain(oldDomainCheckID, newDomainCheckID, "sn_agent_check_secure_param", "check");
  },

  copyAllCheckParamsDefToCurrentDomain: function(oldDomainCheckID, newDomainCheckID) {

      this.copyCheckParamsToCurrentDomain(oldDomainCheckID, newDomainCheckID, "sn_agent_check_param_def", "check_def");
      this.copyCheckParamsToCurrentDomain(oldDomainCheckID, newDomainCheckID, "sn_agent_check_secure_param_def", "check_def");
  },

  copyCheckParamsToCurrentDomain: function(oldDomainCheckID, newDomainCheckID, paramTableName, checkRefField) {

      //copy all check params from domain father to domain child
      var sourceParamsOldDomainGr = new GlideRecord(paramTableName);
      sourceParamsOldDomainGr.addQuery(checkRefField, oldDomainCheckID);
      sourceParamsOldDomainGr.query();
      while (sourceParamsOldDomainGr.next()) {
          sourceParamsOldDomainGr.setWorkflow(false);
          sourceParamsOldDomainGr.setValue(checkRefField, newDomainCheckID);
          if (sourceParamsOldDomainGr.getValue("published_parent")) {
              var checkParamPublishedParentGr = this.getRecordInCurrentDomain(sourceParamsOldDomainGr.getValue("published_parent"), paramTableName);
              sourceParamsOldDomainGr.setValue("published_parent", checkParamPublishedParentGr.getUniqueValue());
          }
          sourceParamsOldDomainGr.update();
      }
  },

  revertDraft: function(policyDraftId) {
      var draftPolicyGr = new GlideRecord("sn_agent_policy");
      if (!draftPolicyGr.get(policyDraftId))
          return;

      var publishedPolicyId = draftPolicyGr.getValue("related_policy");

      var publishedPolicyGr = new GlideRecord("sn_agent_policy");
      if (!publishedPolicyGr.get(publishedPolicyId))
          return;

      //make sure to revert the status to published if needed
      if (publishedPolicyGr.getValue("publish_status") != "1") {
          publishedPolicyGr.setValue("publish_status", "1");
          //status shouldn't change the timestamp of the policy
          publishedPolicyGr.setWorkflow(false);
          publishedPolicyGr.update();
          this.policyStateUtil.synchronizePolicyStatePublishStatus(publishedPolicyGr);
      }

      var draftPolicyId = draftPolicyGr.getValue("sys_id");

      var draftCheckGr = new GlideRecord("sn_agent_check");
      draftCheckGr.addQuery("monitoring_policy", draftPolicyId);
      draftCheckGr.query();
      draftCheckGr.setWorkflow(false);
      draftCheckGr.deleteMultiple();

      //recopy everything from published to draft
      this.clonePolicyTree(publishedPolicyGr, false, draftPolicyGr);


  },

  updatePublishStatusOnDraftCheckChange: function(draftCheckGr) {
      var draftRelatedPolicyGr = new GlideRecord("sn_agent_policy");
      var draftPolicyId = draftCheckGr.getValue("monitoring_policy");
      if (!draftRelatedPolicyGr.get(draftPolicyId))
          return;
      if (draftRelatedPolicyGr.getValue("publish_status") == "1") {
          draftRelatedPolicyGr.setValue("publish_status", "2");
          draftRelatedPolicyGr.update();
          this.policyStateUtil.synchronizePolicyStatePublishStatus(draftRelatedPolicyGr);
          var publishedRelatedPolicyGr = new GlideRecord("sn_agent_policy");
          if (!publishedRelatedPolicyGr.get(draftRelatedPolicyGr.getValue("related_policy")))
              return;
          publishedRelatedPolicyGr.setValue("publish_status", "2");
          publishedRelatedPolicyGr.update();
          this.policyStateUtil.synchronizePolicyStatePublishStatus(publishedRelatedPolicyGr);
      }
  },

  updatePublishStatusOnDraftParamChange: function(draftParamGr) {
      var draftCheckGr = new GlideRecord("sn_agent_check");
      if (!draftCheckGr.get(draftParamGr.getValue("check")))
          return;

      this.updatePublishStatusOnDraftCheckChange(draftCheckGr);
  },

  fixAllPreviousDataToPublished: function() {
      var policyGr = new GlideRecord("sn_agent_policy");
      policyGr.addEncodedQuery("publish_statusIN1,2");
      policyGr.query();

      //run fix script only in case we are in case we are in env that wasn't working with draft mode. 
      if (!policyGr.next()) {
          gs.info("setting is_draft to false for all existing data");

          var paramGr = new GlideRecord("sn_agent_check_param");
          paramGr.setValue("is_draft", false);
          paramGr.setWorkflow(false);
          paramGr.updateMultiple();

          var checkGr = new GlideRecord("sn_agent_check");
          checkGr.setValue("is_draft", false);
          checkGr.setWorkflow(false);
          checkGr.updateMultiple();

          policyGr = new GlideRecord("sn_agent_policy");
          policyGr.setValue("is_draft", false);
          policyGr.setValue("publish_status", "1");
          policyGr.setWorkflow(false);
          policyGr.updateMultiple();
      } else {
          gs.info("env already has published policies, the fix script shouldn't run");
      }

  },

  getCheckInstanceDraftId: function(publishedCheckGr) {
      var checkInstanceGr = new GlideRecord("sn_agent_check");
      checkInstanceGr.addQuery("published_check", publishedCheckGr.sys_id);
      checkInstanceGr.query();
      if (checkInstanceGr.next()) {
          return checkInstanceGr.getValue("sys_id");
      } else {
          //this version came from upgrade and doesn't have draft
          var publishedPolicyGr = new GlideRecord("sn_agent_policy");
          var policyId = publishedCheckGr.getValue("monitoring_policy");
          if (publishedPolicyGr.get(policyId)) {

              this.createDraft(publishedPolicyGr);

              // in case the draft was created in a different domain, let's find the correct pusblished check
              checkInstanceGr = new GlideRecord("sn_agent_check");
              checkInstanceGr.addQuery("sys_domain", new DomainInfo().getCurrentDomain());
              checkInstanceGr.addQuery("sys_overrides", publishedCheckGr.getUniqueValue());
              checkInstanceGr.query();
              if (checkInstanceGr.next())
                  publishedCheckGr = checkInstanceGr;

              //now query again...
              checkInstanceGr = new GlideRecord("sn_agent_check");
              checkInstanceGr.addQuery("published_check", publishedCheckGr.sys_id);
              checkInstanceGr.query();
              if (checkInstanceGr.next()) {
                  return checkInstanceGr.getValue("sys_id");
              }
          }
      }
  },

  updateExistingPublishedCheckWithCheckParams: function(draftCheckId, publishedCheckId) {
      this.updateExistingPublishedCheckparams(draftCheckId, publishedCheckId, "sn_agent_check_param", "published_param");
  },

  updateExistingPublishedCheckWithSecureParams: function(draftCheckId, publishedCheckId) {
      this.updateExistingPublishedCheckparams(draftCheckId, publishedCheckId, "sn_agent_check_secure_param", "published_secure_param");
  },

  createNewPublishNewCheckParams: function(draftCheckId, publishedCheckId, isPublish, isChild) {
      this.createNewPublishCheckParams(draftCheckId, publishedCheckId, "sn_agent_check_param", "published_param", isPublish, isChild);
  },

  createNewPublishNewCheckSecureParams: function(draftCheckId, publishedCheckId, isPublish, isChild) {
      this.createNewPublishCheckParams(draftCheckId, publishedCheckId, "sn_agent_check_secure_param", "published_secure_param", isPublish, isChild);
  },

  updateExistingPublishedCheckparams: function(draftCheckId, publishedCheckId, paramTable, referenceField) {
      var newPublishedParamIds = {};
      //copy all check params that belong to current check instance
      var draftParamsGr = new GlideRecord(paramTable);
      draftParamsGr.addQuery("check", draftCheckId);
      draftParamsGr.query();
      while (draftParamsGr.next()) {
          var publishedParamId = draftParamsGr.getValue(referenceField);
          if (publishedParamId) {
              var publishedParamGr = new GlideRecord(paramTable);
              if (!publishedParamGr.get(publishedParamId))
                  continue;
              this.cloneRecord(draftParamsGr, publishedParamGr);
              publishedParamGr.setValue("check", publishedCheckId);
              //clear the published check param field that was copied from draft
              publishedParamGr.setValue(referenceField, "");
              publishedParamGr.update();
          } else {
              //check param doesn't exist in published records
              publishedParamGr = this.cloneRecord(draftParamsGr);
              publishedParamGr.setValue("check", publishedCheckId);
              publishedParamId = publishedParamGr.insert();
              //don't invoke draft business rules, for the published param 
              draftParamsGr.setValue(referenceField, publishedParamId);
              draftParamsGr.setWorkflow(false);
              draftParamsGr.update();
          }
          newPublishedParamIds[publishedParamId] = true;
      }

      //delete all previouse check params that didn't come from last publish
      var publishedParamsGr = new GlideRecord(paramTable);
      publishedParamsGr.addQuery("check", publishedCheckId);
      publishedParamsGr.addQuery("sys_id", "NOT IN", Object.keys(newPublishedParamIds));
      publishedParamsGr.deleteMultiple();
  },

  createNewPublishCheckParams: function(draftCheckId, publishedCheckId, paramTable, referenceField, isPublish, isChild) {
      //copy all check params that belong to current check instance
      var draftParamsGr = new GlideRecord(paramTable);
      draftParamsGr.addQuery("check", draftCheckId);
      draftParamsGr.query();
      while (draftParamsGr.next()) {
          var publishedParamGr = this.cloneRecord(draftParamsGr);
          publishedParamGr.setValue("check", publishedCheckId);
          if (!isPublish && !isChild) {
              publishedParamGr.setValue(referenceField, draftParamsGr.getValue("sys_id"));
          } else if (isChild) {
              publishedParamGr.setValue("published_parent", draftParamsGr.getValue("sys_id"));
          }

          publishedParamGr.setWorkflow(false);
          var publishedParamId = publishedParamGr.insert();

          // we are interested only in notification about check params table
          if (paramTable == "sn_agent_check_param") {
              gs.eventQueue("sn_agent.notify_check_param_creation", publishedParamGr); //send event to notify about param creation, listener exists in acc_l
          }

          //Not relevant for child policy since it always created in draft mode
          if (isPublish) {
              //don't invoke draft business rules 
              draftParamsGr.setWorkflow(false);
              draftParamsGr.setValue(referenceField, publishedParamId);
              draftParamsGr.update();
          }
      }
  },

  getSandboxPolicyId: function(publishedPolicyGR) {
      var currentDomain = new DomainInfo().getCurrentDomain();
      var draftPolicyGr = new GlideRecord("sn_agent_policy");
      draftPolicyGr.addQuery("related_policy", publishedPolicyGR.sys_id);
      draftPolicyGr.addQuery("sys_domain", currentDomain);
      draftPolicyGr.query();
      if (draftPolicyGr.next()) {
          var draftSysId = draftPolicyGr.sys_id;
      } else {
          draftSysId = this.createDraft(publishedPolicyGR);
      }
      return draftSysId;
  },

  changeActiveValueForPolicy: function(current, activeValue) {
      var currentDomain = new DomainInfo().getCurrentDomain();
      var publishedRecordDoamin = current.sys_domain;
      if (currentDomain != publishedRecordDoamin) {
          current = this.copyPolicyTreeToCurrentDomain(current);
      }

      // Only if we change to active value on the db level
      if (activeValue && current.active != activeValue) {
          var p = new PolicyClientsGeneratorNG();
          var policyFullCalcCycleTime = p.getPolicyFullCalcCycleAsGlideTime();

          var policyStateGr = new GlideRecord('sn_agent_policy_state');
          policyStateGr.addQuery('policy', current.getUniqueValue());
          policyStateGr.query();
          while (policyStateGr.next()) {
              var lastCalcTime = new GlideDateTime(policyStateGr.getValue('last_full_calc_time'));
              var domainId = policyStateGr.getValue('sys_domain');
              // If it has been more than the full re-calc cycle, once the policy activated we will do a full calc - so it will be a no-op here.
              // But if it was not: turn the flag to run CMDB changes on the policy that will run CMDB changes and publishing within a minute.
              if (!policyFullCalcCycleTime.after(lastCalcTime))
                  p.getAndUpdateReCalcFilterFlag("true", domainId);
          }

          current.publish_status = "4"; // Indicate processing
      }

      current.active = activeValue;
      current.update();
      this.policyStateUtil.synchronizePolicyStatePublishStatus(current);

      // Create DB view for activated policy
      var view = new AgentPolicyDBView();
      if (activeValue) {
          if (view)
              view.generateDBView(current);
      }
  },

  /*
  	This method returns true if there was a critical change in the policy.
  	A critical change in the policy would trigger a full policy calculation.
  	Critical change is define whether how we get the monitored CIs changed, if we change the proxy agents settings - cannot compare checks.
  */
  arePoliciesCriticallyDifferent: function(policyGr1, policyGr2) {
      if (policyGr1.getValue("relationship_state") == '2' &&
          policyGr1.getValue("order") != policyGr2.getValue("order"))
          return true;

      for (var field in this.CRITICAL_POLICY_FIELD_TO_BOOLEAN_FIELD) {
          var booleanValueToCheck = this.CRITICAL_POLICY_FIELD_TO_BOOLEAN_FIELD[field];
          // If we have a boolean value to check first, make sure it is set to true.
          if (booleanValueToCheck) {
              if (policyGr1.getValue(booleanValueToCheck) != 1)
                  continue;
          }

          if (policyGr1.getValue(field) != policyGr2.getValue(field))
              return true;
      }

      return false;
  },

  isDraftCriticallyDifferentFromPublished: function(draftGr) {
      if (!draftGr || !draftGr.sys_id || !draftGr.is_draft)
          return false;

      var publishPolicySysId = draftGr.getValue('related_policy');
      if (!publishPolicySysId)
          return true;
      var publishGr = new GlideRecord('sn_agent_policy');
      if (!publishGr.get('sys_id', publishPolicySysId))
          return true;

      var diff = this.arePoliciesCriticallyDifferent(draftGr, publishGr);
      if (diff)
          return true;

      // Continue to compare checks.
      var p = new PolicyClientsGeneratorNG();
      var numOfChecksOnPublished = p.rapidRowCount('sn_agent_check', 'monitoring_policy=' + publishPolicySysId + '^active=true');
      var numOfChecksOnDraft = p.rapidRowCount('sn_agent_check', 'monitoring_policy=' + draftGr.getValue('sys_id') + '^active=true');

      if (numOfChecksOnPublished != numOfChecksOnDraft)
          return true;

      var draftChecksGr = new GlideRecord('sn_agent_check');
      draftChecksGr.addQuery('monitoring_policy', draftGr.getValue('sys_id'));
      draftChecksGr.addActiveQuery();
      draftChecksGr.query();

      while (draftChecksGr.next()) {
          var publishedCheckSysId = draftChecksGr.getValue('published_check');
          if (!publishedCheckSysId)
              return true;
          var publishCheck = new GlideRecord('sn_agent_check');
          if (!publishCheck.get('sys_id', publishedCheckSysId))
              return true;

          if (draftChecksGr.getValue('active') != publishCheck.getValue('active') ||
              draftChecksGr.getValue('check_def') != publishCheck.getValue('check_def'))
              return true;

          // If auto generated, check if the number of CI params is different
          if (draftChecksGr.getValue('auto_generate') == '1') {
              var ciParamRegEx = '{{.labels.params_ci_';
              var draftCiParams = [];
              var publishCiParams = [];
              // Get all ci params keys using regex
              var myRegexp = new RegExp(ciParamRegEx + "(.*?)}}", "gm");

              var match = myRegexp.exec(draftChecksGr.getValue('command'));
              while (match != null) {
                  if (match[1]) {
                      draftCiParams.push(match[1]);
                  }
                  match = myRegexp.exec(draftChecksGr.getValue('command'));
              }

              match = myRegexp.exec(publishCheck.getValue('command'));
              while (match != null) {
                  if (match[1]) {
                      publishCiParams.push(match[1]);
                  }
                  match = myRegexp.exec(publishCheck.getValue('command'));
              }

              if (publishCiParams.length != draftCiParams.length)
                  return true;

              // Items in both arrays can be identical but not in order.
              // As the result is the same regardless of order, we will sort the arrays to make sure the content is different and not the order.
              publishCiParams.sort();
              draftCiParams.sort();

              for (var i = 0; i < publishCiParams.length; i++)
                  if (publishCiParams[i] != draftCiParams[i])
                      return true;
          }
      }

      return false;
  },

  isDraftDifferentFromPublished: function(draftGr) {
      if (!draftGr || !draftGr.sys_id || !draftGr.is_draft)
          return false;

      if (this.isDraftCriticallyDifferentFromPublished(draftGr))
          return true;

      var publishPolicySysId = draftGr.getValue('related_policy');
      if (!publishPolicySysId)
          return true;

      var publishGr = new GlideRecord('sn_agent_policy');
      if (!publishGr.get('sys_id', publishPolicySysId))
          return false;

      var excludedComparisonFields = this.POLICY_EXCLUDED_COMPARISON_FIELDS;
      var checkExcludedComparisonFields = this.CHECK_EXCLUDED_COMPARISON_FIELDS;
      var paramsExcludedComparisonFields = this.PARAMS_EXCLUDED_COMPARISON_FIELDS;

      var isEqual = this.areRecordsFieldsEqual(draftGr, publishGr, excludedComparisonFields);
      if (!isEqual)
          return true;

      // Continue to compare checks.
      var draftChecksGr = new GlideRecord('sn_agent_check');
      draftChecksGr.addQuery('monitoring_policy', draftGr.getValue('sys_id'));
      draftChecksGr.query();

      var checkFields = draftChecksGr.getElements();

      var paramsFields = undefined;
      var secureParamsFields = undefined;

      while (draftChecksGr.next()) {
          var publishedCheckSysId = draftChecksGr.getValue('published_check');
          if (!publishedCheckSysId)
              return true;
          var publishCheck = new GlideRecord('sn_agent_check');
          if (!publishCheck.get('sys_id', publishedCheckSysId))
              return true;

          isEqual = this.areRecordsFieldsEqual(draftChecksGr, publishCheck, checkExcludedComparisonFields, checkFields);
          if (!isEqual)
              return true;

          // Now compare the check's parameters.
          var draftCheckparam = new GlideRecord('sn_agent_check_param');
          draftCheckparam.addQuery('check', draftChecksGr.getUniqueValue());
          draftCheckparam.query();

          if (!paramsFields)
              paramsFields = draftCheckparam.getElements();

          while (draftCheckparam.next()) {
              var publishedCheckParamSysId = draftCheckparam.getValue('published_param');
              if (!publishedCheckParamSysId)
                  return true;
              var publishedCheckparam = new GlideRecord('sn_agent_check_param');
              if (!publishedCheckparam.get('sys_id', publishedCheckParamSysId))
                  return true;

              isEqual = this.areRecordsFieldsEqual(draftCheckparam, publishedCheckparam, paramsExcludedComparisonFields, paramsFields);
              if (!isEqual)
                  return true;
          }

          // now compare the check's secure parameters.
          draftCheckparam = new GlideRecord('sn_agent_check_secure_param');
          draftCheckparam.addQuery('check', draftChecksGr.getUniqueValue());
          draftCheckparam.query();

          if (!secureParamsFields)
              secureParamsFields = draftCheckparam.getElements();

          while (draftCheckparam.next()) {
              var publishedCheckParamSysId = draftCheckparam.getValue('published_secure_param');
              if (!publishedCheckParamSysId)
                  return true;
              var publishedCheckparam = new GlideRecord('sn_agent_check_secure_param');
              if (!publishedCheckparam.get('sys_id', publishedCheckParamSysId))
                  return true;

              isEqual = this.areRecordsFieldsEqual(draftCheckparam, publishedCheckparam, paramsExcludedComparisonFields, secureParamsFields);
              if (!isEqual)
                  return true;
          }
      }

      return false;
  },

  /**
  	This method compares 2 records on 2 GlideRecord pointing to the same table.
  	The method does this by comparing a value of a field from gr1 with the value of the same field in gr2.
  	The method skips the system fields as they are expected to be different.
  	The method support an exlusion list which will instruct the method to not compare specific fields.
  	The method support an input on fields to be compared, otherwise the method will comapre all table's fields.
  	@params:
  		gr1 - a GlideRecord that points to a specific record on a table
  		gr2 - a GlideRecord that points to a specific record on the same table as gr1
  		exclusionList - an array of field names to exclue (skip) in the comparison
  		fields - OPTIONAL. Get the fields to comapre between gr1 and gr2.
  	@return
  		true if every field's value from gr1 is equale to the same field's value in gr2, otherwise false.
  */
  areRecordsFieldsEqual: function(gr1, gr2, exclusionList, fields) {
      if (gr1.getTableName() != gr2.getTableName())
          return false;

      if (!fields)
          fields = gr1.getElements();

      for (var i = 0; i < fields.length; i++) {
          var fieldName = fields[i].getName();

          // Skip system fields and excluded fields
          if (exclusionList.indexOf(fieldName) > -1 || fieldName.startsWith('sys_'))
              continue;

          if (gr1.getValue(fieldName) != gr2.getValue(fieldName))
              return false;
      }

      return true;
  },

  type: 'PolicyDraftUtils'
};

Sys ID

5b945a5a67064410b7b72dbd2685ef9c

Offical Documentation

Official Docs: