001/*-
002 * #%L
003 * HAPI FHIR JPA Server
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.entity;
021
022import ca.uhn.fhir.batch2.model.JobDefinition;
023import ca.uhn.fhir.batch2.model.StatusEnum;
024import jakarta.persistence.Basic;
025import jakarta.persistence.Column;
026import jakarta.persistence.Entity;
027import jakarta.persistence.EnumType;
028import jakarta.persistence.Enumerated;
029import jakarta.persistence.FetchType;
030import jakarta.persistence.Id;
031import jakarta.persistence.Index;
032import jakarta.persistence.Lob;
033import jakarta.persistence.Table;
034import jakarta.persistence.Temporal;
035import jakarta.persistence.TemporalType;
036import jakarta.persistence.Version;
037import org.apache.commons.lang3.builder.ToStringBuilder;
038import org.apache.commons.lang3.builder.ToStringStyle;
039import org.hibernate.Length;
040
041import java.io.Serializable;
042import java.util.Date;
043
044import static ca.uhn.fhir.batch2.model.JobDefinition.ID_MAX_LENGTH;
045import static ca.uhn.fhir.jpa.entity.Batch2WorkChunkEntity.ERROR_MSG_MAX_LENGTH;
046import static ca.uhn.fhir.jpa.entity.Batch2WorkChunkEntity.WARNING_MSG_MAX_LENGTH;
047import static org.apache.commons.lang3.StringUtils.left;
048
049@Entity
050@Table(
051                name = "BT2_JOB_INSTANCE",
052                indexes = {@Index(name = "IDX_BT2JI_CT", columnList = "CREATE_TIME")})
053public class Batch2JobInstanceEntity implements Serializable {
054
055        public static final int STATUS_MAX_LENGTH = 20;
056        public static final int TIME_REMAINING_LENGTH = 100;
057        public static final int PARAMS_JSON_MAX_LENGTH = 2000;
058        private static final long serialVersionUID = 8187134261799095422L;
059        public static final int INITIATING_USER_NAME_MAX_LENGTH = 200;
060        public static final int INITIATING_CLIENT_ID_MAX_LENGTH = 200;
061
062        @Id
063        @Column(name = "ID", length = JobDefinition.ID_MAX_LENGTH, nullable = false)
064        private String myId;
065
066        @Column(name = "CREATE_TIME", nullable = false)
067        @Temporal(TemporalType.TIMESTAMP)
068        private Date myCreateTime;
069
070        @Column(name = "START_TIME", nullable = true)
071        @Temporal(TemporalType.TIMESTAMP)
072        private Date myStartTime;
073
074        @Column(name = "END_TIME", nullable = true)
075        @Temporal(TemporalType.TIMESTAMP)
076        private Date myEndTime;
077
078        @Version
079        @Column(name = "UPDATE_TIME", nullable = true)
080        @Temporal(TemporalType.TIMESTAMP)
081        private Date myUpdateTime;
082
083        @Column(name = "DEFINITION_ID", length = JobDefinition.ID_MAX_LENGTH, nullable = false)
084        private String myDefinitionId;
085
086        @Column(name = "DEFINITION_VER", nullable = false)
087        private int myDefinitionVersion;
088
089        @Column(name = "STAT", length = STATUS_MAX_LENGTH, nullable = false)
090        @Enumerated(EnumType.STRING)
091        private StatusEnum myStatus;
092
093        @Column(name = "JOB_CANCELLED", nullable = false)
094        private boolean myCancelled;
095
096        @Column(name = "FAST_TRACKING", nullable = true)
097        private Boolean myFastTracking;
098
099        // TODO: VC column added in 7.2.0 - Remove non-VC column later
100        @Column(name = "PARAMS_JSON", length = PARAMS_JSON_MAX_LENGTH, nullable = true)
101        private String myParamsJson;
102
103        @Lob // TODO: VC column added in 7.2.0 - Remove non-VC column later
104        @Column(name = "PARAMS_JSON_LOB", nullable = true)
105        private String myParamsJsonLob;
106
107        @Column(name = "PARAMS_JSON_VC", nullable = true, length = Length.LONG32)
108        private String myParamsJsonVc;
109
110        @Column(name = "CMB_RECS_PROCESSED", nullable = true)
111        private Integer myCombinedRecordsProcessed;
112
113        @Column(name = "CMB_RECS_PER_SEC", nullable = true)
114        private Double myCombinedRecordsProcessedPerSecond;
115
116        @Column(name = "TOT_ELAPSED_MILLIS", nullable = true)
117        private Integer myTotalElapsedMillis;
118
119        @Column(name = "WORK_CHUNKS_PURGED", nullable = false)
120        private boolean myWorkChunksPurged;
121
122        @Column(name = "PROGRESS_PCT", nullable = false)
123        private double myProgress;
124
125        @Column(name = "ERROR_MSG", length = ERROR_MSG_MAX_LENGTH, nullable = true)
126        private String myErrorMessage;
127
128        @Column(name = "ERROR_COUNT", nullable = false)
129        private int myErrorCount;
130
131        @Column(name = "EST_REMAINING", length = TIME_REMAINING_LENGTH, nullable = true)
132        private String myEstimatedTimeRemaining;
133
134        @Column(name = "CUR_GATED_STEP_ID", length = ID_MAX_LENGTH, nullable = true)
135        private String myCurrentGatedStepId;
136
137        @Column(name = "WARNING_MSG", length = WARNING_MSG_MAX_LENGTH, nullable = true)
138        private String myWarningMessages;
139
140        @Column(name = "USER_NAME", length = INITIATING_USER_NAME_MAX_LENGTH, nullable = true)
141        private String myTriggeringUsername;
142
143        @Column(name = "CLIENT_ID", length = INITIATING_CLIENT_ID_MAX_LENGTH, nullable = true)
144        private String myTriggeringClientId;
145
146        /**
147         * Any output from the job can be held in this column
148         * Even serialized json
149         */
150        @Lob // TODO: VC column added in 7.2.0 - Remove non-VC column later
151        @Basic(fetch = FetchType.LAZY)
152        @Column(name = "REPORT", nullable = true, length = Integer.MAX_VALUE - 1)
153        private String myReport;
154
155        @Column(name = "REPORT_VC", nullable = true, length = Length.LONG32)
156        private String myReportVc;
157
158        public String getCurrentGatedStepId() {
159                return myCurrentGatedStepId;
160        }
161
162        public void setCurrentGatedStepId(String theCurrentGatedStepId) {
163                myCurrentGatedStepId = theCurrentGatedStepId;
164        }
165
166        public boolean isCancelled() {
167                return myCancelled;
168        }
169
170        public void setCancelled(boolean theCancelled) {
171                myCancelled = theCancelled;
172        }
173
174        public int getErrorCount() {
175                return myErrorCount;
176        }
177
178        public void setErrorCount(int theErrorCount) {
179                myErrorCount = theErrorCount;
180        }
181
182        public Integer getTotalElapsedMillis() {
183                return myTotalElapsedMillis;
184        }
185
186        public void setTotalElapsedMillis(Integer theTotalElapsedMillis) {
187                myTotalElapsedMillis = theTotalElapsedMillis;
188        }
189
190        public Integer getCombinedRecordsProcessed() {
191                return myCombinedRecordsProcessed;
192        }
193
194        public void setCombinedRecordsProcessed(Integer theCombinedRecordsProcessed) {
195                myCombinedRecordsProcessed = theCombinedRecordsProcessed;
196        }
197
198        public Double getCombinedRecordsProcessedPerSecond() {
199                return myCombinedRecordsProcessedPerSecond;
200        }
201
202        public void setCombinedRecordsProcessedPerSecond(Double theCombinedRecordsProcessedPerSecond) {
203                myCombinedRecordsProcessedPerSecond = theCombinedRecordsProcessedPerSecond;
204        }
205
206        public Date getCreateTime() {
207                return myCreateTime;
208        }
209
210        public void setCreateTime(Date theCreateTime) {
211                myCreateTime = theCreateTime;
212        }
213
214        public Date getStartTime() {
215                return myStartTime;
216        }
217
218        public void setStartTime(Date theStartTime) {
219                myStartTime = theStartTime;
220        }
221
222        public Date getEndTime() {
223                return myEndTime;
224        }
225
226        public void setEndTime(Date theEndTime) {
227                myEndTime = theEndTime;
228        }
229
230        public void setUpdateTime(Date theTime) {
231                myUpdateTime = theTime;
232        }
233
234        public Date getUpdateTime() {
235                return myUpdateTime;
236        }
237
238        public String getId() {
239                return myId;
240        }
241
242        public void setId(String theId) {
243                myId = theId;
244        }
245
246        public String getDefinitionId() {
247                return myDefinitionId;
248        }
249
250        public void setDefinitionId(String theDefinitionId) {
251                myDefinitionId = theDefinitionId;
252        }
253
254        public int getDefinitionVersion() {
255                return myDefinitionVersion;
256        }
257
258        public void setDefinitionVersion(int theDefinitionVersion) {
259                myDefinitionVersion = theDefinitionVersion;
260        }
261
262        public StatusEnum getStatus() {
263                return myStatus;
264        }
265
266        public void setStatus(StatusEnum theStatus) {
267                myStatus = theStatus;
268        }
269
270        public String getParams() {
271                if (myParamsJsonVc != null) {
272                        return myParamsJsonVc;
273                }
274                if (myParamsJsonLob != null) {
275                        return myParamsJsonLob;
276                }
277                return myParamsJson;
278        }
279
280        public void setParams(String theParams) {
281                myParamsJsonVc = theParams;
282                myParamsJsonLob = null;
283                myParamsJson = null;
284        }
285
286        public boolean getWorkChunksPurged() {
287                return myWorkChunksPurged;
288        }
289
290        public void setWorkChunksPurged(boolean theWorkChunksPurged) {
291                myWorkChunksPurged = theWorkChunksPurged;
292        }
293
294        public double getProgress() {
295                return myProgress;
296        }
297
298        public void setProgress(double theProgress) {
299                myProgress = theProgress;
300        }
301
302        public String getErrorMessage() {
303                return myErrorMessage;
304        }
305
306        public void setErrorMessage(String theErrorMessage) {
307                myErrorMessage = left(theErrorMessage, ERROR_MSG_MAX_LENGTH);
308        }
309
310        public String getEstimatedTimeRemaining() {
311                return myEstimatedTimeRemaining;
312        }
313
314        public void setEstimatedTimeRemaining(String theEstimatedTimeRemaining) {
315                myEstimatedTimeRemaining = left(theEstimatedTimeRemaining, TIME_REMAINING_LENGTH);
316        }
317
318        public String getReport() {
319                return myReportVc != null ? myReportVc : myReport;
320        }
321
322        public void setReport(String theReport) {
323                myReportVc = theReport;
324                myReport = null;
325        }
326
327        public String getWarningMessages() {
328                return myWarningMessages;
329        }
330
331        public void setWarningMessages(String theWarningMessages) {
332                myWarningMessages = theWarningMessages;
333        }
334
335        public String getTriggeringUsername() {
336                return myTriggeringUsername;
337        }
338
339        public Batch2JobInstanceEntity setTriggeringUsername(String theTriggeringUsername) {
340                myTriggeringUsername = theTriggeringUsername;
341                return this;
342        }
343
344        public String getTriggeringClientId() {
345                return myTriggeringClientId;
346        }
347
348        public Batch2JobInstanceEntity setTriggeringClientId(String theTriggeringClientId) {
349                myTriggeringClientId = theTriggeringClientId;
350                return this;
351        }
352
353        @Override
354        public String toString() {
355                return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
356                                .append("id", myId)
357                                .append("definitionId", myDefinitionId)
358                                .append("definitionVersion", myDefinitionVersion)
359                                .append("errorCount", myErrorCount)
360                                .append("createTime", myCreateTime)
361                                .append("startTime", myStartTime)
362                                .append("endTime", myEndTime)
363                                .append("updateTime", myUpdateTime)
364                                .append("status", myStatus)
365                                .append("cancelled", myCancelled)
366                                .append("combinedRecordsProcessed", myCombinedRecordsProcessed)
367                                .append("combinedRecordsProcessedPerSecond", myCombinedRecordsProcessedPerSecond)
368                                .append("totalElapsedMillis", myTotalElapsedMillis)
369                                .append("workChunksPurged", myWorkChunksPurged)
370                                .append("progress", myProgress)
371                                .append("errorMessage", myErrorMessage)
372                                .append("estimatedTimeRemaining", myEstimatedTimeRemaining)
373                                .append("report", getReport())
374                                .append("warningMessages", myWarningMessages)
375                                .append("initiatingUsername", myTriggeringUsername)
376                                .append("initiatingclientId", myTriggeringClientId)
377                                .toString();
378        }
379
380        /**
381         * @return true if every step of the job has produced exactly 1 chunk.
382         */
383        public boolean isFastTracking() {
384                if (myFastTracking == null) {
385                        myFastTracking = false;
386                }
387                return myFastTracking;
388        }
389
390        public void setFastTracking(boolean theFastTracking) {
391                myFastTracking = theFastTracking;
392        }
393}