All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tigrisdata.db.client.Utilities Maven / Gradle / Ivy

/*
 * Copyright 2022 Tigris Data, 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 com.tigrisdata.db.client;

import com.google.common.base.CaseFormat;
import com.google.common.reflect.ClassPath;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.tigrisdata.db.annotation.TigrisCollection;
import com.tigrisdata.db.client.error.TigrisException;
import com.tigrisdata.db.type.TigrisCollectionType;
import org.atteo.evo.inflector.English;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

final class Utilities {
  private Utilities() {}

  private static final Logger log = LoggerFactory.getLogger(Utilities.class);

  /**
   * Scans the classpath for the given packages and searches for all the top level classes that are
   * of type {@link TigrisCollectionType} and optionally filters them using user supplied filter.
   *
   * @param packagesToScan packages to scan
   * @param filter filter to select classes from scanned classes
   * @return tigris db collection model classes
   */
  static Class[] scanTigrisDBCollectionModels(
      String[] packagesToScan, Optional>> filter) {
    Set> scannedClasses = new HashSet<>();
    for (String packageToScan : packagesToScan) {
      log.debug("scanning package {}", packageToScan);
      try {
        Set> scannedClassesFromThisPackage =
            ClassPath.from(ClassLoader.getSystemClassLoader())
                .getTopLevelClassesRecursive(packageToScan).stream()
                .map(ClassPath.ClassInfo::load)
                .filter(clazz -> TigrisCollectionType.class.isAssignableFrom(clazz))
                .map(clazz -> (Class) clazz)
                .filter(
                    clazz -> filter.map(classPredicate -> classPredicate.test(clazz)).orElse(true))
                .collect(Collectors.toSet());
        log.debug("found {}", scannedClasses);
        scannedClasses.addAll(scannedClassesFromThisPackage);
      } catch (Exception ex) {
        log.warn("failed to scan " + packageToScan, ex);
      }
    }

    Class result[] = new Class[scannedClasses.size()];
    int i = 0;
    for (Class scannedClass : scannedClasses) {
      result[i] = scannedClass;
      i++;
    }
    log.debug("Total classes found={}, all classes = {}", result.length, Arrays.toString(result));
    return result;
  }

  static String getCollectionName(Class clazz) {
    TigrisCollection tigrisCollection = clazz.getAnnotation(TigrisCollection.class);
    if (tigrisCollection != null) {
      return tigrisCollection.value();
    }
    return CaseFormat.UPPER_CAMEL.to(
        CaseFormat.LOWER_UNDERSCORE, English.plural(clazz.getSimpleName()));
  }

  /**
   * Converts from {@link Iterator} of Type F to {@link Iterator} of type T
   *
   * @param iterator source iterator
   * @param converter function that converts F to T type
   * @param  source type
   * @param  destination type
   * @return an instance of {@link Iterator} of type T
   */
  static  Iterator transformIterator(Iterator iterator, Function converter) {
    return new ConvertedIterator<>(iterator, converter);
  }

  /**
   * Converts {@link ListenableFuture} of type F to {@link CompletableFuture} of type T
   *
   * @param listenableFuture source listenable future
   * @param converter function that converts type F to type T
   * @param executor executor to run callback that transforms Future when source Future is complete
   * @param  from type
   * @param  to type
   * @return an instance of {@link CompletableFuture}
   */
  static  CompletableFuture transformFuture(
      ListenableFuture listenableFuture,
      Function converter,
      Executor executor,
      String errorMessage) {
    return transformFuture(listenableFuture, converter, executor, errorMessage, Optional.empty());
  }
  /**
   * Converts {@link ListenableFuture} of type F to {@link CompletableFuture} of type T
   *
   * @param listenableFuture source listenable future
   * @param converter function that converts type F to type T
   * @param executor executor to run callback that transforms Future when source Future is complete
   * @param exceptionHandler handles exception
   * @param  from type
   * @param  to type
   * @return an instance of {@link CompletableFuture}
   */
  static  CompletableFuture transformFuture(
      ListenableFuture listenableFuture,
      Function converter,
      Executor executor,
      String errorMessage,
      Optional, Throwable>> exceptionHandler) {
    CompletableFuture result = new CompletableFuture<>();
    Futures.addCallback(
        listenableFuture,
        new FutureCallback() {
          @Override
          public void onSuccess(F f) {
            result.complete(converter.apply(f));
          }

          @Override
          public void onFailure(Throwable throwable) {
            if (exceptionHandler.isPresent()) {
              exceptionHandler.get().accept(result, throwable);
            } else {
              result.completeExceptionally(new TigrisException(errorMessage, throwable));
            }
          }
        },
        executor);
    return result;
  }

  static class ConvertedIterator implements Iterator {

    private final Iterator sourceIterator;
    private final Function converter;

    public ConvertedIterator(Iterator sourceIterator, Function converter) {
      this.sourceIterator = sourceIterator;
      this.converter = converter;
    }

    @Override
    public boolean hasNext() {
      return sourceIterator.hasNext();
    }

    @Override
    public T next() {
      return converter.apply(sourceIterator.next());
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy