Java tutorial
/** * 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(); } }; } }