Skip to content

Commit

Permalink
feat: label object for input number unit
Browse files Browse the repository at this point in the history
  • Loading branch information
nsenave committed Aug 12, 2024
1 parent 2cb2f19 commit ee053e1
Show file tree
Hide file tree
Showing 7 changed files with 386 additions and 9 deletions.
42 changes: 42 additions & 0 deletions src/main/java/fr/insee/lunatic/conversion/UnitDeserializer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package fr.insee.lunatic.conversion;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import fr.insee.lunatic.model.flat.InputNumber.Unit;
import fr.insee.lunatic.model.flat.LabelType;
import fr.insee.lunatic.model.flat.LabelTypeEnum;

import java.io.IOException;

public class UnitDeserializer extends StdDeserializer<Unit> {

public UnitDeserializer() {
super(Unit.class);
}
protected UnitDeserializer(Class<Unit> unitClass) {
super(unitClass);
}

@Override
public Unit deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException {
JsonNode unitNode = jsonParser.getCodec().readTree(jsonParser);
if (unitNode.isTextual()) {
Unit unit = new Unit();
unit.setValue(unitNode.textValue());
return unit;
}
if (unitNode.isObject()) {
Unit unit = new Unit();
LabelType label = new LabelType();
label.setValue(unitNode.get("value").textValue());
label.setType(LabelTypeEnum.fromValue(unitNode.get("type").textValue()));
unit.setLabel(label);
return unit;
}
return null;
}

}
46 changes: 46 additions & 0 deletions src/main/java/fr/insee/lunatic/conversion/UnitSerializer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package fr.insee.lunatic.conversion;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import fr.insee.lunatic.model.flat.InputNumber.Unit;

import java.io.IOException;

public class UnitSerializer extends StdSerializer<Unit> {

public UnitSerializer() {
super(Unit.class);
}
protected UnitSerializer(Class<Unit> unitClass) {
super(unitClass);
}

@Override
public void serialize(Unit unit, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
if (unit.getLabel() != null){
serializeLabel(unit, jsonGenerator);
return;
}
if (unit.getValue() != null) {
serializeString(unit, jsonGenerator);
return;
}
jsonGenerator.writeNull();
}

private void serializeString(Unit unit, JsonGenerator jsonGenerator) throws IOException {
jsonGenerator.writeString(unit.getValue());
}

private void serializeLabel(Unit unit, JsonGenerator jsonGenerator) throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeFieldName("value");
jsonGenerator.writeString(unit.getLabel().getValue());
jsonGenerator.writeFieldName("type");
jsonGenerator.writeString(unit.getLabel().getType().value());
jsonGenerator.writeEndObject();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
@JsonSubTypes.Type(value = Roundabout.class, name = "Roundabout"),
@JsonSubTypes.Type(value = Table.class, name = "Table"),
@JsonSubTypes.Type(value = Input.class, name = "Input"),
@JsonSubTypes.Type(value = InputNumber.class, name = "InputNumber"),
@JsonSubTypes.Type(value = PairwiseLinks.class, name = "PairwiseLinks"),
@JsonSubTypes.Type(value = Datepicker.class, name = "Datepicker"),
@JsonSubTypes.Type(value = Duration.class, name = "Duration"),
Expand Down
94 changes: 85 additions & 9 deletions src/main/java/fr/insee/lunatic/model/flat/InputNumber.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,98 @@
package fr.insee.lunatic.model.flat;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import fr.insee.lunatic.conversion.UnitDeserializer;
import fr.insee.lunatic.conversion.UnitSerializer;
import lombok.Getter;
import lombok.Setter;

import java.math.BigInteger;

@Getter
@Setter
public class InputNumber
extends ComponentType
implements ComponentSimpleResponseType
{
/**
* Response component to collect numeric data.
*/
public class InputNumber extends ComponentType implements ComponentSimpleResponseType {

protected String unit;
@JsonProperty(required = true)
protected ResponseType response;
public InputNumber() {
super();
this.componentType = ComponentTypeEnum.INPUT_NUMBER;
}

/**
* Wrapper class for the unit property to ensure backward compatibility in serialization/deserialization.
*/
@JsonSerialize(using = UnitSerializer.class)
@JsonDeserialize(using = UnitDeserializer.class)
@Getter
@Setter
public static class Unit {
private String value;
private LabelType label;
}

/** Minimum value allowed. */
@Getter @Setter
protected Double min;

/** Maximum value allowed. */
@Getter @Setter
protected Double max;

/** Number of decimals allowed. null is equivalent to zero. */
@Getter @Setter
protected BigInteger decimals;

/** Unit of the numeric response. */
protected Unit unit;

@JsonProperty("unit")
public Unit getUnitWrapper() {
return unit;
}

@JsonProperty("unit")
public void setUnit(Unit unit) {
this.unit = unit;
}

/** Legacy unit string property.
* @deprecated Use label unit. */
@JsonIgnore
@Deprecated(since = "3.14.0")
public String getUnit() {
if (unit == null)
return null;
return unit.getValue();
}

@JsonIgnore
public LabelType getUnitLabel() {
if (unit == null)
return null;
return unit.getLabel();
}

/** Legacy unit string property.
* @deprecated Use label unit. */
@JsonIgnore
@Deprecated(since = "3.14.0")
public void setUnit(String value) {
unit = new Unit();
unit.setValue(value);
}

@JsonIgnore
public void setUnit(LabelType labelType) {
unit = new Unit();
unit.setLabel(labelType);
}

/** {@link ResponseType} */
@Getter @Setter
@JsonProperty(required = true)
protected ResponseType response;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package fr.insee.lunatic.conversion;

import fr.insee.lunatic.exception.SerializationException;
import fr.insee.lunatic.model.flat.InputNumber;
import fr.insee.lunatic.model.flat.LabelType;
import fr.insee.lunatic.model.flat.LabelTypeEnum;
import fr.insee.lunatic.model.flat.Questionnaire;
import org.json.JSONException;
import org.junit.jupiter.api.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;

import java.io.ByteArrayInputStream;

import static org.junit.jupiter.api.Assertions.*;

class InputNumberSerializationTest {

private final JsonSerializer jsonSerializer = new JsonSerializer();
private final JsonDeserializer jsonDeserializer = new JsonDeserializer();

private final String jsonNoUnit = """
{
"componentType": "Questionnaire",
"components": [
{
"componentType": "InputNumber",
"min": 0,
"max": 100
}
]
}""";

private final String jsonStringUnit = """
{
"componentType": "Questionnaire",
"components": [
{
"componentType": "InputNumber",
"min": 0,
"max": 100,
"unit": "kg"
}
]
}""";

private final String jsonLabelUnit = """
{
"componentType": "Questionnaire",
"components": [
{
"componentType": "InputNumber",
"min": 0,
"max": 100,
"unit": {
"value": "\\"kg\\"",
"type": "VTL|MD"
}
}
]
}""";

@Test
void serializeInputNumber_noUnit() throws SerializationException, JSONException {
//
Questionnaire questionnaire = new Questionnaire();
InputNumber inputNumber = new InputNumber();
inputNumber.setMin(0d);
inputNumber.setMax(100d);
questionnaire.getComponents().add(inputNumber);
//
String result = jsonSerializer.serialize(questionnaire);
//
JSONAssert.assertEquals(jsonNoUnit, result, JSONCompareMode.STRICT);
}

@Test
void serializeInputNumber_stringUnit() throws SerializationException, JSONException {
//
Questionnaire questionnaire = new Questionnaire();
InputNumber inputNumber = new InputNumber();
inputNumber.setMin(0d);
inputNumber.setMax(100d);
inputNumber.setUnit("kg");
questionnaire.getComponents().add(inputNumber);
//
String result = jsonSerializer.serialize(questionnaire);
//
JSONAssert.assertEquals(jsonStringUnit, result, JSONCompareMode.STRICT);
}

@Test
void serializeInputNumber_labelUnit() throws SerializationException, JSONException {
//
Questionnaire questionnaire = new Questionnaire();
InputNumber inputNumber = new InputNumber();
inputNumber.setMin(0d);
inputNumber.setMax(100d);
inputNumber.setUnit(new LabelType());
inputNumber.getUnitLabel().setValue("\"kg\"");
inputNumber.getUnitLabel().setType(LabelTypeEnum.VTL_MD);
questionnaire.getComponents().add(inputNumber);
//
String result = jsonSerializer.serialize(questionnaire);
//
JSONAssert.assertEquals(jsonLabelUnit, result, JSONCompareMode.STRICT);
}

@Test
void deserializeInputNumber_noUnit() throws SerializationException {
//
Questionnaire questionnaire = jsonDeserializer.deserialize(new ByteArrayInputStream(jsonNoUnit.getBytes()));
//
InputNumber inputNumber = assertInstanceOf(InputNumber.class, questionnaire.getComponents().getFirst());
assertNull(inputNumber.getUnit());
assertNull(inputNumber.getUnitLabel());
}

@Test
void deserializeInputNumber_stringUnit() throws SerializationException {
//
Questionnaire questionnaire = jsonDeserializer.deserialize(new ByteArrayInputStream(jsonStringUnit.getBytes()));
//
InputNumber inputNumber = assertInstanceOf(InputNumber.class, questionnaire.getComponents().getFirst());
assertEquals("kg", inputNumber.getUnit());
}

@Test
void deserializeInputNumber_labelUnit() throws SerializationException {
//
Questionnaire questionnaire = jsonDeserializer.deserialize(new ByteArrayInputStream(jsonLabelUnit.getBytes()));
//
InputNumber inputNumber = assertInstanceOf(InputNumber.class, questionnaire.getComponents().getFirst());
assertEquals("\"kg\"", inputNumber.getUnitLabel().getValue());
assertEquals(LabelTypeEnum.VTL_MD, inputNumber.getUnitLabel().getType());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package fr.insee.lunatic.conversion;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import fr.insee.lunatic.model.flat.InputNumber.Unit;
import fr.insee.lunatic.model.flat.LabelTypeEnum;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

class UnitDeserializerTest {

@Test
void deserializeStringUnit() throws JsonProcessingException {
//
Unit unit = new ObjectMapper().readValue("\"kg\"", Unit.class);
//
assertEquals("kg", unit.getValue());
}

@Test
void deserializeLabelUnit() throws JsonProcessingException {
//
String jsonInput = """
{"value": "\\"kg\\"", "type": "VTL|MD"}""";
//
Unit unit = new ObjectMapper().readValue(jsonInput, Unit.class);
//
assertEquals("\"kg\"", unit.getLabel().getValue());
assertEquals(LabelTypeEnum.VTL_MD, unit.getLabel().getType());
}

}
Loading

0 comments on commit ee053e1

Please sign in to comment.