/* * Copyright (c) 2011-2015 EPFL DATA Laboratory * Copyright (c) 2014-2015 The Squall Collaboration (see NOTICE) * * All rights reserved. * * 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 ch.epfl.data.squall.storage.indexes; import gnu.trove.list.array.TIntArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.TreeMap; import org.apache.log4j.Logger; import ch.epfl.data.squall.predicates.ComparisonPredicate; public class BalancedBinaryTreeIndex<KeyType extends Comparable<KeyType>> implements Index<KeyType> { // TEST public static void main(String[] args) { final BalancedBinaryTreeIndex<Integer> bbt = new BalancedBinaryTreeIndex<Integer>(); bbt.put(1, 1); bbt.put(3, 3); bbt.put(6, 6); bbt.put(2, 1); bbt.put(5, 5); bbt.put(9, 1); final TIntArrayList list = bbt.getValues( ComparisonPredicate.NONLESS_OP, 5); for (int i = 0; i < list.size(); i++) LOG.info(list.get(i)); } /** * */ private static final long serialVersionUID = 1L; /** * This is a Red-Black tree implementation of a balanced binary tree; * * @author SaSa */ private static Logger LOG = Logger.getLogger(BalancedBinaryTreeIndex.class); private final TreeMap<KeyType, TIntArrayList> _index; private KeyType _diff = null; public BalancedBinaryTreeIndex() { _index = new TreeMap<KeyType, TIntArrayList>(); } private TIntArrayList flatten(Collection<TIntArrayList> sets) { final TIntArrayList result = new TIntArrayList(); for (final Iterator iterator = sets.iterator(); iterator.hasNext();) { final TIntArrayList tIntArrayList = (TIntArrayList) iterator.next(); result.addAll(tIntArrayList); } return result; } @Override public TIntArrayList getValues(int operator, KeyType key) { if (operator == ComparisonPredicate.GREATER_OP) {// // find all x which // are more than the // specified key if (_diff != null) return flatten(_index.subMap(key, false, performOperation(key, _diff, true), false).values()); return flatten(_index.headMap(key).values()); } else if (operator == ComparisonPredicate.NONLESS_OP) { if (_diff != null) return flatten(_index.subMap(key, true, performOperation(key, _diff, true), true).values()); return flatten(_index.headMap(key, true).values()); } else if (operator == ComparisonPredicate.LESS_OP) { // find all x // which are // less than the // specified key if (_diff != null) return flatten(_index.subMap( performOperation(key, _diff, false), false, key, false) .values()); return flatten(_index.tailMap(key).values()); } else if (operator == ComparisonPredicate.NONGREATER_OP) { if (_diff != null) return flatten(_index.subMap( performOperation(key, _diff, false), true, key, true) .values()); return flatten(_index.tailMap(key, true).values()); } else return null; } @Override public TIntArrayList getValuesWithOutOperator(KeyType key, KeyType... keys) { // TODO Auto-generated method stub return null; } private KeyType performOperation(KeyType k, KeyType diff, boolean isInverse) { // workaround for some compilers Comparable<?> tmpK = k; Comparable<?> tmpDiff = diff; Comparable<?> result = null; if (tmpK instanceof Double) { final Double kd = (Double) tmpK; Double diffd = (Double) tmpDiff; if (isInverse) diffd = -1 * diffd; final Double resultd = kd + diffd; result = resultd; } else if (tmpK instanceof Integer) { final Integer kd = (Integer) tmpK; Integer diffd = (Integer) tmpDiff; if (isInverse) diffd = -1 * diffd; final Integer resultd = kd + diffd; result = resultd; } else if (tmpK instanceof Date) { final Date kd = (Date) tmpK; Integer diffd = (Integer) tmpDiff; if (isInverse) diffd = -1 * diffd; final Calendar c = Calendar.getInstance(); c.setTime(kd); c.add(Calendar.DAY_OF_MONTH, diffd); result = c.getTime(); } else LOG.info("Operation in BalancedBinaryTree not supported for underlying datatype"); return (KeyType) result; } @Override public void put(Integer row_id, KeyType key) { TIntArrayList idsList = _index.get(key); if (idsList == null) { idsList = new TIntArrayList(1); _index.put(key, idsList); } idsList.add(row_id); } @Override public void remove(Integer row_id, KeyType key) { throw new RuntimeException("Not implemented yet"); } public BalancedBinaryTreeIndex setDiff(Object diff) { if (diff != null) _diff = (KeyType) diff; return this; } }