001package co.codewizards.cloudstore.local.dto; 002 003import static co.codewizards.cloudstore.core.objectfactory.ObjectFactoryUtil.*; 004import static java.util.Objects.*; 005 006import java.util.ArrayList; 007import java.util.Collections; 008import java.util.List; 009 010import org.slf4j.Logger; 011import org.slf4j.LoggerFactory; 012 013import co.codewizards.cloudstore.core.dto.DirectoryDto; 014import co.codewizards.cloudstore.core.dto.NormalFileDto; 015import co.codewizards.cloudstore.core.dto.RepoFileDto; 016import co.codewizards.cloudstore.core.dto.SymlinkDto; 017import co.codewizards.cloudstore.core.dto.TempChunkFileDto; 018import co.codewizards.cloudstore.core.dto.jaxb.TempChunkFileDtoIo; 019import co.codewizards.cloudstore.core.oio.File; 020import co.codewizards.cloudstore.core.repo.local.LocalRepoManager; 021import co.codewizards.cloudstore.core.repo.local.LocalRepoTransaction; 022import co.codewizards.cloudstore.local.persistence.Directory; 023import co.codewizards.cloudstore.local.persistence.FileChunk; 024import co.codewizards.cloudstore.local.persistence.NormalFile; 025import co.codewizards.cloudstore.local.persistence.RepoFile; 026import co.codewizards.cloudstore.local.persistence.RepoFileDao; 027import co.codewizards.cloudstore.local.persistence.Symlink; 028import co.codewizards.cloudstore.local.transport.TempChunkFileManager; 029import co.codewizards.cloudstore.local.transport.TempChunkFileWithDtoFile; 030 031public class RepoFileDtoConverter { 032 033 private static final Logger logger = LoggerFactory.getLogger(RepoFileDtoConverter.class); 034 035 private final TempChunkFileManager tempChunkFileManager = TempChunkFileManager.getInstance(); 036 private final FileChunkDtoConverter fileChunkDtoConverter = FileChunkDtoConverter.create(); 037 private final LocalRepoManager localRepoManager; 038 private final LocalRepoTransaction transaction; 039 private final RepoFileDao repoFileDao; 040 private boolean excludeLocalIds; 041 private boolean excludeMutableData; 042 043 public static RepoFileDtoConverter create(final LocalRepoTransaction transaction) { 044 return createObject(RepoFileDtoConverter.class, transaction); 045 } 046 047 protected RepoFileDtoConverter(final LocalRepoTransaction transaction) { 048 this.transaction = requireNonNull(transaction, "transaction"); 049 this.localRepoManager = requireNonNull(transaction.getLocalRepoManager(), "transaction.localRepoManager"); 050 this.repoFileDao = this.transaction.getDao(RepoFileDao.class); 051 } 052 053 public RepoFileDto toRepoFileDto(final RepoFile repoFile, final int depth) { 054 requireNonNull(repoFileDao, "repoFileDao"); 055 requireNonNull(repoFile, "repoFile"); 056 final RepoFileDto repoFileDto; 057 if (repoFile instanceof NormalFile) { 058 final NormalFile normalFile = (NormalFile) repoFile; 059 final NormalFileDto normalFileDto; 060 repoFileDto = normalFileDto = createObject(NormalFileDto.class); 061 if (isExcludeMutableData()) 062 normalFileDto.setLength(-1); 063 else { 064 normalFileDto.setLength(normalFile.getLength()); 065 normalFileDto.setSha1(normalFile.getSha1()); 066 } 067 if (depth > 0) { 068 // TODO this should actually be a SortedSet, but for whatever reason, I started 069 // getting ClassCastExceptions and had to switch to a normal Set :-( 070 final List<FileChunk> fileChunks = new ArrayList<>(normalFile.getFileChunks()); 071 Collections.sort(fileChunks); 072 for (final FileChunk fileChunk : fileChunks) { 073 normalFileDto.getFileChunkDtos().add(fileChunkDtoConverter.toFileChunkDto(fileChunk)); 074 } 075 } 076 if (depth > 1) { 077 final TempChunkFileDtoIo tempChunkFileDtoIo = new TempChunkFileDtoIo(); 078 final File file = repoFile.getFile(localRepoManager.getLocalRoot()); 079 for (final TempChunkFileWithDtoFile tempChunkFileWithDtoFile : tempChunkFileManager.getOffset2TempChunkFileWithDtoFile(file).values()) { 080 final File tempChunkFileDtoFile = tempChunkFileWithDtoFile.getTempChunkFileDtoFile(); 081 if (tempChunkFileDtoFile == null) 082 continue; // incomplete: meta-data not yet written => ignore 083 084 final TempChunkFileDto tempChunkFileDto; 085 try { 086 tempChunkFileDto = tempChunkFileDtoIo.deserialize(tempChunkFileDtoFile); 087 } catch (final Exception x) { 088 logger.warn("toRepoFileDto: Ignoring corrupt tempChunkFileDtoFile '" + tempChunkFileDtoFile.getAbsolutePath() + "': " + x, x); 089 continue; 090 } 091 normalFileDto.getTempFileChunkDtos().add(requireNonNull(tempChunkFileDto.getFileChunkDto(), "tempChunkFileDto.fileChunkDto")); 092 } 093 } 094 } 095 else if (repoFile instanceof Directory) { 096 repoFileDto = createObject(DirectoryDto.class); 097 } 098 else if (repoFile instanceof Symlink) { 099 final Symlink symlink = (Symlink) repoFile; 100 final SymlinkDto symlinkDto; 101 repoFileDto = symlinkDto = createObject(SymlinkDto.class); 102 if (! isExcludeMutableData()) 103 symlinkDto.setTarget(symlink.getTarget()); 104 } 105 else 106 throw new UnsupportedOperationException("RepoFile type not yet supported: " + repoFile); 107 108 if (! isExcludeLocalIds()) { 109 repoFileDto.setId(repoFile.getId()); 110 repoFileDto.setParentId(repoFile.getParent() == null ? null : repoFile.getParent().getId()); 111 repoFileDto.setLocalRevision(repoFile.getLocalRevision()); 112 } 113 repoFileDto.setName(repoFile.getName()); 114 repoFileDto.setLastModified(repoFile.getLastModified()); 115 116 return repoFileDto; 117 } 118 119 public boolean isExcludeLocalIds() { 120 return excludeLocalIds; 121 } 122 public void setExcludeLocalIds(final boolean excludeLocalIds) { 123 this.excludeLocalIds = excludeLocalIds; 124 } 125 126 public boolean isExcludeMutableData() { 127 return excludeMutableData; 128 } 129 public void setExcludeMutableData(boolean excludeMutableData) { 130 this.excludeMutableData = excludeMutableData; 131 } 132}