Package com.pearson.entech.elasticsearch.search.facet.approx.date.internal

Source Code of com.pearson.entech.elasticsearch.search.facet.approx.date.internal.DateFacetParser$DateFieldParser$MinuteOfHour

package com.pearson.entech.elasticsearch.search.facet.approx.date.internal;

import java.io.IOException;

import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.joda.Joda;
import org.elasticsearch.common.joda.TimeZoneRounding;
import org.elasticsearch.common.joda.time.Chronology;
import org.elasticsearch.common.joda.time.DateTimeField;
import org.elasticsearch.common.joda.time.DateTimeZone;
import org.elasticsearch.common.joda.time.MutableDateTime;
import org.elasticsearch.common.joda.time.chrono.ISOChronology;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.trove.impl.Constants;
import org.elasticsearch.common.trove.map.hash.TObjectIntHashMap;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.plain.LongArrayIndexFieldData;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.search.facet.FacetExecutor;
import org.elasticsearch.search.facet.FacetParser;
import org.elasticsearch.search.facet.FacetPhaseExecutionException;
import org.elasticsearch.search.internal.SearchContext;

/**
* This class is responsible for parsing a date facet request, and creating a
* correctly-configured DateFacetExecutor for actually handling the query.
*/
public class DateFacetParser extends AbstractComponent implements FacetParser {

    private final ImmutableMap<String, DateFieldParser> dateFieldParsers;
    private final TObjectIntHashMap<String> rounding = new TObjectIntHashMap<String>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, -1);

    /**
     * Create a new parser.
     *
     * @param settings any extra settings -- not currently used.
     */
    @Inject
    public DateFacetParser(final Settings settings) {
        super(settings);

        dateFieldParsers = MapBuilder.<String, DateFieldParser> newMapBuilder()
                .put("year", new DateFieldParser.YearOfCentury())
                .put("1y", new DateFieldParser.YearOfCentury())
                .put("quarter", new DateFieldParser.Quarter())
                .put("month", new DateFieldParser.MonthOfYear())
                .put("1m", new DateFieldParser.MonthOfYear())
                .put("week", new DateFieldParser.WeekOfWeekyear())
                .put("1w", new DateFieldParser.WeekOfWeekyear())
                .put("day", new DateFieldParser.DayOfMonth())
                .put("1d", new DateFieldParser.DayOfMonth())
                .put("hour", new DateFieldParser.HourOfDay())
                .put("1h", new DateFieldParser.HourOfDay())
                .put("minute", new DateFieldParser.MinuteOfHour())
                .put("1m", new DateFieldParser.MinuteOfHour())
                .put("second", new DateFieldParser.SecondOfMinute())
                .put("1s", new DateFieldParser.SecondOfMinute())
                .immutableMap();

        rounding.put("floor", MutableDateTime.ROUND_FLOOR);
        rounding.put("ceiling", MutableDateTime.ROUND_CEILING);
        rounding.put("half_even", MutableDateTime.ROUND_HALF_EVEN);
        rounding.put("halfEven", MutableDateTime.ROUND_HALF_EVEN);
        rounding.put("half_floor", MutableDateTime.ROUND_HALF_FLOOR);
        rounding.put("halfFloor", MutableDateTime.ROUND_HALF_FLOOR);
        rounding.put("half_ceiling", MutableDateTime.ROUND_HALF_CEILING);
        rounding.put("halfCeiling", MutableDateTime.ROUND_HALF_CEILING);
    }

    @Override
    public String[] types() {
        return new String[] {
                "date_facet"
        };
    }

    @Override
    public FacetExecutor.Mode defaultMainMode() {
        return FacetExecutor.Mode.COLLECTOR;
    }

    @Override
    public FacetExecutor.Mode defaultGlobalMode() {
        return FacetExecutor.Mode.COLLECTOR;
    }

    @Override
    public FacetExecutor parse(final String facetName, final XContentParser parser, final SearchContext context) throws IOException {
        String keyField = null;
        String distinctField = null;
        String valueField = null;
        String sliceField = null;
        //        final String valueScript = null;
        //        String scriptLang = null;
        //        Map<String, Object> params = null;
        String interval = null;
        DateTimeZone preZone = DateTimeZone.UTC;
        DateTimeZone postZone = DateTimeZone.UTC;
        boolean preZoneAdjustLargeInterval = false;
        long preOffset = 0;
        long postOffset = 0;
        float factor = 1.0f;
        final Chronology chronology = ISOChronology.getInstanceUTC();
        XContentParser.Token token;
        String fieldName = null;
        int exactThreshold = 1000;

        while((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
            if(token == XContentParser.Token.FIELD_NAME) {
                fieldName = parser.currentName();
            } else if(token == XContentParser.Token.START_OBJECT) {
                //                if("params".equals(fieldName)) {
                //                    params = parser.map();
                //                }
            } else if(token.isValue()) {
                if("field".equals(fieldName)) {
                    keyField = parser.text();
                } else if("key_field".equals(fieldName) || "keyField".equals(fieldName)) {
                    keyField = parser.text();
                } else if("value_field".equals(fieldName) || "valueField".equals(fieldName)) {
                    valueField = parser.text();
                } else if("distinct_field".equals(fieldName) || "distinctField".equals(fieldName)) {
                    distinctField = parser.text();
                } else if("slice_field".equals(fieldName) || "sliceField".equals(fieldName)) {
                    sliceField = parser.text();
                } else if("interval".equals(fieldName)) {
                    interval = parser.text();
                } else if("time_zone".equals(fieldName) || "timeZone".equals(fieldName)) {
                    preZone = parseZone(parser, token);
                } else if("pre_zone".equals(fieldName) || "preZone".equals(fieldName)) {
                    preZone = parseZone(parser, token);
                } else if("pre_zone_adjust_large_interval".equals(fieldName) || "preZoneAdjustLargeInterval".equals(fieldName)) {
                    preZoneAdjustLargeInterval = parser.booleanValue();
                } else if("post_zone".equals(fieldName) || "postZone".equals(fieldName)) {
                    postZone = parseZone(parser, token);
                } else if("pre_offset".equals(fieldName) || "preOffset".equals(fieldName)) {
                    preOffset = parseOffset(parser.text());
                } else if("post_offset".equals(fieldName) || "postOffset".equals(fieldName)) {
                    postOffset = parseOffset(parser.text());
                } else if("factor".equals(fieldName)) {
                    factor = parser.floatValue();
                    /*
                    } else if("value_script".equals(fieldName) || "valueScript".equals(fieldName)) {
                    valueScript = parser.text();
                    */
                    //                } else if("lang".equals(fieldName)) {
                    //                    scriptLang = parser.text();
                } else if("exact_threshold".equals(fieldName) || "exactThreshold".equals(fieldName)) {
                    exactThreshold = parser.intValue();
                }
            }
        }

        if(valueField != null && distinctField != null)
            throw new FacetPhaseExecutionException(facetName, "[value_field] and [distinct_field] may not be used together");

        if(interval == null) {
            throw new FacetPhaseExecutionException(facetName, "[interval] is required to be set for histogram facet");
        }

        TimeZoneRounding.Builder tzRoundingBuilder;
        final DateFieldParser fieldParser = dateFieldParsers.get(interval);
        if(fieldParser != null) {
            tzRoundingBuilder = TimeZoneRounding.builder(fieldParser.parse(chronology));
        } else {
            // the interval is a time value?
            tzRoundingBuilder = TimeZoneRounding.builder(TimeValue.parseTimeValue(interval, null));
        }

        final TimeZoneRounding tzRounding = tzRoundingBuilder
                .preZone(preZone).postZone(postZone)
                .preZoneAdjustLargeInterval(preZoneAdjustLargeInterval)
                .preOffset(preOffset).postOffset(postOffset)
                .factor(factor)
                .build();

        final LongArrayIndexFieldData keyFieldData = getKeyFieldData(facetName, keyField, context);

        final IndexFieldData<?> valueFieldData = getFieldData(facetName, valueField, context);
        final IndexFieldData<?> distinctFieldData = getFieldData(facetName, distinctField, context);
        final IndexFieldData<?> sliceFieldData = getFieldData(facetName, sliceField, context);

        if(exactThreshold < 0)
            exactThreshold = Integer.MAX_VALUE;

        return new DateFacetExecutor(keyFieldData, valueFieldData, distinctFieldData, sliceFieldData,
                tzRounding, exactThreshold);
    }

    @SuppressWarnings("unchecked")
    private <IFD> IFD getFieldData(final String facetName, final String fieldName, final SearchContext context) {
        if(fieldName != null) {
            final FieldMapper<?> mapper = context.smartNameFieldMapper(fieldName);
            if(mapper == null) {
                throw new FacetPhaseExecutionException(facetName, "no mapping found for " + fieldName);
            }
            // This cast is a workaround to deal with issue #41
            return (IFD) context.fieldData().getForField(mapper);
        }
        return null;
    }

    private LongArrayIndexFieldData getKeyFieldData(final String facetName, final String fieldName, final SearchContext context) {
        if(fieldName != null) {
            final FieldMapper<?> mapper = context.smartNameFieldMapper(fieldName);
            if(mapper == null) {
                throw new FacetPhaseExecutionException(facetName, "no mapping found for " + fieldName);
            }
            if(!"long".equals(mapper.fieldDataType().getType())) {
                throw new FacetPhaseExecutionException(facetName, "key field " + fieldName + " is not of type long");
            }
            return context.fieldData().getForField(mapper);
        }
        else
            throw new FacetPhaseExecutionException(facetName, "[key_field] is required to be set for date facet");
    }

    private long parseOffset(final String offset) throws IOException {
        if(offset.charAt(0) == '-') {
            return -TimeValue.parseTimeValue(offset.substring(1), null).millis();
        }
        final int beginIndex = offset.charAt(0) == '+' ? 1 : 0;
        return TimeValue.parseTimeValue(offset.substring(beginIndex), null).millis();
    }

    private DateTimeZone parseZone(final XContentParser parser, final XContentParser.Token token) throws IOException {
        if(token == XContentParser.Token.VALUE_NUMBER) {
            return DateTimeZone.forOffsetHours(parser.intValue());
        } else {
            final String text = parser.text();
            final int index = text.indexOf(':');
            if(index != -1) {
                final int beginIndex = text.charAt(0) == '+' ? 1 : 0;
                // format like -02:30
                return DateTimeZone.forOffsetHoursMinutes(
                        Integer.parseInt(text.substring(beginIndex, index)),
                        Integer.parseInt(text.substring(index + 1))
                        );
            } else {
                // id, listed here: http://joda-time.sourceforge.net/timezones.html
                return DateTimeZone.forID(text);
            }
        }
    }

    static interface DateFieldParser {

        // Nothing special here; 1:1 the same as in the DateHistogramFacetParser

        DateTimeField parse(Chronology chronology);

        static class WeekOfWeekyear implements DateFieldParser {
            @Override
            public DateTimeField parse(final Chronology chronology) {
                return chronology.weekOfWeekyear();
            }
        }

        static class YearOfCentury implements DateFieldParser {
            @Override
            public DateTimeField parse(final Chronology chronology) {
                return chronology.yearOfCentury();
            }
        }

        static class Quarter implements DateFieldParser {
            @Override
            public DateTimeField parse(final Chronology chronology) {
                return Joda.QuarterOfYear.getField(chronology);
            }
        }

        static class MonthOfYear implements DateFieldParser {
            @Override
            public DateTimeField parse(final Chronology chronology) {
                return chronology.monthOfYear();
            }
        }

        static class DayOfMonth implements DateFieldParser {
            @Override
            public DateTimeField parse(final Chronology chronology) {
                return chronology.dayOfMonth();
            }
        }

        static class HourOfDay implements DateFieldParser {
            @Override
            public DateTimeField parse(final Chronology chronology) {
                return chronology.hourOfDay();
            }
        }

        static class MinuteOfHour implements DateFieldParser {
            @Override
            public DateTimeField parse(final Chronology chronology) {
                return chronology.minuteOfHour();
            }
        }

        static class SecondOfMinute implements DateFieldParser {
            @Override
            public DateTimeField parse(final Chronology chronology) {
                return chronology.secondOfMinute();
            }
        }
    }
}
TOP

Related Classes of com.pearson.entech.elasticsearch.search.facet.approx.date.internal.DateFacetParser$DateFieldParser$MinuteOfHour

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.