package com.kryptnostic.v2.storage.models;
import java.util.EnumSet;
import java.util.UUID;
import javax.annotation.concurrent.Immutable;
import org.joda.time.DateTime;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.kryptnostic.kodex.v1.crypto.ciphers.Cypher;
import com.kryptnostic.v2.constants.Names;
import com.kryptnostic.v2.sharing.models.ObjectUserKey;
/**
*
* @author Matthew Tamayo-Rios <matthew@kryptnostic.com>
*
*/
@Immutable
public class ObjectMetadata {
protected final UUID id;
protected final UUID type;
protected final long version;
protected final long size;
protected EnumSet<CryptoMaterial> uploadedParts;
protected EnumSet<CryptoMaterial> requiredParts;
protected final UUID creator;
protected final DateTime createdTime;
public enum CryptoMaterial {
IV,
TAG,
CONTENTS,
SALT;
public static final EnumSet<CryptoMaterial> DEFAULT_REQUIRED_CRYPTO_MATERIALS = EnumSet.of( IV, CONTENTS );
public static EnumSet<CryptoMaterial> requiredByCypher( Cypher cypher, boolean salted ) {
if ( cypher == null ) {
return EnumSet.of( IV, CONTENTS );
}
EnumSet<CryptoMaterial> required;
switch ( cypher ) {
case AES_GCM_128:
required = EnumSet.of( TAG, IV, CONTENTS );
break;
default:
required = DEFAULT_REQUIRED_CRYPTO_MATERIALS;
break;
}
if ( salted ) {
required.add( SALT );
}
return required;
}
}
@JsonCreator
public ObjectMetadata(
@JsonProperty( Names.ID_FIELD ) UUID id,
@JsonProperty( Names.VERSION_FIELD ) long version,
@JsonProperty( Names.SIZE_FIELD ) long size,
@JsonProperty( Names.TYPE_FIELD ) UUID type,
@JsonProperty( Names.CREATOR_FIELD ) UUID creator,
@JsonProperty( Names.REQUIRED_CRYPTO_MATS_FIELD ) EnumSet<CryptoMaterial> requiredMaterials,
@JsonProperty( Names.CREATED_TIME ) DateTime createdTime) {
this.id = id;
this.version = version;
this.type = type;
this.creator = creator;
this.createdTime = createdTime;
this.size = size;
this.uploadedParts = EnumSet.noneOf( CryptoMaterial.class );
this.requiredParts = requiredMaterials;
}
public static ObjectMetadata newObject(
CreateObjectRequest request,
UUID objectId,
long version,
UUID creator ) {
return new ObjectMetadata(
objectId,
version,
0l,
request.getType(),
creator,
request.getRequiredCryptoMaterials(),
DateTime.now() );
}
public static ObjectMetadata newObject( CreateObjectRequest request, UUID user, UUID objectId ) {
return new ObjectMetadata(
objectId,
0l,
0l,
request.getType(),
user,
request.getRequiredCryptoMaterials(),
DateTime.now() );
}
/**
* @return Document identifier
*/
@JsonProperty( Names.ID_FIELD )
public UUID getId() {
return id;
}
/**
* @return Version of document
*/
@JsonProperty( Names.VERSION_FIELD )
public long getVersion() {
return version;
}
@JsonProperty( Names.CREATOR_FIELD )
public UUID getCreator() {
return creator;
}
@JsonProperty( Names.CREATED_TIME )
public DateTime getCreatedTime() {
return createdTime;
}
@JsonProperty( Names.TYPE_FIELD )
public UUID getType() {
return type;
}
@JsonProperty( Names.SIZE_FIELD )
public long getSize() {
return size;
}
public EnumSet<CryptoMaterial> getRequiredCryptoMaterial() {
return requiredParts;
}
public EnumSet<CryptoMaterial> getCryptoMaterialProgress() {
return uploadedParts;
}
public boolean updateUploadProgress( CryptoMaterial nextUploaded ) {
uploadedParts.add( nextUploaded );
return isFinalized();
}
public boolean isFinalized() {
return uploadedParts.containsAll( requiredParts );
}
public void setUploadedParts( EnumSet<CryptoMaterial> uploadedParts ) {
this.uploadedParts = uploadedParts;
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ( ( createdTime == null ) ? 0 : createdTime.hashCode() );
result = prime * result + ( ( creator == null ) ? 0 : creator.hashCode() );
result = prime * result + ( ( id == null ) ? 0 : id.hashCode() );
result = prime * result + ( ( requiredParts == null ) ? 0 : requiredParts.hashCode() );
result = prime * result + (int) ( size ^ ( size >>> 32 ) );
result = prime * result + ( ( type == null ) ? 0 : type.hashCode() );
result = prime * result + ( ( uploadedParts == null ) ? 0 : uploadedParts.hashCode() );
result = prime * result + (int) ( version ^ ( version >>> 32 ) );
return result;
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals( Object obj ) {
if ( this == obj ) {
return true;
}
if ( obj == null ) {
return false;
}
if ( getClass() != obj.getClass() ) {
return false;
}
ObjectMetadata other = (ObjectMetadata) obj;
if ( createdTime == null ) {
if ( other.createdTime != null ) {
return false;
}
} else if ( !createdTime.equals( other.createdTime ) ) {
return false;
}
if ( creator == null ) {
if ( other.creator != null ) {
return false;
}
} else if ( !creator.equals( other.creator ) ) {
return false;
}
if ( id == null ) {
if ( other.id != null ) {
return false;
}
} else if ( !id.equals( other.id ) ) {
return false;
}
if ( requiredParts == null ) {
if ( other.requiredParts != null ) {
return false;
}
} else if ( !requiredParts.equals( other.requiredParts ) ) {
return false;
}
if ( size != other.size ) {
return false;
}
if ( type == null ) {
if ( other.type != null ) {
return false;
}
} else if ( !type.equals( other.type ) ) {
return false;
}
if ( uploadedParts == null ) {
if ( other.uploadedParts != null ) {
return false;
}
} else if ( !uploadedParts.equals( other.uploadedParts ) ) {
return false;
}
if ( version != other.version ) {
return false;
}
return true;
}
public ObjectUserKey toObjectUserKey( UUID userId ) {
return new ObjectUserKey( this.id, userId );
}
public VersionedObjectUserKey toVersionedObjectUserKey( UUID userId ) {
return new VersionedObjectUserKey( this.id, userId, this.version );
}
}