/* Copyright (c) 2012-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:
* Gabriel Roldan (Boundless) - initial implementation
*/
package org.locationtech.geogig.storage.memory;
import static com.google.common.base.Suppliers.ofInstance;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import org.locationtech.geogig.api.plumbing.merge.Conflict;
import org.locationtech.geogig.repository.RepositoryConnectionException;
import org.locationtech.geogig.storage.AbstractObjectDatabase;
import org.locationtech.geogig.storage.AbstractStagingDatabase;
import org.locationtech.geogig.storage.ObjectDatabase;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
import com.google.common.collect.UnmodifiableIterator;
import com.google.inject.Inject;
/**
* Provides an implementation of a GeoGig staging database that utilizes the heap for the storage of
* objects.
*
* @see AbstractObjectDatabase
*/
public class HeapStagingDatabase extends AbstractStagingDatabase {
private Map<String, Map<String, Conflict>> conflicts = Maps.newHashMap();
/**
* @param repositoryDb the repository reference database, used to get delegate read operations
* to for objects not found here
*/
@Inject
public HeapStagingDatabase(final ObjectDatabase repositoryDb) {
super(ofInstance(repositoryDb), ofInstance(new HeapObjectDatabse()));
}
@Override
public void configure() throws RepositoryConnectionException {
// No-op
}
@Override
public void checkConfig() throws RepositoryConnectionException {
// No-op
}
/**
* Gets all conflicts that match the specified path filter.
*
* @param namespace the namespace of the conflict
* @param pathFilter the path filter, if this is not defined, all conflicts will be returned
* @return the list of conflicts
*/
@Override
public List<Conflict> getConflicts(@Nullable String namespace, @Nullable final String pathFilter) {
if (namespace == null) {
namespace = "root";
}
if (conflicts.get(namespace) == null) {
return ImmutableList.of();
}
if (pathFilter == null) {
return ImmutableList.copyOf(conflicts.get(namespace).values());
}
UnmodifiableIterator<Conflict> filtered = Iterators.filter(conflicts.get(namespace)
.values().iterator(), new Predicate<Conflict>() {
@Override
public boolean apply(@Nullable Conflict c) {
return (c.getPath().startsWith(pathFilter));
}
});
return ImmutableList.copyOf(filtered);
}
/**
* Adds a conflict to the database.
*
* @param namespace the namespace of the conflict
* @param conflict the conflict to add
*/
@Override
public void addConflict(@Nullable String namespace, Conflict conflict) {
if (namespace == null) {
namespace = "root";
}
Map<String, Conflict> conflictMap = conflicts.get(namespace);
if (conflictMap == null) {
conflictMap = Maps.newHashMap();
conflicts.put(namespace, conflictMap);
}
conflictMap.put(conflict.getPath(), conflict);
}
/**
* Removes a conflict from the database.
*
* @param namespace the namespace of the conflict
* @param path the path of feature whose conflict should be removed
*/
@Override
public void removeConflict(@Nullable String namespace, String path) {
if (namespace == null) {
namespace = "root";
}
Map<String, Conflict> conflictMap = conflicts.get(namespace);
if (conflictMap != null) {
conflictMap.remove(path);
}
}
/**
* Gets the specified conflict from the database.
*
* @param namespace the namespace of the conflict
* @param path the conflict to retrieve
* @return the conflict, or {@link Optional#absent()} if it was not found
*/
@Override
public Optional<Conflict> getConflict(@Nullable String namespace, String path) {
if (namespace == null) {
namespace = "root";
}
Map<String, Conflict> conflictMap = conflicts.get(namespace);
if (conflictMap != null) {
return Optional.fromNullable(conflictMap.get(path));
}
return Optional.absent();
}
/**
* Removes all conflicts from the database.
*
* @param namespace the namespace of the conflicts to remove
*/
@Override
public void removeConflicts(@Nullable String namespace) {
if (namespace == null) {
namespace = "root";
}
conflicts.remove(namespace);
}
@Override
public boolean hasConflicts(String namespace) {
if (namespace == null) {
namespace = "root";
}
Map<String, Conflict> conflicts = this.conflicts.get(namespace);
return conflicts != null && !conflicts.isEmpty();
}
}