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

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

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

import com.fasterxml.jackson.databind.JsonNode;
import edu.byu.hbll.box.internal.core.ConfigParser;
import edu.byu.hbll.box.internal.core.DefaultObjectFactory;
import edu.byu.hbll.box.internal.core.Registry;
import java.io.Closeable;
import java.util.ArrayList;
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 java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import lombok.Getter;

/**
 * The principal API into the Box system. Start with a configuration file.
 *
 * 
 * Box box = newBox(config).build();
 * 
* *

Or configure Box programmatically with the builder. * *

 * Box box = newBuilder()...build();
 * 
* * @author Charles Draper */ public class Box implements Closeable { private final Map sources; private final List sourceNames; private final Registry registry; @Getter private final ThreadFactory threadFactory; /** Create a new uninitialized Box. */ private Box(Builder builder) { this.registry = new Registry(this, builder.sources, builder.threadFactory); this.threadFactory = builder.threadFactory; // preserve order Map sources = new LinkedHashMap<>(); registry.getSources().forEach(s -> sources.put(s.getName(), new Source(s, registry))); sources.put( SourceConfig.PRINCIPAL_SOURCE_ALIAS, sources.get(registry.getPrincipalSource().getName())); this.sources = Collections.unmodifiableMap(sources); // preserve order and make sure unique (principal source gets listed twice) Set sourceNames = new LinkedHashSet<>(); this.sources.values().forEach(s -> sourceNames.add(s.getName())); this.sourceNames = List.copyOf(sourceNames); for (String sourceName : this.sourceNames) { Source source = this.sources.get(sourceName); SourceConfig config = source.getConfig(); postInit(source, config.getCursorDb(), ObjectType.CURSOR_DATABASE); postInit(source, config.getDb(), ObjectType.BOX_DATABASE); postInit(source, config.getHarvester(), ObjectType.HARVESTER); postInit(source, config.getProcessor(), ObjectType.PROCESSOR); config.getOthers().forEach(o -> postInit(source, o, ObjectType.OTHER)); } // start all scheduled timers registry.startSchedules(); } private void postInit(Source source, BoxConfigurable object, ObjectType type) { if (object != null) { object.postInit(new InitConfig(this, source, type)); } } /** * Creates a new {@link Box} from the supplied configuration. * * @param config the config to use * @return the new Box builder */ public static Box newBox(JsonNode config) { return newBuilder().config(config).build(); } /** * Creates a new builder. * * @return the new Box builder */ public static Box.Builder newBuilder() { return new Builder(); } /** * Returns the principal source. * * @return the principal source */ public Source getPrincipalSource() { return sources.get(SourceConfig.PRINCIPAL_SOURCE_ALIAS); } /** * Returns a snapshot of the health of the Box system. * * @return the health of Box */ public BoxHealth getHealth() { return registry.getBoxHealthCheck().getHealth(); } /** * Returns the registered source denoted by the name. * *

IMPORTANT: Once a source is registered it should not be modified. * * @param sourceName the name of the source * @return the registered source */ public Source getSource(String sourceName) { return sources.get(registry.verifySource(sourceName)); } /** * Returns a list of the registered sources. * *

IMPORTANT: Once a source is registered it should not be modified. * * @return the list of registered sources */ public Map getSources() { return sources; } /** * Returns a list of names of the registered sources. * * @return list of source names */ public List getSourceNames() { return sourceNames; } /** * Verifies the existence of the source and returns it's name. Throws exception if source is not * recognized. * * @param sourceName the source to verify * @return the sourceName * @throws IllegalArgumentException if source is not recognized */ public String verifySource(String sourceName) { return registry.verifySource(sourceName); } /** Closes this Box instance and shutdowns down all internal scheduling and executors. */ @Override public void close() { registry.preDestroy(); } /** * The configuration used to instantiate Box. Primarily it holds the source definitions. It can * also build the configuration from a {@link JsonNode}. * * @author Charles Draper */ public static class Builder { private List configs = new ArrayList<>(); private List sources = new ArrayList<>(); private ThreadFactory threadFactory = Executors.defaultThreadFactory(); private ObjectFactory objectFactory = new DefaultObjectFactory(); /** * Adds the given source to this configuration. * * @param sourceConfig the {@link SourceConfig} to add * @return this */ public Builder source(SourceConfig sourceConfig) { this.configs.add(sourceConfig); return this; } /** * Sets the thread factory to use for any multithreaded harvesting/processing inside of Box. * * @param threadFactory the thread factory to use * @return this */ public Builder threadFactory(ThreadFactory threadFactory) { this.threadFactory = threadFactory; return this; } /** * Sets all parameters held in the {@link JsonNode}. * * @param config the config to add * @return this */ public Builder config(JsonNode config) { this.configs.add(config); return this; } /** * The factory for creating Box objects such as processor and harvester. {@link * DefaultObjectFactory} is used by default. Frameworks may provide their own factory for * accessing managed objects. * * @param objectFactory a factory for creating Box objects * @return this */ public Builder objectFactory(ObjectFactory objectFactory) { this.objectFactory = objectFactory; return this; } /** * Builds the new Box instance. * * @return the new Box */ public Box build() { // we add sources in the order they were registered because the first one is considered the // principal source unless otherwise indicated for (Object config : configs) { if (config instanceof SourceConfig) { this.sources.add((SourceConfig) config); } else if (config instanceof JsonNode) { this.sources.addAll(ConfigParser.parse((JsonNode) config, objectFactory)); } } return new Box(this); } } }