001/* 002 * Syncany, www.syncany.org 003 * Copyright (C) 2011-2016 Philipp C. Heckel <philipp.heckel@gmail.com> 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU General Public License as published by 007 * the Free Software Foundation, either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU General Public License for more details. 014 * 015 * You should have received a copy of the GNU General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018package org.syncany.database; 019 020import java.util.ArrayList; 021import java.util.Collections; 022import java.util.List; 023 024import org.syncany.database.ChunkEntry.ChunkChecksum; 025 026/** 027 * A file content represents the content of a file. It contains a list of 028 * references to {@link ChunkEntry}s, and identifies a content by its checksum. 029 * 030 * <p>A file content is implicitly referenced by one or many {@link FileVersion}s 031 * through the checksum attribute. A file content always contains the full list of 032 * chunks it resembles. There are no deltas! 033 * 034 * <p>Unlike the chunk list in a {@link MultiChunkEntry}, the order of the chunks 035 * is very important, because a file can only be reconstructed if the order of 036 * its chunks are followed. 037 * 038 * @author Philipp C. Heckel (philipp.heckel@gmail.com) 039 */ 040public class FileContent { 041 private FileChecksum checksum; 042 private long size; 043 044 private List<ChunkChecksum> chunkChecksums; 045 046 public FileContent() { 047 this.chunkChecksums = new ArrayList<ChunkChecksum>(); 048 } 049 050 public void addChunk(ChunkChecksum chunk) { 051 chunkChecksums.add(chunk); 052 } 053 054 public FileChecksum getChecksum() { 055 return checksum; 056 } 057 058 public void setChecksum(FileChecksum checksum) { 059 this.checksum = checksum; 060 } 061 062 public long getSize() { 063 return size; 064 } 065 066 public void setSize(long contentSize) { 067 size = contentSize; 068 } 069 070 public List<ChunkChecksum> getChunks() { 071 return Collections.unmodifiableList(chunkChecksums); 072 } 073 074 @Override 075 public int hashCode() { 076 final int prime = 31; 077 int result = 1; 078 result = prime * result + ((checksum == null) ? 0 : checksum.hashCode()); 079 result = prime * result + ((chunkChecksums == null) ? 0 : chunkChecksums.hashCode()); 080 result = prime * result + (int) (size ^ (size >>> 32)); 081 return result; 082 } 083 084 @Override 085 public boolean equals(Object obj) { 086 if (this == obj) { 087 return true; 088 } 089 if (obj == null) { 090 return false; 091 } 092 if (!(obj instanceof FileContent)) { 093 return false; 094 } 095 FileContent other = (FileContent) obj; 096 if (checksum == null) { 097 if (other.checksum != null) { 098 return false; 099 } 100 } 101 else if (!checksum.equals(other.checksum)) { 102 return false; 103 } 104 if (chunkChecksums == null) { 105 if (other.chunkChecksums != null) { 106 return false; 107 } 108 } 109 else if (!chunkChecksums.equals(other.chunkChecksums)) { 110 return false; 111 } 112 if (size != other.size) { 113 return false; 114 } 115 return true; 116 } 117 118 @Override 119 public String toString() { 120 return "FileContent [checksum=" + checksum + ", contentSize=" + size + ", chunks=" + chunkChecksums + "]"; 121 } 122 123 public static class FileChecksum extends ObjectId { 124 public FileChecksum(byte[] array) { 125 super(array); 126 } 127 128 public static FileChecksum parseFileChecksum(String s) { 129 return new FileChecksum(ObjectId.parseObjectId(s)); 130 } 131 132 public static boolean fileChecksumEquals(FileChecksum checksum1, FileChecksum checksum2) { 133 if (checksum1 != null && checksum2 != null) { 134 return checksum1.equals(checksum2); 135 } 136 else { 137 return checksum1 == null && checksum2 == null; 138 } 139 } 140 } 141}