/* Copyright (C) 2015-2016 Stichting Akvo (Akvo Foundation) * * This file is part of Akvo FLOW. * * Akvo FLOW is free software: you can redistribute it and modify it under the terms of * the GNU Affero General Public License (AGPL) as published by the Free Software Foundation, * either version 3 of the License or any later version. * * Akvo FLOW is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License included below for more details. * * The full license text can also be seen at <http://www.gnu.org/licenses/agpl.html>. */ package org.waterforpeople.mapping.dataexport; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.TimeZone; import org.apache.log4j.Logger; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.DataFormatter; import org.apache.poi.ss.usermodel.Row; import org.waterforpeople.mapping.domain.response.value.Media; import org.waterforpeople.mapping.serialization.response.MediaResponse; import com.gallatinsystems.common.util.StringUtil; public class ExportImportUtils { private static final Logger log = Logger.getLogger(ExportImportUtils.class); private static final ThreadLocal<DataFormatter> DATA_FORMATTER = new ThreadLocal<DataFormatter>() { @Override protected DataFormatter initialValue() { return new DataFormatter(); } }; private static final ThreadLocal<DateFormat> DATE_RESPONSE_FORMAT = new ThreadLocal<DateFormat>() { @Override protected DateFormat initialValue() { DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); df.setTimeZone(TimeZone.getTimeZone("GMT")); return df; }; }; private static final ThreadLocal<DateFormat> DATE_TIME_FORMAT = new ThreadLocal<DateFormat>() { @Override protected DateFormat initialValue() { return new SimpleDateFormat("dd-MM-yyyy HH:mm:ss z"); }; }; /** * Parse cell as string independent of cell type * * @param cell * @return */ public static String parseCellAsString(Cell cell) { return DATA_FORMATTER.get().formatCellValue(cell).trim(); } /** * Calculate the md5 digest of each row up to (and including) the lastColumnIndex * * @param rows * @param lastColumnIndex * @return * @throws NoSuchAlgorithmException */ public static String md5Digest(List<Row> rows, int lastColumnIndex) throws NoSuchAlgorithmException { MessageDigest digest = MessageDigest.getInstance("MD5"); for (Row row : rows) { for (Cell cell : row) { if (cell.getColumnIndex() > lastColumnIndex) { break; } else { String val = parseCellAsString(cell); if (val != null && !val.equals("")) { digest.update(val.getBytes()); } } } } return StringUtil.toHexString(digest.digest()); } /* * Format date into a date-time string. */ public static String formatDateTime(Date date) { if (date != null) { return DATE_TIME_FORMAT.get().format(date); } else { return ""; } } /* * Format DateQuestion response in a human-readable way. This date will not contain time details * (yyyy-MM-dd) */ public static String formatDateResponse(String value) { Date date = parseDatastoreDate(value); if (date != null) { return DATE_RESPONSE_FORMAT.get().format(date); } return ""; } /* * Convert a DateQuestion response value into a Date. Note: Values may be presented in an * inconsistent manner, possibly containing ISO-8601 dates. */ public static Date parseDatastoreDate(String value) { try { return new Date(Long.valueOf(value)); } catch (NumberFormatException e) { log.error("Value is not a valid timestamp: " + value); } // Value is not a timestamp. Try to parse as a spreadsheet value return parseSpreadsheetDate(value); } /* * Parse a date from the spreadsheet. This includes collection dates (date-time) and * DateQuestion responses (ISO8601 or date-time). */ public static Date parseSpreadsheetDate(String dateString) { if (dateString == null || dateString.equals("")) { return null; } // Parse date-time format by default (collection dates and old responses) try { return DATE_TIME_FORMAT.get().parse(dateString); } catch (ParseException e) { // Date is not date-time formatted } // Use ISO 8601 otherwise try { return DATE_RESPONSE_FORMAT.get().parse(dateString); } catch (ParseException e) { // Date is not ISO 8601 } log.warn("Response doesn't contain a valid format: " + dateString); return null; } public static String formatImage(String prefix, String value) { String cell = ""; Media media = MediaResponse.parse(value); String filename = media.getFilename(); final int filenameIndex = filename != null ? filename.lastIndexOf("/") + 1 : -1; if (filenameIndex > 0 && filenameIndex < filename.length()) { cell = prefix + filename.substring(filenameIndex); } return cell; } }