package co.codewizards.cloudstore.local.dto; import static co.codewizards.cloudstore.core.objectfactory.ObjectFactoryUtil.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import co.codewizards.cloudstore.core.dto.DirectoryDto; import co.codewizards.cloudstore.core.dto.NormalFileDto; import co.codewizards.cloudstore.core.dto.RepoFileDto; import co.codewizards.cloudstore.core.dto.SymlinkDto; import co.codewizards.cloudstore.core.dto.TempChunkFileDto; import co.codewizards.cloudstore.core.dto.jaxb.TempChunkFileDtoIo; import co.codewizards.cloudstore.core.oio.File; import co.codewizards.cloudstore.core.repo.local.LocalRepoManager; import co.codewizards.cloudstore.core.repo.local.LocalRepoTransaction; import co.codewizards.cloudstore.core.util.AssertUtil; import co.codewizards.cloudstore.local.persistence.Directory; import co.codewizards.cloudstore.local.persistence.FileChunk; import co.codewizards.cloudstore.local.persistence.NormalFile; import co.codewizards.cloudstore.local.persistence.RepoFile; import co.codewizards.cloudstore.local.persistence.RepoFileDao; import co.codewizards.cloudstore.local.persistence.Symlink; import co.codewizards.cloudstore.local.transport.TempChunkFileManager; import co.codewizards.cloudstore.local.transport.TempChunkFileWithDtoFile; public class RepoFileDtoConverter { private static final Logger logger = LoggerFactory.getLogger(RepoFileDtoConverter.class); private final TempChunkFileManager tempChunkFileManager = TempChunkFileManager.getInstance(); private final FileChunkDtoConverter fileChunkDtoConverter = FileChunkDtoConverter.create(); private final LocalRepoManager localRepoManager; private final LocalRepoTransaction transaction; private final RepoFileDao repoFileDao; private boolean excludeLocalIds; private boolean excludeMutableData; public static RepoFileDtoConverter create(final LocalRepoTransaction transaction) { return createObject(RepoFileDtoConverter.class, transaction); } protected RepoFileDtoConverter(final LocalRepoTransaction transaction) { this.transaction = AssertUtil.assertNotNull(transaction, "transaction"); this.localRepoManager = AssertUtil.assertNotNull(transaction.getLocalRepoManager(), "transaction.localRepoManager"); this.repoFileDao = this.transaction.getDao(RepoFileDao.class); } public RepoFileDto toRepoFileDto(final RepoFile repoFile, final int depth) { AssertUtil.assertNotNull(repoFileDao, "repoFileDao"); AssertUtil.assertNotNull(repoFile, "repoFile"); final RepoFileDto repoFileDto; if (repoFile instanceof NormalFile) { final NormalFile normalFile = (NormalFile) repoFile; final NormalFileDto normalFileDto; repoFileDto = normalFileDto = createObject(NormalFileDto.class); if (isExcludeMutableData()) normalFileDto.setLength(-1); else { normalFileDto.setLength(normalFile.getLength()); normalFileDto.setSha1(normalFile.getSha1()); } if (depth > 0) { // TODO this should actually be a SortedSet, but for whatever reason, I started // getting ClassCastExceptions and had to switch to a normal Set :-( final List<FileChunk> fileChunks = new ArrayList<>(normalFile.getFileChunks()); Collections.sort(fileChunks); for (final FileChunk fileChunk : fileChunks) { normalFileDto.getFileChunkDtos().add(fileChunkDtoConverter.toFileChunkDto(fileChunk)); } } if (depth > 1) { final TempChunkFileDtoIo tempChunkFileDtoIo = new TempChunkFileDtoIo(); final File file = repoFile.getFile(localRepoManager.getLocalRoot()); for (final TempChunkFileWithDtoFile tempChunkFileWithDtoFile : tempChunkFileManager.getOffset2TempChunkFileWithDtoFile(file).values()) { final File tempChunkFileDtoFile = tempChunkFileWithDtoFile.getTempChunkFileDtoFile(); if (tempChunkFileDtoFile == null) continue; // incomplete: meta-data not yet written => ignore final TempChunkFileDto tempChunkFileDto; try { tempChunkFileDto = tempChunkFileDtoIo.deserialize(tempChunkFileDtoFile); } catch (final Exception x) { logger.warn("toRepoFileDto: Ignoring corrupt tempChunkFileDtoFile '" + tempChunkFileDtoFile.getAbsolutePath() + "': " + x, x); continue; } normalFileDto.getTempFileChunkDtos().add(AssertUtil.assertNotNull(tempChunkFileDto.getFileChunkDto(), "tempChunkFileDto.fileChunkDto")); } } } else if (repoFile instanceof Directory) { repoFileDto = createObject(DirectoryDto.class); } else if (repoFile instanceof Symlink) { final Symlink symlink = (Symlink) repoFile; final SymlinkDto symlinkDto; repoFileDto = symlinkDto = createObject(SymlinkDto.class); if (! isExcludeMutableData()) symlinkDto.setTarget(symlink.getTarget()); } else throw new UnsupportedOperationException("RepoFile type not yet supported: " + repoFile); if (! isExcludeLocalIds()) { repoFileDto.setId(repoFile.getId()); repoFileDto.setParentId(repoFile.getParent() == null ? null : repoFile.getParent().getId()); repoFileDto.setLocalRevision(repoFile.getLocalRevision()); } repoFileDto.setName(repoFile.getName()); repoFileDto.setLastModified(repoFile.getLastModified()); return repoFileDto; } public boolean isExcludeLocalIds() { return excludeLocalIds; } public void setExcludeLocalIds(final boolean excludeLocalIds) { this.excludeLocalIds = excludeLocalIds; } public boolean isExcludeMutableData() { return excludeMutableData; } public void setExcludeMutableData(boolean excludeMutableData) { this.excludeMutableData = excludeMutableData; } }