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