/**
* Copyright (C) 2015 meltmedia (christian.trimble@meltmedia.com)
*
* 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.meltmedia.dropwizard.etcd.json;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Supplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import mousio.etcd4j.EtcdClient;
import com.codahale.metrics.MetricRegistry;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* A factory for mapped interfaces to Etcd.
*
* @author Christian Trimble
*/
public class EtcdJson {
private static Logger logger = LoggerFactory.getLogger(EtcdJson.class);
public static class Builder {
private ObjectMapper mapper;
private Supplier<EtcdClient> clientSupplier;
private String baseDirectory = "";
private ScheduledExecutorService executor;
private MetricRegistry registry;
public Builder withMapper(ObjectMapper mapper) {
this.mapper = mapper;
return this;
}
public Builder withClient(Supplier<EtcdClient> clientSupplier) {
this.clientSupplier = clientSupplier;
return this;
}
public Builder withBaseDirectory(String baseDirectory) {
this.baseDirectory = baseDirectory;
return this;
}
public Builder withExecutor(ScheduledExecutorService executor) {
this.executor = executor;
return this;
}
public Builder withMetricRegistry( MetricRegistry registry ) {
this.registry = registry;
return this;
}
public EtcdJson build() {
return new EtcdJson(clientSupplier, executor, mapper, baseDirectory, registry);
}
}
public static Builder builder() {
return new Builder();
}
private Supplier<EtcdClient> clientSupplier;
private ObjectMapper mapper;
private String baseDirectory;
private WatchService watchService;
private ScheduledExecutorService executor;
public EtcdJson(Supplier<EtcdClient> clientSupplier, ScheduledExecutorService executor,
ObjectMapper mapper, String baseDirectory, MetricRegistry registry) {
this.clientSupplier = clientSupplier;
this.executor = executor;
this.mapper = mapper;
this.baseDirectory = baseDirectory;
this.watchService =
WatchService.builder().withEtcdClient(clientSupplier).withExecutor(executor)
.withMapper(mapper).withDirectory(baseDirectory).withMetricRegistry(registry).build();
}
public void start() {
logger.info("starting EtcdFactory.");
this.watchService.start();
logger.info("started EtcdFactory.");
}
public void stop() {
logger.info("stopping EtcdFactory");
this.watchService.stop();
logger.info("Stopped EtcdFactory");
}
public WatchService getWatchService() {
return watchService;
}
public <T> Heartbeat<T> newHeartbeat(String key, T value, int ttl) {
return Heartbeat.<T> builder().withClient(clientSupplier).withExecutor(executor)
.withKey(baseDirectory + key).withMapper(mapper).withValue(value).withTtl(ttl).build();
}
public <T> MappedEtcdDirectory<T> newDirectory(String directory, TypeReference<T> type) {
return new MappedEtcdDirectory<T>(directory, type);
}
public EtcdDirectory newDirectory( String directory ) {
return new EtcdDirectory(directory);
}
public class MappedEtcdDirectory<T> extends EtcdDirectory {
private TypeReference<T> type;
protected MappedEtcdDirectory(String directory, TypeReference<T> type) {
super(directory);
this.type = type;
}
public WatchService.Watch registerWatch(EtcdEventHandler<T> handler) {
return watchService.registerDirectoryWatch(directory, type, handler);
}
public WatchService.Watch registerValueWatch(String key, EtcdEventHandler<T> handler) {
return watchService.registerValueWatch(directory, key, type, handler);
}
public Heartbeat<T> newHeartbeat(String key, T value, int ttl) {
return Heartbeat.<T> builder().withClient(clientSupplier).withExecutor(executor)
.withKey(baseDirectory + directory + key).withMapper(mapper).withValue(value).withTtl(ttl)
.build();
}
public EtcdDirectoryDao<T> newDao() {
return new EtcdDirectoryDao<T>(clientSupplier, baseDirectory + directory, mapper, type);
}
}
public class EtcdDirectory {
protected String directory;
public EtcdDirectory( String directory ) {
this.directory = directory;
}
public <U> MappedEtcdDirectory<U> newDirectory(String directory, TypeReference<U> type) {
return new MappedEtcdDirectory<U>(this.directory + directory, type);
}
public EtcdDirectory newDirectory(String directory) {
return new EtcdDirectory(this.directory + directory);
}
public <U> MappedEtcdDirectory<U> map( TypeReference<U> type ) {
return new MappedEtcdDirectory<U>(this.directory, type);
}
public String getName() {
return this.directory.replaceFirst(".*?([^/]*)\\Z", "$1");
}
public String getPath() {
return this.directory;
}
}
public ObjectMapper getMapper() {
return mapper;
}
}