Name

sn_grc.GRCUtilsBase

Description

General GRC Utilities

Script

var GRCUtilsBase = Class.create();
GRCUtilsBase.prototype = {
  initialize: function() {
      this.grcCmdbIntegrationInstance = null;
  },
  checkClassRollsUpToRoot: function(node, root) {
      return this._checkClassRollsUpToRoot(node, root);
  },
  deleteInactiveEntities: function(entites) {
      return this._deleteInactiveEntities(entites);
  },
  checkProfilesForActivation: function(profileType) {
      this._checkProfilesForActivation(profileType);
  },
  checkProfileForDeactivation: function(profile) {
      return this._checkProfileForDeactivation(profile);
  },
  checkProfilesForDeactivation: function(profileType) {
      this._checkProfilesForDeactivation(profileType);
  },
  checkValidDates: function(current) {
      return this._checkValidDates(current);
  },
  inactiveInvalidProfiles: function() {
      this._inactiveInvalidProfiles();
  },
  generateProfilesFromType: function(typeQuery) {
      return this._generateProfilesFromType(typeQuery);
  },
  getIndicatorTemplatesFromContent: function(current) {
      return this._getIndicatorTemplatesFromContent(current);
  },
  getItemsBasedOnTable: function(current) {
      return this._getItemsBasedOnTable(current);
  },
  getPopupListVersion: function() {
      return this._getPopupListVersion();
  },
  getProfileNameFromAppliesTo: function(profile) {
      return this._getProfileNameFromAppliesTo(profile);
  },
  getTablePlural: function(tableName) {
      return this._getTablePlural(tableName);
  },
  getUnrelatedRecords: function(current) {
      return this._getUnrelatedRecords(current);
  },
  isGRCPlannedTask: function(gr) {
      return this._isGRCPlannedTask(gr);
  },
  relateProfiles: function(type) {
      return this._relateProfiles(type);
  },
  relateProfileTypes: function(profile) {
      return this._relateProfileTypes(profile);
  },
  setDiscreteFields: function(profile) {
      return this._setDiscreteFields(profile);
  },
  startWorkflow: function(workflowName, current) {
      return this._startWorkflow(workflowName, current);
  },
  hasWorkflow: function(workflowName, current, state) {
      return this._hasWorkflow(workflowName, current, state);
  },
  cancelWorkflow: function(workflowName, current) {
      return this._cancelWorkflow(workflowName, current);
  },
  showAddButtonOnItemIndicatorRL: function(parent) {
      return this._showAddButtonOnItemIndicatorRL(parent);
  },
  getDefaultTemplateId: function(tableName) {
      return this._getDefaultTemplateId(tableName);
  },
  getSelectedTemplateIdList: function(itemId, itemFieldName, table, templateFieldName) {
      return this._getSelectedTemplateIdList(itemId, itemFieldName, table, templateFieldName);
  },
  isIndicatorRelationshipAvailable: function(itemId) {
      return this._isRelationshipAvailable(itemId, 'item', 'sn_grc_indicator', 'template', 'content', 'sn_grc_m2m_ind_temp_cont', 'indicator_template');
  },
  isTestPlanRelationshipAvailable: function(itemId) {
      return this._isRelationshipAvailable(itemId, 'control', 'sn_audit_test_plan', 'test_template', 'policy_statement', 'sn_audit_test_template', 'sys_id');
  },
  checkRiskControlRelationshipRolesUIAction: function(parentClassName) {
      return this._checkRiskControlRelationshipRolesUIAction(parentClassName);
  },
  isRiskControlRelationshipAvailable: function(itemId) {
      return this._isRiskControlRelationshipAvailable(itemId);
  },
  userHasRole: function(userId, roleName) {
      return this._userHasRole(userId, roleName);
  },
  removeUsersWithoutRole: function(users, roleName) {
      return this._removeUsersWithoutRole(users, roleName);
  },
  getUpstreamProfileClassListFromProfileClassModel: function(profile) {
      return this._getUpstreamProfileClassListFromProfileClassModel(profile);
  },
  getDownstreamProfileClassListFromProfileClassModel: function(profile) {
      return this._getDownstreamProfileClassListFromProfileClassModel(profile);
  },
  checkProfileToRiskStatementAssociation: function(parent) {
      return this._checkProfileToRiskStatementAssociation(parent);
  },
  checkInheritCommonItemsActionVisible: function(parent) {
      return this._checkInheritCommonItemsActionVisible(parent);
  },
  getCommonRiskControlQueryCondition: function(entityID, table, itemID) {
      return this._getCommonRiskControlQueryCondition(entityID, table, itemID);
  },
  getContentRecords: function(content) {
      return this._getContentRecords(content);
  },
  deleteRecord: function(table, sysIds) {
      return this._deleteRecord(table, sysIds);
  },
  createContentProfileRelationship: function(content, profile) {
      return this._createContentProfileRelationship(content, profile);
  },
  isContentActive: function(content) {
      return this._isContentActive(content);
  },
  isProfileActive: function(profile) {
      return this._isProfileActive(profile);
  },
  deleteCMDBQuery: function(entityFilterId) {
      this._deleteCMDBQuery(entityFilterId);
  },
  associateCmdbGroupToEntityFilter: function(entityFilterId, groupId) {
      return this._associateCmdbGroupToEntityFilter(entityFilterId, groupId);
  },
  canTakeAsmt: function(asmt) {
      return this._canTakeAsmt(asmt);
  },
  getMyAssignments: function() {
      return this._getMyAssignments();
  },

  getMyApprovals: function() {
      return this._getMyApprovals();
  },

  syncEntityOwnerWithSourceOwner: function(profile) {
      return this._syncEntityOwnerWithSourceOwner(profile);
  },

  showSyncEntityOwnerWithSourceOwnerButton: function(profile) {
      return this._showSyncEntityOwnerWithSourceOwnerButton(profile);
  },

  populateSourceFieldInEntity: function(profile) {
      return this._populateSourceFieldInEntity(profile);
  },

  hasUpstream: function(profile) {
      return this._hasUpstream(profile);
  },

  _getMyApprovals: function() {
      var u = gs.getUserID();
      var answer = new Array();
      var i = 0;
      answer[i++] = new String(u);
      var g = new GlideRecord("sys_user_delegate");
      g.addQuery("delegate", u);
      g.addQuery("approvals", "true");
      g.addQuery("starts", "<=", gs.daysAgo(0));
      g.addQuery("ends", ">=", gs.daysAgo(0));
      g.query();
      while (g.next()) {
          answer[i++] = new String(g.user);
      }
      return answer;
  },

  _getMyAssignments: function() {
      var u = gs.getUserID();
      var answer = new Array();
      var i = 0;
      answer[i++] = new String(u);
      var g = new GlideRecord("sys_user_delegate");
      g.addQuery("delegate", u);
      g.addQuery("assignments", "true");
      g.addQuery("starts", "<=", gs.daysAgo(0));
      g.addQuery("ends", ">=", gs.daysAgo(0));
      g.query();
      while (g.next()) {
          answer[i++] = new String(g.user);
      }
      return answer;
  },
  _canTakeAsmt: function(current) {
      return current.metric_type.active && (current.metric_type.evaluation_method == 'attestation_v2' || current.metric_type.evaluation_method == 'risk_assessment' || (current.isValidField('risk_identification') && current.risk_identification != '')) && current.user == gs.getUserID() && (current.state == "ready" || current.state == "wip");
  },
  updateEntityModCount: function(entityId) {
      var entity = new GlideRecord('sn_grc_profile');
      entity.get(entityId);
      entity.sys_mod_count = entity.sys_mod_count + 1;
      entity.setWorkflow(false);
      entity.update();
  },
  showIssueNewButtonWS: function(parent) {
      var parentTable = parent.getTableName();
      return ((parent.sys_class_name == 'sn_compliance_control' || parent.sys_class_name == 'sn_risk_risk') && parent.state != "retired") || (parent.sys_class_name == 'sn_grc_issue' && (parent.active && parent.is_group)) || (parent.sys_class_name == 'sn_compliance_policy_statement') || (parentTable == 'sn_risk_definition') || (parent.sys_class_name == 'sn_compliance_authority_document');
  },
  showIssueNewButton: function(parent) {
      var parentTable = parent.getTableName();
      return (parentTable != 'sn_risk_advanced_event') || ((gs.hasRole('sn_risk.manager') && parentTable == 'sn_risk_advanced_event') && parent.state == "2");
  },
  canShowIssueNewButton: function(parent) {
      var showButton = true;
      var hooks = new GlideScriptedExtensionPoint().getExtensions('sn_grc.issueShowNewButton');
      hooks.forEach(function(hook) {
          if (showButton) {
              showButton = hook.showNewButton(parent);
          }
      });
      return showButton;
  },
  generateNewIssue: function(parent, action) {
      var query = "";
      var hooks = new GlideScriptedExtensionPoint().getExtensions('sn_grc.generateIssue');
      hooks.forEach(function(hook) {
          if (query == "") {
              query = hook.process(parent, action);
          }
      });
      return query;
  },
  showPolicyExceptionNewButton: function(parent) {
      return (parent.sys_class_name == 'sn_grc_issue' && parent.content != '' && parent.active && (parent.assigned_to == gs.getUserID() || gs.hasRole('sn_grc.manager'))) || (parent.sys_class_name == 'sn_compliance_policy' && parent.state == "published") || (parent.sys_class_name == 'sn_compliance_policy_statement' && parent.active);
  },
  _deleteInactiveEntities: function(entites) {
      var gr = new GlideRecord('sn_grc_profile');
      gr.addQuery('sys_id', 'IN', entites);
      gr.query();
      if (gr.canDelete())
          gr.deleteMultiple();
  },
  deleteEntityRelationWhenItemDeleted: function(record) {
      var gr = new GlideRecord('sn_grc_m2m_content_profile');
      gr.addQuery('sn_grc_content', record.getValue('content'));
      gr.addQuery('sn_grc_profile', record.getValue('profile'));
      gr.query();
      if (gr.next() && gr.canDelete()) {
          gr.skipInsertActionToQueue = true;
          gr.deleteRecord();
      }
  },
  getProfilesFromProfileClass: function(profileClassList, profile, direction, returnAlreadyAssociated) {
      var directlyRelatedProfiles = this._getProfileListFromProfileClassModel(profileClassList, profile, direction, returnAlreadyAssociated);
      if (directlyRelatedProfiles == '')
          return "";
      var profileToExcludeList = '';
      this.profilesToExclude = [];
      this.visitedProfiles = {};
      this._findProfilesToExclude(profile, direction);
      this.profilesToExclude.push(profile.sys_id + '');
      profileToExcludeList = this.profilesToExclude.join(',');
      var validProfileList = [];
      if (directlyRelatedProfiles != '') {
          directlyRelatedProfiles = directlyRelatedProfiles.split(",");
          for (i = 0; i < directlyRelatedProfiles.length; i++) {
              if (profileToExcludeList.indexOf(directlyRelatedProfiles[i]) < 0)
                  validProfileList.push(directlyRelatedProfiles[i]);
          }
      }
      return validProfileList.join(',');
  },
  generateProfiles: function(profileType, needUpdateFlag, tableName, selectedIds, userField, contentType, contentId) {
      var response = null;
      if (tableName && selectedIds && userField)
          response = this._generateProfilesFromCis(profileType, tableName, selectedIds, userField, contentType, contentId);
      else
          response = this._generateProfiles(profileType, needUpdateFlag);
      this._cleanUpCmdbQueries(profileType);
      return response;
  },
  generateProfilesJob: function(profileType, needUpdateFlag) {
      var response = this._generateProfilesJob(profileType, needUpdateFlag);
      this._cleanUpCmdbQueries(profileType);
      return response;
  },
  isIssueHierarchyLoop: function(issueId, parentIssueId) {
      if (issueId == parentIssueId)
          return true;
      var issue = new GlideRecord("sn_grc_issue");
      issue.get(parentIssueId);
      while (!issue.parent_issue.nil()) {
          parentIssueId = issue.parent_issue.sys_id + '';
          if (issueId == parentIssueId)
              return true;
          issue = new GlideRecord("sn_grc_issue");
          issue.get(parentIssueId);
      }
      return false;
  },
  getInternalUsers: function() {
      var usersList = [];
      var gr = new GlideRecord('sys_user_has_role');
      if (new GlidePluginManager().isActive('com.glide.explicit_roles'))
          gr.addQuery('role.name', 'snc_internal');
      gr.query();
      while (gr.next()) {
          usersList.push(gr.user + '');
      }
      return 'sys_idIN' + usersList.join(',');
  },
  getInternalGroups: function() {
      var allGroupsList = [];
      var gp = new GlideRecord('sys_user_group');
      gp.query();
      while (gp.next()) {
          allGroupsList.push(gp.getUniqueValue() + '');
      }
      if (new GlidePluginManager().isActive('com.glide.explicit_roles')) {
          gp.initialize();
          var grSQ = gp.addJoinQuery('sys_group_has_role', 'sys_id', 'group');
          grSQ.addCondition('role.name', 'snc_external');
          gp.query();
          while (gp.next()) {
              var index = allGroupsList.indexOf(gp.sys_id + '');
              if (index > -1) {
                  allGroupsList.splice(index, 1);
              }
          }
      }
      return 'sys_idIN' + allGroupsList.join(',');
  },
  isEntityFilterUpdated: function(current, previous) {
      return this._isEntityFilterUpdated(current, previous);
  },
  _cleanUpCmdbQueries: function(profileType) {
      var grEntityFilterQuery = new GlideRecord('sn_grc_enrichment_query');
      grEntityFilterQuery.addQuery('profile_type', profileType.sys_id + '');
      grEntityFilterQuery.addQuery('entity_filter_type', 'query_builder');
      grEntityFilterQuery.query();
      while (grEntityFilterQuery.next()) {
          this._deleteEntityFilterResultTableData(grEntityFilterQuery);
      }
  },
  _isEntityFilterUpdated: function(current, previous) {
      var isUpdated = current.table.changes() || current.condition.changes() || current.entity_filter_type.changes() || current.information_objects.changes() || current.active.changesTo(true);
      if (isUpdated) return true;
      var currentQuery = current.getValue('query') + '';
      var previousQuery = previous.getValue('query') + '';
      if (currentQuery != previousQuery) {
          return true;
      }
      return false;
  },
  cleanupMarkForDeletionEntityTypes: function() {
      var entityType = new GlideRecord('sn_grc_profile_type');
      entityType.addQuery('mark_for_deletion', 'true');
      entityType.query();
      while (entityType.next()) {
          var entityTypeId = entityType.getUniqueValue();
          var actionParms = {
              'action': 'delete_entity_type',
              'source': entityTypeId,
              'table': 'sn_grc_profile_type',
              'entity_type_id': entityTypeId
          };
          new IGEntityTypeActionHandler(actionParms).execute();
          // Delete entity type
          entityType.deleteRecord();
      }
  },
  _getCiUser: function(table, sys_id, userField) {
      var gr = new GlideRecord(table);
      gr.get(sys_id);
      return gr.getValue(userField);
  },
  _generateProfilesFromCis: function(profileType, tableName, selectedIds, userField, contentType, contentId) {
      //Set busy
      profileType.processing_profiles = true;
      profileType.need_update = true;
      profileType.update();
      var ids = selectedIds.split(',');
      for (var i in ids) {
          var profileID;
          var grProf = new GlideRecord('sn_grc_profile');
          grProf.addQuery('table', tableName);
          grProf.addQuery('applies_to', ids[i]);
          grProf.query();
          if (grProf.next()) {
              if (!grProf.active) {
                  grProf.active = true;
                  grProf.update();
              }
              profileID = grProf.sys_id + '';
          } else {
              grProf.initialize();
              grProf.table = tableName;
              grProf.applies_to = ids[i];
              grProf.owned_by = this._getCiUser(tableName, ids[i], userField);
              grProf.sys_domain = profileType.sys_domain;
              profileID = grProf.insert();
          }
          var m2m = new GlideRecord('sn_grc_m2m_profile_profile_type');
          m2m.addQuery('profile_type', profileType.sys_id + '');
          m2m.addQuery('profile', profileID);
          m2m.query();
          if (!m2m.next()) {
              m2m.initialize();
              m2m.setValue('profile_type', profileType.sys_id + '');
              m2m.setValue('profile', profileID);
              m2m.setValue('sys_domain', profileType.sys_domain);
              m2m.update();
          }
      }
      //Set idle
      profileType.processing_profiles = false;
      profileType.need_update = false;
      profileType.update();
      //associate content to PT
      if (contentType && contentId) {
          if (contentType == 'sn_compliance_policy_statement') {
              var grPS = new GlideRecord('sn_compliance_m2m_statement_profile_type');
              grPS.addQuery('sn_grc_profile_type', profileType.sys_id + '');
              grPS.addQuery('sn_compliance_statement', contentId);
              grPS.query();
              if (!grPS.next()) {
                  grPS.initialize();
                  grPS.setValue('sn_grc_profile_type', profileType.sys_id + '');
                  grPS.setValue('sn_compliance_statement', contentId);
                  grPS.insert();
              }
          }
          if (contentType == 'sn_risk_definition') {
              var grRS = new GlideRecord('sn_risk_m2m_risk_definition_profile_type');
              grRS.addQuery('sn_grc_profile_type', profileType.sys_id + '');
              grRS.addQuery('statement', contentId);
              grRS.query();
              if (!grRS.next()) {
                  grRS.initialize();
                  grRS.setValue('sn_grc_profile_type', profileType.sys_id + '');
                  grRS.setValue('statement', contentId);
                  grRS.insert();
              }
          }
      }
  },
  _generateProfiles: function(profileType, needUpdateFlag) {
      var typeQuery = new GlideRecord('sn_grc_enrichment_query');
      if (needUpdateFlag)
          typeQuery.addQuery('need_update', true);
      typeQuery.addQuery('profile_type', profileType.sys_id + '');
      typeQuery.query();
      while (typeQuery.next()) {
          var entitiesResult = this._generateProfilesFromType(typeQuery);
          if (!gs.nil(entitiesResult) && entitiesResult.isFilterExecuted) {
              typeQuery.need_update = false;
              typeQuery.update();
          }
      }
      this._relateProfiles(profileType.sys_id + '');
      profileType.processing_profiles = false;
      profileType.need_update = false;
      profileType.update();
  },
  _isRiskControlRelationshipAvailable: function(itemId) {
      var item = new GlideRecord('sn_grc_item');
      if (item.isValid() && !item.get(itemId))
          return false;
      var isControl = (item.sys_class_name + '' == 'sn_compliance_control');
      var table = 'sn_compliance_control';
      if (isControl)
          table = 'sn_risk_risk';
      var profileId = item.profile;
      var alreadyAssociatedRiskControl = new GlideRecord("sn_risk_m2m_risk_control");
      if (isControl)
          alreadyAssociatedRiskControl.addQuery("sn_compliance_control", itemId);
      else
          alreadyAssociatedRiskControl.addQuery("sn_risk_risk", itemId);
      alreadyAssociatedRiskControl.query();
      var alreadyAssociatedRiskControlIds = [];
      while (alreadyAssociatedRiskControl.next()) {
          if (isControl)
              alreadyAssociatedRiskControlIds.push(alreadyAssociatedRiskControl.sn_risk_risk + '');
          else
              alreadyAssociatedRiskControlIds.push(alreadyAssociatedRiskControl.sn_compliance_control + '');
      }
      var gr = new GlideRecord(table);
      if (gr.isValid()) {
          gr.addQuery('profile', profileId);
          gr.addEncodedQuery('sys_idNOT IN' + alreadyAssociatedRiskControlIds.join(',') + '^EQ');
          gr.setLimit(1);
          gr.query();
          return gr.hasNext();
      } else
          return false;
  },

  _isCommonRiskControlRelationshipAvailable: function(entityId, table, itemID) {
      var m2mGr = new GlideRecord('sn_grc_m2m_item_entity');
      m2mGr.addQuery('item.sys_class_name', table);
      m2mGr.addQuery('item', 'NOT IN', this._getAssociatedCommonRiskOrControls(table, itemID));
      m2mGr.addQuery('active', true);
      m2mGr.addQuery('entity', entityId);
      m2mGr.setLimit(1);
      m2mGr.query();
      return m2mGr.hasNext();
  },

  _getCommonRiskControlQueryCondition: function(entityID, table, itemID) {
      var queryCondition = '';
      var itemType = '';
      if (table == 'sn_compliance_control') {
          itemType = 'Control';
      } else {
          itemType = 'Risk';
      }
      var associatedCommonControls = this._getAssociatedCommonRiskOrControls(table, itemID);
      var allCommonControls = new sn_grc.ItemInheritance().getItemsForReliantEntity(entityID, itemType);
      var finalControls = allCommonControls.filter(function(el) {
          return associatedCommonControls.indexOf(el) < 0;
      });
      queryCondition = 'sys_idIN' + finalControls + '^EQ';
      return queryCondition;
  },

  _getAssociatedCommonRiskOrControls: function(table, itemID) {
      var associatedCommonRiskOrControlIds = [];
      var gr = new GlideRecord('sn_risk_m2m_risk_control');
      if (table == 'sn_compliance_control') {
          gr.addQuery('sn_compliance_control.item_function', '1');
          gr.addQuery('sn_risk_risk', itemID);
      } else {
          gr.addQuery('sn_risk_risk.item_function', '1');
          gr.addQuery('sn_compliance_control', itemID);
      }
      gr.query();
      while (gr.next()) {
          associatedCommonRiskOrControlIds.push(gr.getValue(table));
      }
      return associatedCommonRiskOrControlIds;
  },

  _checkInheritCommonItemsActionVisible: function(parent) {
      var table = 'sn_compliance_control';
      if (parent.getTableName() == 'sn_compliance_control') {
          table = 'sn_risk_risk';
      }
      return parent.state != 'retired' && this.checkRiskControlRelationshipRolesUIAction(parent.getTableName()) && this._isCommonRiskControlRelationshipAvailable(parent.profile, table, parent.getUniqueValue());
  },

  _checkRiskControlRelationshipRolesUIAction: function(parentClassName) {
      return (parentClassName == 'sn_risk_risk' || parentClassName == 'sn_compliance_control') && (gs.hasRole('sn_risk.user') || gs.hasRole('sn_compliance.user'));
  },
  _getSelectedTemplateIdList: function(itemId, itemFieldName, table, templateFieldName) {
      var gr = new GlideRecordSecure(table);
      gr.addQuery(itemFieldName, itemId);
      gr.query();
      var selectedIdList = [];
      while (gr.next())
          selectedIdList.push(gr.getValue(templateFieldName) + '');
      return selectedIdList.join(',');
  },
  _checkClassRollsUpToRoot: function(node, root) {
      if (node.sys_id == root.sys_id)
          return true;
      var classesVisited = {};
      var profileClass = new GlideRecord('sn_grc_profile_class');
      profileClass.query();
      while (profileClass.next())
          classesVisited[profileClass.sys_id] = false;
      classesVisited[node.sys_id] = true;
      var stack = [node];
      while (stack.length != 0) {
          node = stack.pop();
          var parent = new GlideRecord('sn_grc_profile_class');
          parent.addQuery('sys_id', 'IN', node.roll_up_to);
          parent.query();
          while (parent.next()) {
              if (parent.sys_id == root.sys_id)
                  return true;
              if (!classesVisited[parent.sys_id]) {
                  classesVisited[parent.sys_id] = true;
                  var p = new GlideRecord('sn_grc_profile_class');
                  p.get(parent.sys_id);
                  stack.push(p);
              }
          }
      }
      return false;
  },
  _showAddButtonOnItemIndicatorRL: function(parent) {
      //Add button on the Item's indicator related list is visible if one of the follow conditions are met
      //When on risk, statement field should not be empty and the logged in user should have risk manager role
      //When on control, control field should not be empty and logged in user should have compliance manager role
      return ((parent.sys_class_name == 'sn_risk_risk' && !parent.statement.nil() && gs.hasRole('sn_risk.manager')) || (parent.sys_class_name == 'sn_compliance_control' && !parent.content.nil() && gs.hasRole('sn_compliance.manager')));
  },
  getProfileListFromProfileClassModel: function(profile, direction, returnAlreadyAssociated) {
      var profileClassList = "";
      if (direction == "upstream")
          profileClassList = this._getUpstreamProfileClassListFromProfileClassModel(profile);
      else
          profileClassList = this._getDownstreamProfileClassListFromProfileClassModel(profile);
      if (profileClassList == '')
          return "";
      if (returnAlreadyAssociated != null)
          return this._getProfileListFromProfileClassModel(profileClassList, profile, direction, returnAlreadyAssociated);
      else
          return this._getProfileListFromProfileClassModel(profileClassList, profile, direction, false);
  },
  getQueryProfileListFromProfileClassModel: function(profile, direction) {
      var profileClassList = "";
      this.profilesToExclude = [];
      this.visitedProfiles = {};
      if (direction == "upstream")
          profileClassList = this._getUpstreamProfileClassListFromProfileClassModel(profile);
      else
          profileClassList = this._getDownstreamProfileClassListFromProfileClassModel(profile);
      if (profileClassList == '')
          return "^sys_id=-1";
      var query = "profile_classIN" + profileClassList;
      var directlyRelatedProfiles = this._getProfileListFromProfileClassModel(profileClassList, profile, direction, true);
      if (directlyRelatedProfiles != '') {
          directlyRelatedProfiles = directlyRelatedProfiles.split(",");
          this.profilesToExclude.push.apply(this.profilesToExclude, directlyRelatedProfiles);
      }
      this.profilesToExclude.push.apply(this.profilesToExclude, this._inactiveProfileListFromProfileClassList(profileClassList));
      this._findProfilesToExclude(profile, direction);
      var excludes = this.profilesToExclude;
      excludes.push(profile.sys_id + '');
      for (var i = 0; i < excludes.length; i++)
          query += "^sys_id!=" + excludes[i];
      return query;
  },
  _inactiveProfileListFromProfileClassList: function(profileClassList) {
      var inactiveProfiles = new GlideRecord("sn_grc_profile");
      inactiveProfiles.addQuery("profile_class", "IN", profileClassList);
      inactiveProfiles.addQuery("active", false);
      inactiveProfiles.query();
      var inactiveProfileList = [];
      while (inactiveProfiles.next())
          inactiveProfileList.push(inactiveProfiles.getUniqueValue() + '');
      return inactiveProfileList;
  },
  _findProfilesToExclude: function(profile, direction) {
      if (profile.sys_id in this.visitedProfiles)
          return;
      this.visitedProfiles[profile.sys_id] = true;
      var profileList = [];
      var profileClassList = "";
      if (direction == "downstream")
          profileClassList = this._getUpstreamProfileClassListFromProfileClassModel(profile);
      else
          profileClassList = this._getDownstreamProfileClassListFromProfileClassModel(profile);
      if (profileClassList == '')
          return;
      this.profilesToExclude.push.apply(this.profilesToExclude, this._inactiveProfileListFromProfileClassList(profileClassList));
      if (direction == "downstream")
          profileList = this._getProfileListFromProfileClassModel(profileClassList, profile, "upstream", true);
      else
          profileList = this._getProfileListFromProfileClassModel(profileClassList, profile, "downstream", true);
      if (profileList == '')
          return;
      profileList = profileList.split(",");
      this.profilesToExclude.push.apply(this.profilesToExclude, profileList);
      for (var i = 0; i < profileList.length; i++) {
          var pf = new GlideRecord('sn_grc_profile');
          pf.get(profileList[i]);
          this._findProfilesToExclude(pf, direction);
      }
      return;
  },
  _getProfileListFromProfileClassModel: function(profileClassList, profile, direction, returnAlreadyAssociated) {
      var gr = new GlideRecord("sn_grc_profile");
      gr.addEncodedQuery("profile_classIN" + profileClassList);
      gr.addActiveQuery();
      gr.query();
      var profileList = [];
      while (gr.next()) {
          var upstreamProfileId = "";
          var downstreamProfileId = "";
          if (direction == "upstream") {
              upstreamProfileId = gr.getUniqueValue();
              downstreamProfileId = profile.getUniqueValue();
          } else {
              upstreamProfileId = profile.getUniqueValue();
              downstreamProfileId = gr.getUniqueValue();
          }
          var profile_to_profile = new GlideRecord("sn_grc_m2m_profile_profile");
          profile_to_profile.addQuery("upstream_profile", upstreamProfileId);
          profile_to_profile.addQuery("downstream_profile", downstreamProfileId);
          profile_to_profile.query();
          if (returnAlreadyAssociated) {
              if (profile_to_profile.next()) {
                  profileList.push(gr.getUniqueValue());
              }
          } else {
              if (!profile_to_profile.next()) {
                  profileList.push(gr.getUniqueValue());
              }
          }
      }
      return profileList.join(",");
  },
  _isRelationshipAvailable: function(itemId, itemFieldName, table, templateFieldName, templateContentFieldName, templateTable, templateTableFieldName) {
      var item = new GlideRecord("sn_compliance_control");
      var contentId = "";
      if (item.isValid() && item.get(itemId))
          contentId = item.content;
      else {
          item = new GlideRecord("sn_risk_risk");
          if (item.isValid() && item.get(itemId))
              contentId = item.statement;
          else
              return false;
      }
      var selectedList = this._getSelectedTemplateIdList(itemId, itemFieldName, table, templateFieldName);
      var gr = new GlideRecord(templateTable);
      gr.addQuery(templateContentFieldName, contentId);
      gr.addQuery(templateTableFieldName, 'NOT IN', selectedList);
      gr.setLimit(1);
      gr.query();
      return gr.hasNext();
  },
  _getUpstreamProfileClassListFromProfileClassModel: function(profile) {
      if (!profile.profile_class.nil()) {
          var profileClass = new GlideRecord("sn_grc_profile_class");
          if (profileClass.get(profile.profile_class)) {
              var rollUpTo = profileClass.getValue("roll_up_to");
              if (rollUpTo == null) {
                  return "";
              } else {
                  rollUpTo = this._sortProfileClass(rollUpTo);
                  return rollUpTo;
              }
          } else {
              gs.info("error: profile " + profile.sys_id + " reference an invalid profile class: " + profile.profile_class);
              return "";
          }
      } else
          return "";
  },
  _sortProfileClass: function(profileClassList) {
      var gr = new GlideRecord("sn_grc_profile_class");
      gr.addEncodedQuery("sys_idIN" + profileClassList);
      gr.orderBy('name');
      gr.query();
      var sysIds = [];
      while (gr.next())
          sysIds.push(gr.sys_id + '');
      return sysIds.join(',');
  },
  _getDownstreamProfileClassListFromProfileClassModel: function(profile) {
      if (!profile.profile_class.nil()) {
          var profileClass = new GlideRecord("sn_grc_profile_class");
          profileClass.addEncodedQuery("roll_up_toLIKE" + profile.profile_class);
          profileClass.query();
          var profileClassList = [];
          while (profileClass.next()) {
              profileClassList.push(profileClass.getUniqueValue());
          }
          profileClassList = this._sortProfileClass(profileClassList.join(","));
          return profileClassList;
      } else
          return "";
  },
  _getDefaultTemplateId: function(tableName) {
      var template = new GlideRecord(tableName);
      template.addQuery('is_default', true);
      template.query();
      if (template.next())
          return template.sys_id;
      return '';
  },
  _checkProfilesForActivation: function(profileType) {
      var associatedProfileIds = [];
      var profileToProfileType = new GlideRecord('sn_grc_m2m_profile_profile_type');
      profileToProfileType.addQuery('profile_type', profileType.sys_id);
      profileToProfileType.addQuery('profile.active', false);
      profileToProfileType.query();
      while (profileToProfileType.next()) {
          associatedProfileIds.push(profileToProfileType.getValue('profile'));
      }
      if (associatedProfileIds.length == 0) {
          return;
      }
      var profile = new GlideRecord('sn_grc_profile');
      profile.addQuery('sys_id', 'IN', associatedProfileIds);
      profile.active = true;
      profile.skipInsertActionToQueue = true;
      profile.updateMultiple();
      // Activate items from above entities if necessary
      var actionParams = {
          'action': 'activate_bulk_entities',
          'entity_ids': associatedProfileIds
      };
      new sn_grc.IGEntityActionHandler(actionParams).execute();
  },
  _checkProfileForDeactivation: function(profileId) {
      var profile = new GlideRecord('sn_grc_profile');
      if (!profile.get(profileId))
          return;
      var associatedProfileTypes = new GlideRecord('sn_grc_m2m_profile_profile_type');
      associatedProfileTypes.addQuery('profile_type.active', true);
      associatedProfileTypes.addQuery('profile', profileId);
      associatedProfileTypes.setLimit(1);
      associatedProfileTypes.query();
      if (!associatedProfileTypes.hasNext()) {
          profile.active = false;
          profile.skipInsertActionToQueue = true;
          profile.update();
          return true;
      }
      return false;
  },
  _checkProfilesForDeactivation: function(profileType) {
      // Get all of the profiles that are associated with the profile type
      var profileIds = [];
      var associatedProfiles = new GlideRecord('sn_grc_m2m_profile_profile_type');
      associatedProfiles.addQuery('profile_type', profileType.sys_id);
      associatedProfiles.addQuery('profile.active', true);
      associatedProfiles.query();
      while (associatedProfiles.next()) {
          profileIds.push(associatedProfiles.profile.sys_id + '');
      }
      // Filter the profiles to those that are associated with an another profile type that's active
      var ga = new GlideAggregate('sn_grc_m2m_profile_profile_type');
      ga.addQuery('profile', 'IN', profileIds);
      ga.addQuery('profile_type', '!=', profileType.sys_id);
      ga.addQuery('profile_type.active', true);
      ga.groupBy('profile');
      ga.query();
      var remainingActive = [];
      while (ga.next()) {
          remainingActive.push(ga.profile + '');
      }
      // Deactivate the profiles that are associated with the profile type, but not associated
      // with an active profile type
      var needDeactivatedProfileIds = new global.ArrayUtil().diff(profileIds, remainingActive);
      var inactive = new GlideRecord('sn_grc_profile');
      inactive.addQuery('sys_id', 'IN', needDeactivatedProfileIds);
      inactive.active = false;
      inactive.skipInsertActionToQueue = true;
      inactive.updateMultiple();
      var actionParams = {
          'action': 'deactivate_bulk_entities',
          'entity_ids': needDeactivatedProfileIds
      };
      new sn_grc.IGEntityActionHandler(actionParams).execute();
      if (remainingActive.length != profileIds.length) {
          var numProfilesDeactivated = ((profileIds.length - remainingActive.length) + '');
          var pt = new sn_grc.GRCUtils().getMessage("profile_type_lower");
          var pr = new sn_grc.GRCUtils().getMessage("profile_lower");
          var message = gs.getMessage('Deactivated {0} {1}s that are no longer associated with an active {2}', [numProfilesDeactivated, pr, pt]);
          gs.addInfoMessage(message);
      }
  },
  _checkValidDates: function(current) {
      if (current.valid_from.nil() || current.valid_to.nil())
          return false;
      var startDate = (new GlideDateTime(current.valid_from)).getNumericValue();
      var endDate = (new GlideDateTime(current.valid_to)).getNumericValue();
      var nowDate = new GlideDateTime().getNumericValue();
      if (nowDate > endDate) {
          gs.addErrorMessage(gs.getMessage('Valid To date cannot be in the past'));
          return true;
      }
      if (startDate == '' || endDate == '')
          return false;
      // check if conflicting travel start time
      if (startDate >= endDate) {
          gs.addErrorMessage(gs.getMessage('Valid To date must be after Valid From date'));
          return true;
      }
  },
  _inactiveInvalidProfiles: function() {
      var flag = false;
      var profile = new GlideRecord('sn_grc_profile');
      profile.query();
      while (profile.next()) {
          //Standalone Entities will not get deleted from this.
          if (profile.table != '' && profile.applies_to != '') {
              var record = new GlideRecord(profile.table + '');
              record.addQuery('sys_id', profile.applies_to + '');
              record.query();
              if (!record.hasNext()) {
                  profile.setValue('active', false);
                  profile.update();
                  flag = true;
              }
          }
      }
      if (flag) {
          var grcAdminUsers = this._getGRCAdminUserList();
          gs.eventQueue('sn_grc.inactive_entity', null, grcAdminUsers);
      }
  },
  _getGRCAdminUserList: function() {
      var role = this._getAdminRoleRecord();
      var grcAdminList = "";
      if (!gs.nil(role)) {
          var user = new GlideRecord("sys_user_has_role");
          user.addQuery("role", role.getValue("sys_id"));
          user.query();
          while (user.next()) {
              var gr = new GlideRecord("sys_user");
              gr.get(user.getValue("user"));
              if (!gs.nil(gr.getValue("email")))
                  grcAdminList += gr.getValue("email") + '' + ",";
          }
          if (grcAdminList != "")
              grcAdminList = grcAdminList.substring(0, grcAdminList.length - 1);
      }
      return grcAdminList;
  },
  _getAdminRoleRecord: function() {
      var role = new GlideRecord("sys_user_role");
      role.addQuery("name", "sn_grc.admin");
      role.query();
      if (role.next()) {
          return role;
      } else {
          return null;
      }
  },
  _generateProfilesFromType: function(typeQuery) {
      var results = {
          added: 0,
          existing: 0,
          skipped: 0,
          isFilterExecuted: false
      };
      var type = new GlideRecord('sn_grc_profile_type');
      if (!type.get(typeQuery.profile_type))
          return results;
      if (typeQuery.table.nil()) {
          type.processing_profiles = false;
          type.update();
          return results;
      }
      //Look up all records that match the filter.
      var gr = new GlideRecord(typeQuery.table);
      if (!gr.isValid()) {
          type.processing_profiles = false;
          type.update();
          return results;
      }
      gr.initialize();
      var condition = this._getEntityFilterCondition(typeQuery);
      if (condition == undefined) return results;
      results.isFilterExecuted = true;
      gr = this._getTableRecords(typeQuery.table, condition);
      var configurationItems = {};
      //For each record, ensure a Profile exists
      while (gr.next()) {
          var entityId = '';
          var grProf = new GlideRecord('sn_grc_profile');
          grProf.addQuery('applies_to', gr.sys_id);
          grProf.query();
          //Profile already exists.
          if (grProf.next()) {
              entityId = grProf.getValue('sys_id');
              results.existing++;
              if (!grProf.active) {
                  grProf.active = true;
                  grProf.update();
              }
              configurationItems[gr.sys_id] = entityId;
              continue;
          }
          var owner = '';
          if (!typeQuery.owner_field.nil()) {
              var ownerPath = (typeQuery.owner_field + '').split('.');
              var pointer = gr;
              var i = 0;
              while (i < ownerPath.length) {
                  var p = pointer[ownerPath[i]];
                  if (!p || p.nil()) break;
                  pointer = p;
                  i++;
                  if (i == ownerPath.length) owner = pointer;
              }
          }
          if (!owner || owner.nil()) {
              //Skip records with no owner
              if (typeQuery.empty_owner == 'Skip') {
                  results.skipped++;
                  continue;
              }
              //Set the owner from the default
              if (typeQuery.empty_owner == 'Default')
                  owner = typeQuery.default_owner;

              //As now, owner is mandatory to create new entities using entity filter
              if (typeQuery.use_owner_field == false) {
                  owner = typeQuery.default_owner;
              }
          }
          //only create new profiles if the type is active
          if (typeQuery.active) {
              grProf.initialize();
              grProf.table = typeQuery.table;
              grProf.applies_to = gr.sys_id;
              grProf.profile_class = typeQuery.profile_class;
              grProf.owned_by = owner;
              grProf.sys_domain = type.sys_domain;
              grProf.auto_update_entity_owner = typeQuery.auto_update_entity_owner;
              grProf.owner_field_in_source_table = typeQuery.owner_field;
              grProf.owner_last_synched_on = new GlideDateTime();
              entityId = grProf.insert();
              results.added++;
              configurationItems[gr.sys_id] = entityId;
          }
      }
      this._createMappingBetweenEntityAndIO(typeQuery, configurationItems);
      return results;
  },
  _getEntityFilterCondition: function(entityFilter) {
      var queryType = entityFilter.entity_filter_type + '';
      var condition = '';
      switch (queryType) {
          case 'condition_builder':
              condition = entityFilter.condition;
              break;
          case 'query_builder':
              condition = this._getConditionFromCMDBQueryResults(entityFilter);
              break;
          default:
              condition = entityFilter.condition;
              break;
      }
      return condition;
  },
  _getConditionFromCMDBQueryResults: function(entityFilter) {
      var condition = 'sys_idIN';
      var queryResponse = this._getCMDBQueryExecutionResults(entityFilter);
      if (!queryResponse.result) return undefined;
      var requiredCis = queryResponse.ciWithoutIORelations;
      if (gs.nil(requiredCis) || requiredCis.length == 0) return condition;
      condition += requiredCis.join();
      return condition;
  },
  _getTableRecords: function(table, condition) {
      var gr = new GlideRecord(table);
      gr.initialize();
      if (!gs.nil(condition)) {
          gr.addEncodedQuery(condition);
      }
      gr.query();
      return gr;
  },
  _getCMDBQueryExecutionResults: function(entityFilter) {
      var cmdbQueryInstance = this._getGrcCmdbIntegrationInstance();
      var ioFilters = '';
      if (!gs.nil(entityFilter.information_objects)) {
          ioFilters = entityFilter.information_objects + '';
      }
      var cmdbQueryResponse = cmdbQueryInstance.findConfigurationItems(entityFilter.getUniqueValue(), entityFilter.table + '', entityFilter.getValue('query') + '', ioFilters, false);
      return cmdbQueryResponse;
  },
  _createMappingBetweenEntityAndIO: function(entityFilter, configurationItems) {
      var cmdbQueryInstance = this._getGrcCmdbIntegrationInstance();
      var queryType = entityFilter.entity_filter_type + '';
      var associations = '';
      switch (queryType) {
          case 'condition_builder':
              associations = null;
              break;
          case 'query_builder':
              associations = cmdbQueryInstance.findConfigurationItems(entityFilter.getUniqueValue(), entityFilter.table + '', entityFilter.getValue('query'), entityFilter.getValue('information_objects'), false).ciWithIORelations;
              break;
          default:
              associations = null;
              break;
      }
      if (!gs.nil(associations)) {
          var table = 'sn_grc_m2m_profile_information_object';
          for (var key in configurationItems) {
              this._createMapping(table, configurationItems[key], associations[key]);
          }
      }
  },
  _createMapping: function(table, entitySysId, ioValues) {
      ioValues = Object.keys(ioValues);
      if (!gs.nil(ioValues) && ioValues.length > 0) {
          var gr = new GlideRecord(table);
          for (var j = 0; j < ioValues.length; j++) {
              gr.initialize();
              gr.addQuery('sn_grc_profile', entitySysId);
              gr.addQuery('information_object', ioValues[j]);
              gr.setLimit(1);
              gr.query();
              if (!gr.hasNext()) {
                  gr.initialize();
                  gr.setValue('sn_grc_profile', entitySysId);
                  gr.setValue('information_object', ioValues[j]);
                  gr.insert();
              }
          }
      }
  },
  _getGrcCmdbIntegrationInstance: function() {
      if (!gs.nil(this.grcCmdbIntegrationInstance)) {
          return this.grcCmdbIntegrationInstance;
      }
      this.grcCmdbIntegrationInstance = new sn_grc.GRCCMDBQueryIntegration();
      return this.grcCmdbIntegrationInstance;
  },
  _getPopupListVersion: function() {
      /*
          commenting since list team doesn't support v3 much
          var listV3 = GlidePluginManager.isActive('com.glide.ui.list_v3_components');
          var doctype = this._getDoctype();
          var concourse = this._getConcourse();
  		
          return (doctype && concourse && listV3) ? 3 : 2;*/
      return 2;
  },
  _getConcourse: function() {
      var pref = new GlideRecord('sys_user_preference');
      pref.addQuery('name', 'use.concourse');
      pref.addQuery('user', gs.getUserID());
      pref.query();
      if (pref.next())
          return pref.value == 'true';
      pref = new GlideRecord('sys_user_preference');
      pref.addQuery('name', 'use.concourse');
      pref.addQuery('system', true);
      pref.query();
      if (pref.next())
          return pref.value == 'true';
      return false;
  },
  _getDoctype: function() {
      return gs.getProperty('glide.ui.doctype', 'false') == 'true';
  },
  _getIndicatorTemplatesFromContent: function(current) {
      var query = 'active=true^category=' + current.category + ' Template';
      if (!gs.nil(current.item)) {
          var templateIds = [];
          var m2m = new GlideRecord('sn_grc_m2m_ind_temp_cont');
          m2m.addQuery('content', current.item.content);
          m2m.query();
          while (m2m.next())
              templateIds.push(m2m.indicator_template + '');
          query = query + "^sys_idIN" + templateIds.join(',');
      }
      return query;
  },
  _getItemsBasedOnTable: function(current) {
      var type = current.category == 'Risk Indicator' ? 'sn_risk_risk' : 'sn_compliance_control';
      var query = "^state!=retired^sys_class_name=" + type;
      if (current.entity) {
          query = "profile=" + current.entity + query;
      }
      var contentIds = [];
      if (!current.template.nil()) {
          var m2m = new GlideRecord('sn_grc_m2m_ind_temp_cont');
          m2m.addQuery('indicator_template', current.template);
          m2m.query();
          while (m2m.next())
              contentIds.push(m2m.content + '');
          query = query + '^contentIN' + contentIds.join(',');
      }
      return query;
  },
  _getItemSysIdsForIndicator: function(profileID, childTables) {
      var itemSysIds = [];
      for (var j = 0; j < childTables.length; j++) {
          var rec = new GlideRecord(childTables[j]);
          if (rec.canRead()) {
              if (profileID != "")
                  rec.addQuery("profile", profileID);
              rec.addQuery("state", "!=", "retired");
              rec.query();
              while (rec.next())
                  itemSysIds.push(rec.getUniqueValue());
          } else
              continue;
      }
      return itemSysIds;
  },
  _getProfileNameFromAppliesTo: function(profile) {
      var gr = new GlideRecord(profile.table);
      if (gr.get(profile.applies_to)) return gr.getDisplayValue();
      return '';
  },
  _getTablePlural: function(tableName) {
      var doc = new GlideRecord('sys_documentation');
      doc.addQuery('name', tableName);
      doc.addQuery('element', 'ISEMPTY', '');
      doc.addQuery('language', gs.getSession().getLanguage());
      doc.setLimit(1);
      doc.query();
      if (doc.next())
          return doc.plural;
      var gr = new GlideRecord(tableName);
      if (gr.isValid())
          return gr.getLabel();
      return null;
  },
  _getUnrelatedRecords: function(current) {
      var idArray = this._getContentRecords(current);
      var queryString = 'sys_id!=' + idArray[0];
      for (var i = 1; i < idArray.length; i++) {
          queryString += "^sys_id!=" + idArray[i];
      }
      var contentList = new GlideRecord(current.getRecordClassName());
      contentList.addEncodedQuery(queryString);
      if (current.getRecordClassName() == 'sn_risk_definition') {
          if (gs.getProperty('sn_risk_advanced.risk_hierarchy_max_levels') != null) {
              var maximumLevel = 0;
              var gr = new GlideAggregate('sn_risk_definition');
              gr.addQuery('active=true');
              gr.addQuery('risk_hierarchy', 'CONTAINS', current.sys_id);
              gr.addAggregate('MAX', 'level');
              gr.groupBy('active');
              gr.query();
              if (gr.next()) {
                  maximumLevel = parseInt(gr.getAggregate('MAX', 'level'));
              } else {
                  maximumLevel = current.level;
              }
              contentList.addQuery('level', '<=', gs.getProperty('sn_risk_advanced.risk_hierarchy_max_levels') - (maximumLevel - current.level + 1));
          }
      }
      contentList.query();
      var sysIDs = [];
      while (contentList.next()) {
          sysIDs.push(contentList.getValue('sys_id'));
      }
      return "sys_idIN" + sysIDs;
  },
  _getChildrenIDs: function(children) {
      var childrenIDs = '';
      while (children.next()) {
          var childID = children.getUniqueValue();
          var grandChild = new GlideRecord(children.getRecordClassName());
          grandChild.addQuery('parent', childID);
          grandChild.query();
          childrenIDs += "," + childID + this._getChildrenIDs(grandChild);
      }
      return childrenIDs;
  },
  _getContentRecords: function(current) {
      var sysIDs = current.sys_id;
      var children = new GlideRecord(current.getRecordClassName());
      children.addQuery('parent', current.sys_id);
      children.query();
      sysIDs += "," + this._getChildrenIDs(children);
      var idArray = sysIDs.split(',');
      return idArray;
  },
  _isGRCPlannedTask: function(gr) {
      var tables = new GlideTableHierarchy(gr.getTableName()).getHierarchy();
      return tables.indexOf('sn_grc_issue') >= 0 ||
          tables.indexOf('sn_audit_task') >= 0 ||
          tables.indexOf('sn_audit_engagement') >= 0;
  },
  _relateProfiles: function(type) {
      var results = {
          added: 0,
          existing: 0,
          removed: 0
      };
      //Get all records that match the condition
      var ids = {};
      var failedEntityFilters = [];
      var enrichmentQuery = new GlideRecord('sn_grc_enrichment_query');
      enrichmentQuery.addActiveQuery();
      enrichmentQuery.addQuery('profile_type', type);
      enrichmentQuery.query();
      while (enrichmentQuery.next()) {
          var condition = this._getEntityFilterCondition(enrichmentQuery);
          if (condition == undefined) {
              failedEntityFilters.push(enrichmentQuery.getUniqueValue());
              continue;
          }
          var gr = this._getTableRecords(enrichmentQuery.table, condition);
          while (gr.next()) {
              if (ids.hasOwnProperty(gr.sys_id + '')) {
                  ids[gr.sys_id + ''] = ids[gr.sys_id + ''] + ',' + enrichmentQuery.getUniqueValue();
              } else {
                  ids[gr.sys_id + ''] = enrichmentQuery.getUniqueValue();
              }
          }
      }
      //Remove any unwanted m2m records if they are not created manually
      var util = new ItemGenerationV2Conditions();
      var grUnwanted = new GlideRecord('sn_grc_m2m_profile_profile_type');
      grUnwanted.addQuery('profile_type', type);
      grUnwanted.addQuery('created_one_off', false);
      grUnwanted.query();
      while (grUnwanted.next()) {
          if (grUnwanted.profile) {
              var recordId = grUnwanted.profile.applies_to + '';
              if (recordId in ids)
                  continue;
          }
          if (gs.nil(grUnwanted.entity_filters) || !this._isEntityAssociatedWithFailedEntityFilter(failedEntityFilters, grUnwanted.entity_filters.split(','))) {
              var entityId = grUnwanted.getValue('profile');
              grUnwanted.skipInsertActionToQueue = true;
              grUnwanted.deleteRecord();
              if (util.entityTypeHasActiveContentAssociation(type) || util.entityTypeHasItemAssociation(type, false)) {
                  var actionParms = {
                      action: 'remove_entity_from_entity_type',
                      entity_type_id: type,
                      entity_id: entityId,
                  };
                  new sn_grc.IGEntityToEntityTypeActionHandler(actionParms).execute();
              }
              results.removed++;
          }
      }
      //Create any missing m2m records
      for (var i in ids) {
          //Get the Profile if it exists
          var grRP = new GlideRecord('sn_grc_profile');
          grRP.addQuery('applies_to', i);
          grRP.query();
          if (!grRP.next())
              continue;
          //Check for an existing m2m
          var m2m = new GlideRecord('sn_grc_m2m_profile_profile_type');
          m2m.addQuery('profile_type', type);
          m2m.addQuery('profile', grRP.sys_id);
          m2m.query();
          if (m2m.next()) {
              var associatedEntityFilters = !gs.nil(m2m.entity_filters) ? m2m.entity_filters.split(',') : null;
              if (!gs.nil(associatedEntityFilters) && associatedEntityFilters.length > 0 && failedEntityFilters.length > 0) {
                  var failedExistingFilters = associatedEntityFilters.filter(function(obj) {
                      return failedEntityFilters.indexOf(obj) > -1;
                  });
                  associatedEntityFilters = ids[i] + ',' + failedExistingFilters.join();
              } else {
                  associatedEntityFilters = ids[i];
              }
              m2m.entity_filters = associatedEntityFilters;
              m2m.update();
              results.existing++;
              continue;
          }
          m2m.initialize();
          m2m.profile_type = type;
          m2m.profile = grRP.sys_id;
          m2m.entity_filters = ids[i];
          //Query Profile Type
          var grProfileType = new GlideRecord('sn_grc_profile_type');
          grProfileType.get(type);
          //Explicitly set sys_domain of m2m record from profile type record
          m2m.sys_domain = grProfileType.sys_domain;
          m2m.created_one_off = false;
          m2m.skipInsertActionToQueue = true;
          m2m.insert();
          if (util.entityTypeHasActiveContentAssociation(type) || util.entityTypeHasItemAssociation(type, true)) {
              var actionParms2 = {
                  action: 'add_entity_to_entity_type',
                  entity_type_id: type,
                  entity_id: grRP.sys_id,
              };
              new sn_grc.IGEntityToEntityTypeActionHandler(actionParms2).execute();
          }
          results.added++;
      }
      return results;
  },
  _isEntityAssociatedWithFailedEntityFilter: function(failedEntityFilters, entityAssociatedFilters) {
      if (failedEntityFilters.length == 0 ||
          entityAssociatedFilters.length == 0) return false;
      return failedEntityFilters.some(function(item) {
          return entityAssociatedFilters.indexOf(item) != -1;
      });
  },
  _relateProfileTypes: function(profile) {
      var results = {
          added: 0,
          existing: 0,
          removed: 0
      };
      //Get all Profile Types where the conditions are met by the Applies to
      var ids = {};
      var enrichmentQuery = new GlideRecord('sn_grc_enrichment_query');
      enrichmentQuery.addActiveQuery();
      enrichmentQuery.query();
      while (enrichmentQuery.next()) {
          var gr = new GlideRecord(enrichmentQuery.table);
          gr.addQuery('sys_id', profile.applies_to);
          var condition = this._getEntityFilterCondition(enrichmentQuery);
          if (condition != '') {
              gr.addEncodedQuery(condition);
          }
          gr.query();
          if (gr.next()) {
              if (gs.nil(ids[enrichmentQuery.profile_type + '']) || ids[enrichmentQuery.profile_type + ''].length == 0) {
                  ids[enrichmentQuery.profile_type + ''] = [];
              }
              ids[enrichmentQuery.profile_type + ''].push(enrichmentQuery.getUniqueValue());
          }
      }
      var strIDs = Object.keys(ids).join(',');
      var profileId = profile.getUniqueValue();
      var util = new ItemGenerationV2Conditions();
      //Remove any m2m records that no longer apply				
      var grUnwanted = new GlideRecord('sn_grc_m2m_profile_profile_type');
      grUnwanted.addQuery('profile', profileId);
      grUnwanted.addQuery('created_one_off', false);
      grUnwanted.query();
      while (grUnwanted.next()) {
          var entityTypeId = grUnwanted.getValue('profile_type');
          if (entityTypeId && strIDs.indexOf(grUnwanted.profile_type + '') != -1) continue;
          grUnwanted.skipInsertActionToQueue = true;
          grUnwanted.deleteRecord();
          if (util.entityTypeHasActiveContentAssociation(grUnwanted.getValue('profile_type')) || util.entityTypeHasItemAssociation(grUnwanted.getValue('profile_type'), false)) {
              var actionParms = {
                  action: 'remove_entity_from_entity_type',
                  entity_type_id: entityTypeId,
                  entity_id: profileId,
              };
              new sn_grc.IGEntityToEntityTypeActionHandler(actionParms).execute();
          }
          results.removed++;
      }
      //Create any missing m2m records
      for (var i in ids) {
          //Check for an existing m2m
          var m2m = new GlideRecord('sn_grc_m2m_profile_profile_type');
          m2m.addQuery('profile', profileId);
          m2m.addQuery('profile_type', i);
          m2m.query();
          if (m2m.next()) {
              results.existing++;
              continue;
          }
          m2m.initialize();
          m2m.profile = profileId;
          m2m.profile_type = i;
          m2m.created_one_off = false;
          m2m.skipInsertActionToQueue = true;
          m2m.entity_filters = ids[i + ''].join();
          m2m.insert();
          if (util.entityTypeHasActiveContentAssociation(i) || util.entityTypeHasItemAssociation(i, true)) {
              var actionParms2 = {
                  action: 'add_entity_to_entity_type',
                  entity_type_id: i,
                  entity_id: profileId,
              };
              new sn_grc.IGEntityToEntityTypeActionHandler(actionParms2).execute();
          }
          results.added++;
      }
      return results;
  },
  _setDiscreteFields: function(profile) {
      var fieldList = {
          'alm_asset': 'alm_asset',
          'ast_contract': 'ast_contract',
          'cmdb': 'cmdb_ci',
          'cmn_location': 'cmn_location',
          'core_company': 'core_company',
          'task': 'task',
          'cmn_department': 'cmn_department'
      };
      var baseTable = getAbsoluteBase(profile.table);
      for (var table in fieldList) {
          var field = fieldList[table];
          if (baseTable == table) {
              profile[field] = profile.applies_to + '';
          } else {
              if (shouldClearDiscreteField(table)) {
                  profile[field] = '';
              }
          }
      }

      function getAbsoluteBase(tableName) {
          var gr = new GlideRecord('sys_db_object');
          gr.addQuery('name', tableName);
          gr.query();
          if (!gr.next()) return false;
          while (!gr.super_class.nil()) {
              gr = gr.super_class;
          }
          return gr.name + '';
      }

      function shouldClearDiscreteField(newTable) {
          if (table == 'cmn_location' || table == 'cmn_department') {
              return false;
          }
          return true;
      }
  },
  handleCreateOnRetiredItem: function(current, fieldName) {
      if (current[fieldName].state + "" == "retired") {
          gs.addErrorMessage(gs.getMessage("Can not pick a retired {0} ({1})", [fieldName, GlideStringUtil.escapeHTML(current[fieldName].name)]));
          return true;
      }
      return false;
  },
  _startWorkflow: function(workflowName, current) {
      var w = new global.Workflow();
      w.startFlow(w.getWorkflowFromName(workflowName), current, current.operation(), {});
  },
  _hasWorkflow: function(workflowName, current, state) {
      var w = new global.Workflow();
      var workflowVersion = w.getVersionFromName(workflowName);
      if (workflowVersion == '')
          return false;
      var contexts = w.getContexts(current);
      while (contexts && contexts.next()) {
          if (contexts.workflow_version == workflowVersion && contexts.state == state)
              return true;
      }
      return false;
  },
  _cancelWorkflow: function(workflowName, current) {
      var w = new global.Workflow();
      var workflowVersion = w.getVersionFromName(workflowName);
      if (workflowVersion == '')
          return;
      var contexts = w.getContexts(current);
      while (contexts && contexts.next()) {
          if (contexts.workflow_version == workflowVersion && contexts.state == 'executing')
              w.cancelContext(contexts);
      }
  },
  _userHasRole: function(userId, roleName) {
      if (!userId || !roleName)
          return false;
      return this._userHasRoleName(userId, roleName);
  },
  _removeUsersWithoutRole: function(users, roleName) {
      users = users.split(',');
      if (users.length == 0)
          return '';
      var ary = [];
      for (var i = 0; i < users.length; i++)
          if (this._userHasRoleName(users[i], roleName))
              ary.push(users[i]);
      return ary.join(',');
  },
  _userHasRoleName: function(userId, roleName) {
      var gr = new GlideRecord('sys_user_has_role');
      gr.addQuery('user', userId);
      gr.addQuery('role.name', roleName);
      gr.setLimit(1);
      gr.query();
      return gr.hasNext();
  },
  getMessage: function(code) {
      return this._getMessage(code);
  },
  _getMessage: function(code) {
      var gr = new GlideRecord("sn_grc_message_configuration");
      gr.addQuery("code", code);
      gr.query();
      gr.next();
      var nomenClatureFlag = gs.getProperty('sn_grc.enable_nomenclature_labels', 'false');
      if (nomenClatureFlag.equalsIgnoreCase("true")) {
          return gr.getDisplayValue("nomenclature_message");
      } else {
          return gr.getDisplayValue("rollback_message");
      }
  },
  _checkProfileToRiskStatementAssociation: function(parent) {
      if (parent.active == "1" && ((parent.getTableName() == 'sn_compliance_policy_statement' && gs.hasRole('sn_compliance.manager')) || (parent.getTableName() == 'sn_risk_definition' && gs.hasRole('sn_risk.manager'))))
          return true;
      else
          return false;
  },
  refreshEntityCount: function() {
      this._refreshEntityCount();
  },
  _refreshEntityCount: function() {
      var entityTypes = new GlideRecord('sn_grc_profile_type');
      entityTypes.query();
      while (entityTypes.next()) {
          var entityToEntityType = new GlideAggregate('sn_grc_m2m_profile_profile_type');
          entityToEntityType.addAggregate('COUNT');
          entityToEntityType.addQuery('profile_type', entityTypes.getUniqueValue());
          entityToEntityType.query();
          var count = 0;
          if (entityToEntityType.next()) {
              count = entityToEntityType.getAggregate('COUNT');
          }
          entityTypes.setValue('entity_count', count);
          entityTypes.update();
      }
  },
  getUnrelatedRecordsForHierarchy: function(record, tableName) {
      return this._getUnrelatedRecordsForHierarchy(record, tableName);
  },
  _getUnrelatedRecordsForHierarchy: function(record, tableName) {
      var children = [record.getUniqueValue()];
      var immediateParents = [record.getUniqueValue()];
      this.getChildrenRecords(children, immediateParents, tableName);
      return "sys_class_name=" + tableName + "^sys_idNOT IN" + children;
  },
  getChildrenRecords: function(children, immediateParents, tableName) {
      return this._getChildrenRecords(children, immediateParents, tableName);
  },
  _getChildrenRecords: function(children, immediateParents, tableName) {
      if (immediateParents.length == 0) {
          return;
      }
      var table = new GlideRecord(tableName);
      table.addQuery('parent', 'IN', immediateParents);
      table.query();
      immediateParents = [];
      while (table.next()) {
          children.push(table.getUniqueValue());
          immediateParents.push(table.getUniqueValue());
      }
      return this._getChildrenRecords(children, immediateParents, tableName);
  },
  validateParent: function(current, table) {
      return this._validateParent(current, table);
  },
  _validateParent: function(current, table) {
      var currentId = current.getUniqueValue();
      while (!current.parent.nil()) {
          var parent = current.parent;
          if (currentId == parent) {
              return false;
          }
          current = new GlideRecord(table);
          current.get(parent);
      }
      return true;
  },
  addBusinessUser: function(userId, groupId) {
      this._addUserToBusinessGroup(userId, groupId);
  },
  _addUserToBusinessGroup: function(userId, groupId) {
      var userGroupRecord = new GlideRecord("sys_user_grmember");
      userGroupRecord.addQuery("user", userId);
      userGroupRecord.addQuery("group", groupId);
      userGroupRecord.query();
      if (!userGroupRecord.hasNext()) {
          userGroupRecord.initialize();
          userGroupRecord.setValue("user", userId);
          userGroupRecord.setValue("group", groupId);
          userGroupRecord.insert();
      }
  },
  _generateProfilesJob: function(profileType, needUpdateFlag) {
      var typeQuery = new GlideRecord('sn_grc_enrichment_query');
      if (needUpdateFlag)
          typeQuery.addQuery('need_update', true);
      typeQuery.addQuery('profile_type', profileType.sys_id + '');
      typeQuery.query();
      while (typeQuery.next()) {
          var entitiesResult = this._generateProfilesFromType(typeQuery);
          if (!gs.nil(entitiesResult) && entitiesResult.isFilterExecuted) {
              typeQuery.need_update = false;
              typeQuery.update();
          }
      }
      var unwantedRecords = [];
      unwantedRecords = this._relateProfilesJob(profileType.sys_id + '');
      if (unwantedRecords.length == 0) {
          profileType.processing_profiles = false;
      }
      profileType.need_update = false;
      profileType.update();
      return unwantedRecords;
  },
  _relateProfilesJob: function(type) {
      var flag = this._isEntityTypesFilterAssociatedWithOtherEntityType(type);
      //Get all records that match the condition
      var ids = {};
      var failedEntityFilters = [];
      var enrichmentQuery = new GlideRecord('sn_grc_enrichment_query');
      enrichmentQuery.addActiveQuery();
      enrichmentQuery.addQuery('profile_type', type);
      enrichmentQuery.query();
      while (enrichmentQuery.next()) {
          var condition = this._getEntityFilterCondition(enrichmentQuery);
          if (condition == undefined) {
              failedEntityFilters.push(enrichmentQuery.getUniqueValue());
              continue;
          }
          var gr = this._getTableRecords(enrichmentQuery.table, condition);
          while (gr.next()) {
              if (ids.hasOwnProperty(gr.sys_id + '')) {
                  ids[gr.sys_id + ''] = ids[gr.sys_id + ''] + ',' + enrichmentQuery.getUniqueValue();
              } else {
                  ids[gr.sys_id + ''] = enrichmentQuery.getUniqueValue();
              }
          }
      }
      //store or delete unwanted m2m records depending upon flag if they are not created manually 
      var util = new ItemGenerationV2Conditions();
      var unwantedRecords = [];
      var grUnwanted = new GlideRecord('sn_grc_m2m_profile_profile_type');
      grUnwanted.addQuery('profile_type', type);
      grUnwanted.addQuery('created_one_off', false);
      grUnwanted.query();
      while (grUnwanted.next()) {
          if (grUnwanted.profile) {
              var recordId = grUnwanted.profile.applies_to + '';
              if (recordId in ids)
                  continue;
          }
          if ((gs.nil(grUnwanted.entity_filters) || !this._isEntityAssociatedWithFailedEntityFilter(failedEntityFilters, grUnwanted.entity_filters.split(',')))) {
              if (flag) {
                  unwantedRecords.push(grUnwanted.getValue("sys_id"));
              } else {
                  var entityId = grUnwanted.getValue('profile');
                  grUnwanted.skipInsertActionToQueue = true;
                  grUnwanted.deleteRecord();
                  if (util.entityTypeHasActiveContentAssociation(type) || util.entityTypeHasItemAssociation(type, false)) {
                      var actionParms = {
                          action: 'remove_entity_from_entity_type',
                          entity_type_id: type,
                          entity_id: entityId,
                      };
                      new sn_grc.IGEntityToEntityTypeActionHandler(actionParms).execute();
                  }
              }
          }
      }
      //Create any missing m2m records
      for (var i in ids) {
          //Get the Profile if it exists
          var grRP = new GlideRecord('sn_grc_profile');
          grRP.addQuery('applies_to', i);
          grRP.query();
          if (!grRP.next())
              continue;
          //Check for an existing m2m
          var m2m = new GlideRecord('sn_grc_m2m_profile_profile_type');
          m2m.addQuery('profile_type', type);
          m2m.addQuery('profile', grRP.sys_id);
          m2m.query();
          if (m2m.next()) {
              var associatedEntityFilters = !gs.nil(m2m.entity_filters) ? m2m.entity_filters.split(',') : null;
              if (!gs.nil(associatedEntityFilters) && associatedEntityFilters.length > 0 && failedEntityFilters.length > 0) {
                  var failedExistingFilters = associatedEntityFilters.filter(function(obj) {
                      return failedEntityFilters.indexOf(obj) > -1;
                  });
                  associatedEntityFilters = ids[i] + ',' + failedExistingFilters.join();
              } else {
                  associatedEntityFilters = ids[i];
              }
              m2m.entity_filters = associatedEntityFilters;
              m2m.update();
              continue;
          }
          m2m.initialize();
          m2m.profile_type = type;
          m2m.profile = grRP.sys_id;
          m2m.entity_filters = ids[i];
          //Query Profile Type
          var grProfileType = new GlideRecord('sn_grc_profile_type');
          grProfileType.get(type);
          //Explicitly set sys_domain of m2m record from profile type record
          m2m.sys_domain = grProfileType.sys_domain;
          m2m.created_one_off = false;
          m2m.skipInsertActionToQueue = true;
          m2m.insert();
          if (util.entityTypeHasActiveContentAssociation(type) || util.entityTypeHasItemAssociation(type, true)) {
              var actionParms2 = {
                  action: 'add_entity_to_entity_type',
                  entity_type_id: type,
                  entity_id: grRP.sys_id,
              };
              new sn_grc.IGEntityToEntityTypeActionHandler(actionParms2).execute();
          }
      }
      return unwantedRecords;
  },
  _isEntityTypesFilterAssociatedWithOtherEntityType: function(profileType) {
      var flag = false;
      var profileFilter = new GlideRecord("sn_grc_enrichment_query");
      profileFilter.addActiveQuery();
      profileFilter.addQuery('profile_type', profileType);
      profileFilter.query();
      //checks if table is associated with multiple entity types
      while (profileFilter.next()) {
          var enrichmentquery = new GlideRecord("sn_grc_enrichment_query");
          enrichmentquery.addActiveQuery();
          enrichmentquery.addQuery("table", profileFilter.getValue("table"));
          enrichmentquery.addEncodedQuery("profile_typeISNOTEMPTY^profile_type!=" + profileType);
          enrichmentquery.query();
          if (enrichmentquery.next()) {
              flag = true;
              break;
          }
      }
      return flag;
  },
  _deleteRecord: function(table, sysIds) {
      for (var i = 0; i < sysIds.length; i++) {
          var gr = new GlideRecord(table);
          if (gr.get(sysIds[i]))
              gr.deleteRecord();
      }
  },
  isExternalUser: function(userId, externalRoleId) {
      var userRoleGr = new GlideRecord("sys_user_has_role");
      userRoleGr.addQuery("user", userId);
      userRoleGr.addQuery("role", externalRoleId);
      userRoleGr.query();
      if (userRoleGr.next())
          return true;
      else
          return false;
  },
  getProfileClassesRollingUpToRoot: function(current) {
      return this._getProfileClassesRollingUpToRoot(current);
  },
  _getProfileClassesRollingUpToRoot: function(current) {
      var classesList = [];
      if (!current.roll_up_to) {
          var root = new GlideRecord('sn_grc_profile_class');
          root.addQuery('is_root', 'true');
          root.query();
          if (root.next()) {
              var classesVisited = {};
              var Class = new GlideRecord('sn_grc_profile_class');
              Class.query();
              while (Class.next()) {
                  classesVisited[Class.getUniqueValue()] = false;
              }
              var stack = [root.getUniqueValue()];
              classesList.push(root.getUniqueValue());
              while (stack.length != 0) {
                  root = stack.pop();
                  var child = new GlideRecord("sn_grc_profile_class");
                  child.addQuery('roll_up_to', "CONTAINS", root);
                  child.query();
                  while (child.next()) {
                      if (!classesVisited[child.getUniqueValue()]) {
                          classesList.push(child.getUniqueValue());
                          classesVisited[child.getUniqueValue()] = true;
                          stack.push(child.getUniqueValue());
                      }
                  }
              }
              return "sys_idIN" + classesList.join(',');
          }
      }
      return "sys_idISNOTEMPTY^sys_id!=" + current.getUniqueValue();
  },
  _createContentProfileRelationship: function(content, profile) {
      var contentProfileRelationship = new GlideRecord('sn_grc_m2m_content_profile');
      if (contentProfileRelationship.canCreate()) {
          contentProfileRelationship.setValue('sn_grc_content', content);
          contentProfileRelationship.setValue('sn_grc_profile', profile);
          contentProfileRelationship.insert();
          return true;
      }
      return false;
  },
  _isContentActive: function(content) {
      var contentRecord = new GlideRecord('sn_grc_content');
      if (contentRecord.canRead() && contentRecord.get(content)) {
          return contentRecord.active;
      }
      return false;
  },
  _isProfileActive: function(profile) {
      var profileRecord = new GlideRecord('sn_grc_profile');
      if (profileRecord.canRead() && profileRecord.get(profile)) {
          return profileRecord.active;
      }
      return false;
  },
  _deleteCMDBQuery: function(entityFilterId) {
      if (!gs.nil(entityFilterId)) {
          var grEntityFilterToCmdbGroup = new GlideRecord("sn_grc_m2m_enrichment_query_cmdb_group");
          grEntityFilterToCmdbGroup.addQuery('entity_filter', entityFilterId);
          grEntityFilterToCmdbGroup.query();
          while (grEntityFilterToCmdbGroup.next()) {
              new global.CMDBQueryUtils().deleteCMDBGroup(grEntityFilterToCmdbGroup.getValue('cmdb_group'));
              grEntityFilterToCmdbGroup.deleteRecord();
          }
      }
  },
  _deleteEntityFilterResultTableData: function(entityFilter) {
      var resultTable = this._getQueryResultTable(entityFilter.getValue('final_query'));
      if (!gs.nil(resultTable)) {
          new global.CMDBQueryUtils().deleteRecords(resultTable);
          return;
      }

      var entityFilterId = entityFilter.getUniqueValue();
      if (!gs.nil(entityFilterId)) {
          var grEntityFilterToCmdbGroup = new GlideRecord("sn_grc_m2m_enrichment_query_cmdb_group");
          grEntityFilterToCmdbGroup.addQuery('entity_filter', entityFilterId);
          grEntityFilterToCmdbGroup.query();
          if (grEntityFilterToCmdbGroup.next()) {
              var grGroupToQueryMapper = new GlideRecord('cmdb_group_contains_qb_query');
              grGroupToQueryMapper.addQuery('group', grEntityFilterToCmdbGroup.getValue('cmdb_group'));
              grGroupToQueryMapper.query();
              while (grGroupToQueryMapper.next()) {
                  resultTable = this._getQueryResultTable(grGroupToQueryMapper.getValue('qb_query'));
                  if (!gs.nil(resultTable)) {
                      new global.CMDBQueryUtils().deleteRecords(resultTable);
                  }
              }
          }
      }
  },
  _getQueryResultTable: function(queryId) {
      var name = '';
      var glideRecord = new GlideRecord('cmdb_qb_table_mapping');
      glideRecord.addQuery('query', queryId);
      glideRecord.setLimit(1);
      glideRecord.query();
      if (glideRecord.next()) {
          name = glideRecord.getValue('table_name');
      }
      return name;
  },
  _associateCmdbGroupToEntityFilter: function(entityFilterId, groupId) {
      if (!gs.nil(entityFilterId) && !gs.nil(groupId)) {
          var grEntityFilterCmdbGroupMap = new GlideRecord("sn_grc_m2m_enrichment_query_cmdb_group");
          grEntityFilterCmdbGroupMap.addQuery('entity_filter', entityFilterId);
          grEntityFilterCmdbGroupMap.addQuery('cmdb_group', groupId);
          grEntityFilterCmdbGroupMap.query();
          if (!grEntityFilterCmdbGroupMap.hasNext()) {
              grEntityFilterCmdbGroupMap.initialize();
              grEntityFilterCmdbGroupMap.entity_filter = entityFilterId;
              grEntityFilterCmdbGroupMap.cmdb_group = groupId;
              return grEntityFilterCmdbGroupMap.insert();
          }
      }
  },
  isRetiringItems: function() {
      gs.addErrorMessage(gs.getMessage('Item Generation requires that at least version GRC: Risk Management (13.x.x) and GRC: Policy and Compliance Management (13.x.x) be activated.'));
      return false;
  },


  getValueFromField: function(record, fieldName) {

      var value = '';

      var ownerPath = (fieldName).split('.');
      var pointer = record;
      var i = 0;
      while (i < ownerPath.length) {
          var p = pointer[ownerPath[i]];
          if (!p || p.nil()) {
              break;
          }
          pointer = p;
          i++;
          if (i == ownerPath.length) {
              value = pointer;
          }
      }
      return value;
  },
  _syncEntityOwnerWithSourceOwner: function(profile) {
      if (profile) {
          if (!profile.table.nil() && !profile.applies_to.nil() && !profile.owner_field_in_source_table.nil()) {
              var sourceRecord = new GlideRecord(profile.table);
              var isSourceRecordPresent = sourceRecord.get(profile.applies_to);
              if (isSourceRecordPresent) {
                  var newOwner = this.getValueFromField(sourceRecord, profile.getValue('owner_field_in_source_table'));
                  if (newOwner) {
                      profile.setValue('owned_by', newOwner);
                  }
              }
          }
          profile.setValue('owner_last_synched_on', new GlideDateTime());
          profile.update();
      }
  },

  _showSyncEntityOwnerWithSourceOwnerButton: function(profile) {

      if (profile && !profile.table.nil() && !profile.applies_to.nil() && !profile.owner_field_in_source_table.nil() && profile.auto_update_entity_owner) {

          var sourceRecord = new GlideRecord(profile.table);
          var isSourceRecordPresent = sourceRecord.get(profile.applies_to);
          if (isSourceRecordPresent) {
              var newOwner = this.getValueFromField(sourceRecord, profile.getValue('owner_field_in_source_table'));
              if (newOwner && newOwner != profile.getValue('owned_by')) {
                  return 'true';
              }
          }
      }
      return 'false';

  },

  _populateSourceFieldInEntity: function(profile) {

      // 		for existing entities, steps to populate source field:-
      // 		If for an entity, in all related entity filters if owner field is same, pick any
      // 		otherwise pick the entity filter which has owner field value on source table same as entitiy's owner
      // 		otherwise pick the oldest entity filter

      if (profile) {

          // mark this as true so that this profile is not again picked in subsequent batch
          profile.tried_populating_owner_source_while_upgrade = true;

          if (!profile.table.nil() && !profile.applies_to.nil() && profile.owner_field_in_source_table.nil()) {

              var sourceRecord = new GlideRecord(profile.table);
              var isSourceRecordPresent = sourceRecord.get(profile.applies_to);
              var profileToProfileType = new GlideRecord('sn_grc_m2m_profile_profile_type');
              profileToProfileType.addQuery('profile', profile.getUniqueValue());
              profileToProfileType.query();
              if (isSourceRecordPresent) {
                  var oldestEntityFilterOwnerField = null;
                  var oldestEntityFilterCreationTime = null;
                  while (profileToProfileType.next()) {
                      var entityFilter = new GlideRecord('sn_grc_enrichment_query');
                      entityFilter.addQuery('profile_type', profileToProfileType.profile_type);
                      entityFilter.query();
                      while (entityFilter.next()) {
                          if (entityFilter.use_owner_field && !entityFilter.owner_field.nil() && entityFilter.table == profile.table) {
                              var newOwner = this.getValueFromField(sourceRecord, entityFilter.getValue('owner_field'));
                              if (newOwner && newOwner == profile.getValue('owned_by')) {
                                  profile.owner_field_in_source_table = entityFilter.owner_field;
                                  profile.update();
                                  return;
                              }
                              if (!oldestEntityFilterOwnerField) {
                                  oldestEntityFilterOwnerField = entityFilter.owner_field;
                                  oldestEntityFilterCreationTime = new GlideDateTime(entityFilter.sys_created_on);
                              } else {
                                  var currentEntityFilterCreationTime = new GlideDateTime(entityFilter.sys_created_on);
                                  if (currentEntityFilterCreationTime.compareTo(oldestEntityFilterCreationTime) < 0) {
                                      oldestEntityFilterOwnerField = entityFilter.owner_field;
                                      oldestEntityFilterCreationTime = currentEntityFilterCreationTime;
                                  }
                              }
                          }
                      }
                  }
                  if (oldestEntityFilterOwnerField) {
                      profile.owner_field_in_source_table = oldestEntityFilterOwnerField;
                  }
              }
          }

          profile.update();

      }
  },

  _hasUpstream: function(entity) {
      var profileToProfile = new GlideRecord('sn_grc_m2m_profile_profile');
      profileToProfile.addQuery('downstream_profile', entity.getUniqueValue());
      profileToProfile.addQuery('upstream_profile.active', true);
      profileToProfile.setLimit(1);
      profileToProfile.query();

      if (profileToProfile.next()) {
          return true;
      }

      return false;
  },

  hasRemediationTaskReadAccess: function(current) {
      var hasRemediationTaskReadAccess = current.issue.assigned_to == gs.getUserID() || current.assigned_to == gs.getUserID() || current.issue.issue_manager == gs.getUserID();
      if (current.watch_list != '') {
          return hasRemediationTaskReadAccess || current.watch_list.includes(gs.getUserID());
      }
      return hasRemediationTaskReadAccess;
  },
  
  showControlNewButtonWS: function(parent){
    var tables = ['sn_compliance_policy','sn_risk_advanced_risk_identification','sn_grc_profile','sn_privacy_processing_activity','sn_gf_goal'];
    var parentTableName = parent.getTableName();
    if(tables.indexOf(parentTableName)!=-1 || (parentTableName=='sn_compliance_policy_statement' && parent.getValue("active")==0))
      return false;
    return true;
  },

  type: 'GRCUtilsBase'
};

Sys ID

b2d44761cb200200829cf865734c9cf6

Offical Documentation

Official Docs: