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