001package co.codewizards.cloudstore.local.persistence;
002
003import java.io.File;
004import java.util.HashSet;
005import java.util.Set;
006
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.SUPERCLASS_TABLE)
021@Discriminator(strategy=DiscriminatorStrategy.VALUE_MAP, value="NormalFile")
022@Indices({
023        @Index(name="NormalFile_sha1_length", members={"sha1", "length"})
024})
025@Queries({
026        @Query(name="getNormalFiles_sha1_length", value="SELECT WHERE this.sha1 == :sha1 && this.length == :length")
027})
028public class NormalFile extends RepoFile {
029
030        private long length;
031
032        @Persistent(nullValue=NullValue.EXCEPTION)
033        private String sha1;
034
035        private boolean inProgress;
036
037        @Persistent(mappedBy="normalFile", dependentElement="true")
038        private Set<FileChunk> fileChunks;
039
040        /**
041         * Gets the file size in bytes.
042         * <p>
043         * It reflects the {@link File#length() File.length} property.
044         * @return the file size in bytes.
045         */
046        public long getLength() {
047                return length;
048        }
049        public void setLength(long size) {
050                this.length = size;
051        }
052        /**
053         * Gets the <a href="http://en.wikipedia.org/wiki/SHA-1">SHA-1</a> of the file.
054         * @return the <a href="http://en.wikipedia.org/wiki/SHA-1">SHA-1</a> of the file.
055         */
056        public String getSha1() {
057                return sha1;
058        }
059        public void setSha1(String sha) {
060                this.sha1 = sha;
061        }
062
063        /**
064         * Is this file in progress of being synced?
065         * <p>
066         * If yes, it is ignored in change-sets in order to prevent inconsistent data to propagate further.
067         * <p>
068         * TODO We should later implement a mechanism that parks all modifications locally (not in the DB, but in the
069         * meta-directory) before applying them to the file in one transaction.
070         * @return <code>true</code>, if it is currently in progress of being synced; <code>false</code> otherwise.
071         */
072        public boolean isInProgress() {
073                return inProgress;
074        }
075        public void setInProgress(boolean inProgress) {
076                this.inProgress = inProgress;
077        }
078
079        public Set<FileChunk> getFileChunks() {
080                // TODO (1) This should be a SortedSet (a TreeSet), but for whatever reason, this does not work anymore
081                // and causes ClassCastExceptions :-(
082                // TODO (2) this should return a decorator which automatically calls FileChunk.makeReadOnly() when
083                // enlisting a new instance!
084                if (fileChunks == null)
085                        fileChunks = new HashSet<>();
086
087                return fileChunks;
088        }
089}