001package co.codewizards.cloudstore.local.persistence; 002 003import static co.codewizards.cloudstore.core.util.HashUtil.sha1; 004import static co.codewizards.cloudstore.core.util.Util.assertNotNull; 005 006import javax.jdo.annotations.Column; 007import javax.jdo.annotations.Discriminator; 008import javax.jdo.annotations.DiscriminatorStrategy; 009import javax.jdo.annotations.Index; 010import javax.jdo.annotations.Indices; 011import javax.jdo.annotations.Inheritance; 012import javax.jdo.annotations.InheritanceStrategy; 013import javax.jdo.annotations.NullValue; 014import javax.jdo.annotations.PersistenceCapable; 015import javax.jdo.annotations.Persistent; 016import javax.jdo.annotations.Queries; 017import javax.jdo.annotations.Query; 018 019@PersistenceCapable 020@Inheritance(strategy=InheritanceStrategy.NEW_TABLE) 021@Discriminator(strategy=DiscriminatorStrategy.VALUE_MAP, value="CopyModification") 022@Indices({ 023 @Index(name="CopyModification_fromPathSha1", members={"fromPathSha1"}), 024 @Index(name="CopyModification_toPathSha1", members={"toPathSha1"}), 025 @Index(name="CopyModification_sha1_length", members={"sha1", "length"}) 026}) 027// Note: It would be nice, but we cannot add unique keys combining localRevision and one of the properties here 028// in this sub-class, because there are 2 separate tables (InheritanceStrategy.NEW_TABLE). 029@Queries({ 030 @Query(name="getCopyModificationsForPathAfter_pathSha1_localRevision_remoteRepository", value="SELECT WHERE this.pathSha1 == :pathSha1 && this.localRevision > :localRevision"), 031 @Query(name="getCopyModifications_sha1_length", value="SELECT WHERE this.sha1 == :sha1 && this.length == :length") 032}) 033public class CopyModification extends Modification { 034 035 @Persistent(nullValue=NullValue.EXCEPTION, defaultFetchGroup="true") 036 @Column(jdbcType="CLOB") 037 private String fromPath; 038 039 @Persistent(nullValue=NullValue.EXCEPTION) 040 private String fromPathSha1; 041 042 @Persistent(nullValue=NullValue.EXCEPTION, defaultFetchGroup="true") 043 @Column(jdbcType="CLOB") 044 private String toPath; 045 046 @Persistent(nullValue=NullValue.EXCEPTION) 047 private String toPathSha1; 048 049 private long length; 050 051 private String sha1; 052 053 /** 054 * Gets the source path of the copied file. 055 * <p> 056 * This path is always relative to the local repository's root; even if the remote repository uses a 057 * {@link RemoteRepository#getLocalPathPrefix() path-prefix}. Stripping of the path-prefix is 058 * done during DTO generation. 059 * @return the source path of the copied file. Never <code>null</code>. 060 */ 061 public String getFromPath() { 062 return fromPath; 063 } 064 public void setFromPath(String fromPath) { 065 assertNotNull("fromPath", fromPath); 066 if (fromPath.isEmpty()) 067 throw new IllegalArgumentException("fromPath is empty! fromPath must start with '/' and thus has a minimum length of 1 char!"); 068 069 if (!fromPath.startsWith("/")) 070 throw new IllegalArgumentException("fromPath does not start with '/'!"); 071 072 this.fromPath = fromPath; 073 this.fromPathSha1 = sha1(fromPath); 074 } 075 076 public String getToPath() { 077 return toPath; 078 } 079 public void setToPath(String toPath) { 080 assertNotNull("toPath", toPath); 081 if (toPath.isEmpty()) 082 throw new IllegalArgumentException("toPath is empty! toPath must start with '/' and thus has a minimum length of 1 char!"); 083 084 if (!toPath.startsWith("/")) 085 throw new IllegalArgumentException("toPath does not start with '/'!"); 086 087 this.toPath = toPath; 088 this.toPathSha1 = sha1(toPath); 089 } 090 091 public long getLength() { 092 return length; 093 } 094 public void setLength(long length) { 095 this.length = length; 096 } 097 public String getSha1() { 098 return sha1; 099 } 100 public void setSha1(String sha1) { 101 this.sha1 = sha1; 102 } 103 104}