|
| 1 | +/** |
| 2 | + * DataNormalizer Script Include |
| 3 | + * ---------------------------------------------------------------- |
| 4 | + * Provides reusable utility functions to standardize and sanitize |
| 5 | + * common data fields such as names, emails, phone numbers, addresses, |
| 6 | + * and dates. Supports both server-side and client-side (GlideAjax) |
| 7 | + * for flexible integration across multiple modules. |
| 8 | + * ---------------------------------------------------------------- |
| 9 | + */ |
| 10 | + |
| 11 | +var DataNormalizer = Class.create(); |
| 12 | +DataNormalizer.prototype = Object.extendsObject(AbstractAjaxProcessor, { |
| 13 | + |
| 14 | + initialize: function() { |
| 15 | + this.debug = true; // Toggle debug logging |
| 16 | + }, |
| 17 | + |
| 18 | + /** |
| 19 | + * Logs structured error messages to system logs. |
| 20 | + * @param {String} method - Method name where the error occurred. |
| 21 | + * @param {Object} error - JavaScript error object. |
| 22 | + * @param {Object} [context] - Optional additional context data. |
| 23 | + */ |
| 24 | + logError: function(method, error, context) { |
| 25 | + gs.error('[DataNormalizer] Error in {0}: {1} | Context: {2}', |
| 26 | + method, error.message, JSON.stringify(context || {})); |
| 27 | + }, |
| 28 | + |
| 29 | + /** |
| 30 | + * Logs informational messages when debug mode is enabled. |
| 31 | + * @param {String} message - The message to log. |
| 32 | + */ |
| 33 | + logInfo: function(message) { |
| 34 | + if (this.debug) |
| 35 | + gs.info('[DataNormalizer] {0}', message); |
| 36 | + }, |
| 37 | + |
| 38 | + /** |
| 39 | + * Normalizes personal names by removing special characters |
| 40 | + * and applying proper case formatting. |
| 41 | + * Example: "JOHN DOE" → "John Doe" |
| 42 | + * |
| 43 | + * @param {String} name - Input name value. |
| 44 | + * @returns {String} - Normalized name. |
| 45 | + */ |
| 46 | + normalizeName: function(name) { |
| 47 | + try { |
| 48 | + if (!name) return ''; |
| 49 | + name = name.trim().replace(/[^a-zA-Z\s]/g, ''); |
| 50 | + var formatted = name.split(/\s+/) |
| 51 | + .map(function(w) { |
| 52 | + return w.charAt(0).toUpperCase() + w.slice(1).toLowerCase(); |
| 53 | + }) |
| 54 | + .join(' '); |
| 55 | + this.logInfo('normalizeName: "' + name + '" → "' + formatted + '"'); |
| 56 | + return formatted; |
| 57 | + } catch (e) { |
| 58 | + this.logError('normalizeName', e, { name: name }); |
| 59 | + return name; |
| 60 | + } |
| 61 | + }, |
| 62 | + |
| 63 | + /** |
| 64 | + * Normalizes email addresses by trimming whitespace, |
| 65 | + * converting to lowercase, and removing invalid characters. |
| 66 | + * |
| 67 | + * @param {String} email - Input email value. |
| 68 | + * @returns {String} - Normalized email. |
| 69 | + */ |
| 70 | + normalizeEmail: function(email) { |
| 71 | + try { |
| 72 | + if (!email) return ''; |
| 73 | + var clean = email.trim().toLowerCase().replace(/[,;]+/g, ''); |
| 74 | + this.logInfo('normalizeEmail: "' + email + '" → "' + clean + '"'); |
| 75 | + return clean; |
| 76 | + } catch (e) { |
| 77 | + this.logError('normalizeEmail', e, { email: email }); |
| 78 | + return email; |
| 79 | + } |
| 80 | + }, |
| 81 | + |
| 82 | + /** |
| 83 | + * Standardizes phone numbers by removing non-numeric characters |
| 84 | + * and adding country codes where applicable. |
| 85 | + * |
| 86 | + * @param {String} phone - Input phone number. |
| 87 | + * @param {String} [defaultCountryCode] - Optional default country code (e.g., "91"). |
| 88 | + * @returns {String} - Normalized phone number. |
| 89 | + */ |
| 90 | + normalizePhone: function(phone, defaultCountryCode) { |
| 91 | + try { |
| 92 | + if (!phone) return ''; |
| 93 | + var digits = phone.replace(/\D/g, ''); |
| 94 | + var result; |
| 95 | + |
| 96 | + if (digits.length == 10 && defaultCountryCode) |
| 97 | + result = '+' + defaultCountryCode + ' ' + digits; |
| 98 | + else if (digits.length > 10 && digits.startsWith('91')) |
| 99 | + result = '+' + digits.slice(0, 2) + ' ' + digits.slice(2); |
| 100 | + else |
| 101 | + result = '+' + digits; |
| 102 | + |
| 103 | + this.logInfo('normalizePhone: "' + phone + '" → "' + result + '"'); |
| 104 | + return result; |
| 105 | + } catch (e) { |
| 106 | + this.logError('normalizePhone', e, { phone: phone }); |
| 107 | + return phone; |
| 108 | + } |
| 109 | + }, |
| 110 | + |
| 111 | + /** |
| 112 | + * Cleans and formats postal addresses by removing excess spaces |
| 113 | + * and applying title case to each word. |
| 114 | + * |
| 115 | + * @param {String} address - Input address text. |
| 116 | + * @returns {String} - Normalized address. |
| 117 | + */ |
| 118 | + normalizeAddress: function(address) { |
| 119 | + try { |
| 120 | + if (!address) return ''; |
| 121 | + address = address.trim().replace(/\s{2,}/g, ' '); |
| 122 | + var result = address.split(' ') |
| 123 | + .map(function(w) { |
| 124 | + return w.charAt(0).toUpperCase() + w.slice(1).toLowerCase(); |
| 125 | + }) |
| 126 | + .join(' '); |
| 127 | + this.logInfo('normalizeAddress: "' + address + '" → "' + result + '"'); |
| 128 | + return result; |
| 129 | + } catch (e) { |
| 130 | + this.logError('normalizeAddress', e, { address: address }); |
| 131 | + return address; |
| 132 | + } |
| 133 | + }, |
| 134 | + |
| 135 | + /** |
| 136 | + * Converts date strings into system-standard display format |
| 137 | + * using GlideDateTime APIs. |
| 138 | + * |
| 139 | + * @param {String} dateStr - Input date string. |
| 140 | + * @returns {String} - Normalized date in display format. |
| 141 | + */ |
| 142 | + normalizeDate: function(dateStr) { |
| 143 | + try { |
| 144 | + if (!dateStr) return ''; |
| 145 | + var gdt = new GlideDateTime(dateStr); |
| 146 | + var formatted = gdt.getDate().getDisplayValue(); |
| 147 | + this.logInfo('normalizeDate: "' + dateStr + '" → "' + formatted + '"'); |
| 148 | + return formatted; |
| 149 | + } catch (e) { |
| 150 | + this.logError('normalizeDate', e, { date: dateStr }); |
| 151 | + return dateStr; |
| 152 | + } |
| 153 | + }, |
| 154 | + |
| 155 | + /** |
| 156 | + * Generic text cleanup. Removes invalid placeholders such as |
| 157 | + * 'N/A', '--', or empty values. |
| 158 | + * |
| 159 | + * @param {String} value - Input text value. |
| 160 | + * @returns {String} - Cleaned text. |
| 161 | + */ |
| 162 | + cleanValue: function(value) { |
| 163 | + try { |
| 164 | + if (!value) return ''; |
| 165 | + var cleaned = value.trim(); |
| 166 | + var invalid = ['n/a', 'none', 'na', '-', '--']; |
| 167 | + if (invalid.indexOf(cleaned.toLowerCase()) > -1) return ''; |
| 168 | + this.logInfo('cleanValue: "' + value + '" → "' + cleaned + '"'); |
| 169 | + return cleaned; |
| 170 | + } catch (e) { |
| 171 | + this.logError('cleanValue', e, { value: value }); |
| 172 | + return value; |
| 173 | + } |
| 174 | + }, |
| 175 | + |
| 176 | + /** |
| 177 | + * Dynamically detects field type and applies the corresponding |
| 178 | + * normalization method. |
| 179 | + * |
| 180 | + * @param {String} fieldName - The field name or label. |
| 181 | + * @param {String} value - The value to normalize. |
| 182 | + * @returns {String} - Normalized value. |
| 183 | + */ |
| 184 | + smartNormalize: function(fieldName, value) { |
| 185 | + try { |
| 186 | + if (!value) return ''; |
| 187 | + var field = fieldName.toLowerCase(); |
| 188 | + var result; |
| 189 | + |
| 190 | + if (field.indexOf('email') >= 0) |
| 191 | + result = this.normalizeEmail(value); |
| 192 | + else if (field.indexOf('phone') >= 0 || field.indexOf('mobile') >= 0) |
| 193 | + result = this.normalizePhone(value, '91'); |
| 194 | + else if (field.indexOf('name') >= 0) |
| 195 | + result = this.normalizeName(value); |
| 196 | + else if (field.indexOf('address') >= 0) |
| 197 | + result = this.normalizeAddress(value); |
| 198 | + else if (field.indexOf('date') >= 0) |
| 199 | + result = this.normalizeDate(value); |
| 200 | + else |
| 201 | + result = this.cleanValue(value); |
| 202 | + |
| 203 | + this.logInfo('smartNormalize: Field=' + fieldName + ', Result=' + result); |
| 204 | + return result; |
| 205 | + } catch (e) { |
| 206 | + this.logError('smartNormalize', e, { fieldName: fieldName, value: value }); |
| 207 | + return value; |
| 208 | + } |
| 209 | + }, |
| 210 | + |
| 211 | + /** |
| 212 | + * Client-callable method exposed via GlideAjax. |
| 213 | + * Accepts parameters from client scripts and returns |
| 214 | + * normalized values synchronously. |
| 215 | + * |
| 216 | + * @returns {String} - Normalized value for client-side use. |
| 217 | + */ |
| 218 | + normalizeFromClient: function() { |
| 219 | + try { |
| 220 | + var field = this.getParameter('sysparm_fieldName'); |
| 221 | + var value = this.getParameter('sysparm_value'); |
| 222 | + var normalized = this.smartNormalize(field, value); |
| 223 | + return normalized; |
| 224 | + } catch (e) { |
| 225 | + this.logError('normalizeFromClient', e, { field: field, value: value }); |
| 226 | + return value; |
| 227 | + } |
| 228 | + }, |
| 229 | + |
| 230 | + type: 'DataNormalizer' |
| 231 | +}); |
0 commit comments