package tudelft.healthpsychology.traumaontologies.answerstate;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.util.StdConverter;
import tudelft.healthpsychology.traumaontologies.questiontypes.TypedQuestion;
import tudelft.utilities.tree.Tree;
/**
* Handles the process in filling in the properties of an {@link OntologyNode}.
* The most accurate available {@link OntologyNode} was determined already. The
* process here is to get answers to all the questions relevant for such a node.
* Properties are picked up from the comment fields behind the given
* OntologyNode and its parents.
* immutable.
*
*/
public class PropertiesAnswerState implements AnswerState {
private final String nodelabel;
@JsonSerialize(converter = PropMapSerializer.class)
private final Map answers;
/**
*
* @param object the ontologynode class for which all properties need to be
* collected and answered.
* @param answers the already collected answers to the properties
*/
@JsonCreator
public PropertiesAnswerState(@JsonProperty("nodelabel") String objectlabel,
@JsonProperty("answers") @JsonDeserialize(converter = PropMapDeserializer.class) Map answers) {
this.nodelabel = objectlabel;
this.answers = answers;
}
/**
* Convenience constructor for initial state
*
* @param nodelabel the label of initial node
*/
@SuppressWarnings("unchecked")
public PropertiesAnswerState(String nodelabel) {
this(nodelabel, Collections.EMPTY_MAP);
}
@Override
public PropertiesAnswerState with(String answer,
Tree, OntologyNode> tree) {
Property property = getProperty(tree);
if (property == null)
return this;
if (!property.getQuestionType().fits(answer)) {
throw new IllegalArgumentException("The answer string must fit an "
+ property.getQuestionType());
}
Map newanswers = new HashMap(
answers);
newanswers.put(property, answer);
return new PropertiesAnswerState(nodelabel, newanswers);
}
/**
*
* @return the main node label for this object. Mainly for testing
*/
public String getNode() {
return nodelabel;
}
@Override
public TypedQuestion getOptions(
Tree, OntologyNode> tree) {
Property prop = getProperty(tree);
if (prop == null)
return null;
return prop.getQuestionType();
}
/**
*
* @return the answers given so far.
*/
public Map getAnswers() {
return answers;
}
/**
*
* @return the property to be answered, or null if no such property (all
* have been answered)
*/
private Property getProperty(
Tree, OntologyNode> tree) {
Set remaining = new HashSet<>(
tree.get(nodelabel).getAttribute());
remaining.removeAll(answers.keySet());
if (remaining.isEmpty()) {
return null;
}
return remaining.iterator().next();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((answers == null) ? 0 : answers.hashCode());
result = prime * result
+ ((nodelabel == null) ? 0 : nodelabel.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PropertiesAnswerState other = (PropertiesAnswerState) obj;
if (answers == null) {
if (other.answers != null)
return false;
} else if (!answers.equals(other.answers))
return false;
if (nodelabel == null) {
if (other.nodelabel != null)
return false;
} else if (!nodelabel.equals(other.nodelabel))
return false;
return true;
}
}
/****** serialization of key-value pair of Map **********/
class PropString {
@JsonProperty
private final Property prop;
@JsonProperty
private final String answer;
@JsonCreator
public PropString(@JsonProperty("prop") Property prop,
@JsonProperty("answer") String answer) {
this.prop = prop;
this.answer = answer;
}
public Property getProp() {
return prop;
}
public String getAnswer() {
return answer;
}
}
/**
* Custom serializer to map the Map into a List
*
*/
class PropMapSerializer
extends StdConverter