Skip to content

Commit

Permalink
lineage-manipulation refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
kennsippell committed Dec 9, 2024
1 parent 4ecf723 commit af9a9ac
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 73 deletions.
76 changes: 4 additions & 72 deletions src/lib/hierarchy-operations/lineage-manipulation.js
Original file line number Diff line number Diff line change
@@ -1,75 +1,4 @@

/**
* Given a doc, replace the lineage information therein with "replaceWith"
*
* @param {Object} doc A CouchDB document containing a hierarchy that needs replacing
* @param {Object} params SonarQube
* @param {Object} params.replaceWith The new hierarchy { parent: { _id: 'parent', parent: { _id: 'grandparent' } }
* @param {string} params.startingFromId Only the part of the lineage "after" this id will be replaced
* @param {boolean} params.merge When true, startingFromId is replaced and when false, startingFromId's parent is replaced
*/
function replaceLineage(doc, lineageAttributeName, params) {
const { replaceWith, startingFromId, merge } = params;

// Replace the full lineage
if (!startingFromId) {
return replaceEntireLineage(doc, lineageAttributeName, replaceWith);
}

function getInitialState() {
if (merge) {
return {
element: doc,
attributeName: lineageAttributeName,
};
}

return {
element: doc[lineageAttributeName],
attributeName: 'parent',
};
}

function traverseOne() {
const compare = merge ? state.element[state.attributeName] : state.element;
if (compare?._id === startingFromId) {
return replaceEntireLineage(state.element, state.attributeName, replaceWith);
}

state.element = state.element[state.attributeName];
state.attributeName = 'parent';
}

const state = getInitialState();
while (state.element) {
const result = traverseOne();
if (result) {
return result;
}
}

return false;
}

function replaceParentLineage(doc, params) {
return replaceLineage(doc, 'parent', params);
}

function replaceContactLineage(doc, params) {
return replaceLineage(doc, 'contact', params);
}

const replaceEntireLineage = (replaceInDoc, lineageAttributeName, replaceWith) => {
if (!replaceWith) {
const lineageWasDeleted = !!replaceInDoc[lineageAttributeName];
replaceInDoc[lineageAttributeName] = undefined;
return lineageWasDeleted;
} else {
replaceInDoc[lineageAttributeName] = replaceWith;
}

return true;
};
const { replaceContactLineage, replaceParentLineage } = require('./replace-lineage');

/*
Function borrowed from shared-lib/lineage
Expand All @@ -96,6 +25,9 @@ const minifyLineagesInDoc = doc => {

if ('contact' in doc) {
doc.contact = minifyLineage(doc.contact);
if (doc.contact && !doc.contact.parent) {
delete doc.contact.parent; // for unit test clarity
}
}

if (doc.type === 'data_record') {
Expand Down
77 changes: 77 additions & 0 deletions src/lib/hierarchy-operations/replace-lineage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
function replaceLineage(doc, lineageAttributeName, params) {
// Replace the full lineage
if (!params.startingFromId) {
return replaceEntireLineage(doc, lineageAttributeName, params.replaceWith);
}

const selectedFunction = params.merge ? replaceLineageForMerge : replaceLineageForMove;
return selectedFunction(doc, lineageAttributeName, params);
}

function replaceLineageForMove(doc, lineageAttributeName, params) {
let currentElement = doc[lineageAttributeName];
while (currentElement) {
if (currentElement?._id === params.startingFromId) {
return replaceEntireLineage(currentElement, 'parent', params.replaceWith);
}

currentElement = currentElement.parent;
}

return false;
}

function replaceLineageForMerge(doc, lineageAttributeName, params) {
let currentElement = doc;
let currentAttributeName = lineageAttributeName;
while (currentElement) {
if (currentElement[currentAttributeName]?._id === params.startingFromId) {
return replaceEntireLineage(currentElement, currentAttributeName, params.replaceWith);
}

currentElement = currentElement[currentAttributeName];
currentAttributeName = 'parent';
}

return false;
}

function replaceEntireLineage(replaceInDoc, lineageAttributeName, replaceWith) {
if (!replaceWith) {
const lineageWasDeleted = !!replaceInDoc[lineageAttributeName];
replaceInDoc[lineageAttributeName] = undefined;
return lineageWasDeleted;
} else {
replaceInDoc[lineageAttributeName] = replaceWith;
}

return true;
}

module.exports = {
/**
* Given a doc, replace the lineage information therein with "replaceWith"
*
* @param {Object} doc A CouchDB document containing a hierarchy that needs replacing
* @param {Object} params
* @param {Object} params.replaceWith The new hierarchy { parent: { _id: 'parent', parent: { _id: 'grandparent' } }
* @param {string} params.startingFromId Only the part of the lineage "after" this id will be replaced
* @param {boolean} params.merge When true, startingFromId is replaced and when false, startingFromId's parent is replaced
*/
replaceParentLineage: (doc, params) => {
return replaceLineage(doc, 'parent', params);
},

/**
* Given a doc, replace the lineage information therein with "replaceWith"
*
* @param {Object} doc A CouchDB document containing a hierarchy that needs replacing
* @param {Object} params
* @param {Object} params.replaceWith The new hierarchy { parent: { _id: 'parent', parent: { _id: 'grandparent' } }
* @param {string} params.startingFromId Only the part of the lineage "after" this id will be replaced
* @param {boolean} params.merge When true, startingFromId is replaced and when false, startingFromId's parent is replaced
*/
replaceContactLineage: (doc, params) => {
return replaceLineage(doc, 'contact', params);
},
};
1 change: 0 additions & 1 deletion test/lib/hierarchy-operations/hierarchy-operations.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,6 @@ describe('move-contacts', () => {
type: 'data_record',
contact: {
_id: 'dne',
parent: undefined,
},
fields: {
patient_uuid: 'district_1'
Expand Down

0 comments on commit af9a9ac

Please sign in to comment.