package de.is24.infrastructure.gridfs.http.repos;
import com.mongodb.DBObject;
import de.is24.infrastructure.gridfs.http.domain.Container;
import de.is24.infrastructure.gridfs.http.domain.FileInfo;
import de.is24.infrastructure.gridfs.http.domain.FolderInfo;
import de.is24.infrastructure.gridfs.http.domain.RepoEntry;
import de.is24.infrastructure.gridfs.http.domain.RepoType;
import de.is24.infrastructure.gridfs.http.domain.SortField;
import de.is24.infrastructure.gridfs.http.domain.SortOrder;
import de.is24.infrastructure.gridfs.http.exception.RepositoryNotFoundException;
import de.is24.infrastructure.gridfs.http.metadata.RepoEntriesRepository;
import de.is24.util.monitoring.spring.TimeMeasurement;
import org.apache.commons.lang.NotImplementedException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import static com.google.common.collect.Maps.newLinkedHashMap;
import static de.is24.infrastructure.gridfs.http.domain.FolderInfo.fromRepoEntry;
import static de.is24.infrastructure.gridfs.http.domain.RepoType.VIRTUAL;
import static de.is24.infrastructure.gridfs.http.domain.SortField.name;
import static de.is24.infrastructure.gridfs.http.domain.SortOrder.asc;
import static java.lang.String.format;
@Service
public class VirtualRepositoryInfoProvider implements RepositoryInfoProvider {
private final RepoEntriesRepository entriesRepository;
private final RepositoryInfoProvider staticRepositoryInfoProvider;
@Autowired
public VirtualRepositoryInfoProvider(RepoEntriesRepository entriesRepository,
RepositoryInfoProvider staticRepositoryInfoProvider) {
this.entriesRepository = entriesRepository;
this.staticRepositoryInfoProvider = staticRepositoryInfoProvider;
}
@Override
@TimeMeasurement
public Container<FolderInfo> getRepos(SortField sortBy, SortOrder sortOrder) {
final Sort sort = new Sort(sortOrder.asDirection(), sortBy.name());
List<RepoEntry> virtualRepos = entriesRepository.findByType(VIRTUAL, sort);
return new Container<>("virtual", adaptVirtualRepos(virtualRepos));
}
@Override
public Container<FolderInfo> getArchs(String repoName, SortField sortBy, SortOrder sortOrder) {
Container<FolderInfo> staticArchsContainer = staticRepositoryInfoProvider.getArchs(
getVirtualRepoOrThrowNotFoundException(repoName).getTarget(), sortBy, sortOrder);
return new Container<>(pathWithSuffix(repoName), staticArchsContainer);
}
private RepoEntry getVirtualRepoOrThrowNotFoundException(String repoName) throws RepositoryNotFoundException {
RepoEntry virtualRepo = entriesRepository.findFirstByNameAndType(repoName, VIRTUAL);
if (virtualRepo == null) {
throw new RepositoryNotFoundException("Virtual repository not found.", repoName);
}
return virtualRepo;
}
@Override
public Container<FileInfo> getFileInfo(String repoName, String arch,
SortField sortBy, SortOrder sortOrder) {
RepoEntry virtualRepo = getVirtualRepoOrThrowNotFoundException(repoName);
Container<FileInfo> staticFileInfo = staticRepositoryInfoProvider.getFileInfo(virtualRepo.getTarget(), arch,
sortBy, sortOrder);
return new Container<>(pathWithSuffix(format("%s/%s", repoName, arch)), staticFileInfo);
}
@Override
public RepoType[] getValidRepoTypes() {
return new RepoType[] { VIRTUAL };
}
private static String pathWithSuffix(String suffix) {
return "virtual/" + suffix;
}
private List<FolderInfo> adaptVirtualRepos(List<RepoEntry> virtualRepos) {
Map<String, Long> sizeByName = getSizeByName();
List<FolderInfo> result = new ArrayList<>(virtualRepos.size());
for (RepoEntry virtualRepo : virtualRepos) {
Long size = sizeByName.get(virtualRepo.getTarget());
if (size == null) {
size = 0L;
}
FolderInfo folderInfo = fromRepoEntry(virtualRepo, size);
result.add(folderInfo);
}
return result;
}
Map<String, Long> getSizeByName() {
Iterable<DBObject> dbObjects = staticRepositoryInfoProvider.getReposAggregation(name, asc);
Map<String, Long> result = newLinkedHashMap();
for (DBObject object : dbObjects) {
FolderInfo folderInfo = new FolderInfo(object);
result.put(folderInfo.getName(), folderInfo.getSize());
}
return result;
}
@Override
public Container<FileInfo> find(String filenameRegex, String repo, String arch, SortField sortBy,
SortOrder sortOrder) {
return null;
}
@Override
public Container<FileInfo> find(String filenameRegex, String repo, SortField sortBy, SortOrder sortOrder) {
return null;
}
@Override
public Container<FileInfo> find(String filenameRegex, SortField sortBy, SortOrder sortOrder) {
return null;
}
@Override
public Iterable<DBObject> getReposAggregation(SortField sortBy, SortOrder sortOrder) {
// "this is not defined for virtual repos"
throw new NotImplementedException();
}
@Override
public List<RepoEntry> find(String repoNameRegex, String tag, Date newer, Date older) {
return new ArrayList<>();
}
@Override
public List<RepoEntry> find(String repoNameRegex, Date newer, Date older) {
return new ArrayList<>();
}
@Override
public List<RepoEntry> find(String repoNameRegex) {
return entriesRepository.findByTypeAndNameMatchesRegex(VIRTUAL, repoNameRegex);
}
@Override
public boolean isExternalRepo(String repoName) {
return getVirtualRepoOrThrowNotFoundException(repoName).isExternal();
}
@Override
public String getRedirectUrl(String repoName) {
RepoEntry repoEntry = getVirtualRepoOrThrowNotFoundException(repoName);
if (!repoEntry.isExternal()) {
throw new IllegalArgumentException(repoName + " is not an external repo");
}
return repoEntry.getTarget();
}
@Override
public String getRedirectUrl(String repoName, String arch) {
String url = getRedirectUrl(repoName);
if (!url.endsWith("/")) {
url += "/";
}
return url + arch + "/";
}
}