Skip to content

Commit 9e345c2

Browse files
committed
BROWSE-402 Display expression for Object property axioms
1 parent 52f27b3 commit 9e345c2

File tree

3 files changed

+99
-37
lines changed

3 files changed

+99
-37
lines changed

i18n/Languages.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ i18n_expression_text2 = SNOMED CT Compositional Grammar is a lightweight syntax
125125
i18n_expression_text3 = These expressions are generated as an example from the published concept definition, a Pre-coordinated Expression is direct reference to the concept, and Post-coordinated expressions are generated from the stated or inferred relationships. In a Sufficiently Defined concept, all three will be equivalent
126126
i18n_conceptId = Concept Id
127127
i18n_concept_not_found = Concept not found
128+
i18n_other_expressions = Other Expressions
128129

129130
# Taxonomy panel
130131
i18n_reset = Reset

snomed-interaction-components/js/conceptExpressions.js

Lines changed: 91 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -98,40 +98,45 @@ var conceptToPostCoordinatedExpression = function(concept, relsProperty, div, op
9898
};
9999

100100
function formatOwlAxiomExpression (owlExpression, conceptsMap) {
101-
var text = owlExpression;
101+
var lines = getLines(owlExpression);
102102

103-
// Add new line char
103+
// Add tab char
104+
var tabCount = 0;
105+
for (var i = 0 ; i < lines.length; i++) {
106+
lines[i] = lines[i].trim();
107+
if (lines[i].indexOf(')') !== -1) {
108+
tabCount--;
109+
}
110+
if (i !== 0 && tabCount > 0) {
111+
for (var j = 0 ; j < tabCount; j++) {
112+
lines[i] = '\t' + lines[i];
113+
}
114+
}
115+
if (lines[i].indexOf('(') !== -1) {
116+
tabCount++;
117+
}
118+
119+
// Fill FSN
120+
lines[i] = fillConceptFSN(lines[i], conceptsMap);
121+
}
122+
return lines.join('\n');
123+
}
124+
125+
function addTabToLine(line, tabCount) {}
126+
127+
function getLines(text) {
104128
text = text.replace(/\(/g, "(\n");
105129
text = text.replace(/\)/g, "\n)\n");
106130
text = text.replace(/(:\d*)\s/g, "$&\n");
107131
text = text.replace(/(:roleGroup)\s/g, "$&\n");
108132

109-
var textArr = text.split("\n");
110-
textArr = textArr.filter(function (el) {
133+
var lines = text.split("\n");
134+
lines = lines.filter(function (el) {
111135
el = el.trim();
112136
return el != '';
113137
});
114138

115-
// Add tab char
116-
var tabCount = 0;
117-
for (var i = 0 ; i < textArr.length; i++) {
118-
textArr[i] = textArr[i].trim();
119-
if (textArr[i].indexOf(')') !== -1) {
120-
tabCount--;
121-
}
122-
if (i !== 0 && tabCount > 0) {
123-
for (var j = 0 ; j < tabCount; j++) {
124-
textArr[i] = '\t' + textArr[i];
125-
}
126-
}
127-
if (textArr[i].indexOf('(') !== -1) {
128-
tabCount++;
129-
}
130-
131-
// Fill FSN
132-
textArr[i] = fillConceptFSN(textArr[i], conceptsMap);
133-
}
134-
return textArr.join('\n');
139+
return lines;
135140
}
136141

137142
function fillConceptFSN (text, conceptsMap) {
@@ -153,8 +158,28 @@ function fillConceptFSN (text, conceptsMap) {
153158
}
154159
}
155160

156-
function renderExpressionForAxioms (concept, members, classAxiomOwlExpressions, gciAxiomOwlExpressions) {
157-
var owlAxiomExpressions = {};
161+
function getConceptIdsFromOwlExpresstion(owlExpression) {
162+
var lines = getLines(owlExpression);
163+
var conceptIds = [];
164+
for (var i = 0 ; i < lines.length; i++) {
165+
var line = lines[i].trim();
166+
const match = /(^:\d*)/g;
167+
if (match.test(line)) {
168+
conceptIds.push(line.substring(1,line.length));
169+
}
170+
}
171+
return conceptIds;
172+
}
173+
174+
function renderExpressionForAxioms (concept, members, classAxiomOwlExpressions, gciAxiomOwlExpressions, otherOwlExpressions) {
175+
Handlebars.registerHelper('if_gr', function(a, b, opts) {
176+
if (a > b)
177+
return opts.fn(this);
178+
else
179+
return opts.inverse(this);
180+
});
181+
182+
var owlAxiomExpressions = {};
158183

159184
members.forEach(function(item) {
160185
if (item.additionalFields.hasOwnProperty('owlExpression')) {
@@ -195,21 +220,30 @@ function renderExpressionForAxioms (concept, members, classAxiomOwlExpressions,
195220
owlAxiomExpression[key] = formatOwlAxiomExpression(owlAxiomExpressions[key], conceptsMap);
196221
}
197222

223+
var inUseOwlExpressionIds = [];
198224
if(concept.classAxioms && concept.classAxioms.length !== 0) {
199225
concept.classAxioms.forEach(function(classAxiom){
200226
if (owlAxiomExpression.hasOwnProperty(classAxiom.axiomId)) {
201227
classAxiomOwlExpressions.push(owlAxiomExpression[classAxiom.axiomId]);
228+
inUseOwlExpressionIds.push(classAxiom.axiomId);
202229
}
203230
});
204231
}
205232

206233
if(concept.gciAxioms && concept.gciAxioms.length !== 0) {
207-
concept.gciAxioms.forEach(function(classAxiom){
208-
if (owlAxiomExpression.hasOwnProperty(classAxiom.axiomId)) {
209-
gciAxiomOwlExpressions.push(owlAxiomExpression[classAxiom.axiomId]);
234+
concept.gciAxioms.forEach(function(gciAxiom){
235+
if (owlAxiomExpression.hasOwnProperty(gciAxiom.axiomId)) {
236+
gciAxiomOwlExpressions.push(owlAxiomExpression[gciAxiom.axiomId]);
237+
inUseOwlExpressionIds.push(gciAxiom.axiomId);
210238
}
211239
});
212240
}
241+
242+
for (var key in owlAxiomExpressions) {
243+
if (!inUseOwlExpressionIds.includes(key)) {
244+
otherOwlExpressions.push(owlAxiomExpressions[key]);
245+
}
246+
}
213247
}
214248

215249
var renderExpression = function(concept, inferredConcept, div, options) {
@@ -219,14 +253,15 @@ var renderExpression = function(concept, inferredConcept, div, options) {
219253
var plainPreCoordinatedExpression = tmp.textContent || tmp.innerText || "";
220254
plainPreCoordinatedExpression = plainPreCoordinatedExpression.replace(/\s\s+/g, ' ');
221255

222-
if((concept.classAxioms && concept.classAxioms.length !== 0) || concept.gciAxioms && concept.gciAxioms.length !== 0) {
256+
if((concept.classAxioms && concept.classAxioms.length !== 0) || (concept.gciAxioms && concept.gciAxioms.length !== 0)) {
223257

224258
$.getJSON(options.serverUrl + "/" + options.edition + "/" + ((options.release && options.release !== 'None') ? options.release + '/': '') + "members?referencedComponentId=" + concept.conceptId + '&active=true', function(result) {
225259
}).done(function(result) {
226260
var classAxiomOwlExpressions = [];
227-
var gciAxiomOwlExpressions = [];
261+
var gciAxiomOwlExpressions = [];
262+
var otherOwlExpressions = [];
228263
if (result.total > 0) {
229-
renderExpressionForAxioms (concept, result.items, classAxiomOwlExpressions, gciAxiomOwlExpressions)
264+
renderExpressionForAxioms (concept, result.items, classAxiomOwlExpressions, gciAxiomOwlExpressions, otherOwlExpressions)
230265
}
231266

232267
var inferredHtml = conceptToPostCoordinatedExpression(concept, "relationships", div, options);
@@ -243,17 +278,36 @@ var renderExpression = function(concept, inferredConcept, div, options) {
243278
plainPreCoordinatedExpression: plainPreCoordinatedExpression,
244279
plainStatedExpression: plainStatedExpression,
245280
classAxiomOwlExpressions: classAxiomOwlExpressions,
281+
otherOwlExpressions: otherOwlExpressions,
246282
gciAxiomOwlExpressions: gciAxiomOwlExpressions,
247283
plainInferredExpression: plainInferredExpression
248284
};
249-
div.html(JST["snomed-interaction-components/views/conceptDetailsPlugin/tabs/expression.hbs"](context).trim());
285+
if (otherOwlExpressions.length !== 0) {
286+
var conceptIds = [];
287+
otherOwlExpressions.forEach(function(expression) {
288+
conceptIds = conceptIds.concat(getConceptIdsFromOwlExpresstion(expression));
289+
});
290+
291+
$.getJSON(options.serverUrl + "/" + options.edition + "/" + ((options.release && options.release !== 'None') ? options.release + '/': '') + "concepts?conceptIds=" + conceptIds.join(','), function(result) {
292+
}).done(function(result) {
293+
var conceptsMap = {};
294+
if (result && result.items) {
295+
result.items.forEach(function(item) {
296+
conceptsMap[item.conceptId] = item.fsn.term;
297+
});
298+
}
299+
for (var i = 0; i < otherOwlExpressions.length; i++) {
300+
otherOwlExpressions[i] = formatOwlAxiomExpression(otherOwlExpressions[i], conceptsMap);
301+
}
302+
div.html(JST["snomed-interaction-components/views/conceptDetailsPlugin/tabs/expression.hbs"](context).trim());
303+
});
304+
} else {
305+
div.html(JST["snomed-interaction-components/views/conceptDetailsPlugin/tabs/expression.hbs"](context).trim());
306+
}
250307

251308
if (panel.clipboard) panel.clipboard.destroy();
252309
panel.clipboard = new Clipboard('.clip-btn-exp');
253-
panel.clipboard.on('success', function(e) {
254-
// console.info('Action:', e.action);
255-
// console.info('Text:', e.text);
256-
// console.info('Trigger:', e.trigger);
310+
panel.clipboard.on('success', function(e) {
257311
alertEvent("Copied!", "info");
258312
e.clearSelection();
259313
});

snomed-interaction-components/views/conceptDetailsPlugin/tabs/expression.hbs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@
2222
<p class="" style="margin-top: 20px;"><span class='i18n' data-i18n-id='i18n_expression_inferred_concept_definition'>{{i18n "i18n_expression_inferred_concept_definition" "Expression from Inferred Concept Definition"}}</span> (*)&nbsp;&nbsp;&nbsp;&nbsp;<small><i class="glyphicon glyphicon-export clip-btn-exp" id="{{divElementId}}-copy-inferred-expression" data-clipboard-text="{{plainInferredExpression}}"></i></small></p>
2323
<div class="expression-code" style="margin-top: 10px; padding: 10px;">{{{inferredExpressionHtml}}}</div>
2424
<br><br>
25+
26+
{{#if_gr otherOwlExpressions.length 0}}
27+
<p class=""><span class='i18n' data-i18n-id='i18n_other_expressions'>{{i18n "i18n_other_expressions" "Other Expressions"}}</span> (*)</p>
28+
{{#each otherOwlExpressions}}
29+
<div class="expression-code" style="margin-top: 10px; padding: 10px;"><pre>{{this}}</pre></div>
30+
{{/each}}
31+
{{/if_gr}}
2532
<div class="well small">
2633
<p>(*) <span class='i18n' data-i18n-id='i18n_expression_text1'>{{i18n "i18n_expression_text1" "The expressions are generated according to the ABNF syntax found in the \"SNOMED CT Compositional Grammar Specification and Guide\""}}</span> (<a href="http://snomed.org/compgrammar" target="_blank">http://snomed.org/compgrammar</a>)</p>
2734
<p><span class='i18n' data-i18n-id='i18n_expression_text2'>{{i18n "i18n_expression_text2" "SNOMED CT Compositional Grammar is a lightweight syntax for the representation of SNOMED CT expressions. SNOMED CT expressions are used in Electronic Health Records (EHRs) to represent clinical meanings in a way that enables automatic interpretation. They are also carried in messages, used to define precoordinated concepts and used to represent links between SNOMED CT and other terminologies"}}</span>.</p>

0 commit comments

Comments
 (0)