org.apache.lens.cube.metadata.timeline.EndsAndHolesPartitionTimeline.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.lens.cube.metadata.timeline.EndsAndHolesPartitionTimeline.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.lens.cube.metadata.timeline;

import java.util.*;

import org.apache.lens.cube.metadata.MetastoreUtil;
import org.apache.lens.cube.metadata.TimePartition;
import org.apache.lens.cube.metadata.TimeRange;
import org.apache.lens.cube.metadata.UpdatePeriod;
import org.apache.lens.server.api.error.LensException;

import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.ToString;

/**
 * One implementation of PartitionTimeline that stores first partition, latest partition and a collection of holes in
 * between them, excluding the edges(start and end values).  This is the default Timeline for tables that don't specify
 * which Timeline Class to use in it's params.
 */
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class EndsAndHolesPartitionTimeline extends PartitionTimeline {
    private TimePartition first;
    private TreeSet<TimePartition> holes = Sets.newTreeSet();
    private TimePartition latest;

    public EndsAndHolesPartitionTimeline(String storageTableName, UpdatePeriod updatePeriod, String partCol) {
        super(storageTableName, updatePeriod, partCol);
    }

    @Override
    public boolean add(@NonNull TimePartition partition) throws LensException {
        if (isEmpty()) {
            // First partition being added
            first = partition;
            latest = partition;
            return true;
        }
        if (partition.before(first)) {
            addHolesBetween(partition, first, partition.getUpdatePeriod());
            first = partition;
            return true;
        } else if (partition.after(latest)) {
            addHolesBetween(latest, partition, partition.getUpdatePeriod());
            latest = partition;
            return true;
        } else {
            return holes.remove(partition);
        }
    }

    @Override
    public boolean drop(@NonNull TimePartition toDrop) throws LensException {
        if (first.equals(latest) && first.equals(toDrop)) {
            this.first = null;
            this.latest = null;
            this.holes.clear();
            return true;
        } else if (first.equals(toDrop)) {
            this.first = this.getNextPartition(first, latest, 1);
            return true;
        } else if (latest.equals(toDrop)) {
            this.latest = this.getNextPartition(latest, first, -1);
            return true;
        } else {
            return addHole(toDrop);
        }
    }

    @Override
    public TimePartition latest() {
        return latest;
    }

    @Override
    public Map<String, String> toProperties() {
        HashMap<String, String> ret = Maps.newHashMap();
        ret.put("first", "");
        ret.put("latest", "");
        MetastoreUtil.addNameStrings(ret, "holes", holes);
        if (isEmpty()) {
            return ret;
        }
        ret.put("first", first.getDateString());
        ret.put("latest", latest.getDateString());
        return ret;
    }

    @Override
    public boolean initFromProperties(Map<String, String> properties) throws LensException {
        first = null;
        latest = null;
        holes.clear();
        String firstStr = properties.get("first");
        String latestStr = properties.get("latest");
        String holesStr = MetastoreUtil.getNamedStringValue(properties, "holes");
        if (!Strings.isNullOrEmpty(firstStr)) {
            first = TimePartition.of(getUpdatePeriod(), firstStr);
        }
        if (!Strings.isNullOrEmpty(latestStr)) {
            latest = TimePartition.of(getUpdatePeriod(), latestStr);
        }
        holes = Sets.newTreeSet();
        if (!Strings.isNullOrEmpty(holesStr)) {
            for (String hole : holesStr.split("\\s*,\\s*")) {
                holes.add(TimePartition.of(getUpdatePeriod(), hole));
            }
        }
        return isConsistent();
    }

    private boolean addHole(TimePartition toDrop) {
        return holes.add(toDrop);
    }

    private void addHolesBetween(TimePartition begin, TimePartition end, UpdatePeriod updatePeriod)
            throws LensException {
        for (Date date : TimeRange.iterable(begin.next().getDate(), end.getDate(), updatePeriod, 1)) {
            addHole(TimePartition.of(updatePeriod, date));
        }
    }

    private TimePartition getNextPartition(TimePartition begin, TimePartition end, int increment)
            throws LensException {
        for (Date date : TimeRange.iterable(begin.partitionAtDiff(increment).getDate(),
                end.partitionAtDiff(increment).getDate(), begin.getUpdatePeriod(), increment)) {
            TimePartition value = TimePartition.of(begin.getUpdatePeriod(), date);
            if (!holes.contains(value)) {
                return value;
            } else {
                holes.remove(value);
            }
        }
        return null;
    }

    public boolean isEmpty() {
        return first == null && latest == null && holes.isEmpty();
    }

    @Override
    public boolean isConsistent() {
        if (first == null && latest != null) {
            return false;
        }
        if (latest == null && first != null) {
            return false;
        }
        for (TimePartition hole : holes) {
            if (!hole.after(first) || !hole.before(latest)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean exists(TimePartition toCheck) {
        return !isEmpty() && !toCheck.before(first) && !toCheck.after(latest) && !holes.contains(toCheck);
    }

    @Override
    public Iterator<TimePartition> iterator() {

        return new Iterator<TimePartition>() {
            TimePartition cur = getFirst();

            @Override
            public boolean hasNext() {
                return cur != null && getLatest() != null && !cur.after(getLatest());
            }

            @Override
            public TimePartition next() {
                while (holes.contains(cur)) {
                    cur = cur.next();
                }
                TimePartition toReturn = cur;
                cur = cur.next();
                return toReturn;
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }
}