/* * RomRaider Open-Source Tuning, Logging and Reflashing * Copyright (C) 2006-2016 RomRaider.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package com.romraider.logger.ecu.ui.handler.file; import static com.romraider.Settings.COMMA; import static com.romraider.Settings.SEMICOLON; import static com.romraider.util.ParamChecker.checkNotNull; import static java.util.Collections.synchronizedList; import static java.util.Collections.synchronizedMap; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import com.romraider.logger.ecu.comms.query.Response; import com.romraider.logger.ecu.definition.ConvertorUpdateListener; import com.romraider.logger.ecu.definition.LoggerData; import com.romraider.logger.ecu.ui.MessageListener; import com.romraider.logger.ecu.ui.StatusChangeListener; public final class FileUpdateHandlerImpl implements FileUpdateHandler, ConvertorUpdateListener { private final Map<LoggerData, Integer> loggerDatas = synchronizedMap(new LinkedHashMap<LoggerData, Integer>()); private final List<StatusChangeListener> listeners = synchronizedList(new ArrayList<StatusChangeListener>()); private final FileLogger fileLogger; private final Set<String> locales = new HashSet<String>( Arrays.asList(new String[] { "be_BY","bg_BG","ca_ES","cs_CZ","da_DK","de_AT","de_CH","de_DE","de_LU", "el_CY","el_GR","es_AR","es_BO","es_CL","es_CO","es_EC","es_ES","es_PE", "es_PY","es_UY","es_VE","et_EE","fi_FI","fr_BE","fr_CA","fr_CH","fr_FR", "fr_LU","hr_HR","hu_HU","in_ID","is_IS","it_CH","it_IT","lt_LT","lv_LV", "mk_MK","nl_BE","nl_NL","no_NO","no_NO_NY","pl_PL","pt_BR","pt_PT", "ro_RO","ru_RU","sk_SK","sl_SI","sq_AL","sr_BA","sr_CS","sr_ME","sr_RS", "sv_SE","tr_TR","uk_UA","vi_VN" } )); private final String delimiter = locales.contains(Locale.getDefault().toString()) ? SEMICOLON : COMMA; private Line currentLine = new Line(loggerDatas.keySet()); public FileUpdateHandlerImpl(MessageListener messageListener) { fileLogger = new FileLoggerImpl(messageListener); } @Override public synchronized void addListener(StatusChangeListener listener) { checkNotNull(listener, "listener"); listeners.add(listener); } @Override public synchronized void registerData(LoggerData loggerData) { if (loggerDatas.keySet().contains(loggerData)) { loggerDatas.put(loggerData, loggerDatas.get(loggerData) + 1); } else { loggerDatas.put(loggerData, 1); resetLine(); writeHeaders(); } } @Override public synchronized void handleDataUpdate(Response response) { if (fileLogger.isStarted()) { for (LoggerData loggerData : response.getData()) { currentLine.updateParamValue(loggerData, loggerData.getSelectedConvertor().format(response.getDataValue(loggerData))); } if (currentLine.isFull()) { fileLogger.writeLine(currentLine.values(), response.getTimestamp()); resetLine(); } } } @Override public synchronized void deregisterData(LoggerData loggerData) { if (loggerDatas.keySet().contains(loggerData) && loggerDatas.get(loggerData) > 1) { loggerDatas.put(loggerData, loggerDatas.get(loggerData) - 1); } else { loggerDatas.remove(loggerData); resetLine(); writeHeaders(); } } @Override public synchronized void cleanUp() { if (fileLogger.isStarted()) { fileLogger.stop(); } } @Override public synchronized void reset() { } @Override public synchronized void notifyConvertorUpdate(LoggerData updatedLoggerData) { resetLine(); writeHeaders(); } @Override public synchronized void start() { if (!fileLogger.isStarted()) { fileLogger.start(); notifyListeners(true); writeHeaders(); } } @Override public synchronized void stop() { if (fileLogger.isStarted()) { fileLogger.stop(); notifyListeners(false); } } private void resetLine() { currentLine = new Line(loggerDatas.keySet()); } private void writeHeaders() { if (fileLogger.isStarted()) { fileLogger.writeHeaders(currentLine.headers()); } } private void notifyListeners(boolean loggingToFile) { for (StatusChangeListener listener : listeners) { if (loggingToFile) { listener.loggingData(); } else { listener.readingData(); } } } private final class Line { private final Map<LoggerData, String> loggerDataValues; public Line(Set<LoggerData> loggerDatas) { this.loggerDataValues = new LinkedHashMap<LoggerData, String>(); for (LoggerData loggerData : loggerDatas) { loggerDataValues.put(loggerData, null); } } public synchronized void updateParamValue(LoggerData loggerData, String value) { if (loggerDataValues.containsKey(loggerData)) { loggerDataValues.put(loggerData, value); } } public synchronized boolean isFull() { for (LoggerData loggerData : loggerDataValues.keySet()) { if (loggerDataValues.get(loggerData) == null) { return false; } } return true; } public synchronized String headers() { final StringBuilder buffer = new StringBuilder(); for (LoggerData loggerData : loggerDataValues.keySet()) { buffer.append(delimiter).append(loggerData.getName()).append(" (") .append(loggerData.getSelectedConvertor().getUnits()).append(')'); } return buffer.toString(); } public synchronized String values() { final StringBuilder buffer = new StringBuilder(); for (LoggerData loggerData : loggerDataValues.keySet()) { String value = loggerDataValues.get(loggerData); buffer.append(delimiter).append(value); } return buffer.toString(); } } }