Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CARDS-1904 / CARDS-1937 #1199

Draft
wants to merge 7 commits into
base: dev
Choose a base branch
from
6 changes: 4 additions & 2 deletions modules/data-entry/src/main/features/feature.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@
"service.ranking:Integer":150,
"scripts":[
"create path (cards:dataQuery) /query \n\n # Allow all users to query; the actual results will obey their access rights \n set ACL for everyone \n allow jcr:read on /query \n end \n\n create path (cards:QuestionnairesHomepage) /Questionnaires \n create path (cards:FormsHomepage) /Forms \n create path (cards:QueryCacheHomepage) /QueryCache \n create path (cards:SubjectsHomepage) /Subjects \n create path (cards:SubjectTypesHomepage) /SubjectTypes ",
"create service user cards-answer-editor \n set ACL on /Questionnaires \n allow jcr:read for cards-answer-editor \n end"
"create service user cards-answer-editor \n set ACL on /Questionnaires \n allow jcr:read for cards-answer-editor \n end",
"create service user cards-reference-answer-editor \n set ACL for cards-reference-answer-editor \n allow jcr:read,rep:write,jcr:versionManagement on /Questionnaires,/Forms \n end"
]
},
"org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended~cards-data-entry":{
Expand All @@ -80,7 +81,8 @@
"io.uhndata.cards.data-model-forms-impl:computedAnswers=[cards-answer-editor]",
"io.uhndata.cards.data-model-forms-impl:referenceAnswers=[cards-answer-editor]",
"io.uhndata.cards.data-model-forms-impl:maxFormsOfTypePerSubjectValidator=[sling-readall]",
"io.uhndata.cards.data-model-forms-impl:requiredSubjectTypesValidator=[sling-readall]"
"io.uhndata.cards.data-model-forms-impl:requiredSubjectTypesValidator=[sling-readall]",
"io.uhndata.cards.data-model-forms-impl:referenceAnswersChangedListener=[cards-reference-answer-editor]"
]
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,11 @@ default String evaluate(Node question, Map<String, Object> values)
* expression has unmet dependencies or the actual evaluation result cannot be converted to the desired type
*/
Object evaluate(Node question, Map<String, Object> values, Type<?> type);

/**
*
* @param question the question node
* @return list of all the questions names that is used to compute an answer
*/
Set<String> getQuestionsNames(Node question);
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.uhndata.cards.forms.api.FormUtils;
import io.uhndata.cards.forms.api.QuestionnaireUtils;
Expand All @@ -48,6 +49,7 @@
*/
public abstract class AnswersEditor extends DefaultEditor
{
private static final Logger LOGGER = LoggerFactory.getLogger(AnswersEditor.class);
// This holds the builder for the current node. The methods called for editing specific properties don't receive the
// actual parent node of those properties, so we must manually keep track of the current node.
protected final NodeBuilder currentNodeBuilder;
Expand Down Expand Up @@ -154,6 +156,16 @@ protected Node getQuestionnaire()
}
}

protected Node getForm()
{
final String formId = this.currentNodeBuilder.getProperty("jcr:uuid").getValue(Type.STRING);
try {
return this.serviceSession.getNodeByIdentifier(formId);
} catch (RepositoryException e) {
return null;
}
}

// Returns a QuestionTree if any children of this node contains an unanswered matching question, else null
protected QuestionTree getUnansweredMatchingQuestions(final Node currentNode)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ private void computeAnswer(final Map.Entry<Node, NodeBuilder> entry,
@SuppressWarnings("unchecked")
Type<Object> untypedResultType = (Type<Object>) resultType;
answer.setProperty(FormUtils.VALUE_PROPERTY, result, untypedResultType);
Set<String> computedFromQuestionPaths =
getQuestionPathsFromNames(this.expressionUtils.getQuestionsNames(question));
answer.setProperty("computedFrom", computedFromQuestionPaths, Type.STRINGS);
}
// Update the computed value in the map of existing answers
String questionName = this.questionnaireUtils.getQuestionName(question);
Expand All @@ -186,6 +189,23 @@ private void computeAnswer(final Map.Entry<Node, NodeBuilder> entry,
}
}

private Set<String> getQuestionPathsFromNames(final Set<String> names)
{
Set<String> paths = new HashSet<>();
Node formNode = getForm();
Node questionnaire = getQuestionnaire();
try {
for (String computedFromQuestionName : names) {
Node questionNode = this.questionnaireUtils.getQuestion(questionnaire, computedFromQuestionName);
Node changingAnswer = this.formUtils.getAnswer(formNode, questionNode);
paths.add(changingAnswer.getPath());
}
} catch (RepositoryException e) {
LOGGER.error("Error getting path of question. " + e.getMessage());
}
return paths;
}

private List<String> sortDependencies(final Map<String, Set<String>> computedAnswerDependencies)
{
final List<String> result = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

Expand Down Expand Up @@ -90,6 +91,43 @@ public Object evaluate(final Node question, final Map<String, Object> values, fi
return null;
}

@Override
public Set<String> getQuestionsNames(Node question)
{
return expressionInputs(getExpressionFromQuestion(question));
}

private Set<String> expressionInputs(final String expression)
{
String expr = expression;

Set<String> questionNames = new HashSet<>();

int start = expr.indexOf(START_MARKER);
int end = expr.indexOf(END_MARKER, start);

while (start > -1 && end > -1) {
int defaultStart = expr.indexOf(DEFAULT_MARKER, start);
boolean hasDefault = defaultStart > -1 && defaultStart < end;

String questionName;
if (hasDefault) {
questionName = expr.substring(start + START_MARKER.length(), defaultStart);
} else {
questionName = expr.substring(start + START_MARKER.length(), end);
}

questionNames.add(questionName);

// Remove the start and end tags
expr = expr.substring(0, start) + questionName + expr.substring(end + END_MARKER.length());

start = expr.indexOf(START_MARKER);
end = expr.indexOf(END_MARKER, start);
}
return questionNames;
}

private ExpressionUtilsImpl.ParsedExpression parseExpressionInputs(final String expression,
final Map<String, Object> values)
{
Expand Down
Loading