com.teradata.tpcds.distribution.CalendarDistribution.java Source code

Java tutorial

Introduction

Here is the source code for com.teradata.tpcds.distribution.CalendarDistribution.java

Source

/*
 * 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 com.teradata.tpcds.distribution;

import com.google.common.collect.ImmutableList;
import com.teradata.tpcds.distribution.DistributionUtils.WeightsBuilder;
import com.teradata.tpcds.random.RandomNumberStream;
import com.teradata.tpcds.type.Date;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import static com.google.common.base.Preconditions.checkState;
import static com.teradata.tpcds.distribution.DistributionUtils.getDistributionIterator;
import static com.teradata.tpcds.distribution.DistributionUtils.getListFromCommaSeparatedValues;
import static com.teradata.tpcds.distribution.DistributionUtils.getWeightForIndex;
import static com.teradata.tpcds.distribution.DistributionUtils.pickRandomValue;
import static com.teradata.tpcds.type.Date.isLeapYear;
import static java.lang.Integer.parseInt;

public class CalendarDistribution {
    private static final int NUM_WEIGHT_FIELDS = Weights.values().length;
    private static final String VALUES_AND_WEIGHTS_FILENAME = "calendar.dst";
    private static final int[][] DAYS_BEFORE_MONTH = { { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
            { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 } };
    private static final CalendarDistribution CALENDAR_DISTRIBUTION = buildCalendarDistribution();

    private final ImmutableList<Integer> daysOfYear; // ordinal for the day of year.  Numbering is consistent across leap years and non-leap years   For example, March 1st will always be 61.
    private final ImmutableList<Integer> quarters;
    private final ImmutableList<Integer> holidayFlags;
    private final ImmutableList<ImmutableList<Integer>> weightLists;

    private CalendarDistribution(ImmutableList<Integer> daysOfYear, ImmutableList<Integer> quarters,
            ImmutableList<Integer> holidayFlags, ImmutableList<ImmutableList<Integer>> weightLists) {
        this.daysOfYear = daysOfYear;
        this.quarters = quarters;
        this.holidayFlags = holidayFlags;
        this.weightLists = weightLists;
    }

    private static CalendarDistribution buildCalendarDistribution() {
        ImmutableList.Builder<Integer> daysOfYearBuilder = ImmutableList.builder();
        ImmutableList.Builder<Integer> quartersBuilder = ImmutableList.builder();
        ImmutableList.Builder<Integer> holidayFlagsBuilder = ImmutableList.builder();

        List<WeightsBuilder> weightsBuilders = new ArrayList<>(NUM_WEIGHT_FIELDS);
        for (int i = 0; i < NUM_WEIGHT_FIELDS; i++) {
            weightsBuilders.add(new WeightsBuilder());
        }

        Iterator<List<String>> iterator = getDistributionIterator(VALUES_AND_WEIGHTS_FILENAME);
        while (iterator.hasNext()) {
            List<String> fields = iterator.next();
            checkState(fields.size() == 2, "Expected line to contain 2 parts but it contains %d: %s", fields.size(),
                    fields);

            List<String> values = getListFromCommaSeparatedValues(fields.get(0));
            checkState(values.size() == 8, "Expected line to contain 8 values, but it contained %d, %s",
                    values.size(), values);

            // month names, days of month, seasons, month numbers, and firsts of month are never used, so we ignore them
            daysOfYearBuilder.add(parseInt(values.get(0)));
            quartersBuilder.add(parseInt(values.get(5)));
            holidayFlagsBuilder.add(parseInt(values.get(7)));

            List<String> weights = getListFromCommaSeparatedValues(fields.get(1));
            checkState(weights.size() == NUM_WEIGHT_FIELDS,
                    "Expected line to contain %d weights, but it contained %d, %s", NUM_WEIGHT_FIELDS,
                    weights.size(), values);
            for (int i = 0; i < weights.size(); i++) {
                weightsBuilders.get(i).computeAndAddNextWeight(parseInt(weights.get(i)));
            }
        }

        ImmutableList.Builder<ImmutableList<Integer>> weightsListBuilder = ImmutableList
                .<ImmutableList<Integer>>builder();
        for (WeightsBuilder weightsBuilder : weightsBuilders) {
            weightsListBuilder.add(weightsBuilder.build());
        }

        return new CalendarDistribution(daysOfYearBuilder.build(), quartersBuilder.build(),
                holidayFlagsBuilder.build(), weightsListBuilder.build());
    }

    public static int getIndexForDate(Date date) {
        return DAYS_BEFORE_MONTH[isLeapYear(date.getYear()) ? 1 : 0][date.getMonth() - 1] + date.getDay() - 1;
    }

    public static int getQuarterAtIndex(int index) {
        return CALENDAR_DISTRIBUTION.quarters.get(index - 1); // number passed in is a 1-based index
    }

    public static int getIsHolidayFlagAtIndex(int index) {
        return CALENDAR_DISTRIBUTION.holidayFlags.get(index - 1); // number passed in is a 1-based index
    }

    public static int getWeightForDayNumber(int dayNumber, Weights weights) {
        return getWeightForIndex(dayNumber, getWeights(weights));
    }

    public static int getMaxWeight(Weights weights) {
        ImmutableList<Integer> weightsList = getWeights(weights);
        return weightsList.get(weightsList.size() - 1);
    }

    public static int pickRandomDayOfYear(Weights weights, RandomNumberStream stream) {
        return pickRandomValue(CALENDAR_DISTRIBUTION.daysOfYear, getWeights(weights), stream);
    }

    private static ImmutableList<Integer> getWeights(Weights weights) {
        return CALENDAR_DISTRIBUTION.weightLists.get(weights.ordinal());
    }

    public enum Weights {
        UNIFORM, UNIFORM_LEAP_YEAR, SALES, SALES_LEAP_YEAR, RETURNS, RETURNS_LEAP_YEAR, COMBINED_SKEW, LOW, MEDIUM, HIGH
    }
}