/******************************************************************************* * Copyright (c) 2014 EURA NOVA. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v2.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * Contributors: * Aldemar Reynaga - initial API and implementation * Salim Jouili - initial API and implementation ******************************************************************************/ package com.steffi.traversal; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import com.steffi.model.SteffiEdge; import com.steffi.model.SteffiVertex; /** * @author Aldemar Reynaga * Basic implementation of a traversal that uses the basic retrieval API to explore the graph */ public class SimpleTraversal implements Traversal { protected List<Evaluator> evaluators; protected List<EdgeTraversalConf> edgeTraversalConfs; protected Method method; protected int hops; public SimpleTraversal() { evaluators = new ArrayList<Evaluator>(); edgeTraversalConfs = new ArrayList<EdgeTraversalConf>(); } @Override public void addEvaluators(Evaluator... evaluators) { this.evaluators.addAll(Arrays.asList(evaluators)); } @Override public void setMethod(Method method) { this.method = method; } @Override public void addEdgeTraversalConfs(EdgeTraversalConf... edgeTraversalConfs) { this.edgeTraversalConfs.addAll(Arrays.asList(edgeTraversalConfs)); } @Override public void setHops(int hops) { this.hops = hops; } @Override public TraversalResults traverse(SteffiVertex startVertex) { try { return graphSearch(startVertex); } catch (Exception x) { throw new RuntimeException(x); } } private boolean isConfiguredEdgeType(SteffiEdge edge) { if (edgeTraversalConfs.isEmpty()) return true; for (EdgeTraversalConf traversalConf : edgeTraversalConfs) { if (traversalConf.getEdgeType().equals(edge.getEdgeType())) { if (traversalConf.getName() == null) { if (edge.getName() == null) return true; } else if (traversalConf.getName().equals(edge.getName())) return true; } } return false; } boolean evalVertex(TraversalResults results, ReducedVertexPath vertexPath) { boolean stop = false; for (Evaluator evaluator : evaluators) { switch (evaluator.evaluate(vertexPath)) { case EXCLUDE_AND_CONTINUE: break; case EXCLUDE_AND_STOP: stop = true; break; case INCLUDE_AND_CONTINUE: results.addVertexPath(vertexPath); break; case INCLUDE_AND_STOP: results.addVertexPath(vertexPath); stop = true; break; } } return stop; } boolean isNotExploredEdge(SteffiEdge edge, Set<Long> explored, Collection<ReducedVertexPath> frontier) { if (explored.contains(edge.getDestCellId())) return false; for (ReducedVertexPath vertexPath : frontier) if (vertexPath.getVertexId() == edge.getDestCellId()) return false; return true; } private TraversalResults graphSearch(SteffiVertex startVertex) throws IOException { ReducedVertexPath vertexPath = null, childVertexPath = null; LinkedList<ReducedVertexPath> frontier = new LinkedList<ReducedVertexPath>(); Set<Long> explored = new HashSet<Long>(); TraversalResults traversalResults = new TraversalResultsImpl(); traversalResults.setTime(new Date().getTime()); vertexPath = new ReducedVertexPath(startVertex.getId()); vertexPath.setVertex(startVertex); if (evalVertex(traversalResults, vertexPath)) return traversalResults; frontier.add(vertexPath); while (true) { if (frontier.isEmpty()) { traversalResults.setTime((new Date().getTime() - traversalResults.getTime())); return traversalResults; } vertexPath = frontier.pop(); explored.add(vertexPath.getVertex().getId()); if ((vertexPath.getDepth()+1) <= hops) { for (SteffiEdge edge : vertexPath.getVertex().getEdges()) { if (isConfiguredEdgeType(edge)) { childVertexPath = new ReducedVertexPath(vertexPath, edge.getEdgeType(), edge.getName(), edge.getDestCellId(), vertexPath.getDepth()+1); if (childVertexPath.getVertex() == null) { System.out.println("Severe error, vertex not found, id: " + edge.getDestCellId()); return traversalResults; } if (evalVertex(traversalResults, childVertexPath)) { traversalResults.setTime((new Date().getTime() - traversalResults.getTime())); return traversalResults; } if (isNotExploredEdge(edge, explored, frontier)) frontier.push(childVertexPath); } } } } } @Override public Collection<Evaluator> getEvaluators() { return this.evaluators; } @Override public Collection<EdgeTraversalConf> getEdgeTraversalConfs() { return this.edgeTraversalConfs; } @Override public int getHops() { return this.hops; } }