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