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}