package com.after_sunrise.oss.otdb.je.service;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.io.IOUtils;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.after_sunrise.oss.otdb.api.service.TickIterator;
import com.after_sunrise.oss.otdb.api.service.TickService;
import com.after_sunrise.oss.otdb.api.tick.Tick;
import com.google.common.annotations.VisibleForTesting;
/**
* @author takanori.takase
*/
public class JeTickService implements TickService {
private static final String DEFAULT = "open-tickdb-context-read.xml";
private final Lock lock = new ReentrantLock();
private volatile String config = DEFAULT;
private volatile ConfigurableApplicationContext context;
private volatile TickService delegate;
public void setConfig(String config) {
try {
lock.lock();
_setConfig(config);
} finally {
lock.unlock();
}
}
private void _setConfig(String config) {
if (getClass().getClassLoader().getResource(config) == null) {
throw new IllegalArgumentException("Invalid config : " + config);
}
if (delegate != null) {
throw new IllegalStateException("Tick service already initialized.");
}
this.config = config;
}
@Override
public void initialize() throws IOException {
try {
lock.lock();
_initialize();
} catch (IOException e) {
IOUtils.closeQuietly(this);
throw e;
} finally {
lock.unlock();
}
}
private void _initialize() throws IOException {
if (delegate != null) {
throw new IOException("Tick service already initialized.");
}
context = new ClassPathXmlApplicationContext(config);
delegate = context.getBean(JeTickServiceDelegate.class);
delegate.initialize();
}
@Override
public void close() throws IOException {
try {
lock.lock();
_close();
} finally {
lock.unlock();
}
}
private void _close() throws IOException {
if (delegate == null) {
throw new IOException("Tick service already closed.");
}
IOUtils.closeQuietly(delegate);
delegate = null;
context.close();
}
@VisibleForTesting
TickService getDelegate() throws IOException {
TickService reference;
try {
lock.lock();
reference = delegate;
} finally {
lock.unlock();
}
if (reference == null) {
throw new IOException("Service not initialized.");
}
return reference;
}
@Override
public List<Tick> find(String code, Long start, Long end)
throws IOException {
return getDelegate().find(code, start, end);
}
@Override
public List<Tick> find(String code, Long start, Long end,
Set<Integer> fields) throws IOException {
return getDelegate().find(code, start, end, fields);
}
@Override
public TickIterator iterate(String code, Long start, Long end)
throws IOException {
return getDelegate().iterate(code, start, end);
}
@Override
public TickIterator iterate(String code, Long start, Long end,
Set<Integer> fields) throws IOException {
return getDelegate().iterate(code, start, end, fields);
}
}