001/* 002 * Licensed under the Apache License, Version 2.0 (the "License"); 003 * you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at 005 * 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * 008 * Unless required by applicable law or agreed to in writing, software 009 * distributed under the License is distributed on an "AS IS" BASIS, 010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 011 * See the License for the specific language governing permissions and 012 * limitations under the License. 013 */ 014package org.gbif.api.model.pipelines; 015 016import org.gbif.api.jackson.LocalDateTimeSerDe; 017import org.gbif.api.model.registry.LenientEquals; 018 019import java.io.Serializable; 020import java.time.LocalDateTime; 021import java.util.Comparator; 022import java.util.HashSet; 023import java.util.Objects; 024import java.util.Set; 025import java.util.StringJoiner; 026 027import com.fasterxml.jackson.annotation.JsonInclude; 028import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 029import com.fasterxml.jackson.databind.annotation.JsonSerialize; 030 031/** 032 * Models a step in pipelines. 033 */ 034public class PipelineStep implements LenientEquals<PipelineStep>, Serializable { 035 036 private static final long serialVersionUID = 460047082156621661L; 037 038 @JsonInclude(JsonInclude.Include.NON_DEFAULT) 039 private long key; 040 041 private StepType type; 042 private StepRunner runner; 043 044 @JsonSerialize(using = LocalDateTimeSerDe.LocalDateTimeSerializer.class) 045 @JsonDeserialize(using = LocalDateTimeSerDe.LocalDateTimeDeserializer.class) 046 private LocalDateTime started; 047 048 @JsonSerialize(using = LocalDateTimeSerDe.LocalDateTimeSerializer.class) 049 @JsonDeserialize(using = LocalDateTimeSerDe.LocalDateTimeDeserializer.class) 050 private LocalDateTime finished; 051 052 private Status state; 053 private String message; 054 private Long numberRecords; 055 private String pipelinesVersion; 056 private String createdBy; 057 058 @JsonSerialize(using = LocalDateTimeSerDe.LocalDateTimeSerializer.class) 059 @JsonDeserialize(using = LocalDateTimeSerDe.LocalDateTimeDeserializer.class) 060 private LocalDateTime modified; 061 062 private String modifiedBy; 063 private Set<MetricInfo> metrics = new HashSet<>(); 064 065 public static final Comparator<PipelineStep> STEPS_BY_TYPE_ASC = 066 (s1, s2) -> { 067 StepType st1 = s1 != null ? s1.getType() : null; 068 StepType st2 = s2 != null ? s2.getType() : null; 069 070 if (st1 == null) { 071 return (st2 == null) ? 0 : 1; 072 } else if (st2 == null) { 073 return -1; 074 } 075 return st1.compareTo(st2); 076 }; 077 078 /** 079 * Comparator that sorts pipeline steps by start date and then by finished date in ascending order. 080 */ 081 public static final Comparator<PipelineStep> STEPS_BY_FINISHED_ASC = 082 (s1, s2) -> { 083 LocalDateTime finished1 = s1 != null ? s1.getFinished() : null; 084 LocalDateTime finished2 = s2 != null ? s2.getFinished() : null; 085 086 if (finished1 == null && finished2 == null) { 087 return STEPS_BY_TYPE_ASC.compare(s1, s2); 088 } 089 090 if (finished1 == null) { 091 return 1; 092 } else if (finished2 == null) { 093 return -1; 094 } 095 096 if (finished1.equals(finished2)) { 097 return STEPS_BY_TYPE_ASC.compare(s1, s2); 098 } 099 100 return finished1.compareTo(finished2); 101 }; 102 103 public long getKey() { 104 return key; 105 } 106 107 public StepType getType() { 108 return type; 109 } 110 111 public PipelineStep setType(StepType type) { 112 this.type = type; 113 return this; 114 } 115 116 public StepRunner getRunner() { 117 return runner; 118 } 119 120 public PipelineStep setRunner(StepRunner runner) { 121 this.runner = runner; 122 return this; 123 } 124 125 public LocalDateTime getStarted() { 126 return started; 127 } 128 129 public PipelineStep setStarted(LocalDateTime started) { 130 this.started = started; 131 return this; 132 } 133 134 public LocalDateTime getFinished() { 135 return finished; 136 } 137 138 public PipelineStep setFinished(LocalDateTime finished) { 139 this.finished = finished; 140 return this; 141 } 142 143 public Status getState() { 144 return state; 145 } 146 147 public PipelineStep setState(Status state) { 148 this.state = state; 149 return this; 150 } 151 152 public String getMessage() { 153 return message; 154 } 155 156 public PipelineStep setMessage(String message) { 157 this.message = message; 158 return this; 159 } 160 161 public void setKey(long key) { 162 this.key = key; 163 } 164 165 public Long getNumberRecords() { 166 return numberRecords; 167 } 168 169 public PipelineStep setNumberRecords(Long numberRecords) { 170 this.numberRecords = numberRecords; 171 return this; 172 } 173 174 public String getPipelinesVersion() { 175 return pipelinesVersion; 176 } 177 178 public PipelineStep setPipelinesVersion(String pipelinesVersion) { 179 this.pipelinesVersion = pipelinesVersion; 180 return this; 181 } 182 183 public String getCreatedBy() { 184 return createdBy; 185 } 186 187 public PipelineStep setCreatedBy(String createdBy) { 188 this.createdBy = createdBy; 189 return this; 190 } 191 192 public LocalDateTime getModified() { 193 return modified; 194 } 195 196 public PipelineStep setModified(LocalDateTime modified) { 197 this.modified = modified; 198 return this; 199 } 200 201 public String getModifiedBy() { 202 return modifiedBy; 203 } 204 205 public PipelineStep setModifiedBy(String modifiedBy) { 206 this.modifiedBy = modifiedBy; 207 return this; 208 } 209 210 public Set<MetricInfo> getMetrics() { 211 return metrics; 212 } 213 214 public PipelineStep setMetrics(Set<MetricInfo> metrics) { 215 this.metrics = metrics; 216 return this; 217 } 218 219 public PipelineStep addMetricInfo(MetricInfo metricInfo) { 220 metrics.add(metricInfo); 221 return this; 222 } 223 224 /** 225 * Enum to represent the status of a step. 226 */ 227 public enum Status { 228 RUNNING, 229 FAILED, 230 SUBMITTED, 231 COMPLETED, 232 ABORTED, 233 QUEUED 234 } 235 236 /** 237 * Inner class to store metrics. 238 */ 239 public static class MetricInfo implements Serializable { 240 241 private static final long serialVersionUID = 1872427841009786709L; 242 243 private String name; 244 private String value; 245 246 public MetricInfo() { 247 // needed for jackson 248 } 249 250 public MetricInfo(String name, String value) { 251 this.name = name; 252 this.value = value; 253 } 254 255 public String getName() { 256 return name; 257 } 258 259 public String getValue() { 260 return value; 261 } 262 263 public void setName(String name) { 264 this.name = name; 265 } 266 267 public void setValue(String value) { 268 this.value = value; 269 } 270 271 @Override 272 public boolean equals(Object o) { 273 if (this == o) { 274 return true; 275 } 276 if (o == null || getClass() != o.getClass()) { 277 return false; 278 } 279 MetricInfo that = (MetricInfo) o; 280 return Objects.equals(name, that.name) && Objects.equals(value, that.value); 281 } 282 283 @Override 284 public int hashCode() { 285 return Objects.hash(name, value); 286 } 287 288 @Override 289 public String toString() { 290 return new StringJoiner(", ", MetricInfo.class.getSimpleName() + "[", "]") 291 .add("name='" + name + "'") 292 .add("value='" + value + "'") 293 .toString(); 294 } 295 } 296 297 @Override 298 public boolean equals(Object o) { 299 if (this == o) return true; 300 if (o == null || getClass() != o.getClass()) return false; 301 PipelineStep that = (PipelineStep) o; 302 return key == that.key 303 && Objects.equals(type, that.type) 304 && Objects.equals(runner, that.runner) 305 && Objects.equals(started, that.started) 306 && Objects.equals(finished, that.finished) 307 && state == that.state 308 && Objects.equals(message, that.message) 309 && Objects.equals(metrics, that.metrics) 310 && Objects.equals(numberRecords, that.numberRecords) 311 && Objects.equals(pipelinesVersion, that.pipelinesVersion) 312 && Objects.equals(createdBy, that.createdBy) 313 && Objects.equals(modified, that.modified) 314 && Objects.equals(modifiedBy, that.modifiedBy); 315 } 316 317 @Override 318 public int hashCode() { 319 return Objects.hash( 320 key, 321 type, 322 runner, 323 started, 324 finished, 325 state, 326 message, 327 metrics, 328 numberRecords, 329 pipelinesVersion, 330 createdBy, 331 modified, 332 modifiedBy); 333 } 334 335 @Override 336 public String toString() { 337 return new StringJoiner(", ", PipelineStep.class.getSimpleName() + "[", "]") 338 .add("key=" + key) 339 .add("type=" + type) 340 .add("runner=" + runner) 341 .add("started=" + started) 342 .add("finished=" + finished) 343 .add("state=" + state) 344 .add("message='" + message + "'") 345 .add("numberRecords='" + numberRecords + "'") 346 .add("pipelinesVersion='" + pipelinesVersion + "'") 347 .add("createdBy='" + createdBy + "'") 348 .add("modified=" + modified) 349 .add("modifiedBy='" + modifiedBy + "'") 350 .add("metrics=" + metrics) 351 .toString(); 352 } 353 354 @Override 355 public boolean lenientEquals(PipelineStep other) { 356 if (this == other) return true; 357 return Objects.equals(type, other.type) 358 && Objects.equals(runner, other.runner) 359 && Objects.equals(finished, other.finished) 360 && state == other.state 361 && Objects.equals(message, other.message) 362 && Objects.equals(metrics, other.metrics) 363 && Objects.equals(numberRecords, other.numberRecords) 364 && Objects.equals(pipelinesVersion, other.pipelinesVersion); 365 } 366}