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.io.File; 021import java.util.Date; 022 023import org.syncany.database.FileContent.FileChecksum; 024import org.syncany.database.PartialFileHistory.FileHistoryId; 025 026/** 027 * A file version represents a version of a file at a certain time and captures 028 * all of a file's properties. 029 * 030 * <p>A {@link PartialFileHistory} typically consists of multiple <code>FileVersion</code>s, 031 * each of which is the incarnation of the same file, but with either changed properties, 032 * or changed content. 033 * 034 * <p>The <code>FileVersion</code>'s checksum attribute implicitly links to a {@link FileContent}, 035 * which represents the content of a file. Multiple file versions can link to the same file content. 036 * 037 * @see PartialFileHistory 038 * @author Philipp C. Heckel (philipp.heckel@gmail.com) 039 */ 040public class FileVersion implements Cloneable { 041 // Optional 042 private FileHistoryId fileHistoryId; 043 044 // Mandatory 045 private Long version; // TODO [low] This can be an Integer. No need for a long! 046 private String path; 047 private FileType type; 048 private FileStatus status; 049 private Long size; 050 private Date lastModified; 051 052 // Mandatory (if type is symlink) 053 private String linkTarget; 054 055 // Optional 056 private FileChecksum checksum; 057 private Date updated; 058 private String posixPermissions; 059 private String dosAttributes; 060 061 public FileVersion() { 062 // Fressen. 063 } 064 065 public FileHistoryId getFileHistoryId() { 066 return fileHistoryId; 067 } 068 069 public void setFileHistoryId(FileHistoryId fileHistoryId) { 070 this.fileHistoryId = fileHistoryId; 071 } 072 073 public Long getVersion() { 074 return version; 075 } 076 077 public void setVersion(Long version) { 078 this.version = version; 079 } 080 081 public FileType getType() { 082 return type; 083 } 084 085 public void setType(FileType type) { 086 this.type = type; 087 } 088 089 public Date getLastModified() { 090 return lastModified; 091 } 092 093 public void setLastModified(Date lastModified) { 094 this.lastModified = lastModified; 095 } 096 097 public Date getUpdated() { 098 return updated; 099 } 100 101 public void setUpdated(Date updated) { 102 this.updated = updated; 103 } 104 105 public FileStatus getStatus() { 106 return status; 107 } 108 109 public void setStatus(FileStatus status) { 110 this.status = status; 111 } 112 113 public String getPath() { 114 return path; 115 } 116 117 public String getName() { 118 return new File(path).getName(); 119 } 120 121 public void setPath(String path) { 122 this.path = path; 123 } 124 125 public FileChecksum getChecksum() { 126 return checksum; 127 } 128 129 public void setChecksum(FileChecksum checksum) { 130 this.checksum = checksum; 131 } 132 133 public Long getSize() { // TODO [low] Redundant field 'size', this field should not exist. Instead the content's size should be used. This was introduced as a convenience field. 134 return size; 135 } 136 137 public void setSize(Long size) { 138 this.size = size; 139 } 140 141 public String getLinkTarget() { 142 return linkTarget; 143 } 144 145 public void setLinkTarget(String linkTarget) { 146 this.linkTarget = linkTarget; 147 } 148 149 public String getPosixPermissions() { 150 return posixPermissions; 151 } 152 153 public void setPosixPermissions(String posixPermissions) { 154 this.posixPermissions = posixPermissions; 155 } 156 157 public String getDosAttributes() { 158 return dosAttributes; 159 } 160 161 public void setDosAttributes(String dosAttributes) { 162 this.dosAttributes = dosAttributes; 163 } 164 165 @Override 166 public String toString() { 167 return "FileVersion [version=" + version + ", path=" + path + ", type=" + type + ", status=" + status + ", size=" + size + ", lastModified=" 168 + lastModified + ", linkTarget=" + linkTarget + ", checksum=" + checksum + ", updated=" 169 + updated + ", posixPermissions=" + posixPermissions + ", dosAttributes=" + dosAttributes + "]"; 170 } 171 172 @Override 173 public FileVersion clone() { 174 try { 175 FileVersion clone = (FileVersion) super.clone(); 176 177 clone.setChecksum(getChecksum()); 178 clone.setLastModified(getLastModified()); 179 clone.setUpdated(getUpdated()); 180 clone.setPath(getPath()); 181 clone.setType(getType()); 182 clone.setVersion(getVersion()); 183 clone.setSize(getSize()); 184 clone.setDosAttributes(getDosAttributes()); 185 clone.setPosixPermissions(getPosixPermissions()); 186 clone.setLinkTarget(getLinkTarget()); 187 clone.setStatus(getStatus()); 188 189 return clone; 190 } 191 catch (Exception ex) { 192 throw new RuntimeException(ex); 193 } 194 } 195 196 @Override 197 public int hashCode() { 198 final int prime = 31; 199 int result = 1; 200 result = prime * result + ((checksum == null) ? 0 : checksum.hashCode()); 201 result = prime * result + ((dosAttributes == null) ? 0 : dosAttributes.hashCode()); 202 result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode()); 203 result = prime * result + ((linkTarget == null) ? 0 : linkTarget.hashCode()); 204 result = prime * result + ((path == null) ? 0 : path.hashCode()); 205 result = prime * result + ((posixPermissions == null) ? 0 : posixPermissions.hashCode()); 206 result = prime * result + ((size == null) ? 0 : size.hashCode()); 207 result = prime * result + ((status == null) ? 0 : status.hashCode()); 208 result = prime * result + ((type == null) ? 0 : type.hashCode()); 209 result = prime * result + ((updated == null) ? 0 : updated.hashCode()); 210 result = prime * result + ((version == null) ? 0 : version.hashCode()); 211 return result; 212 } 213 214 @Override 215 public boolean equals(Object obj) { 216 if (this == obj) { 217 return true; 218 } 219 if (obj == null) { 220 return false; 221 } 222 if (!(obj instanceof FileVersion)) { 223 return false; 224 } 225 FileVersion other = (FileVersion) obj; 226 if (checksum == null) { 227 if (other.checksum != null) { 228 return false; 229 } 230 } 231 else if (!checksum.equals(other.checksum)) { 232 return false; 233 } 234 if (dosAttributes == null) { 235 if (other.dosAttributes != null) { 236 return false; 237 } 238 } 239 else if (!dosAttributes.equals(other.dosAttributes)) { 240 return false; 241 } 242 if (lastModified == null) { 243 if (other.lastModified != null) { 244 return false; 245 } 246 } 247 else if (!lastModified.equals(other.lastModified)) { 248 return false; 249 } 250 if (linkTarget == null) { 251 if (other.linkTarget != null) { 252 return false; 253 } 254 } 255 else if (!linkTarget.equals(other.linkTarget)) { 256 return false; 257 } 258 if (path == null) { 259 if (other.path != null) { 260 return false; 261 } 262 } 263 else if (!path.equals(other.path)) { 264 return false; 265 } 266 if (posixPermissions == null) { 267 if (other.posixPermissions != null) { 268 return false; 269 } 270 } 271 else if (!posixPermissions.equals(other.posixPermissions)) { 272 return false; 273 } 274 if (size == null) { 275 if (other.size != null) { 276 return false; 277 } 278 } 279 else if (!size.equals(other.size)) { 280 return false; 281 } 282 if (status != other.status) { 283 return false; 284 } 285 if (type != other.type) { 286 return false; 287 } 288 if (updated == null) { 289 if (other.updated != null) { 290 return false; 291 } 292 } 293 else if (!updated.equals(other.updated)) { 294 return false; 295 } 296 if (version == null) { 297 if (other.version != null) { 298 return false; 299 } 300 } 301 else if (!version.equals(other.version)) { 302 return false; 303 } 304 return true; 305 } 306 307 public enum FileStatus { 308 NEW("NEW"), 309 CHANGED("CHANGED"), 310 RENAMED("RENAMED"), 311 DELETED("DELETED"); 312 313 private String name; 314 315 private FileStatus(String name) { 316 this.name = name; 317 } 318 319 public boolean equalsName(String otherName) { 320 return (otherName == null) ? false : name.equals(otherName); 321 } 322 323 @Override 324 public String toString() { 325 return name; 326 } 327 } 328 329 /** 330 * A {@link FileVersion} can be of either one of the types in this enum. 331 * Types are treated differently during the index and synchronization process. 332 */ 333 public enum FileType { 334 FILE("FILE"), 335 FOLDER("FOLDER"), 336 SYMLINK("SYMLINK"); 337 338 private String name; 339 340 private FileType(String name) { 341 this.name = name; 342 } 343 344 public boolean equalsName(String otherName) { 345 return (otherName == null) ? false : name.equals(otherName); 346 } 347 348 @Override 349 public String toString() { 350 return name; 351 } 352 } 353}