/* AWE - Amanzi Wireless Explorer
* http://awe.amanzi.org
* (C) 2008-2009, AmanziTel AB
*
* This library is provided under the terms of the Eclipse Public License
* as described at http://www.eclipse.org/legal/epl-v10.html. Any use,
* reproduction or distribution of the library constitutes recipient's
* acceptance of this agreement.
*
* This library is distributed WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
package org.amanzi.neo.loader.core.saver.drive.impl;
import java.util.HashMap;
import java.util.Map;
import org.amanzi.neo.loader.core.IMappedStringData;
import org.amanzi.neo.loader.core.internal.LoaderCorePlugin;
import org.amanzi.neo.loader.core.saver.impl.AbstractDriveSaver;
import org.amanzi.neo.loader.core.synonyms.SynonymsManager;
import org.amanzi.neo.models.drive.DriveType;
import org.amanzi.neo.models.drive.IDriveModel.IDriveType;
import org.amanzi.neo.nodeproperties.IGeoNodeProperties;
import org.amanzi.neo.nodeproperties.IMeasurementNodeProperties;
import org.amanzi.neo.nodeproperties.ITimePeriodNodeProperties;
import org.amanzi.neo.nodetypes.INodeType;
import org.amanzi.neo.providers.IDriveModelProvider;
import org.amanzi.neo.providers.IProjectModelProvider;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
/**
* TODO Purpose of
* <p>
* </p>
*
* @author Nikolay Lagutko (nikolay.lagutko@amanzitel.com)
* @since 1.0.0
*/
public class GeoptimaSaver extends AbstractDriveSaver {
/** int DOMINANT_TIMEOUT field */
private static final int DOMINANT_TIMEOUT = 5000;
/** String UNKNOWN_VALUE field */
private static final String UNKNOWN_VALUE = "unknown";
private static final Logger LOGGER = Logger.getLogger(GeoptimaSaver.class);
private static final String NEIGHBOUR_SIGNAL_EVENT_NAME = "neighbor_signal";
private static final String SIGNAL_EVENT_NAME = "signal";
private static final String SIGNAL_STRENGTH = "signal_strength";
private static final String NEIGHBOUR_SIGNAL_STRENGTH = "neighbour_signal_strength";
private static final String DOMINANT_PROPERTY = "dominant";
private static final String DELTA_RSSI_PROPERTY = "delta_rssi";
private static final String TIMESTAMP_PROPERTY = "Time";
private final IMeasurementNodeProperties measurementNodeProperties;
private final Map<String, Map<String, Object>> signalCache = new HashMap<String, Map<String, Object>>();
public GeoptimaSaver() {
this(LoaderCorePlugin.getInstance().getTimePeriodNodeProperties(), LoaderCorePlugin.getInstance().getGeoNodeProperties(),
LoaderCorePlugin.getInstance().getDriveModelProvider(), LoaderCorePlugin.getInstance().getProjectModelProvider(),
LoaderCorePlugin.getInstance().getMeasurementNodeProperties(), SynonymsManager.getInstance());
}
/**
* @param projectModelProvider
* @param synonymsManager
*/
protected GeoptimaSaver(final ITimePeriodNodeProperties timePeriodNodeProperties, final IGeoNodeProperties geoNodeProperties,
final IDriveModelProvider driveModelProvider, final IProjectModelProvider projectModelProvider,
final IMeasurementNodeProperties measurementNodeProperties, final SynonymsManager synonymsManager) {
super(timePeriodNodeProperties, geoNodeProperties, driveModelProvider, projectModelProvider, synonymsManager);
this.measurementNodeProperties = measurementNodeProperties;
}
@Override
protected IDriveType getDriveType() {
return DriveType.GEOPTIMA;
}
@Override
protected Map<String, Object> getElementProperties(final INodeType nodeType, final IMappedStringData data,
final boolean addNonMappedHeaders) {
fixDate(data);
Map<String, Object> result = super.getElementProperties(nodeType, data, addNonMappedHeaders);
String event = (String)result.get(measurementNodeProperties.getEventProperty());
if (!StringUtils.isEmpty(event)) {
Object imeiObject = result.get(measurementNodeProperties.getIMEIProperty());
String imei = imeiObject == null ? StringUtils.EMPTY : imeiObject.toString();
if (!StringUtils.isEmpty(imei)) {
if (event.equals(SIGNAL_EVENT_NAME)) {
updateSignalCache(result, imei);
} else if (event.equals(NEIGHBOUR_SIGNAL_EVENT_NAME)) {
updateProperties(result, imei);
}
} else {
LOGGER.warn("No IMEI was found in line <" + data + ">");
}
} else {
LOGGER.warn("No event was found in line <" + data + ">");
}
return result;
}
private void updateSignalCache(final Map<String, Object> data, final String imei) {
Map<String, Object> cacheData = new HashMap<String, Object>();
cacheData.put(getTimePeriodNodeProperties().getTimestampProperty(),
data.get(getTimePeriodNodeProperties().getTimestampProperty()));
cacheData.put(SIGNAL_STRENGTH, data.get(SIGNAL_STRENGTH));
signalCache.put(imei, cacheData);
}
private void updateProperties(final Map<String, Object> data, final String imei) {
Map<String, Object> cacheData = signalCache.get(imei);
Boolean dominantValue = null;
if (cacheData != null) {
long previousTimestamp = (Long)cacheData.get(getTimePeriodNodeProperties().getTimestampProperty());
long currentTimestamp = (Long)data.get(getTimePeriodNodeProperties().getTimestampProperty());
if (currentTimestamp - previousTimestamp < DOMINANT_TIMEOUT) {
Integer signalStrength = (Integer)cacheData.get(SIGNAL_STRENGTH);
Integer neighbourStrength = (Integer)data.get(NEIGHBOUR_SIGNAL_STRENGTH);
if (signalStrength != null && neighbourStrength != null) {
Integer deltaRssi = neighbourStrength - signalStrength;
dominantValue = deltaRssi > 0;
if (dominantValue) {
data.put(DELTA_RSSI_PROPERTY, deltaRssi);
}
}
}
} else {
LOGGER.warn("No cached data for IMEI <" + imei + ">.");
}
data.put(DOMINANT_PROPERTY, dominantValue == null ? UNKNOWN_VALUE : dominantValue);
}
private void fixDate(final IMappedStringData data) {
String time = data.get(TIMESTAMP_PROPERTY);
if (time == null) {
return;
}
int lastPointIndex = time.lastIndexOf(".");
time = time.substring(0, lastPointIndex + 4);
data.put(TIMESTAMP_PROPERTY, time);
}
}