/* 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.service.impl; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.amanzi.awe.correlation.exceptions.DuplicatedProxyException; import org.amanzi.awe.correlation.model.CorrelationNodeTypes; import org.amanzi.awe.correlation.nodeproperties.ICorrelationProperties; import org.amanzi.awe.correlation.service.ICorrelationService; import org.amanzi.neo.models.network.NetworkElementType; import org.amanzi.neo.nodetypes.NodeTypeNotExistsException; import org.amanzi.neo.services.INodeService; import org.amanzi.neo.services.exceptions.DatabaseException; import org.amanzi.neo.services.exceptions.ServiceException; import org.amanzi.neo.services.impl.internal.AbstractService; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.neo4j.graphdb.Direction; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Path; import org.neo4j.graphdb.Relationship; import org.neo4j.graphdb.RelationshipType; import org.neo4j.graphdb.Transaction; import org.neo4j.graphdb.traversal.Evaluation; import org.neo4j.graphdb.traversal.Evaluator; import org.neo4j.graphdb.traversal.Evaluators; import org.neo4j.graphdb.traversal.TraversalDescription; import org.neo4j.kernel.Traversal; /** * TODO Purpose of * <p> * </p> * * @author Vladislav_Kondratenko * @since 1.0.0 */ public class CorrelationService extends AbstractService implements ICorrelationService { public static enum CorrelationRelationshipType implements RelationshipType { CORRELATION, CORRELATED, PROXY; } private static final Logger LOGGER = Logger.getLogger(CorrelationService.class); private static final TraversalDescription INCOMING_PROXIES_TRAVERSAL = Traversal.description().depthFirst() .evaluator(Evaluators.excludeStartPosition()).relationships(CorrelationRelationshipType.PROXY, Direction.INCOMING); private static final TraversalDescription OUTGOUING_PROXIES_TRAVERSAL = Traversal.description().depthFirst() .evaluator(Evaluators.excludeStartPosition()).relationships(CorrelationRelationshipType.PROXY, Direction.OUTGOING); private final INodeService nodeSerivce; private final ICorrelationProperties correlationProperties; private final String CORRELATION_MODEL_NAME_FORMAT = "%s:%s@%s:%s"; /** * @param nodeSerivce * @param generalNodeProeprties */ public CorrelationService(final GraphDatabaseService graphDb, final INodeService nodeSerivce, final ICorrelationProperties correlationProperties) { super(graphDb, null); this.nodeSerivce = nodeSerivce; this.correlationProperties = correlationProperties; } @Override public Node createCorrelationModelNode(final Node networkRoot, final Node measurementRoot, final String correlationProperty, final String correlatedProperty) throws ServiceException { assert networkRoot != null; assert measurementRoot != null; assert !StringUtils.isEmpty(correlatedProperty); assert correlationProperty != null; assert !correlationProperty.isEmpty(); String networkName = nodeSerivce.getNodeName(networkRoot); String measurementName = nodeSerivce.getNodeName(measurementRoot); String modelName = String.format(CORRELATION_MODEL_NAME_FORMAT, networkName, correlationProperty, measurementName, correlatedProperty); Node modelNode = nodeSerivce.createNode(networkRoot, CorrelationNodeTypes.CORRELATION_MODEL, CorrelationRelationshipType.CORRELATION, String.format(modelName, networkName, measurementName)); nodeSerivce.updateProperty(modelNode, correlationProperties.getCorrelatedNodeProperty(), correlatedProperty); nodeSerivce.updateProperty(modelNode, correlationProperties.getCorrelationNodeProperty(), correlationProperty); nodeSerivce.linkNodes(measurementRoot, modelNode, CorrelationRelationshipType.CORRELATED); return modelNode; } @Override public Node createProxy(final Node rootNode, final Node sectorNode, final Node measurementNode, final String measuremntName) throws ServiceException { assert rootNode != null; assert sectorNode != null; assert !StringUtils.isEmpty(measuremntName); Node proxyNode = findProxy(sectorNode, measurementNode, measuremntName); if (proxyNode != null) { throw new DuplicatedProxyException(rootNode, sectorNode, measurementNode); } proxyNode = findSectorProxyForModel(sectorNode, measuremntName); if (proxyNode == null) { proxyNode = nodeSerivce.createNodeInChain(rootNode, CorrelationNodeTypes.PROXY); nodeSerivce.linkNodes(proxyNode, sectorNode, CorrelationRelationshipType.PROXY); } Relationship relationship = nodeSerivce.linkNodes(proxyNode, measurementNode, CorrelationRelationshipType.PROXY); nodeSerivce.updateProperty(relationship, correlationProperties.getCorrelatedModelNameProperty(), measuremntName); return proxyNode; } @Override public void deleteModel(final Node root) throws ServiceException, NodeTypeNotExistsException { assert root != null; assert nodeSerivce.getNodeType(root).equals(CorrelationNodeTypes.CORRELATION_MODEL); final Transaction tx = getGraphDb().beginTx(); try { for (final Relationship rel : root.getRelationships(Direction.INCOMING)) { rel.delete(); } deleteNode(root); tx.success(); } catch (final Exception e) { tx.failure(); throw new DatabaseException(e); } finally { tx.finish(); } } /** * @param root * @throws NodeTypeNotExistsException * @throws ServiceException */ private void deleteNode(final Node root) throws ServiceException, NodeTypeNotExistsException { if (!nodeSerivce.getNodeType(root).equals(CorrelationNodeTypes.CORRELATION_MODEL) || !nodeSerivce.getNodeType(root).equals(CorrelationNodeTypes.PROXY)) { return; } final List<Node> nextNode = new ArrayList<Node>(); for (final Relationship rel : root.getRelationships(Direction.OUTGOING)) { nextNode.add(rel.getOtherNode(root)); rel.delete(); } for (final Relationship rel : root.getRelationships()) { rel.delete(); } root.delete(); for (final Node node : nextNode) { deleteNode(node); } } @Override public Iterator<Node> findAllNetworkCorrelations(final Node networkRoot) throws ServiceException { assert networkRoot != null; return nodeSerivce .getChildren(networkRoot, CorrelationNodeTypes.CORRELATION_MODEL, CorrelationRelationshipType.CORRELATION); } @Override public Node findCorrelationModelNode(final Node networkRoot, final Node measurementRoot, final String correlationProperty, final String correlatedProperty) throws ServiceException { assert networkRoot != null; assert measurementRoot != null; assert !StringUtils.isEmpty(correlatedProperty); assert correlationProperty != null; assert !correlationProperty.isEmpty(); Iterator<Node> children = nodeSerivce.getChildren(networkRoot, CorrelationNodeTypes.CORRELATION_MODEL, CorrelationRelationshipType.CORRELATION); if (children == null || !children.hasNext()) { return null; } String networkName = nodeSerivce.getNodeName(networkRoot); String measuremerntName = nodeSerivce.getNodeName(measurementRoot); String modelName = String.format(CORRELATION_MODEL_NAME_FORMAT, networkName, correlationProperty, measuremerntName, correlatedProperty); while (children.hasNext()) { Node modelNode = children.next(); if (nodeSerivce.getNodeName(modelNode).equals(modelName)) { return modelNode; } } return null; } private Node findMeasurementInProxy(final Node proxy, final Node measurementNode, final String measuremntName) throws ServiceException { Iterable<Relationship> rel = proxy.getRelationships(CorrelationRelationshipType.PROXY, Direction.OUTGOING); if (rel == null || !rel.iterator().hasNext()) { return null; } Iterator<Relationship> relationships = rel.iterator(); while (relationships.hasNext()) { Relationship relation = relationships.next(); if (relation.hasProperty(correlationProperties.getCorrelatedModelNameProperty()) && relation.getProperty(correlationProperties.getCorrelatedModelNameProperty()).equals(measuremntName)) { Node proxyMeasurement = relation.getOtherNode(proxy); if (proxyMeasurement.equals(measurementNode)) { return proxyMeasurement; } } } return null; } @Override public Node findMeasurementModel(final Node correlation) throws ServiceException { assert correlation != null; return nodeSerivce.getParent(correlation, CorrelationRelationshipType.CORRELATED); } @Override public Node findProxy(final Node sectorNode, final Node measurementNode, final String measuremntName) throws ServiceException { Iterator<Node> proxies = findSectorProxies(sectorNode); Node proxyNode = null; while (proxies.hasNext()) { Node proxy = proxies.next(); proxyNode = findMeasurementInProxy(proxy, measurementNode, measuremntName); if (proxyNode != null) { break; } } return proxyNode; } public Iterator<Node> findSectorProxies(final Node sectorNode) { assert sectorNode != null; return INCOMING_PROXIES_TRAVERSAL.traverse(sectorNode).nodes().iterator(); } @Override public Node findSectorProxyForModel(final Node sectorNode, final String measuremntName) { Iterator<Node> proxies = findSectorProxies(sectorNode); Node proxyNode = null; while (proxies.hasNext()) { proxyNode = proxies.next(); for (Relationship rel : proxyNode.getRelationships(Direction.OUTGOING, CorrelationRelationshipType.PROXY)) { Node otherNode = rel.getOtherNode(proxyNode); if (otherNode.equals(sectorNode)) { continue; } else if (rel.getProperty(correlationProperties.getCorrelatedModelNameProperty()).equals(measuremntName)) { return otherNode; } } } return null; } @Override public Iterator<Node> getMeasurementForProxy(final Node proxy, final String name) throws ServiceException { return OUTGOUING_PROXIES_TRAVERSAL.evaluator(new Evaluator() { @Override public Evaluation evaluate(final Path path) { Object property = path.lastRelationship().getProperty(correlationProperties.getCorrelatedModelNameProperty(), null); if (property != null && name.equals(property)) { return Evaluation.INCLUDE_AND_CONTINUE; } return Evaluation.EXCLUDE_AND_CONTINUE; } }).traverse(proxy).nodes().iterator(); } @Override public Node getSectorForProxy(final Node proxy) throws ServiceException { return searchNode(proxy); } private Node searchNode(final Node proxy) throws ServiceException { Iterable<Relationship> relations = proxy.getRelationships(Direction.OUTGOING, CorrelationRelationshipType.PROXY); if (proxy == null || !relations.iterator().hasNext()) { return null; } Node searchableNode; for (Relationship relation : relations) { searchableNode = relation.getOtherNode(proxy); try { if (nodeSerivce.getNodeType(searchableNode).equals(NetworkElementType.SECTOR)) { return searchableNode; } } catch (NodeTypeNotExistsException e) { LOGGER.error("can't get type for node" + searchableNode); searchableNode = null; } } return null; } }