/* 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.awe.correlation.engine;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.amanzi.awe.correlation.CorrelationPlugin;
import org.amanzi.awe.correlation.exception.CorrelationEngineException;
import org.amanzi.awe.correlation.model.ICorrelationModel;
import org.amanzi.awe.correlation.provider.ICorrelationModelProvider;
import org.amanzi.neo.core.transactional.AbstractTransactional;
import org.amanzi.neo.dto.IDataElement;
import org.amanzi.neo.models.exceptions.ModelException;
import org.amanzi.neo.models.measurement.IMeasurementModel;
import org.amanzi.neo.models.network.INetworkModel;
import org.amanzi.neo.models.network.NetworkElementType;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
/**
* TODO Purpose of
* <p>
* </p>
*
* @author Vladislav_Kondratenko
* @since 1.0.0
*/
public class CorrelationEngine extends AbstractTransactional {
@SuppressWarnings("unused")
private static class ID {
private final String correlatedProperies;
private final IMeasurementModel measurementModel;
private final String correlatedProeprty;
private final INetworkModel networkModel;
/**
* @param model
* @param period
* @param template
* @param propertyName
*/
public ID(final INetworkModel networkModel, final IMeasurementModel measurementModel, final String correlationProperties,
final String correlatedroperties) {
super();
this.networkModel = networkModel;
this.correlatedProeprty = correlationProperties;
this.measurementModel = measurementModel;
this.correlatedProperies = correlatedroperties;
}
@Override
public boolean equals(final Object obj) {
return EqualsBuilder.reflectionEquals(this, obj, false);
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this, false);
}
}
private static final Logger LOGGER = Logger.getLogger(CorrelationEngine.class);
private final ICorrelationModelProvider modelProvider;
private final INetworkModel networkModel;
private final String correlationPropertyName;
private final IMeasurementModel measurementModel;
private final String correlatedPropertyName;
private static Map<ID, CorrelationEngine> engineCache = new HashMap<ID, CorrelationEngine>();
public static synchronized List<ICorrelationModel> getAllNetworkCorrelations(final INetworkModel network) {
try {
return CorrelationPlugin.getDefault().getCorrelationModelProvider().findAll(network);
} catch (ModelException e) {
LOGGER.error("can't get all correlation", e);
return null;
}
}
public static synchronized CorrelationEngine getEngine(final INetworkModel networkModel, final String correlationProperties,
final IMeasurementModel measurementModel, final String correlatedroperties) {
final ID id = new ID(networkModel, measurementModel, correlationProperties, correlatedroperties);
CorrelationEngine result = engineCache.get(id);
if (result == null) {
result = new CorrelationEngine(networkModel, correlationProperties, measurementModel, correlatedroperties);
engineCache.put(id, result);
}
return result;
}
public static synchronized void removeModel(final ICorrelationModel model) throws ModelException {
assert model != null;
try {
CorrelationPlugin.getDefault().getCorrelationModelProvider().removeModel(model);
} catch (ModelException e) {
LOGGER.error("can't remove model ", e);
throw e;
}
}
/**
* @param correlationModelProvider
* @param networkModel
* @param correlationProperty
* @param measurementModel
* @param correlatedroperties
*/
protected CorrelationEngine(final ICorrelationModelProvider correlationModelProvider, final INetworkModel networkModel,
final String correlationProperty, final IMeasurementModel measurementModel, final String correlatedroperties) {
this.modelProvider = correlationModelProvider;
this.networkModel = networkModel;
this.correlationPropertyName = correlationProperty;
this.measurementModel = measurementModel;
this.correlatedPropertyName = correlatedroperties;
}
private CorrelationEngine(final INetworkModel networkModel, final String correlationProperties,
final IMeasurementModel measurementModel, final String correlatedroperties) {
this(CorrelationPlugin.getDefault().getCorrelationModelProvider(), networkModel, correlationProperties, measurementModel,
correlatedroperties);
}
public ICorrelationModel build(IProgressMonitor monitor) throws CorrelationEngineException {
LOGGER.info("Start correlation colculating for network <" + networkModel.getName() + "> and measurement model <"
+ measurementModel.getName() + "> by properties " + correlationPropertyName + " and " + correlatedPropertyName);
if (monitor == null) {
monitor = new NullProgressMonitor();
}
startTransaction();
ICorrelationModel correlationModel = null;
monitor.beginTask("Start correlation calculation", 1);
boolean isSuccess = false;
try {
correlationModel = modelProvider.findCorrelationModel(networkModel, measurementModel, correlationPropertyName,
correlatedPropertyName);
if (correlationModel == null) {
LOGGER.info("CorrelationModel not exists in Database. Create new one.");
correlationModel = modelProvider.createCorrelationModel(networkModel, measurementModel, correlationPropertyName,
correlatedPropertyName);
buildCorrelation(correlationModel, monitor);
}
isSuccess = true;
} catch (final Exception e) {
LOGGER.error("An error occured on Statistics Calculation", e);
throw new CorrelationEngineException(networkModel, measurementModel, correlationPropertyName, correlatedPropertyName, e);
} finally {
saveTx(isSuccess, false);
monitor.done();
}
LOGGER.info("Finished Correlation Calculation");
return correlationModel;
}
/**
* @param correlationModel
* @param monitor
* @throws ModelException
*/
private void buildCorrelation(final ICorrelationModel correlationModel, final IProgressMonitor monitor) throws ModelException {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Building statistics");
}
try {
computeCorrelation(correlationModel, monitor);
} catch (final ModelException e) {
LOGGER.error("Error on calculating statistics", e);
throw e;
} finally {
correlationModel.finishUp();
}
}
/**
* @param correlationModel
* @param monitor
* @throws ModelException
*/
private void computeCorrelation(final ICorrelationModel correlationModel, final IProgressMonitor monitor) throws ModelException {
String subProgressName = "Compute correlation for network <" + networkModel.getName() + "> and measurement model <"
+ measurementModel.getName() + "> by properties " + correlationPropertyName + " and " + correlatedPropertyName;
final IProgressMonitor subProgressMonitor = new SubProgressMonitor(monitor, 1);
monitor.subTask(subProgressName);
subProgressMonitor.beginTask(subProgressName, networkModel.getPropertyStatistics().getCount(NetworkElementType.SECTOR));
for (IDataElement sector : networkModel.getAllElementsByType(NetworkElementType.SECTOR)) {
Object correlationProperty = sector.get(correlationPropertyName);
Object sectorLac = sector.get("lac");
if (correlationProperty == null) {
subProgressMonitor.worked(1);
continue;
}
Iterable<IDataElement> correlatedElements = measurementModel.findElementByProperty(this.correlatedPropertyName,
correlationProperty);
for (IDataElement element : correlatedElements) {
Object measurementLac = element.get("lac");
if (measurementLac != null && sectorLac != null && !measurementLac.equals(sectorLac)) {
continue;
}
correlationModel.getProxy(sector, element);
}
updateTransaction();
subProgressMonitor.worked(1);
}
}
}