package org.n3r.eql.impl;
import com.google.common.base.Optional;
import com.google.common.base.Throwables;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.LoadingCache;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.n3r.eql.base.EqlResourceLoader;
import org.n3r.eql.parser.EqlBlock;
import org.n3r.eql.util.C;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import static org.n3r.eql.impl.EqlResourceLoaderHelper.updateFileCache;
@Slf4j @NoArgsConstructor
public class FileEqlResourceLoader extends AbstractEqlResourceLoader {
static Cache<String, Optional<Map<String, EqlBlock>>> fileCache;
static LoadingCache<EqlUniqueSqlId, Optional<EqlBlock>> sqlCache;
static {
fileCache = CacheBuilder.newBuilder().build();
sqlCache = EqlResourceLoaderHelper.buildSqlCache(fileCache);
}
@Override
public EqlBlock loadEqlBlock(String sqlClassPath, String sqlId) {
load(this, sqlClassPath);
val eqlBlock = sqlCache.getUnchecked(new EqlUniqueSqlId(sqlClassPath, sqlId));
if (eqlBlock.isPresent()) return eqlBlock.get();
throw new RuntimeException("unable to find sql id " + sqlId);
}
@Override
public Map<String, EqlBlock> load(String classPath) {
return load(this, classPath);
}
@SneakyThrows
private Map<String, EqlBlock> load(final EqlResourceLoader eqlResourceLoader,
final String sqlClassPath) {
val valueLoader = new Callable<Optional<Map<String, EqlBlock>>>() {
@Override
public Optional<Map<String, EqlBlock>> call() throws Exception {
String sqlContent = C.classResourceToString(sqlClassPath);
if (sqlContent == null) {
log.warn("classpath sql {} not found", sqlClassPath);
return Optional.absent();
}
return Optional.of(updateFileCache(sqlContent,
eqlResourceLoader, sqlClassPath, eqlLazyLoad));
}
};
try {
return fileCache.get(sqlClassPath, valueLoader).orNull();
} catch (ExecutionException e) {
throw Throwables.getRootCause(e);
}
}
}