package de.saxsys.projectiler; import java.util.Date; import java.util.List; import java.util.logging.Logger; import de.saxsys.projectiler.api.ConnectionException; import de.saxsys.projectiler.api.ProjectileClientApi; import de.saxsys.projectiler.api.ProjectileApiException; import de.saxsys.projectiler.api.Credentials; import de.saxsys.projectiler.api.InvalidCredentialsException; import de.saxsys.projectiler.ws.rest.RetrofitClient; /** * Automatic time tracking in Projectile. * * @author stefan.bley */ public class Projectiler { private static final Logger LOGGER = Logger.getLogger(Projectiler.class.getSimpleName()); private final UserDataStore dataStore = UserDataStore.getInstance(); private final ProjectileClientApi crawler; public static Projectiler createDefaultProjectiler() { return new Projectiler(new RetrofitClient(new SystemSettings())); } protected Projectiler(final ProjectileClientApi crawler) { this.crawler = crawler; } public String getUserName() { return dataStore.getUserName(); } public boolean isCheckedIn() { return dataStore.isCheckedIn(); } /** * Invoke a checkin, i.e. start a working period. * * @return checkin date */ public Date checkin() { final Date start = DateUtil.resetSeconds(new Date()); dataStore.setStartDate(start); dataStore.save(); LOGGER.info("Checked in at " + DateUtil.formatShort(start)); return start; } /** * Invoke a checkout, i.e. finish a working period. * * @param projectName project to clock your time to * @param comment optional comment * @throws ProjectileApiException * @throws ConnectionException if connection to Projectile fails * @throws IllegalStateException if invoked while not being checked in or if work time is less than one minute */ public Date checkout(final String projectName, final String comment) throws ProjectileApiException { if (!isCheckedIn()) { throw new IllegalStateException("Must be checked in before checking out."); } final Date start = dataStore.getStartDate(); final Date end = new Date(); if (DateUtil.formatHHmm(start).equals(DateUtil.formatHHmm(end))) { dataStore.clearStartDate(); dataStore.save(); throw new IllegalStateException("Work time must be at least 1 minute."); } try { crawler.clock(createCredentials(), projectName, start, end, comment); } finally { dataStore.clearStartDate(); dataStore.save(); } LOGGER.info("Checked out at " + DateUtil.formatShort(end)); return end; } /** * Retrieve available project names. * * @return list of project names or empty list * @throws ConnectionException if connection to Projectile fails * @throws ProjectileApiException if an error occoures in the crawles */ public List<String> getProjectNames() throws ConnectionException, ProjectileApiException { return crawler.getProjectNames(createCredentials()); } /** * Verify credentials and save them to the userdata store. * * @param username Projectile username * @param password Projectile password * @throws InvalidCredentialsException if credentials are invalid * @throws ConnectionException if connection to Projectile fails * @throws ProjectileApiException */ public void saveCredentials(final String username, final String password) throws InvalidCredentialsException, ConnectionException, ProjectileApiException { crawler.checkCredentials(new Credentials(username, password)); dataStore.setCredentials(username, password); dataStore.save(); } /** Save the project name to the userdata store. */ public void saveProjectName(final String projectKey) { dataStore.setProjectName(projectKey); dataStore.save(); } private Credentials createCredentials() { return new Credentials(dataStore.getUserName(), dataStore.getPassword()); } }