org.dashbuilder.dataset.backend.BackendIntervalBuilderDynamicDate.java Source code

Java tutorial

Introduction

Here is the source code for org.dashbuilder.dataset.backend.BackendIntervalBuilderDynamicDate.java

Source

/**
 * Copyright (C) 2014 JBoss Inc
 *
 * 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 org.dashbuilder.dataset.backend;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;

import javax.enterprise.context.ApplicationScoped;

import org.apache.commons.lang.StringUtils;
import org.dashbuilder.dataset.DataSet;
import org.dashbuilder.dataset.engine.DataSetHandler;
import org.dashbuilder.dataset.engine.group.Interval;
import org.dashbuilder.dataset.engine.group.IntervalBuilder;
import org.dashbuilder.dataset.engine.group.IntervalList;
import org.dashbuilder.dataset.group.DateIntervalType;
import org.dashbuilder.dataset.group.ColumnGroup;
import org.dashbuilder.dataset.sort.DataSetSort;
import org.dashbuilder.dataset.sort.ColumnSort;
import org.dashbuilder.dataset.sort.SortOrder;
import org.dashbuilder.dataset.sort.SortedList;
import org.dashbuilder.dataset.date.Quarter;

import static org.dashbuilder.dataset.group.DateIntervalType.*;

/**
 * Interval builder for date columns which generates intervals depending on the underlying data available.
 */
@ApplicationScoped
public class BackendIntervalBuilderDynamicDate implements IntervalBuilder {

    public IntervalList build(DataSetHandler handler, ColumnGroup columnGroup) {
        IntervalDateRangeList results = new IntervalDateRangeList(columnGroup);
        DataSet dataSet = handler.getDataSet();
        List values = dataSet.getColumnById(columnGroup.getSourceId()).getValues();
        if (values.isEmpty()) {
            return results;
        }

        // Sort the column dates.
        DataSetSort sortOp = new DataSetSort();
        sortOp.addSortColumn(new ColumnSort(columnGroup.getSourceId(), SortOrder.ASCENDING));
        DataSetHandler sortResults = handler.sort(sortOp);
        List<Integer> sortedRows = sortResults.getRows();
        if (sortedRows == null || sortedRows.isEmpty()) {
            return results;
        }

        // Get the lower & upper limits.
        SortedList sortedValues = new SortedList(values, sortedRows);
        Date minDate = (Date) sortedValues.get(0);
        Date maxDate = (Date) sortedValues.get(sortedValues.size() - 1);

        // If min/max are equals then create a single interval.
        if (minDate.compareTo(maxDate) == 0) {
            IntervalDateRange interval = new IntervalDateRange(DAY, minDate, maxDate);
            for (int row = 0; row < sortedValues.size(); row++)
                interval.rows.add(row);
            results.add(interval);
            return results;
        }

        // Calculate the interval type used according to the constraints set.
        int maxIntervals = columnGroup.getMaxIntervals();
        if (maxIntervals < 1)
            maxIntervals = 15;
        DateIntervalType intervalType = YEAR;
        long millis = (maxDate.getTime() - minDate.getTime());
        for (DateIntervalType type : values()) {
            long nintervals = millis / getDurationInMillis(type);
            if (nintervals < maxIntervals) {
                intervalType = type;
                break;
            }
        }

        // Ensure the interval mode obtained is always greater or equals than the preferred interval size.
        DateIntervalType intervalSize = null;
        if (!StringUtils.isBlank(columnGroup.getIntervalSize())) {
            intervalSize = getByName(columnGroup.getIntervalSize());
        }
        if (intervalSize != null && compare(intervalType, intervalSize) == -1) {
            intervalType = intervalSize;
        }

        // Adjust the minDate according to the interval type.
        Calendar gc = GregorianCalendar.getInstance();
        gc.setLenient(false);
        gc.setTime(minDate);
        if (YEAR.equals(intervalType)) {
            gc.set(Calendar.MONTH, 0);
            gc.set(Calendar.DAY_OF_MONTH, 1);
            gc.set(Calendar.HOUR, 0);
            gc.set(Calendar.MINUTE, 0);
            gc.set(Calendar.SECOND, 0);
            gc.set(Calendar.MILLISECOND, 0);
        }
        if (QUARTER.equals(intervalType)) {
            int currentMonth = gc.get(Calendar.MONTH);
            int firstMonthYear = columnGroup.getFirstMonthOfYear().getIndex();
            int rest = Quarter.getPositionInQuarter(firstMonthYear, currentMonth);
            gc.add(Calendar.MONTH, rest * -1);
            gc.set(Calendar.DAY_OF_MONTH, 1);
            gc.set(Calendar.HOUR, 0);
            gc.set(Calendar.MINUTE, 0);
            gc.set(Calendar.SECOND, 0);
            gc.set(Calendar.MILLISECOND, 0);
        }
        if (MONTH.equals(intervalType)) {
            gc.set(Calendar.DAY_OF_MONTH, 1);
            gc.set(Calendar.HOUR, 0);
            gc.set(Calendar.MINUTE, 0);
            gc.set(Calendar.SECOND, 0);
            gc.set(Calendar.MILLISECOND, 0);
        }
        if (DAY.equals(intervalType) || DAY_OF_WEEK.equals(intervalType)) {
            gc.set(Calendar.HOUR, 0);
            gc.set(Calendar.MINUTE, 0);
            gc.set(Calendar.SECOND, 0);
            gc.set(Calendar.MILLISECOND, 0);
        }
        if (HOUR.equals(intervalType)) {
            gc.set(Calendar.MINUTE, 0);
            gc.set(Calendar.SECOND, 0);
            gc.set(Calendar.MILLISECOND, 0);
        }
        if (MINUTE.equals(intervalType)) {
            gc.set(Calendar.SECOND, 0);
            gc.set(Calendar.MILLISECOND, 0);
        }
        if (SECOND.equals(intervalType)) {
            gc.set(Calendar.MILLISECOND, 0);
        }

        // Create the intervals according to the min/max dates.
        int index = 0;
        while (gc.getTime().compareTo(maxDate) <= 0) {
            Date intervalMinDate = gc.getTime();

            // Go to the next interval
            if (MILLENIUM.equals(intervalType)) {
                gc.add(Calendar.YEAR, 1000);
            }
            if (CENTURY.equals(intervalType)) {
                gc.add(Calendar.YEAR, 100);
            }
            if (DECADE.equals(intervalType)) {
                gc.add(Calendar.YEAR, 10);
            }
            if (YEAR.equals(intervalType)) {
                gc.add(Calendar.YEAR, 1);
            }
            if (QUARTER.equals(intervalType)) {
                gc.add(Calendar.MONTH, 3);
            }
            if (MONTH.equals(intervalType)) {
                gc.add(Calendar.MONTH, 1);
            }
            if (WEEK.equals(intervalType)) {
                gc.add(Calendar.DAY_OF_MONTH, 7);
            }
            if (DAY.equals(intervalType) || DAY_OF_WEEK.equals(intervalType)) {
                gc.add(Calendar.DAY_OF_MONTH, 1);
            }
            if (HOUR.equals(intervalType)) {
                gc.add(Calendar.HOUR_OF_DAY, 1);
            }
            if (MINUTE.equals(intervalType)) {
                gc.add(Calendar.MINUTE, 1);
            }
            if (SECOND.equals(intervalType)) {
                gc.add(Calendar.SECOND, 1);
            }

            // Create the interval.
            Date intervalMaxDate = gc.getTime();
            IntervalDateRange interval = new IntervalDateRange(intervalType, intervalMinDate, intervalMaxDate);
            results.add(interval);

            // Add the target rows to the interval.
            boolean stop = false;
            while (!stop) {
                if (index >= sortedValues.size()) {
                    stop = true;
                } else {
                    Date dateValue = (Date) sortedValues.get(index);
                    Integer row = sortedRows.get(index);
                    if (dateValue.before(intervalMaxDate)) {
                        interval.rows.add(row);
                        index++;
                    } else {
                        stop = true;
                    }
                }
            }
        }

        // Reverse intervals if requested
        boolean asc = columnGroup.isAscendingOrder();
        if (!asc)
            Collections.reverse(results);

        return results;
    }

    private static SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");

    /**
     * A list containing date range intervals.
     */
    public class IntervalDateRangeList extends IntervalList {

        public IntervalDateRangeList(ColumnGroup columnGroup) {
            super(columnGroup);
        }

        public Interval locateInterval(Object value) {
            Date d = (Date) value;
            for (Interval interval : this) {
                IntervalDateRange dateRange = (IntervalDateRange) interval;
                if (d.equals(dateRange.minDate) || (d.after(dateRange.minDate) && d.before(dateRange.maxDate))) {
                    return interval;
                }
            }
            return null;
        }
    }

    /**
     * A date interval holding dates belonging to a given range.
     */
    public class IntervalDateRange extends Interval {

        protected DateIntervalType intervalType;
        protected Date minDate;
        protected Date maxDate;

        public IntervalDateRange(DateIntervalType intervalType, Date minDate, Date maxDate) {
            super();
            this.name = calculateName(intervalType, minDate);
            this.intervalType = intervalType;
            this.minDate = minDate;
            this.maxDate = maxDate;

        }

        public String calculateName(DateIntervalType intervalType, Date d) {
            Locale l = Locale.getDefault();
            if (MILLENIUM.equals(intervalType)) {
                SimpleDateFormat formatYear = new SimpleDateFormat("yyyy", l);
                return formatYear.format(d);
            }
            if (CENTURY.equals(intervalType)) {
                SimpleDateFormat formatYear = new SimpleDateFormat("yyyy", l);
                return formatYear.format(d);
            }
            if (DECADE.equals(intervalType)) {
                SimpleDateFormat formatYear = new SimpleDateFormat("yyyy", l);
                return formatYear.format(d);
            }
            if (YEAR.equals(intervalType)) {
                SimpleDateFormat format = new SimpleDateFormat("yyyy", l);
                return format.format(d);
            }
            if (QUARTER.equals(intervalType)) {
                SimpleDateFormat format = new SimpleDateFormat("MMM yyyy", l);
                return format.format(d);
            }
            if (MONTH.equals(intervalType)) {
                SimpleDateFormat format = new SimpleDateFormat("MMMM yyyy", l);
                return format.format(d);
            }
            if (WEEK.equals(intervalType)) {
                return DateFormat.getDateInstance(DateFormat.SHORT, l).format(d);
            }
            if (DAY.equals(intervalType) || DAY_OF_WEEK.equals(intervalType)) {
                SimpleDateFormat format = new SimpleDateFormat("EEE", l);
                return format.format(d) + " " + DateFormat.getDateInstance(DateFormat.SHORT, l).format(d);
            }
            if (HOUR.equals(intervalType)) {
                SimpleDateFormat format = new SimpleDateFormat("HH", l);
                return format.format(d) + "h";
            }
            if (MINUTE.equals(intervalType)) {
                SimpleDateFormat format = new SimpleDateFormat("mm", l);
                return format.format(d);
            }
            if (SECOND.equals(intervalType)) {
                SimpleDateFormat format = new SimpleDateFormat("ss", l);
                return format.format(d);
            }
            return format.format(d);
        }
    }
}