edu.byu.hbll.box.Box Maven / Gradle / Ivy
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