/* 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 static org.locationtech.geogig.storage.sqlite.SQLiteStorage.FORMAT_NAME; import static org.locationtech.geogig.storage.sqlite.SQLiteStorage.VERSION; import java.util.List; import org.locationtech.geogig.api.Platform; import org.locationtech.geogig.api.plumbing.merge.Conflict; import org.locationtech.geogig.repository.RepositoryConnectionException; import org.locationtech.geogig.storage.AbstractStagingDatabase; import org.locationtech.geogig.storage.ConfigDatabase; import org.locationtech.geogig.storage.ObjectDatabase; import com.google.common.base.Optional; import com.google.common.base.Suppliers; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; /** * Base class for SQLite based staging database. * * @author Justin Deoliveira, Boundless * * @param <T> */ public abstract class SQLiteStagingDatabase<T> extends AbstractStagingDatabase { final ConfigDatabase configdb; final Platform platform; private T cx; public SQLiteStagingDatabase(ObjectDatabase repoDb, SQLiteObjectDatabase<T> stageDb, ConfigDatabase configdb, Platform platform) { super(Suppliers.ofInstance(repoDb), Suppliers.ofInstance(stageDb)); this.configdb = configdb; this.platform = platform; } @SuppressWarnings("unchecked") @Override public void open() { super.open(); cx = ((SQLiteObjectDatabase<T>) stagingDb).cx; init(cx); } @Override public Optional<Conflict> getConflict(String namespace, String path) { List<Conflict> conflicts = getConflicts(namespace, path); if (conflicts.isEmpty()) { return Optional.absent(); } return Optional.of(conflicts.get(0)); } @Override public boolean hasConflicts(String namespace) { int count = count(namespace, cx); return count > 0; } @Override public List<Conflict> getConflicts(String namespace, String pathFilter) { return Lists.newArrayList(Iterables.transform(get(namespace, pathFilter, cx), StringToConflict.INSTANCE)); } @Override public void addConflict(String namespace, Conflict conflict) { put(namespace, conflict.getPath(), conflict.toString(), cx); } @Override public void removeConflict(String namespace, String path) { remove(namespace, path, cx); } @Override public void removeConflicts(String namespace) { for (Conflict c : Iterables.transform(get(namespace, null, cx), StringToConflict.INSTANCE)) { removeConflict(namespace, c.getPath()); } } @Override public void configure() throws RepositoryConnectionException { RepositoryConnectionException.StorageType.STAGING.configure(configdb, FORMAT_NAME, VERSION); } @Override public void checkConfig() throws RepositoryConnectionException { RepositoryConnectionException.StorageType.STAGING.verify(configdb, FORMAT_NAME, VERSION); } /** * Creates the object table with the following schema: * * <pre> * conflicts(namespace:varchar, path:varchar, conflict:varchar) * </pre> * * Implementations of this method should be prepared to be called multiple times, so must check * if the table already exists. * * @param cx The connection object. */ protected abstract void init(T cx); /** * Returns the number of conflicts matching the specified namespace filter. * * @param namespace Namespace value, may be <code>null</code>. * */ protected abstract int count(final String namespace, T cx); /** * Returns all conflicts matching the specified namespace and pathFilter. * * @param namespace Namespace value, may be <code>null</code>. * @param pathFilter Path filter, may be <code>null</code>. * */ protected abstract Iterable<String> get(String namespace, String pathFilter, T cx); /** * Adds a conflict. * * @param namespace The conflict namespace. * @param path The path of the conflict. * @param conflict The conflict value. */ protected abstract void put(String namespace, String path, String conflict, T cx); /** * Removed a conflict. * * @param namespace The conflict namespace. * @param path The path of the conflict. */ protected abstract void remove(String namespace, String path, T cx); }