/** * The contents of this file are subject to the OpenMRS Public License * Version 1.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://license.openmrs.org * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * Copyright (C) OpenMRS, LLC. All Rights Reserved. */ package org.openmrs.module.sync.scheduler; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openmrs.api.APIException; import org.openmrs.api.context.Context; import org.openmrs.module.sync.SyncRecordState; import org.openmrs.module.sync.api.SyncService; import org.openmrs.module.sync.server.SyncServerRecord; import org.openmrs.scheduler.tasks.AbstractTask; import org.springframework.util.StringUtils; /** * This task deletes rows in the sync_record and sync_server_record tables that are older and not * needed anymore. (Sync_import is not touched at this point) */ public class CleanupSyncTablesTask extends AbstractTask { private static Log log = LogFactory.getLog(CleanupSyncTablesTask.class); protected static final String PROPERTY_DAYS_BACK = "delete_entries_files_older_than_x_days"; private Integer DEFAULT_DAYS_BACK_TO_START_DELETE = 90; /** * Comma delimited list of {@link SyncRecordState} names that will be deleted. These states on * the {@link SyncServerRecord} rows. */ protected static final String PROPERTY_STATES_TO_DELETE = "sync_record_states_to_delete"; // by default let the service decide which states to delete private SyncRecordState[] DEFAULT_STATES_TO_DELETE = new SyncRecordState[] { }; /** * Do the actual deleting of tables. */ public void execute() { Context.openSession(); log.debug("Starting sync table cleanup ... "); try { if (Context.isAuthenticated() == false) authenticate(); // get the possibly user-defined settings Map<String, String> props = null; if (taskDefinition != null) props = taskDefinition.getProperties(); Integer daysBack = getIntegerProperty(PROPERTY_DAYS_BACK, props, DEFAULT_DAYS_BACK_TO_START_DELETE); Calendar today = Calendar.getInstance(); today.add(Calendar.DATE, -1 * daysBack); Date deleteTo = today.getTime(); SyncRecordState[] statesToDelete = getSyncRecordStateProperty(PROPERTY_STATES_TO_DELETE, props, DEFAULT_STATES_TO_DELETE); // do the actual deleting SyncService syncService = Context.getService(SyncService.class); Integer quantityDeleted = syncService.deleteSyncRecords(statesToDelete, deleteTo); log.info("There were " + quantityDeleted + " sync records cleaned out"); } catch (Throwable t) { log.error("Error while doing sync table cleanup", t); throw new APIException(t); } finally { Context.closeSession(); } } /** * Get the given property name from the given Map object. If not found or if the value is an * invalid integer, return defaultValue * * @param propertyName the prop key to look for * @param props the key-value map to look in * @param defaultValue the default integer if the value is invalid * @return the defined value for prop in props */ protected static Integer getIntegerProperty(String propertyName, Map<String, String> props, Integer defaultValue) { if (props != null) { String prop = props.get(propertyName); if (prop != null) { try { return Integer.valueOf(prop); } catch (NumberFormatException e) { log.error("Unable to convert property value for " + propertyName + " : '" + prop + "' to an integer"); } } } return defaultValue; } /** * Get the given property name from the given props and convert it to an array of * {@link SyncRecordState}s * * @param propertyName the prop key to look for * @param props the key-value map to look in * @param defaultStates the default array if the value is invalid * @return an array of {@link SyncRecordState}s */ protected static SyncRecordState[] getSyncRecordStateProperty(String propertyName, Map<String, String> props, SyncRecordState[] defaultStates) { if (props != null) { String prop = props.get(propertyName); if (StringUtils.hasLength(prop)) { try { List<SyncRecordState> states = new ArrayList<SyncRecordState>(); for (String stateName : prop.split(",")) { SyncRecordState state = SyncRecordState.valueOf(stateName.trim()); states.add(state); } return states.toArray(new SyncRecordState[] {}); } catch (Exception e) { log.error("Unable to convert property value for " + propertyName + " : '" + prop + "' to an array of states"); } } } return defaultStates; } }