Java tutorial
/* * Autopsy Forensic Browser * * Copyright 2013 Basis Technology Corp. * Contact: carrier <at> sleuthkit <dot> org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sleuthkit.autopsy.timeline.utils; import javax.annotation.concurrent.Immutable; import org.joda.time.DateTime; import org.joda.time.DateTimeFieldType; import org.joda.time.Days; import org.joda.time.Hours; import org.joda.time.Interval; import org.joda.time.Minutes; import org.joda.time.Months; import org.joda.time.Seconds; import org.joda.time.Years; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; import org.sleuthkit.autopsy.timeline.TimeLineController; import org.sleuthkit.autopsy.timeline.zooming.TimeUnits; /** * bundles up the results of analyzing a time range for the appropriate * {@link TimeUnits} to use to visualize it. Partly, this class exists * so I don't have to have more member variables in other places , and partly * because I can only return a single value from a function. This might only be * a temporary design but is working well for now. */ @Immutable public class RangeDivisionInfo { /** the size of the periods we should divide the interval into */ private final TimeUnits blockSize; /** The number of Blocks we are going to divide the interval into. */ private final int numberOfBlocks; /** a {@link DateTimeFormatter} corresponding to the block size for the * tick marks on the date axis of the graph */ private final DateTimeFormatter tickFormatter; /** an adjusted lower bound for the range such that is lines up with a block * boundary before or at the start of the timerange */ private final long lowerBound; /** an adjusted upper bound for the range such that is lines up with a block * boundary at or after the end of the timerange */ private final long upperBound; /** the time range this {@link RangeDivisionInfo} describes */ private final Interval timeRange; public Interval getTimeRange() { return timeRange; } private RangeDivisionInfo(Interval timeRange, int periodsInRange, TimeUnits periodSize, DateTimeFormatter tickformatter, long lowerBound, long upperBound) { super(); this.numberOfBlocks = periodsInRange; this.blockSize = periodSize; this.tickFormatter = tickformatter; this.lowerBound = lowerBound; this.upperBound = upperBound; this.timeRange = timeRange; } /** * Static factory method. * * Determine the period size, number of periods, whole period bounds, and * formatters to use to visualize the given timerange. * * @param timeRange * * @return */ public static RangeDivisionInfo getRangeDivisionInfo(Interval timeRange) { //Check from largest to smallest unit //TODO: make this more generic... reduce code duplication -jm DateTimeFieldType timeUnit; final DateTime startWithZone = timeRange.getStart().withZone(TimeLineController.getJodaTimeZone()); final DateTime endWithZone = timeRange.getEnd().withZone(TimeLineController.getJodaTimeZone()); if (Years.yearsIn(timeRange).isGreaterThan(Years.THREE)) { timeUnit = DateTimeFieldType.year(); long lower = startWithZone.property(timeUnit).roundFloorCopy().getMillis(); long upper = endWithZone.property(timeUnit).roundCeilingCopy().getMillis(); return new RangeDivisionInfo(timeRange, Years.yearsIn(timeRange).get(timeUnit.getDurationType()) + 1, TimeUnits.YEARS, ISODateTimeFormat.year(), lower, upper); } else if (Months.monthsIn(timeRange).isGreaterThan(Months.THREE)) { timeUnit = DateTimeFieldType.monthOfYear(); long lower = startWithZone.property(timeUnit).roundFloorCopy().getMillis(); long upper = endWithZone.property(timeUnit).roundCeilingCopy().getMillis(); return new RangeDivisionInfo(timeRange, Months.monthsIn(timeRange).getMonths() + 1, TimeUnits.MONTHS, DateTimeFormat.forPattern("YYYY'-'MMMM"), lower, upper); // NON-NLS } else if (Days.daysIn(timeRange).isGreaterThan(Days.THREE)) { timeUnit = DateTimeFieldType.dayOfMonth(); long lower = startWithZone.property(timeUnit).roundFloorCopy().getMillis(); long upper = endWithZone.property(timeUnit).roundCeilingCopy().getMillis(); return new RangeDivisionInfo(timeRange, Days.daysIn(timeRange).getDays() + 1, TimeUnits.DAYS, DateTimeFormat.forPattern("YYYY'-'MMMM'-'dd"), lower, upper); // NON-NLS } else if (Hours.hoursIn(timeRange).isGreaterThan(Hours.THREE)) { timeUnit = DateTimeFieldType.hourOfDay(); long lower = startWithZone.property(timeUnit).roundFloorCopy().getMillis(); long upper = endWithZone.property(timeUnit).roundCeilingCopy().getMillis(); return new RangeDivisionInfo(timeRange, Hours.hoursIn(timeRange).getHours() + 1, TimeUnits.HOURS, DateTimeFormat.forPattern("YYYY'-'MMMM'-'dd HH"), lower, upper); // NON-NLS } else if (Minutes.minutesIn(timeRange).isGreaterThan(Minutes.THREE)) { timeUnit = DateTimeFieldType.minuteOfHour(); long lower = startWithZone.property(timeUnit).roundFloorCopy().getMillis(); long upper = endWithZone.property(timeUnit).roundCeilingCopy().getMillis(); return new RangeDivisionInfo(timeRange, Minutes.minutesIn(timeRange).getMinutes() + 1, TimeUnits.MINUTES, DateTimeFormat.forPattern("YYYY'-'MMMM'-'dd HH':'mm"), lower, upper); // NON-NLS } else { timeUnit = DateTimeFieldType.secondOfMinute(); long lower = startWithZone.property(timeUnit).roundFloorCopy().getMillis(); long upper = endWithZone.property(timeUnit).roundCeilingCopy().getMillis(); return new RangeDivisionInfo(timeRange, Seconds.secondsIn(timeRange).getSeconds() + 1, TimeUnits.SECONDS, DateTimeFormat.forPattern("YYYY'-'MMMM'-'dd HH':'mm':'ss"), lower, upper); // NON-NLS } } public DateTimeFormatter getTickFormatter() { return tickFormatter; } public int getPeriodsInRange() { return numberOfBlocks; } public TimeUnits getPeriodSize() { return blockSize; } public long getUpperBound() { return upperBound; } public long getLowerBound() { return lowerBound; } }