001/*
002 * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     bdelbosc
016 */
017package org.nuxeo.elasticsearch.aggregate;
018
019import static org.nuxeo.elasticsearch.ElasticSearchConstants.AGG_FORMAT_PROP;
020
021import java.util.ArrayList;
022import java.util.Collection;
023import java.util.Collections;
024import java.util.Comparator;
025import java.util.List;
026import java.util.Map;
027
028import org.codehaus.jackson.annotate.JsonIgnore;
029import org.elasticsearch.index.query.FilterBuilders;
030import org.elasticsearch.index.query.OrFilterBuilder;
031import org.elasticsearch.index.query.RangeFilterBuilder;
032import org.elasticsearch.search.aggregations.AggregationBuilders;
033import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation;
034import org.elasticsearch.search.aggregations.bucket.range.date.DateRange;
035import org.elasticsearch.search.aggregations.bucket.range.date.DateRangeBuilder;
036import org.nuxeo.ecm.core.api.DocumentModel;
037import org.nuxeo.ecm.platform.query.api.AggregateDefinition;
038import org.nuxeo.ecm.platform.query.api.AggregateRangeDateDefinition;
039import org.nuxeo.ecm.platform.query.core.BucketRangeDate;
040
041/**
042 * @since 6.0
043 */
044public class DateRangeAggregate extends AggregateEsBase<BucketRangeDate> {
045
046    public DateRangeAggregate(AggregateDefinition definition, DocumentModel searchDocument) {
047        super(definition, searchDocument);
048    }
049
050    @JsonIgnore
051    @Override
052    public DateRangeBuilder getEsAggregate() {
053        DateRangeBuilder ret = AggregationBuilders.dateRange(getId()).field(getField());
054        for (AggregateRangeDateDefinition range : getDateRanges()) {
055            if (range.getFromAsString() != null) {
056                if (range.getToAsString() != null) {
057                    ret.addRange(range.getKey(), range.getFromAsString(), range.getToAsString());
058                } else {
059                    ret.addUnboundedFrom(range.getKey(), range.getFromAsString());
060                }
061            } else if (range.getToAsString() != null) {
062                ret.addUnboundedTo(range.getKey(), range.getToAsString());
063            }
064        }
065        Map<String, String> props = getProperties();
066        if (props.containsKey(AGG_FORMAT_PROP)) {
067            ret.format(props.get(AGG_FORMAT_PROP));
068        }
069        return ret;
070    }
071
072    @JsonIgnore
073    @Override
074    public OrFilterBuilder getEsFilter() {
075        if (getSelection().isEmpty()) {
076            return null;
077        }
078        OrFilterBuilder ret = FilterBuilders.orFilter();
079        for (AggregateRangeDateDefinition range : getDateRanges()) {
080            if (getSelection().contains(range.getKey())) {
081                RangeFilterBuilder rangeFilter = FilterBuilders.rangeFilter(getField());
082                if (range.getFromAsString() != null) {
083                    rangeFilter.gte(range.getFromAsString());
084                }
085                if (range.getToAsString() != null) {
086                    rangeFilter.lt(range.getToAsString());
087                }
088                ret.add(rangeFilter);
089            }
090        }
091        return ret;
092    }
093
094    @JsonIgnore
095    @Override
096    public void parseEsBuckets(Collection<? extends MultiBucketsAggregation.Bucket> buckets) {
097        List<BucketRangeDate> nxBuckets = new ArrayList<>(buckets.size());
098        for (MultiBucketsAggregation.Bucket bucket : buckets) {
099            DateRange.Bucket rangeBucket = (DateRange.Bucket) bucket;
100            nxBuckets.add(new BucketRangeDate(bucket.getKey(), getDateTime(rangeBucket.getFromAsDate()),
101                    getDateTime(rangeBucket.getToAsDate()), rangeBucket.getDocCount()));
102        }
103        Collections.sort(nxBuckets, new BucketRangeDateComparator());
104        this.buckets = nxBuckets;
105    }
106
107    protected class BucketRangeDateComparator implements Comparator<BucketRangeDate> {
108        @Override
109        public int compare(BucketRangeDate arg0, BucketRangeDate arg1) {
110            return definition.getAggregateDateRangeDefinitionOrderMap().get(arg0.getKey()).compareTo(
111                    definition.getAggregateDateRangeDefinitionOrderMap().get(arg1.getKey()));
112        }
113    }
114
115}