source: TraumaOntologies/src/main/java/tudelft/healthpsychology/traumaontologies/answerstate/AnswersBreathFirstState.java@ 5

Last change on this file since 5 was 5, checked in by Bart Vastenhouw, 5 years ago

Intermediate update

File size: 7.1 KB
Line 
1package tudelft.healthpsychology.traumaontologies.answerstate;
2
3import java.util.Collection;
4import java.util.HashMap;
5import java.util.LinkedList;
6import java.util.List;
7import java.util.Map;
8import java.util.Optional;
9
10import com.fasterxml.jackson.annotation.JsonCreator;
11import com.fasterxml.jackson.annotation.JsonProperty;
12
13import tudelft.healthpsychology.traumaontologies.questiontypes.Bool;
14import tudelft.healthpsychology.traumaontologies.questiontypes.TypedQuestion;
15import tudelft.utilities.tree.Tree;
16
17/**
18 * {@link #node} points to a type of object of which there may be multiple
19 * relevant instances , eg "Persoon". This keeps track of asking the user all
20 * details about all instances.
21 *
22 * So this contains the state of a set of answers for a given OntologyNode,
23 * handling breath first:
24 * <ol>
25 * <li>The top level node eg #Persoon contains a main question (with the name as
26 * indicated in the constructor).
27 *
28 * <li>We repeat asking for this main question until user says he has no more
29 * relevant items of this type (so no more relevant person)
30 *
31 * <li>for each item, we determine the best fitting ontology class and ask the
32 * questions for this class.
33 * </ol>
34 *
35 */
36public class AnswersBreathFirstState implements AnswerState {
37
38 private final String nodelabel; // root node that this answer is about
39 private final List<OntoPropAnswerState> answerstates;
40 // the main properties of the nodes.
41 // We keep asking for more of these as long as this is not null.
42 private final Property mainProperty;
43 private final boolean askForMore;
44 private final Bool morequestion;
45
46 /**
47 * Construct new state with a list of OntologyAnswerState, the last being
48 * possibly nonfinal If the last is final and askedForMore=true
49 *
50 * @param node the node label that this answer is about.
51 * @param answerstates the list of answer states about node/mainprop.
52 * @param mainprop the main question, eg the property related to "Naam".
53 * This is the property to be asked first. node must
54 * have a property with this question. If not null, the
55 * user wants to add a mainprop. If mainprop=null, it
56 * means the user does not want to add more items. This
57 * can be null only if answerstates contains at least 1
58 * item.
59 * @param askMore true if we need to ask {@link #MOREANSWER}. Can only
60 * be true if mainprop is not null. If false, we look at
61 * mainprop to see if we need to add more.
62 * @param morequestion the question to ask for more, eg "zijn er nog meer
63 * relevante personen?".
64 */
65 @JsonCreator
66 public AnswersBreathFirstState(@JsonProperty("nodelabel") String node,
67 @JsonProperty("answerstates") List<OntoPropAnswerState> answerstates,
68 @JsonProperty("mainProperty") Property mainprop,
69 @JsonProperty("askForMore") boolean askMore,
70 @JsonProperty("morequestion") Bool morequestion) {
71 if (answerstates.isEmpty() && mainprop == null) {
72 throw new IllegalArgumentException(
73 "mainprop must be not null if answerstates is empty");
74 }
75 if (askMore && mainprop == null) {
76 throw new IllegalArgumentException(
77 "If askForMore then mainprop must be not null");
78 }
79 this.nodelabel = node;
80 this.answerstates = answerstates;
81 this.mainProperty = mainprop;
82 this.askForMore = askMore;
83 this.morequestion = morequestion;
84 }
85
86 /**
87 * Convenience constructor : new state with one open OntologyAnswerState
88 *
89 * @param node the node that this answer is about.
90 * @param mainproperty the main question property, eg "Naam". This is the
91 * question of the property to be asked first. The node
92 * must have a property with this question.
93 * @param havemore the question to as if there are more items like this.
94 */
95 public AnswersBreathFirstState(OntologyNode node, String mainproperty,
96 String havemore) {
97 this(node.getLabel(), new LinkedList<>(),
98 getMainProp(node, mainproperty), false,
99 new Bool(havemore, "internal"));
100 }
101
102 @Override
103 public TypedQuestion getOptions(
104 Tree<String, Collection<Property>, OntologyNode> tree) {
105 if (askForMore) {
106 return morequestion;
107 }
108 if (mainProperty != null) {
109 return mainProperty.getQuestionType();
110 }
111
112 // now handle each one depth-first.
113 for (OntoPropAnswerState state : answerstates) {
114 TypedQuestion opts = state.getOptions(tree);
115 if (opts != null)
116 return opts;
117 }
118 return null;
119 }
120
121 @Override
122 public AnswersBreathFirstState with(String answer,
123 Tree<String, Collection<Property>, OntologyNode> tree) {
124 TypedQuestion opts = getOptions(tree);
125 if (opts == null)
126 return this;
127 if (!opts.fits(answer)) {
128 throw new IllegalArgumentException(
129 "Answer " + answer + " does not fit " + opts);
130 }
131 OntologyNode node = tree.get(nodelabel);
132 if (askForMore) {
133 /**
134 * question was MOREANSWER. Just handle the yes/no answer. if answer
135 * is no, set mainProperty to null
136 */
137 return new AnswersBreathFirstState(nodelabel, answerstates,
138 Bool.matchesYes(answer) ? mainProperty : null, false,
139 morequestion);
140
141 }
142 // askForMore may be true or false if we get here. Check mainproperty
143 if (mainProperty != null) {
144 /*
145 * User answered main question. Add new OntoPropAnswerState with the
146 * first answer already there . NOTICE we create node here with
147 * WRONG NODE (Typically "Persoon" ipv eg "Collega" // as we do not
148 * know the correct node type at this point
149 */
150 LinkedList<OntoPropAnswerState> newAnswerStates = new LinkedList<>(
151 answerstates);
152 Map<Property, String> answer1 = new HashMap<>();
153 answer1.put(mainProperty, answer);
154 PropertiesAnswerState firstAnswer = new PropertiesAnswerState(
155 nodelabel, answer1);
156 newAnswerStates.add(new OntoPropAnswerState(
157 new OntologyAnswerState(node, answer), firstAnswer));
158 return new AnswersBreathFirstState(nodelabel, newAnswerStates,
159 mainProperty, true, morequestion);
160 }
161
162 /*
163 * If we get here, mainProperty=null. We're done collecting the main
164 * properties. Continue depth first now on collected answerstates
165 */
166 int activeanswer = 0;
167 while (answerstates.get(activeanswer).getOptions(tree) == null)
168 activeanswer++;
169
170 LinkedList<OntoPropAnswerState> newAnswerStates = new LinkedList<>(
171 answerstates);
172 newAnswerStates.set(activeanswer,
173 answerstates.get(activeanswer).with(answer, tree));
174
175 return new AnswersBreathFirstState(nodelabel, newAnswerStates, null,
176 false, morequestion);
177 }
178
179 /**
180 *
181 * @param node
182 * @param mainquestion
183 * @return the {@link Property} of the node of which the ID equals to the
184 * given mainquestion.
185 */
186 private static Property getMainProp(OntologyNode node,
187 String mainquestion) {
188 Optional<Property> mainprop = node.getAttribute().stream().filter(
189 prop -> mainquestion.equals(prop.getQuestionType().getId()))
190 .findFirst();
191 if (!mainprop.isPresent()) {
192 throw new IllegalArgumentException("Node " + node
193 + " must have a property/attribute with the main question '"
194 + mainquestion + "'");
195 }
196 return mainprop.get();
197
198 }
199
200}
Note: See TracBrowser for help on using the repository browser.