package com.constellio.app.ui.pages.search.criteria; import java.lang.reflect.Type; import org.apache.commons.lang3.StringUtils; import org.joda.time.LocalDateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import com.constellio.app.ui.pages.search.criteria.Criterion.BooleanOperator; import com.constellio.app.ui.pages.search.criteria.Criterion.SearchOperator; import com.constellio.app.ui.pages.search.criteria.RelativeCriteria.RelativeSearchOperator; import com.constellio.model.entities.EnumWithSmallCode; import com.constellio.model.entities.schemas.MetadataValueType; import com.constellio.model.entities.schemas.ModifiableStructure; import com.constellio.model.entities.schemas.StructureFactory; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; import com.google.gson.reflect.TypeToken; public class CriterionFactory implements StructureFactory { final String DATE_TIME_ISO_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS"; @Override public String toString(ModifiableStructure structure) { return gson().toJson(structure); } @Override public Criterion build(String serializedCriterion) { Criterion criterion = new Criterion(); if (StringUtils.isNotBlank(serializedCriterion)) { TypeToken<Criterion> listTypeToken = new TypeToken<Criterion>() { }; criterion = gson().fromJson(serializedCriterion, listTypeToken.getType()); criterion = rebuildCriterion(criterion); } return criterion; } private Criterion rebuildCriterion(Criterion criterion) { Criterion newCriterion = new Criterion(); newCriterion.setSchemaType(criterion.getSchemaType()); BooleanOperator booleanOperator = criterion.getBooleanOperator(); newCriterion.setBooleanOperator(booleanOperator); newCriterion.setMetadata(criterion.getMetadataCode(), criterion.getMetadataType(), criterion.getEnumClassName()); SearchOperator searchOperator = criterion.getSearchOperator(); newCriterion.setSearchOperator(searchOperator); RelativeCriteria relativeCriteria = criterion.getRelativeCriteria(); newCriterion.setRelativeCriteria(relativeCriteria); newCriterion.setLeftParens(criterion.isLeftParens()); newCriterion.setRightParens(criterion.isRightParens()); MetadataValueType metadataValueType = criterion.getMetadataType(); String value = null; if (criterion.getValue() != null) { value = "" + criterion.getValue(); } String endValue = null; if (criterion.getEndValue() != null) { endValue = "" + criterion.getEndValue(); } switch (metadataValueType) { case DATE: case DATE_TIME: if (relativeCriteria != null && (relativeCriteria.getRelativeSearchOperator() == RelativeSearchOperator.PAST || relativeCriteria.getRelativeSearchOperator() == RelativeSearchOperator.FUTURE)) { Double newValue = Double.valueOf(value); newCriterion.setValue(newValue); } else if (value != null) { LocalDateTime ldt = new LocalDateTime().parse(value); newCriterion.setValue(ldt); } if (relativeCriteria != null && (relativeCriteria.getEndRelativeSearchOperator() == RelativeSearchOperator.PAST || relativeCriteria.getEndRelativeSearchOperator() == RelativeSearchOperator.FUTURE)) { Double newEndValue = Double.valueOf(endValue); newCriterion.setEndValue(newEndValue); } else if (endValue != null) { LocalDateTime ldt = new LocalDateTime().parse(endValue); newCriterion.setEndValue(ldt); } break; case STRING: newCriterion.setValue(value); break; case TEXT: newCriterion.setValue(value); break; case INTEGER: newCriterion.setValue(Integer.valueOf(value)); break; case NUMBER: if (value != null) { double doubleValue = Double.parseDouble(value); newCriterion.setValue(doubleValue); if (endValue != null) { double doubleEndValue = Double.parseDouble(endValue); newCriterion.setEndValue(doubleEndValue); } } else { newCriterion.setValue(null); } break; case BOOLEAN: Boolean booleanValue = null; if (value != null) { booleanValue = Boolean.parseBoolean(value); } newCriterion.setValue(booleanValue); break; case REFERENCE: newCriterion.setValue(value); break; case CONTENT: newCriterion.setValue(value); break; case STRUCTURE: newCriterion.setValue(value); break; case ENUM: Class clazz = null; try { clazz = Class.forName(criterion.getEnumClassName()); } catch (ClassNotFoundException e) { newCriterion.setValue(null); } if (value != null) { newCriterion.setValue(Enum.valueOf(clazz, value)); } else { newCriterion.setValue(null); } break; default: throw new UnsupportedOperationException("Unknow metadata type"); } return newCriterion; } // private JsonSerializer<LocalDateTime> newLocalDateTimeTypeAdapter() { return new JsonSerializer<LocalDateTime>() { @Override public JsonElement serialize(LocalDateTime src, Type typeOfSrc, JsonSerializationContext context) { final DateTimeFormatter formatter = DateTimeFormat.forPattern(DATE_TIME_ISO_PATTERN); return new JsonPrimitive(formatter.print(src)); } }; } private JsonSerializer<EnumWithSmallCode> newEnumWithSmallCodeTypeAdapter() { return new JsonSerializer<EnumWithSmallCode>() { @Override public JsonElement serialize(EnumWithSmallCode src, Type typeOfSrc, JsonSerializationContext context) { return new JsonPrimitive(src.getClass().getName()); } }; } private Gson gson() { GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(EnumWithSmallCode.class, newEnumWithSmallCodeTypeAdapter()); gsonBuilder = new GsonBuilder().registerTypeAdapter(LocalDateTime.class, newLocalDateTimeTypeAdapter()); return gsonBuilder.create(); } }