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

edu.byu.hbll.box.SourceConfig Maven / Gradle / Ivy

There is a newer version: 2.5.3
Show newest version
package edu.byu.hbll.box;

import edu.byu.hbll.box.impl.MemoryDatabase;
import edu.byu.hbll.scheduler.CronSchedule;
import edu.byu.hbll.scheduler.PeriodicSchedule;
import edu.byu.hbll.scheduler.Schedule;
import java.time.Duration;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.Getter;
import lombok.Singular;

/** The configuration of a source in Box. */
@lombok.Builder
@Getter
public class SourceConfig {

  /** Always points to the principal source. */
  public static final String PRINCIPAL_SOURCE_ALIAS = "box";

  /** For participating operations, this refers to all sources. */
  public static final String ALL_SOURCES_ALIAS = "all";

  /** Reserved source names. */
  public static final Set RESERVED_SOURCE_NAMES =
      Set.of(PRINCIPAL_SOURCE_ALIAS, ALL_SOURCES_ALIAS);

  /** The name of the source. */
  private final String name;

  /**
   * Whether to enable or disable this source. A disabled source behaves like it doesn't even exist.
   * Default true.
   */
  @lombok.Builder.Default private final boolean enabled = true;

  /**
   * Whether to mark this source as the principal source or in other words the main source of the
   * box. Also some apis are simplified for the principal source because no source name has to be
   * specified. If no source is explicitly marked as principal, the first one added to the
   * configuration will be considered as principal. Default false.
   */
  private final boolean principal;

  /** The processor to use for this source. Setting this enables direct processing of documents. */
  private final Processor processor;

  /**
   * How long to wait before running a batch at less than capacity. Only valid for the processor.
   * Default Duration.ZERO.
   */
  @lombok.Builder.Default private final Duration batchDelay = Duration.ZERO;

  /** The maximum size a batch can grow before processing occurs. Default 1. */
  @lombok.Builder.Default private final int batchCapacity = 1;

  /** How many threads should be processing batches. Default 1. */
  @lombok.Builder.Default private final int threadCount = 1;

  /** How long to suspend processing threads after each batch. Default Duration.ZERO. */
  @lombok.Builder.Default private final Duration suspend = Duration.ZERO;

  /** Stop processing when quota is reached. Default 0 (no quota). */
  private final int quota;

  /**
   * When to reset the processed count to zero to allow more processing to occur until the quota is
   * reached again. Default midnight each day.
   */
  @lombok.Builder.Default private final Schedule quotaReset = CronSchedule.of("0 0 0 * * * *");

  /** When to turn on processing for a window of time. Default null (always on). */
  private final Schedule on;

  /** When to turn of processing for a window of time. Default null (always on). */
  private final Schedule off;

  /**
   * Whether or not to enable or disable this processor. If disabled, this source behaves as if it
   * doesn't have a processor. Default true.
   */
  @lombok.Builder.Default private final boolean processEnabled = true;

  /**
   * The harvester to use for this source. Setting this enables harvesting of documents. Default
   * null.
   */
  private final Harvester harvester;

  /**
   * Whether or not to enable or disable this harvester. If disabled, this source behaves as if it
   * doesn't have a harvester. Default true.
   */
  @lombok.Builder.Default private final boolean harvestEnabled = true;

  /** A cron-like schedule of when to run the harvester. Default every minute. */
  @lombok.Builder.Default private final Schedule harvestSchedule = PeriodicSchedule.ofMinutes(1);

  /**
   * A cron-like schedule of when to reset the harvester and cause it to start from the very
   * beginning. Default null (never).
   *
   * @deprecated use {@link #reharvestSchedule} instead
   */
  @Deprecated private final Schedule harvestResetSchedule;

  /**
   * Reharvest according to this cron-like schedule. This tells Box to start a new secondary harvest
   * from the beginning. Default null (never).
   */
  private final Schedule reharvestSchedule;

  /** Whether or not to save new deleted documents during harvests. Default false. */
  private final boolean saveDeleted;

  @lombok.Builder.Default private final Duration retryDelay = Duration.ofMinutes(1);
  @lombok.Builder.Default private final double retryJitter = 0.5;

  /** Reprocess old documents that haven't been processed for this long. Default null (never). */
  private final Duration reprocessAge;

  /** When to go looking for old documents to reprocess. Default every minute. */
  @lombok.Builder.Default private final Schedule reprocessSchedule = PeriodicSchedule.ofMinutes(1);

  /** Remove deleted documents that have been deleted for this long. Default 90 days. */
  @lombok.Builder.Default private final Duration removeAge = Duration.ofDays(90);

  /** When to run the remove process. Default every minute. */
  @lombok.Builder.Default private final Schedule removeSchedule = PeriodicSchedule.ofMinutes(1);

  /**
   * Each time a document is saved, fields that match the dot-notated paths will be added as facets
   * with the given name.
   */
  private final Map> facetFields;

  /**
   * Whether or not to save documents to the database. This is important for sources that need to
   * always process in real-time. Default true.
   */
  @lombok.Builder.Default private final boolean save = true;

  /** Whether or not to always process documents synchronously in real-time. Default false. */
  private final boolean process;

  /** Whether to wait for requested documents to be processed if not already. Default false. */
  private final boolean wait;

  /**
   * Whether or not this source is only a dependency for other sources. When set to true, documents
   * from this source are only saved if they are dependencies for other sources. Default false.
   */
  private final boolean dependencyOnly;

  /** The default limit of documents to return for harvest type queries. Default 10. */
  @lombok.Builder.Default private final int defaultLimit = 10;

  /**
   * Use this database for storing documents and other info for Box. Databases are source specific
   * so do not use the same one for multiple sources. Default MemoryDatabase.
   */
  @lombok.Builder.Default private final BoxDatabase db = new MemoryDatabase();

  /**
   * In the case that the database is read-only database, it's still important to know where a
   * harvest left off. This will override the regular db if set. Default null.
   */
  private final BoxDatabase cursorDb;

  /** If there is any other extension class that you want Box to manage. */
  @Singular private final List others;

  /** Whether or not to enable posting of documents to web endpoints. */
  private final boolean postEnabled;

  /**
   * Returns cursorDb if not null, otherwise db.
   *
   * @return cursorDb if not null, otherwise db
   */
  public BoxDatabase getPreferredCursorDb() {
    return cursorDb != null ? cursorDb : db;
  }

  /**
   * Returns a builder for {@link SourceConfig}.
   *
   * @return a builder
   */
  public static SourceConfigBuilder builder() {
    return new SourceConfigBuilder().new InnerSourceConfigBuilder();
  }

  /** The builder for {@link SourceConfig}. */
  public static class SourceConfigBuilder {

    private Map> facetFields = new LinkedHashMap<>();

    /**
     * Each time a document is saved, fields that match the dot-notated paths will be added as
     * facets with the given name.
     *
     * @param name name of the facet
     * @param path path to the field in the document
     * @return this
     */
    public SourceConfigBuilder facetFields(String name, String... path) {
      return facetFields(name, Arrays.asList(path));
    }

    /**
     * Each time a document is saved, fields that match the dot-notated paths will be added as
     * facets with the given name.
     *
     * @param name name of facet
     * @param path path to the field in the document
     * @return this
     */
    public SourceConfigBuilder facetFields(String name, Collection path) {
      facetFields.computeIfAbsent(name, k -> new LinkedHashSet<>()).addAll(path);
      return this;
    }

    /**
     * Returns the source's name.
     *
     * @return the source's name
     */
    protected String getName() {
      return name;
    }

    private class InnerSourceConfigBuilder extends SourceConfigBuilder {

      @Override
      public SourceConfig build() {

        if (RESERVED_SOURCE_NAMES.contains(super.name)) {
          throw new IllegalArgumentException(super.name + " is a reserved source name");
        }

        Map> newFacetFields = new LinkedHashMap<>();
        super.facetFields
            .entrySet()
            .forEach(
                e ->
                    newFacetFields.put(
                        e.getKey(),
                        Collections.unmodifiableSet(new LinkedHashSet<>(e.getValue()))));

        super.facetFields = Collections.unmodifiableMap(newFacetFields);

        return super.build();
      }
    }
  }

  /**
   * Creates a new builder for SourceConfig.
   *
   * @deprecated Use {@link SourceConfig#builder()} instead.
   * @author Charles Draper
   */
  @Deprecated
  public static class Builder extends SourceConfigBuilder {

    /**
     * Creates a new {@link Builder}.
     *
     * @param name the name of the source
     */
    public Builder(String name) {
      if (RESERVED_SOURCE_NAMES.contains(name)) {
        throw new IllegalArgumentException(name + " is a reserved source name");
      }

      name(name);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy