Last active
August 18, 2020 14:41
-
-
Save ahuggins-nhs/e8c627c2827ac48fc3b0b49b2d46fd2e to your computer and use it in GitHub Desktop.
A field-to-property mapping utility
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class FieldMap { | |
/** | |
* @param {string} fieldName | |
* @param {string} propertyName | |
* @param {string} objectName | |
* @param {boolean} [active=false] | |
*/ | |
constructor (fieldName, propertyName, objectName, active = false) { | |
/** | |
* @private | |
* @type {string} | |
*/ | |
this._fieldName = fieldName | |
/** | |
* @private | |
* @type {string} | |
*/ | |
this._propertyName = propertyName | |
/** | |
* @private | |
* @type {string} | |
*/ | |
this._objectName = objectName | |
/** | |
* @private | |
* @type {boolean} | |
*/ | |
this._active = active | |
/** | |
* @private | |
* @type {boolean} | |
*/ | |
this.modified = false | |
} | |
/** @param {boolean} _active */ | |
set active (_active) { | |
if (this._active !== _active) { | |
this.modified = true | |
this._active = _active | |
} | |
} | |
/** @param {string} _fieldName */ | |
set fieldName (_fieldName) { | |
if (this._fieldName !== _fieldName) { | |
this.modified = true | |
this._fieldName = _fieldName | |
} | |
} | |
/** @param {string} _propertyName */ | |
set propertyName (_propertyName) { | |
if (this._propertyName !== _propertyName) { | |
this.modified = true | |
this._propertyName = _propertyName | |
} | |
} | |
/** Immutable property objectName. | |
* @param {string} _objectName | |
*/ | |
set objectName (_objectName) { | |
// Makes objectName immutable. | |
} | |
get active () { | |
return this._active | |
} | |
get fieldName () { | |
this.active = true | |
return this._fieldName | |
} | |
get propertyName () { | |
this.active = true | |
return this._propertyName | |
} | |
get objectName () { | |
this.active = true | |
return this._objectName | |
} | |
toJSON () { | |
return { | |
fieldName: this._fieldName, | |
propertyName: this._propertyName, | |
objectName: this._objectName, | |
active: this._active | |
} | |
} | |
toTableRow () { | |
return { | |
PartitionKey: this._objectName, | |
RowKey: this._fieldName + '::' + this._propertyName, | |
...this.toJSON() | |
} | |
} | |
} | |
class FieldMapper { | |
/** @param {Array<{ PartitionKey?: string, RowKey?: string, fieldName: string, propertyName: string, objectName: string, active: boolean }>} tableRows */ | |
constructor (tableRows = []) { | |
/** @type {Map<string, FieldMap>} */ | |
this.fields = new Map() | |
/** @type {Map<string, FieldMapper>} */ | |
this.mappers = new Map() | |
for (const tableRow of tableRows) { | |
this.setFieldMap(tableRow.fieldName, tableRow.propertyName, tableRow.objectName, tableRow.active) | |
} | |
this.isChild = false | |
} | |
/** | |
* @param {string} propertyName | |
* @returns {string} | |
*/ | |
getFieldName (propertyName) { | |
return this.fields.get(propertyName).fieldName | |
} | |
/** | |
* @param {string} fieldName | |
* @returns {string} | |
*/ | |
getPropertyName (fieldName) { | |
return this.fields.get(fieldName).propertyName | |
} | |
/** Get the field map instance for a field name or property name. | |
* @param {string} fieldNameOrPropertyName | |
* @returns {FieldMap} | |
*/ | |
getFieldMap (fieldNameOrPropertyName) { | |
return this.fields.get(fieldNameOrPropertyName) | |
} | |
/** Get a field mapper instance for a specific object name. | |
* @param {string} objectName | |
* @returns {FieldMapper} | |
*/ | |
getObjectMap (objectName) { | |
return this.mappers.get(objectName) | |
} | |
/** Method for creating and propagating field maps. | |
* @param {string} fieldName | |
* @param {string} propertyName | |
* @param {string} objectName | |
* @param {boolean} [active=false] | |
*/ | |
setFieldMap (fieldName, propertyName, objectName, active = false) { | |
// Short-circuit for child field maps. | |
if (objectName instanceof FieldMap) { | |
this.fields.set(fieldName, objectName) | |
this.fields.set(propertyName, objectName) | |
return | |
} else { | |
if (this.isChild) return | |
} | |
const field = new FieldMap(fieldName, propertyName, objectName, active) | |
this.fields.set(fieldName, field) | |
this.fields.set(propertyName, field) | |
let mapper = this.mappers.get(objectName) | |
if (!(mapper instanceof FieldMapper)) { | |
mapper = new FieldMapper() | |
mapper.isChild = true | |
this.mappers.set(objectName, mapper) | |
} | |
mapper.setFieldMap(fieldName, propertyName, field) | |
} | |
/** Get all modified field maps to table rows. | |
* @param {boolean} [allMaps=false] - Optionally get all field maps. | |
* @returns {Array<{ PartitionKey: string, RowKey: string, fieldName: string, propertyName: string, objectName: string, active: boolean }>} | |
*/ | |
toTableRows (allMaps = false) { | |
const tableRows = [] | |
if (this.isChild) { | |
// Create a set so that there are no duplicate fieldMap references. | |
const fieldMaps = new Set(this.fields.values()) | |
for (const fieldMap of fieldMaps) { | |
if (fieldMap.modified || allMaps) { | |
// Only create a table row if the data was modified. | |
tableRows.push(fieldMap.toTableRow()) | |
} | |
} | |
} else { | |
// Parent should get tablerows from children. | |
const objectMaps = new Set(this.mappers.values()) | |
for (const objectMap of objectMaps) { | |
tableRows.push(...objectMap.toTableRows(allMaps)) | |
} | |
} | |
return tableRows | |
} | |
} | |
module.exports = { | |
FieldMapper | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const test = new FieldMapper([{ fieldName: 'one', propertyName: 'two', objectName: 'three', active: false }]) | |
console.log('Internal map:', test.fields) | |
console.log('Internal map:', test.mappers) | |
console.log('Number of table rows before modification:', test.toTableRows().length) | |
console.log('Field map references are the same instance:', test.getFieldMap('one') === test.getFieldMap('two')) | |
console.log('JSON string of field map:', JSON.stringify(test.getFieldMap('two'))) | |
console.log('Get the field name of the property:', test.getFieldName('two')) // Makes the field map active and sets it to 'modified' | |
console.log('Number of table rows after modification:', test.toTableRows().length) // 1 | |
console.log('Field mapper by object name:', test.getObjectMap('three')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment