/*
* Copyright (C) 2015 SoftIndex LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.datakernel.aggregation.fieldtype;
import com.google.common.reflect.TypeParameter;
import com.google.common.reflect.TypeToken;
import io.datakernel.codegen.Expression;
import io.datakernel.codegen.utils.Primitives;
import io.datakernel.serializer.StringFormat;
import io.datakernel.serializer.asm.*;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import java.lang.reflect.Type;
import java.util.Set;
import static io.datakernel.codegen.Expressions.call;
import static io.datakernel.codegen.Expressions.value;
public final class FieldTypes {
private FieldTypes() {
}
public static FieldType<Byte> ofByte() {
return new FieldType<>(byte.class, new SerializerGenByte());
}
public static FieldType<Short> ofShort() {
return new FieldType<>(short.class, new SerializerGenShort());
}
public static FieldType<Integer> ofInt() {
return new FieldType<>(int.class, new SerializerGenInt(true));
}
public static FieldType<Long> ofLong() {
return new FieldType<>(long.class, new SerializerGenLong(true));
}
public static FieldType<Float> ofFloat() {
return new FieldType<>(float.class, new SerializerGenFloat());
}
public static FieldType<Double> ofDouble() {
return new FieldType<>(double.class, new SerializerGenDouble());
}
public static <T> FieldType<T> ofSet(FieldType<T> fieldType) {
SerializerGenSet serializer = new SerializerGenSet(fieldType.getSerializer());
Type wrappedNestedType = fieldType.getDataType() instanceof Class ?
Primitives.wrap((Class) fieldType.getDataType()) :
fieldType.getDataType();
Type dataType = new TypeToken<Set<T>>() {}
.where(new TypeParameter<T>() {}, (TypeToken<T>) TypeToken.of(wrappedNestedType))
.getType();
return new FieldType<>(Set.class, dataType, serializer);
}
public static <T extends Enum<T>> FieldType<T> ofEnum(Class<T> enumClass) {
return new FieldType<>(enumClass, new SerializerGenEnum(enumClass));
}
public static FieldType<String> ofString() {
return new FieldType<>(String.class, new SerializerGenString());
}
public static FieldType<String> ofString(StringFormat format) {
return new FieldType<>(String.class, new SerializerGenString(format));
}
public static FieldType<LocalDate> ofLocalDate() {
return new FieldTypeDate();
}
public static FieldType<LocalDate> ofLocalDate(LocalDate startDate) {
return new FieldTypeDate(startDate);
}
private static final class FieldTypeDate extends FieldType<LocalDate> {
private final LocalDate startDate;
FieldTypeDate() {
this(LocalDate.parse("1970-01-01"));
}
FieldTypeDate(LocalDate startDate) {
super(int.class, LocalDate.class, new SerializerGenInt(true));
this.startDate = startDate;
}
@Override
public Expression toValue(Expression internalValue) {
return call(value(startDate), "plusDays", internalValue);
}
@Override
public Object toInternalValue(LocalDate value) {
return Days.daysBetween(startDate, value).getDays();
}
}
}