Name

global.PatternLibrary

Description

ServiceWatch Pattern Library helper functions

Script

var PatternLibrary = Class.create();
PatternLibrary.prototype = {
  initialize: function() {
  	this.notification_handler = new MIDNotificationHandler();
  	this.ciTypesDeflator = new SNC.CiTypesDocUtilWrapper();
  	this.citypes_catalog_name = 'citypes_catalog';
  	this.citypes_key = 'citypes_xml';
  	this.citypes_version_key = 'citypes_xml_version';
  	this.saHashName = 'ci_types_version';
  },

  getCiTypeData: function() {
  	var cis = GlideDBObjectManager.get().getAllChildrenOf('cmdb_ci');
  	var cisToCheck = this.getCiTypeNames();

  	var result = this.getCiTypeDataOnNames(this.convertToJsArray(cisToCheck));
  	result['cis'] = cis;

  	return result;
  },

  getCiTypeDataOnNamesJson: function(ciNames) {
  	var cis = GlideDBObjectManager.get().getAllChildrenOf('cmdb_ci');

  	var ciTypeData = this.getCiTypeDataOnNames(ciNames);

  	var map = ciTypeData.map;
  	var labels = ciTypeData.labels;
  	var sys_dictionary_override = ciTypeData.sys_dictionary_override;

  	return this.toJson(cis, map, labels,sys_dictionary_override);
  },

  getCiTypeDataOnNames: function(ciNames) {
  	var requiredAttributesEnabled = GlideProperties.getBoolean("glide.required.attribute.enabled", true);
  	var map = {};
  	var labels = {};
  	// populate the sys_dictionary_override map.
  	var sys_dictionary_override = {};
  	for (var i = 0; i < ciNames.length; i++) {
  		var table = '' + ciNames[i];
  		var isEndpoint = GlideDBObjectManager.get().isInstanceOf(table, 'cmdb_ci_endpoint');
  		var list = map[table];
  		if (list == null) {
  			list = [];
  			map[table] = list;
  		}
  		var td = GlideTableDescriptor.get(table);
  		var sc = td.getSchema();
  		var attrNames = sc.keySet();
  		var it = attrNames.iterator();
  		while (it.hasNext()) {
  			var attrName = '' + it.next();
  			if (attrName.startsWith('sys_') && (attrName !== 'sys_class_name'))
  				continue;
  			var ed = sc.get(attrName);

  			var defValue = '';
  			if (isEndpoint) {
  				defValue = '' + ed.getDefault();
  				if (defValue === 'null')
  					defValue = '';
  			}
  			list.push({
  				'name': attrName,
  				'type': '' + ed.getInternalType(),
  				'size' : '' + ed.getLength(),
  				'mandatory' : (requiredAttributesEnabled && (attrName != 'company')) ?
  					(ed.isMandatory() ? '1' : '0') : '0',
  				'attrs' : '' + ed.serializeAttributes(),
  				'defaultValue' : defValue
  			});
  		}
  	}

  	return {
  		'map': map,
  		'labels': labels,
  		'sys_dictionary_override': sys_dictionary_override
  	};
  },

  getCiTypeNames: function() {
  	var ciNames = GlideDBObjectManager.get().getAllExtensions('cmdb_ci');
  	ciNames.add(0, 'cmdb_ci');

  	return ciNames;
  },

  // create xml with ci types and their fields
  getCiTypesXml: function() {
  	var ciData = this.getCiTypeData();

  	var cis = ciData.cis;
  	var map = ciData.map;
  	var labels = ciData.labels;
  	var sys_dictionary_override = ciData.sys_dictionary_override;

  	return this.toXml(cis, map, labels,sys_dictionary_override);
  },

  // create json with ci types and their fields
  getCiTypesJson: function() {
  	var ciData = this.getCiTypeData();

  	var cis = ciData.cis;
  	var map = ciData.map;
  	var labels = ciData.labels;
  	var sys_dictionary_override = ciData.sys_dictionary_override;

  	return this.toJson(cis, map, labels,sys_dictionary_override);
  },

  // build map of table name -> map of field name to default value
  buildDefaultValueOverride : function (sys_dictionary_override) {
  	var defaultValueOverride = {};
  	var grOverride = new GlideRecord('sys_dictionary_override');
  	grOverride.addQuery("default_value_override", '1');
  	grOverride.addQuery("base_table", ['cmdb_ci_endpoint', 'cmdb_ci_endpoint_inclusion']);
  	grOverride.query();
  	while (grOverride.next()) {
  		var fieldToDefaultValue = defaultValueOverride[grOverride.name];
  		if (fieldToDefaultValue == null) {
  			fieldToDefaultValue = {};
  			defaultValueOverride[grOverride.name] = fieldToDefaultValue;
  		}
  		fieldToDefaultValue[grOverride.element] = grOverride.default_value;
  	}
  	return defaultValueOverride;
  },

  // build map of table name -> map of field name to mandatory flag
  buildSysOverride : function (sys_dictionary_override) {
  	var grOverride = new GlideRecord('sys_dictionary_override');
  	grOverride.addQuery("mandatory_override", '1');
  	grOverride.query();
  	while (grOverride.next()) {
  		var fieldToMandatory = sys_dictionary_override[grOverride.name];
  		if (fieldToMandatory == null) {
  			fieldToMandatory = [];
  			sys_dictionary_override[grOverride.name] = fieldToMandatory;
  		}
  		fieldToMandatory[grOverride.element] = grOverride.mandatory;
  	}
  },

  // serialize to json, return a string
  toJson : function (cis, map, labels, sys_dictionary_override) {
  	var it = cis.iterator();
  	var containsRelTypeId = getContainsRelTypeId();

  	var requiredAttributesEnabled = GlideProperties.getBoolean("glide.required.attribute.enabled", true);

  	var jsonResult = {};

  	while (it.hasNext()) {
  		var ci = it.next();

  		if (ci.getName().indexOf('$') > -1)
  			continue;
  		if (!map.hasOwnProperty(ci.getName()))
  			continue;

  		try {
  			jsonResult[ci.getName()] = {};
  			var ciEle = jsonResult[ci.getName()];

  			if (ci.getParent() !== null)
  				ciEle.__parent = ci.getParent().getName();
  			ciEle.label = GlideTableDescriptor.get(ci.getName()).getLabel() + '';

  			var parentCiType = getParentCiType(ci.getName(), containsRelTypeId);
  			if (GlideStringUtil.notNil(parentCiType))
  				ciEle.parentCiType = parentCiType;

  			var fields = map[ci.getName()];
  			if (fields != null) {
  				for (var i = 0; i < fields.length; i++) {
  					var field = fields[i];
  					//verify that there are np white spaces in the field names
  					if(field['name'].indexOf(' ') != -1)
  						continue;

  					try {
  						ciEle[field['name']] = {};
  						var fieldEle = ciEle[field['name']];

  						fieldEle.type = field['type'];
  						fieldEle.size = field['size'];

  						if (requiredAttributesEnabled) {
  							fieldEle.mandatory = field['mandatory'];
  							// If there is override on the mandatory flag then use it
  							var mandatoryOverride = sys_dictionary_override[ci.getName()];
  							if (mandatoryOverride != null && mandatoryOverride[field['name']] != null) {
  								fieldEle.mandatory = mandatoryOverride[field['name']];
  							}
  						} else {
  							fieldEle.mandatory = 0;
  						}

  						if (field['defaultValue'])
  							fieldEle.defaultValue = field['defaultValue'];

  					} catch (err) {
  						gs.log("PatternLibrary: Failed to create JSON element for field " + field['name'] + "." + err);
  					}
  				}
  			}
  			// Add fields from sys_dictionary override
  			var mandatoryOverride = sys_dictionary_override[ci.getName()];
  			if (mandatoryOverride != null) {
  				for (var fieldName in mandatoryOverride) {
  					fieldEle[fieldName] = {};
  					var fieldEle = ciEle[fieldName];

  					fieldEle.mandatory = mandatoryOverride[fieldName];
  				}
  			}
  		} catch (err) {
  			gs.log("PatternLibrary: Failed to create JSON element for CI type " + ci.getName() + "." + err);
  		}
  	}

  	return jsonResult;
  },

  // serialize to xml, return a document
  toXml : function(cis, map, labels,sys_dictionary_override) {
  	var it = cis.iterator();
  	var $ = GlideXMLUtil;
  	var doc = $.newDocument('cis');
  	var root = doc.getDocumentElement();
  	var containsRelTypeId = getContainsRelTypeId();

  	var requiredAttributesEnabled = GlideProperties.getBoolean("glide.required.attribute.enabled", true);

  	while (it.hasNext()) {
  		var ci = it.next();

  		//PRB718906: In case of reparenting the temporary backup table rep$... may be created
  		//This can cause exception because of unescaped character $
  		//This table does not represent CI type, so we will ignore it
  		if (ci.getName().indexOf('$') > -1)
  			continue;
  		try {
  			var ciEle = $.newElement(root, ci.getName());
  			if (ci.getParent() !== null)
  				ciEle.setAttribute('parent', ci.getParent().getName());
  			ciEle.setAttribute('label', GlideTableDescriptor.get(ci.getName()).getLabel());
  			// In case of Inclusion CI Type, setting the parent CI type based on
  			// cmdb_metadata_containment
  			var parentCiType = getParentCiType(ci.getName(), containsRelTypeId);
  			if (GlideStringUtil.notNil(parentCiType))
  				ciEle.setAttribute('parentCiType', parentCiType);
  			var fields = map[ci.getName()];
  			if (fields != null) {
  				for (var i = 0; i < fields.length; i++) {
  					var field = fields[i];
  					//verify that there are np white spaces in the field names
  					if(field['name'].indexOf(' ') != -1)
  						continue;

  					try {
  						var fieldEle = $.newElement(ciEle, field['name']);
  						fieldEle.setAttribute('type', field['type']);
  						fieldEle.setAttribute('size', field['size']);
  						if (requiredAttributesEnabled) {
  							fieldEle.setAttribute('mandatory', field['mandatory']);
  							// If there is override on the mandatory flag then use it
  							var mandatoryOverride = sys_dictionary_override[ci.getName()];
  							if (mandatoryOverride != null && mandatoryOverride[field['name']] != null) {
  								fieldEle.setAttribute('mandatory', mandatoryOverride[field['name']]);
  							}
  						} else {
  							fieldEle.setAttribute('mandatory', '0');
  						}
  						if (field['defaultValue'])
  							fieldEle.setAttribute('defaultValue', field['defaultValue']);

  					} catch (err) {
  						gs.log("PatternLibrary: Failed to create XML element for field " + field['name'] + "." + err);
  					}
  				}
  			}
  			// Add fields from sys_dictionary override
  			var mandatoryOverride = sys_dictionary_override[ci.getName()];
  			if (mandatoryOverride != null) {
  				for (var fieldName in mandatoryOverride) {
  					var fieldEle = $.newElement(ciEle, fieldName);
  					fieldEle.setAttribute('mandatory', mandatoryOverride[fieldName]);
  				}
  			}
  		} catch (err) {
  			gs.log("PatternLibrary: Failed to create XML element for CI type " + ci.getName() + "." + err);
  		}

  	}
  	return doc;
  },

  convertToJsArray : function(inputArr) {
  	var result = [];

  	var it = inputArr.iterator();
  	while(it.hasNext()) {
  		result.push(it.next());
  	}

  	return result;
  },

  // Notify MID Servers of changes in patterns
  notifyMIDs : function(patternName, action, optional) {
  	var message = "*** Discovery pattern " + patternName +" has changed (" + action + ")";
  	if (optional)
  		message = "*** Confirmation status for discovery pattern " + patternName +" has changed (" + action + ")"
  	+ ", Notifying MID Servers ***";

  	gs.log(message);
  	this.notification_handler.notifyMIDServers('FileChange', 'sa_pattern');
  },

  //This is invoked by legacy code
  getCiTypes: function() {
  	return this.getCiTypesXml();
  },

  // Notify MID Servers of changes in CI Types
  notifyMIDsCitChanged : function() {
  	gs.log('######  CIT changed  ######');
  	var ciTypesJson  = this.getCiTypesJson();
  	var deflatedStr;
  	try {
  		deflatedStr = this.ciTypesDeflator.deflateJsonAsString(ciTypesJson);
  	} catch(err) {
  		gs.log('##### Unable to deflate CI types while notifying mids #####');
  		deflatedStr = JSON.stringifiy(ciTypesJson);
  	}
  	this.notification_handler.notifyMIDServers('CitChanged',undefined,deflatedStr);
  },
  // Notify MID Servers of changes in Custom Operations
  notifyMIDsCustomOperationsChange : function() {
  	gs.log('######  Custom Operations changed  ######');
  	this.notification_handler.notifyMIDServers('CustomOperationChanged');
  },
  // Notify MID Servers of changes in Custom Parsing Strategy
  notifyMIDsCustomParsingStrategyChange : function() {
  	gs.log('######  Custom Parsing Strategy changed  ######');
  	this.notification_handler.notifyMIDServers('CustomParsingStrategyChanged');
  },
  // Notify MID Servers of changes in Metadata Rules
  notifyMIDsMetadataRulesChange : function() {
  	gs.log('######  Metadata Rules changed  ######');
  	this.notification_handler.notifyMIDServers('MetadataRulesChanged');
  },

  // Notify MID Servers of changes in Library Application Category
  notifyMIDsLibsApplCategoryChange : function() {
  	gs.log('######  Library Application Category changed  ######');
  	this.notification_handler.notifyMIDServers('LibsApplCategoryChanged');
  },

  // Notify MID Servers of changes in Device Info Application Category
  notifyMIDsLibsDeviceInfoCategoryChange : function() {
  	gs.log('######  Library Device Info Category changed  ######');
  	this.notification_handler.notifyMIDServers('LibsDeviceInfoCategoryChanged');
  },

  // Notify MID Servers of changes in Pattern Extension
  notifyMIDsPatternExtensionChanged: function() {
  	gs.log('######  Pattern Extension changed  ######');
  	this.notification_handler.notifyMIDServers('PatternExtensionChanged');
  },

  type: 'PatternLibrary'
};
function getParentCiType(ciType, relTypeId) {
  if (GlideStringUtil.nil(relTypeId))
  	return null;

  var gr = new GlideRecord('cmdb_metadata_containment');
  gr.addQuery('ci_type', ciType);
  gr.query();
  while(gr.next()) {
  	if (GlideStringUtil.nil(gr.getValue('parent_id'))) {
  		return getReversedContainmentParentCiType(gr.getValue('sys_id'), relTypeId);
  	} else if (gr.getValue('is_reverse') == '0') {
  		if (relTypeId.equals(gr.getValue('rel_type'))) {
  			var innerGr = new GlideRecord('cmdb_metadata_containment');
  			if (innerGr.get(gr.getValue('parent_id')))
  				return innerGr.getValue('ci_type');
  		}
  	}
  }

  return null;
}
function getContainsRelTypeId() {
  var relTypeGr = new GlideRecord('cmdb_rel_type');
  relTypeGr.addQuery('parent_descriptor','Contains');
  relTypeGr.query();
  if (!relTypeGr.next())
  	return null;

  return relTypeGr.getValue('sys_id');
}
function getReversedContainmentParentCiType(parentId, relTypeId) {
  var containerGr = new GlideRecord('cmdb_metadata_containment');
  containerGr.addQuery('parent_id', parentId);
  containerGr.addQuery('is_reverse', true);
  containerGr.addQuery('rel_type', relTypeId);
  containerGr.query();
  if (!containerGr.next()) {
  	return null;
  }

  return containerGr.getValue('ci_type');
}

Sys ID

5b0da736ef33210039a3b14341e42201

Offical Documentation

Official Docs: