package tudelft.healthpsychology.traumaontologies.answerstate; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import tudelft.healthpsychology.traumaontologies.questiontypes.TypedQuestion; import tudelft.utilities.tree.Tree; /** * Contains a answer to an ontology node: both the {@link OntologyAnswerState} * and the {@link PropertiesAnswerState}. The answerstate can be partial, eg the * OntologyAnswerState or PropertiesAnswerState may be not yet complete. *

* The node state has 2 main phases: 1. ontologyState is not final (has open * options). then this is the next question to be asked. 2. ontologyState is * final. Thus, he most accurate ontology node matching the user's idea is * available. All questions pertinent to that node are asked. *

* Special substitutions are done on elements of the form [XXX] where XXX is * some word string. If XXX is some property for which a value was already * collected in the {@link #propertiesState}, then the [XXX] is replaced with * that value. */ public class OntoPropAnswerState implements AnswerState { private final OntologyAnswerState ontologyState; private final PropertiesAnswerState propertiesState; /** * @param ontoState the state of the ontology question node. * @param propState the OntologyProperties state. Can (but does not need to * ) be null while ontoState has options (is not final) */ @JsonCreator public OntoPropAnswerState( @JsonProperty("ontologyState") OntologyAnswerState ontoState, @JsonProperty("propertiesState") PropertiesAnswerState propState) { this.ontologyState = ontoState; this.propertiesState = propState; } /** * Convenience constructor that starts with a ontology node * * @param node the {@link OntologyNode} to start at. * @pram nameOfObject a name of the object, to make the question to the user * more specific which is especially relevant if this is part of a * breath-first and the user entered some name or so some time before. * If null, "het" ("it") is used. */ public OntoPropAnswerState(OntologyNode node, String nameOfObject) { this(new OntologyAnswerState(node, nameOfObject), null); } /** * * @return current {@link OntologyAnswerState} */ public OntologyAnswerState getOntologyAnswer() { return ontologyState; } /** * * @return current properties answer state, or null if the ontology answer * has not been answered yet. */ public PropertiesAnswerState getPropertyAnswer() { return propertiesState; } @Override public TypedQuestion getOptions( Tree, OntologyNode> tree) { TypedQuestion options = ontologyState.getOptions(tree); if (options == null) { options = propertiesState.getOptions(tree); } if (options == null) return null; return options.substitute(getSubstitutions()); } @Override public OntoPropAnswerState with(String answer, Tree, OntologyNode> tree) { TypedQuestion ontoOptions = ontologyState.getOptions(tree); if (ontoOptions != null) { if (!ontoOptions.fits(answer)) { throw new IllegalArgumentException( "answer " + answer + " does not fit " + ontoOptions); } OntologyAnswerState newOntoState = ontologyState.with(answer, tree); PropertiesAnswerState newPropState = propertiesState; if (newOntoState.getOptions(tree) == null) { // onto is final, set up the prop state. if (propertiesState == null) { newPropState = new PropertiesAnswerState( newOntoState.getNode()); } else { // we already had prop answers, keep them. newPropState = new PropertiesAnswerState( newOntoState.getNode(), propertiesState.getAnswers()); } } return new OntoPropAnswerState(newOntoState, newPropState); } // if we get here, the ontostate is final and prop state has been set TypedQuestion propOptions = propertiesState.getOptions(tree); if (propOptions != null) { if (!propOptions.fits(answer)) { throw new IllegalArgumentException( "answer " + answer + " does not fit " + propOptions); } return new OntoPropAnswerState(ontologyState, propertiesState.with(answer, tree)); } // both already final so this is a final state. return this; } /** * * @return substitution list based on the answers provided so far. For * example if we collected the answer "Jaap" as an answer for a node * labeled "Naam", we add a substitution "[Naam]"/"Jaap". */ private Map getSubstitutions() { if (propertiesState == null) return Collections.emptyMap(); Map props = propertiesState.getAnswers(); Map substis = new HashMap<>(); for (Property prop : props.keySet()) { substis.put("\\[" + prop.getQuestionType().getId() + "\\]", props.get(prop)); } return substis; } }