package com.mysema.luja.serializer;
import java.util.Date;
import java.util.Locale;
import java.util.regex.Pattern;
import org.apache.lucene.document.DateTools;
import org.apache.lucene.document.Field.Index;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.joda.time.ReadableInstant;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.mysema.luja.annotations.DateResolution;
import com.mysema.luja.annotations.Field;
import com.mysema.luja.annotations.Resolution;
import com.mysema.query.lucene.LuceneSerializer;
import com.mysema.query.types.Path;
/**
* Lucene query serializer that understands Luja annotations and quides the
* Lucene serializer. Supports LocalDate, LocalDateTime, ReadableInstant and
* java.util.Date.
*
* @author laimw
*
*/
public class AnnotationSerializer extends LuceneSerializer {
private static final Splitter WS_SPLITTER = Splitter.on(Pattern.compile("\\s+"));
public AnnotationSerializer(Locale sortLocale) {
super(true, true, sortLocale);
}
@Override
protected String[] convert(Path<?> leftSide, Object rightSide) {
String str = handleDates(leftSide, rightSide);
if (str != null) {
return new String[] { str };
}
str = rightSide.toString();
//Split and lowercase analyzed cases
if (isAnalyzed(leftSide)) {
str = str.toLowerCase();
if (!str.equals("")) {
return Iterables.toArray(WS_SPLITTER.split(str), String.class);
}
}
return new String[] { str };
}
private String handleDates(Path<?> leftSide, Object rightSide) {
Long instant = null;
Resolution resolution = null;
if (rightSide instanceof Date) {
instant = ((Date) rightSide).getTime();
resolution = Resolution.MILLISECOND;
} else if (rightSide instanceof LocalDate) {
instant = ((LocalDate) rightSide).toDateTimeAtStartOfDay(DateTimeZone.UTC).getMillis();
resolution = Resolution.DAY;
} else if (rightSide instanceof LocalDateTime) {
instant = ((LocalDateTime) rightSide).toDateTime(DateTimeZone.UTC).getMillis();
resolution = Resolution.MILLISECOND;
} else if (rightSide instanceof ReadableInstant) {
instant = ((ReadableInstant) rightSide).getMillis();
resolution = Resolution.MILLISECOND;
}
if (instant == null) {
return null;
}
if (leftSide.getAnnotatedElement().isAnnotationPresent(DateResolution.class)) {
resolution = leftSide.getAnnotatedElement().getAnnotation(DateResolution.class).value();
}
return DateTools.timeToString(instant, resolution.asLuceneResolution());
}
private boolean isAnalyzed(Path<?> path) {
if (path.getAnnotatedElement().isAnnotationPresent(Field.class)) {
Field fieldAnnotation = path.getAnnotatedElement().getAnnotation(Field.class);
if (fieldAnnotation.index() == Index.ANALYZED
|| fieldAnnotation.index() == Index.ANALYZED_NO_NORMS) {
return true;
}
}
return false;
}
}