001/*- 002 * #%L 003 * HAPI FHIR Storage api 004 * %% 005 * Copyright (C) 2014 - 2024 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.jpa.binary.api; 021 022import ca.uhn.fhir.model.api.IModelJson; 023import ca.uhn.fhir.rest.server.util.JsonDateDeserializer; 024import ca.uhn.fhir.rest.server.util.JsonDateSerializer; 025import com.fasterxml.jackson.annotation.JsonProperty; 026import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 027import com.fasterxml.jackson.databind.annotation.JsonSerialize; 028import com.google.common.hash.HashingInputStream; 029import jakarta.annotation.Nonnull; 030import org.apache.commons.lang3.builder.ToStringBuilder; 031 032import java.util.Date; 033 034public class StoredDetails implements IModelJson { 035 036 @JsonProperty(value = "binaryContentId") 037 private String myBinaryContentId; 038 039 /** 040 * This field exists to fix a break that changing this property name caused. 041 * in 7.2.0 we went from blobId to binaryContentId. However this did not consider installations using filesystem 042 * mode storage in which the data on disk was not updated, and needed to be Serialized/Deserialized at runtime. 043 * Existing stored details used `blobId`. This causes Jackson deserialization failures which are tough to recover 044 * from without manually modifying all those stored details 045 * on disk. 046 * This field is a relic to support old blobs post-upgrade to 7.2.0. It is not ever surfaced to the user, and is proxied 047 * into `myBinaryContentId` when needed. 048 */ 049 @JsonProperty(value = "blobId") 050 private String myBlobId; 051 052 @JsonProperty("bytes") 053 private long myBytes; 054 055 @JsonProperty("contentType") 056 private String myContentType; 057 058 @JsonProperty("hash") 059 private String myHash; 060 061 @JsonProperty("published") 062 @JsonSerialize(using = JsonDateSerializer.class) 063 @JsonDeserialize(using = JsonDateDeserializer.class) 064 private Date myPublished; 065 066 /** 067 * Constructor 068 */ 069 @SuppressWarnings("unused") 070 public StoredDetails() { 071 super(); 072 } 073 074 /** 075 * Constructor 076 */ 077 public StoredDetails( 078 @Nonnull String theBinaryContentId, 079 long theBytes, 080 @Nonnull String theContentType, 081 HashingInputStream theIs, 082 Date thePublished) { 083 myBinaryContentId = theBinaryContentId; 084 myBytes = theBytes; 085 myContentType = theContentType; 086 myHash = theIs.hash().toString(); 087 myPublished = thePublished; 088 } 089 090 @Override 091 public String toString() { 092 return new ToStringBuilder(this) 093 .append("binaryContentId", getBinaryContentId()) 094 .append("bytes", myBytes) 095 .append("contentType", myContentType) 096 .append("hash", myHash) 097 .append("published", myPublished) 098 .toString(); 099 } 100 101 public String getHash() { 102 return myHash; 103 } 104 105 public StoredDetails setHash(String theHash) { 106 myHash = theHash; 107 return this; 108 } 109 110 public Date getPublished() { 111 return myPublished; 112 } 113 114 public StoredDetails setPublished(Date thePublished) { 115 myPublished = thePublished; 116 return this; 117 } 118 119 @Nonnull 120 public String getContentType() { 121 return myContentType; 122 } 123 124 public StoredDetails setContentType(String theContentType) { 125 myContentType = theContentType; 126 return this; 127 } 128 129 @Nonnull 130 public String getBinaryContentId() { 131 if (myBinaryContentId == null && myBlobId != null) { 132 return myBlobId; 133 } else { 134 return myBinaryContentId; 135 } 136 } 137 138 public StoredDetails setBinaryContentId(String theBinaryContentId) { 139 myBinaryContentId = theBinaryContentId; 140 return this; 141 } 142 143 public long getBytes() { 144 return myBytes; 145 } 146 147 public StoredDetails setBytes(long theBytes) { 148 myBytes = theBytes; 149 return this; 150 } 151}