/* 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.model.impl;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.amanzi.awe.correlation.model.CorrelationNodeTypes;
import org.amanzi.awe.correlation.model.ICorrelationModel;
import org.amanzi.awe.correlation.model.IProxyElement;
import org.amanzi.awe.correlation.nodeproperties.ICorrelationProperties;
import org.amanzi.awe.correlation.service.ICorrelationService;
import org.amanzi.neo.dto.IDataElement;
import org.amanzi.neo.impl.dto.DataElement;
import org.amanzi.neo.impl.util.AbstractDataElementIterator;
import org.amanzi.neo.models.exceptions.ModelException;
import org.amanzi.neo.models.impl.internal.AbstractNamedModel;
import org.amanzi.neo.models.measurement.IMeasurementModel;
import org.amanzi.neo.models.measurement.MeasurementNodeType;
import org.amanzi.neo.models.network.INetworkModel;
import org.amanzi.neo.models.network.NetworkElementType;
import org.amanzi.neo.nodeproperties.IGeneralNodeProperties;
import org.amanzi.neo.nodeproperties.INetworkNodeProperties;
import org.amanzi.neo.nodeproperties.ITimePeriodNodeProperties;
import org.amanzi.neo.nodetypes.INodeType;
import org.amanzi.neo.nodetypes.NodeTypeNotExistsException;
import org.amanzi.neo.services.INodeService;
import org.amanzi.neo.services.exceptions.ServiceException;
import org.apache.log4j.Logger;
import org.neo4j.graphdb.Node;
/**
* TODO Purpose of
* <p>
* </p>
*
* @author Vladislav_Kondratenko
* @since 1.0.0
*/
public class CorrelationModel extends AbstractNamedModel implements ICorrelationModel {
protected final class ProxyIterator extends AbstractDataElementIterator<IProxyElement> {
/**
* @param nodeIterator
*/
public ProxyIterator(final Iterator<Node> nodeIterator) {
super(nodeIterator);
}
@Override
protected IProxyElement createDataElement(final Node node) {
try {
Node sector = correlationService.getSectorForProxy(node);
Iterator<Node> measurements = correlationService.getMeasurementForProxy(node, measurementModel.getName());
return new ProxyElement(getRootNode(), new DataElement(sector), new DataElementIterator(measurements));
} catch (ServiceException e) {
LOGGER.error("can't create proxyElement", e);
return null;
}
}
}
private static final Logger LOGGER = Logger.getLogger(CorrelationModel.class);
private final INetworkNodeProperties networkNodeProperties;
private final ICorrelationService correlationService;
private IMeasurementModel measurementModel;
private INetworkModel networkModel;
private final Map<IDataElement, IProxyElement> proxiesCache = new HashMap<IDataElement, IProxyElement>();
private final Map<IProxyElement, Set<IDataElement>> measurementCache = new HashMap<IProxyElement, Set<IDataElement>>();
private final ICorrelationProperties correlationNodeProperties;
private String correlatedProperty;
private String correlationProperties;
private Long startTime = Long.MAX_VALUE;
private Long endTime = Long.MIN_VALUE;
private int proxiesCount;
private final ITimePeriodNodeProperties timePeriodNodeProperties;
private Integer totalSectorsCount;
private Integer correlatedMCount;
private Integer totalMCount;
public CorrelationModel(final ICorrelationService correlationService, final INodeService nodeService,
final IGeneralNodeProperties generalNodeProperties, final INetworkNodeProperties networkNodeProperties,
final ICorrelationProperties correlationNodeProperties, final ITimePeriodNodeProperties timePeriodNodeProperties) {
super(nodeService, generalNodeProperties);
this.networkNodeProperties = networkNodeProperties;
this.correlationService = correlationService;
this.correlationNodeProperties = correlationNodeProperties;
this.timePeriodNodeProperties = timePeriodNodeProperties;
}
private void computeCorrelatedM() {
for (Set<IDataElement> measurements : measurementCache.values()) {
correlatedMCount += measurements.size();
}
}
@Override
public void delete() throws ModelException {
try {
correlationService.deleteModel(getRootNode());
} catch (ServiceException e) {
processException("Can't remove model" + getName(), e);
} catch (NodeTypeNotExistsException e) {
processException("Can't remove model" + getName(), e);
}
}
@Override
public Iterable<IProxyElement> findAllProxies() throws ModelException {
Iterator<Node> proxies = null;
try {
getNodeService().getChildrenChain(getRootNode());
} catch (ServiceException e) {
processException("can't get proxies for model " + this, e);
}
return new ProxyIterator(proxies).toIterable();
}
@Override
public void finishUp() throws ModelException {
try {
totalSectorsCount = networkModel.getPropertyStatistics().getCount(NetworkElementType.SECTOR);
proxiesCount = proxiesCache.size();
computeCorrelatedM();
totalMCount = measurementModel.getPropertyStatistics().getCount(MeasurementNodeType.M);
getNodeService().updateProperty(getRootNode(), correlationNodeProperties.getProxiesCountNodeProperty(), proxiesCount);
getNodeService().updateProperty(getRootNode(), timePeriodNodeProperties.getStartDateTimestampProperty(), startTime);
getNodeService().updateProperty(getRootNode(), timePeriodNodeProperties.getEndDateTimestampProperty(), endTime);
getNodeService().updateProperty(getRootNode(), correlationNodeProperties.getTotalSectorsCount(), totalSectorsCount);
getNodeService().updateProperty(getRootNode(), correlationNodeProperties.getCorrelatedMCountNodeProperty(),
correlatedMCount);
getNodeService().updateProperty(getRootNode(), correlationNodeProperties.getTotalMCountNodeProperty(), totalMCount);
proxiesCache.clear();
measurementCache.clear();
} catch (ServiceException e) {
processException("can't update properties", e);
}
}
@Override
public Iterable<IDataElement> getAllElementsByType(final INodeType nodeType) throws ModelException {
return null;
}
@Override
public Integer getCorrelatedMCount() {
return correlatedMCount;
}
@Override
public String getCorrelatedProperty() {
return correlatedProperty;
}
@Override
public String getCorrelationProperty() {
return correlationProperties;
}
@Override
public Long getEndTime() {
return endTime;
}
@Override
public IMeasurementModel getMeasurementModel() {
return measurementModel;
}
@Override
protected INodeType getModelType() {
return CorrelationNodeTypes.CORRELATION_MODEL;
}
/**
* @return Returns the networkNodeProperties.
*/
public INetworkNodeProperties getNetworkNodeProperties() {
return networkNodeProperties;
}
@Override
public INetworkModel getNetworModel() {
return networkModel;
}
@Override
public int getProxiesCount() {
return proxiesCount;
}
@Override
public IProxyElement getProxy(final IDataElement sector, final IDataElement correlatedElement) throws ModelException {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("getProxy(" + sector + "," + correlatedElement + ")");
}
assert sector != null;
assert correlatedElement != null;
IProxyElement proxy = proxiesCache.get(sector);
Node sectorNode = ((DataElement)sector).getNode();
Node measurementNode = ((DataElement)correlatedElement).getNode();
try {
Node proxyNode = correlationService.findProxy(sectorNode, measurementNode, measurementModel.getName());
if (proxyNode == null) {
proxyNode = correlationService.createProxy(getRootNode(), sectorNode, measurementNode, measurementModel.getName());
Long timestamp = getNodeService().getNodeProperty(measurementNode, timePeriodNodeProperties.getTimestampProperty(),
startTime, false);
updateTimestamp(timestamp);
}
if (proxy == null) {
proxy = new ProxyElement(proxyNode, sector);
proxiesCache.put(sector, proxy);
}
if (measurementCache.get(proxy) == null) {
measurementCache.put(proxy, new HashSet<IDataElement>());
}
measurementCache.get(proxy).add(correlatedElement);
} catch (ServiceException e) {
processException("can't create proxy node for sector " + sector + " and measurement " + correlatedElement, e);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(getFinishLogStatement("getProxy(" + sector + "," + correlatedElement + ")"));
}
return proxy;
}
@Override
public Long getStartTime() {
return startTime;
}
@Override
public Integer getTotalMCount() {
return totalMCount;
}
@Override
public Integer getTotalSectorsCount() {
return totalSectorsCount;
}
@Override
public void initialize(final Node rootNode) throws ModelException {
super.initialize(rootNode);
try {
this.correlatedProperty = getNodeService().getNodeProperty(rootNode,
correlationNodeProperties.getCorrelatedNodeProperty(), null, true);
this.correlationProperties = getNodeService().getNodeProperty(rootNode,
correlationNodeProperties.getCorrelationNodeProperty(), null, true);
this.startTime = getNodeService().getNodeProperty(rootNode, timePeriodNodeProperties.getStartDateTimestampProperty(),
startTime, false);
this.endTime = getNodeService().getNodeProperty(rootNode, timePeriodNodeProperties.getEndDateTimestampProperty(),
endTime, false);
this.proxiesCount = getNodeService().getNodeProperty(rootNode, correlationNodeProperties.getProxiesCountNodeProperty(),
0, false);
this.totalSectorsCount = getNodeService().getNodeProperty(rootNode, correlationNodeProperties.getTotalSectorsCount(),
0, false);
this.correlatedMCount = getNodeService().getNodeProperty(rootNode,
correlationNodeProperties.getCorrelatedMCountNodeProperty(), 0, false);
this.totalMCount = getNodeService().getNodeProperty(rootNode, correlationNodeProperties.getTotalMCountNodeProperty(),
0, false);
} catch (ServiceException e) {
processException("can't get property from model" + getName(), e);
}
}
/**
* @param measurementModel
*/
public void setCorrelatedModels(final INetworkModel networkModel, final IMeasurementModel measurementModel) {
this.networkModel = networkModel;
this.measurementModel = measurementModel;
}
private void updateTimestamp(final long timestamp) {
startTime = Math.min(startTime, timestamp);
endTime = Math.max(endTime, timestamp);
}
}