/* Copyright (c) 2014 Boundless and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/edl-v10.html
*
* Contributors:
* Justin Deoliveira (Boundless) - initial implementation
*/
package org.locationtech.geogig.storage.sqlite;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import org.locationtech.geogig.api.Platform;
import org.locationtech.geogig.api.plumbing.ResolveGeogigDir;
import org.locationtech.geogig.api.porcelain.ConfigException;
import org.locationtech.geogig.api.porcelain.ConfigException.StatusCode;
import org.locationtech.geogig.storage.ConfigDatabase;
import com.google.common.base.Optional;
/**
* Base class for SQLite based config database.
*
* @author Justin Deoliveira, Boundless
*
*/
public abstract class SQLiteConfigDatabase implements ConfigDatabase {
final Platform platform;
File lastWorkingDir;
File lastUserDir;
Config local;
Config global;
protected SQLiteConfigDatabase(Platform platform) {
this.platform = platform;
}
@Override
public Optional<String> get(String key) {
return get(new Entry(key), String.class, local());
}
@Override
public Optional<String> getGlobal(String key) {
return get(new Entry(key), String.class, global());
}
@Override
public <T> Optional<T> get(String key, Class<T> c) {
return get(new Entry(key), c, local());
}
@Override
public <T> Optional<T> getGlobal(String key, Class<T> c) {
return get(new Entry(key), c, global());
}
@Override
public Map<String, String> getAll() {
return all(local());
}
@Override
public Map<String, String> getAllGlobal() {
return all(global());
}
@Override
public Map<String, String> getAllSection(String section) {
return all(section, local());
}
@Override
public Map<String, String> getAllSectionGlobal(String section) {
return all(section, global());
}
@Override
public List<String> getAllSubsections(String section) {
return list(section, local());
}
@Override
public List<String> getAllSubsectionsGlobal(String section) {
return list(section, global());
}
@Override
public void put(String key, Object value) {
put(new Entry(key), value, local());
}
@Override
public void putGlobal(String key, Object value) {
put(new Entry(key), value, global());
}
@Override
public void remove(String key) {
remove(new Entry(key), local());
}
@Override
public void removeGlobal(String key) {
remove(new Entry(key), global());
}
@Override
public void removeSection(String key) {
removeAll(key, local());
}
@Override
public void removeSectionGlobal(String key) {
removeAll(key, global());
}
<T> Optional<T> get(Entry entry, Class<T> clazz, Config config) {
String raw = get(entry, config);
if (raw != null) {
return Optional.of(convert(raw, clazz));
}
return Optional.absent();
}
<T> T convert(String value, Class<T> clazz) {
// TODO: actually convert
return clazz.cast(value);
}
void put(Entry entry, Object value, Config config) {
put(entry, (String) (value != null ? value.toString() : null), config);
}
Config local() {
if (local == null || !lastWorkingDir.equals(platform.pwd())) {
final Optional<URL> url = new ResolveGeogigDir(platform).call();
if (!url.isPresent()) {
throw new ConfigException(StatusCode.INVALID_LOCATION);
}
URL u = url.get();
File localFile;
try {
localFile = new File(new File(u.toURI()), "config.db");
} catch (URISyntaxException e) {
localFile = new File(u.getPath(), "config.db");
}
lastWorkingDir = platform.pwd();
local = new Config(localFile);
}
return local;
}
Config global() {
if (global == null || !lastUserDir.equals(platform.getUserHome())) {
File home = platform.getUserHome();
if (home == null) {
throw new ConfigException(StatusCode.USERHOME_NOT_SET);
}
File globalDir = new File(home.getPath(), ".geogig");
if (globalDir.exists() && !globalDir.isDirectory()) {
throw new IllegalStateException(globalDir.getAbsolutePath()
+ " exists but is not a directory");
}
if (!globalDir.exists() && !globalDir.mkdir()) {
throw new ConfigException(StatusCode.CANNOT_WRITE);
}
lastUserDir = home;
global = new Config(new File(globalDir, "config.db"));
}
return global;
}
protected static class Config {
final File file;
public Config(File file) {
this.file = file;
}
}
protected static class Entry {
final String section;
final String key;
public Entry(String entry) {
String[] split = entry.split("\\.");
section = split[0];
key = split[1];
}
}
protected abstract String get(Entry entry, Config config);
protected abstract Map<String, String> all(Config config);
protected abstract Map<String, String> all(String section, Config config);
protected abstract List<String> list(String section, Config config);
protected abstract void put(Entry entry, String value, Config config);
protected abstract void remove(Entry entry, Config config);
protected abstract void removeAll(String section, Config config);
}