package co.codewizards.cloudstore.local.persistence; import static co.codewizards.cloudstore.core.util.Util.*; import java.util.HashSet; import java.util.Set; import javax.jdo.annotations.Discriminator; import javax.jdo.annotations.DiscriminatorStrategy; import javax.jdo.annotations.Index; import javax.jdo.annotations.Indices; import javax.jdo.annotations.Inheritance; import javax.jdo.annotations.InheritanceStrategy; import javax.jdo.annotations.NullValue; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.Queries; import javax.jdo.annotations.Query; import co.codewizards.cloudstore.core.oio.File; @PersistenceCapable @Inheritance(strategy=InheritanceStrategy.SUPERCLASS_TABLE) @Discriminator(strategy=DiscriminatorStrategy.VALUE_MAP, value="NormalFile") @Indices({ @Index(name="NormalFile_sha1_length", members={"sha1", "length"}) }) @Queries({ @Query(name="getNormalFiles_sha1_length", value="SELECT WHERE this.sha1 == :sha1 && this.length == :length") }) public class NormalFile extends RepoFile { private long length; @Persistent(nullValue=NullValue.EXCEPTION) private String sha1; private boolean inProgress; @Persistent(mappedBy="normalFile", dependentElement="true") private Set<FileChunk> fileChunks; public NormalFile() { } /** * Gets the file size in bytes. * <p> * It reflects the {@link File#length() File.length} property. * @return the file size in bytes. */ public long getLength() { return length; } public void setLength(final long length) { if (! equal(this.length, length)) this.length = length; } /** * Gets the <a href="http://en.wikipedia.org/wiki/SHA-1">SHA-1</a> of the file. * @return the <a href="http://en.wikipedia.org/wiki/SHA-1">SHA-1</a> of the file. */ public String getSha1() { return sha1; } public void setSha1(final String sha) { if (! equal(this.sha1, sha)) this.sha1 = sha; } /** * Is this file in progress of being synced? * <p> * If yes, it is ignored in change-sets in order to prevent inconsistent data to propagate further. * <p> * TODO We should later implement a mechanism that parks all modifications locally (not in the DB, but in the * meta-directory) before applying them to the file in one transaction. * @return <code>true</code>, if it is currently in progress of being synced; <code>false</code> otherwise. */ public boolean isInProgress() { return inProgress; } public void setInProgress(final boolean inProgress) { if (! equal(this.inProgress, inProgress)) this.inProgress = inProgress; } public Set<FileChunk> getFileChunks() { // TODO (1) This should be a SortedSet (a TreeSet), but for whatever reason, this does not work anymore // and causes ClassCastExceptions :-( // TODO (2) this should return a decorator which automatically calls FileChunk.makeReadOnly() when // enlisting a new instance! if (fileChunks == null) fileChunks = new HashSet<>(); return fileChunks; } }