001package org.kuali.common.devops.archive; 002 003import static com.google.common.base.Preconditions.checkArgument; 004import static java.lang.System.currentTimeMillis; 005import static java.util.concurrent.TimeUnit.MILLISECONDS; 006import static org.kuali.common.util.base.Precondition.checkMin; 007 008import javax.validation.constraints.Min; 009 010import org.kuali.common.core.build.ValidatingBuilder; 011import org.kuali.common.core.validate.annotation.IdiotProofImmutable; 012 013import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 014import com.google.common.base.Stopwatch; 015 016@IdiotProofImmutable 017@JsonDeserialize(builder = TimedInterval.Builder.class) 018public final class TimedInterval { 019 020 private final long start; 021 private final long stop; 022 @Min(0) 023 private final long elapsed; // negative elapsed time is not allowed 024 025 private TimedInterval(Builder builder) { 026 this.start = builder.start; 027 this.stop = builder.stop; 028 this.elapsed = builder.elapsed; 029 } 030 031 public static TimedInterval build(Stopwatch sw) { 032 return build(sw.elapsed(MILLISECONDS)); 033 } 034 035 public static TimedInterval build(long elapsed) { 036 long stop = currentTimeMillis(); 037 long start = stop - elapsed; 038 return builder().withStart(start).withStop(stop).withElapsed(elapsed).build(); 039 } 040 041 public static Builder builder() { 042 return new Builder(); 043 } 044 045 public static class Builder extends ValidatingBuilder<TimedInterval> { 046 047 private long start; 048 private long stop; 049 private long elapsed; 050 051 public Builder withStart(long start) { 052 this.start = start; 053 return this; 054 } 055 056 public Builder withStop(long stop) { 057 this.stop = stop; 058 return this; 059 } 060 061 public Builder withElapsed(long elapsed) { 062 this.elapsed = elapsed; 063 return this; 064 } 065 066 @Override 067 public TimedInterval build() { 068 return checkInstance(validate(new TimedInterval(this))); 069 } 070 071 private static TimedInterval checkInstance(TimedInterval instance) { 072 checkMin(instance.stop, instance.start, "stop"); 073 long expected = instance.elapsed; 074 long actual = instance.stop - instance.start; 075 checkArgument(expected == actual, "elapsed must equal (stop - start) -> [%s != %s]", expected, actual); 076 return instance; 077 } 078 } 079 080 public long getStart() { 081 return start; 082 } 083 084 public long getStop() { 085 return stop; 086 } 087 088 public long getElapsed() { 089 return elapsed; 090 } 091 092}