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}