/* *************************************************************************************** * Copyright (C) 2006 EsperTech, Inc. All rights reserved. * * http://www.espertech.com/esper * * http://www.espertech.com * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the GPL license * * a copy of which has been included with this distribution in the license.txt file. * *************************************************************************************** */ package com.espertech.esper.example.cycledetect; import com.espertech.esper.client.EventBean; import com.espertech.esper.collection.RefCountedSetAtomicInteger; import com.espertech.esper.epl.agg.access.AggregationState; import com.espertech.esper.epl.expression.core.ExprEvaluatorContext; import org.jgrapht.alg.CycleDetector; import org.jgrapht.graph.DefaultDirectedGraph; import java.util.Collection; import java.util.Set; public class CycleDetectorAggregationState implements AggregationState { private final CycleDetectorAggregationStateFactory factory; private final RefCountedSetAtomicInteger<Object> vertexReferenceCount = new RefCountedSetAtomicInteger(); private DefaultDirectedGraph<Object, EventBean> graph; private CycleDetector<Object, EventBean> cycleDetector; public CycleDetectorAggregationState(CycleDetectorAggregationStateFactory factory) { this.factory = factory; graph = new DefaultDirectedGraph<Object, EventBean>(EventBean.class); } public void applyEnter(EventBean[] eventsPerStream, ExprEvaluatorContext exprEvaluatorContext) { Object from = factory.getFromEvaluator().evaluate(eventsPerStream, true, exprEvaluatorContext); Object to = factory.getToEvaluator().evaluate(eventsPerStream, true, exprEvaluatorContext); if (vertexReferenceCount.add(from)) { graph.addVertex(from); } if (vertexReferenceCount.add(to)) { graph.addVertex(to); } EventBean event = eventsPerStream[0]; graph.addEdge(from, to, event); } public void applyLeave(EventBean[] eventsPerStream, ExprEvaluatorContext exprEvaluatorContext) { graph.removeEdge(eventsPerStream[0]); Object from = factory.getFromEvaluator().evaluate(eventsPerStream, true, exprEvaluatorContext); Object to = factory.getToEvaluator().evaluate(eventsPerStream, true, exprEvaluatorContext); if (vertexReferenceCount.remove(from)) { graph.removeVertex(from); } if (vertexReferenceCount.remove(to)) { graph.removeVertex(to); } } public void clear() { graph = new DefaultDirectedGraph<Object, EventBean>(EventBean.class); } public int size() { return 0; } public boolean hasCycle() { long start = System.currentTimeMillis(); cycleDetector = new CycleDetector<Object, EventBean>(graph); boolean detected = cycleDetector.detectCycles(); long delta = System.currentTimeMillis() - start; // System.out.println("Cycle " + (detected ? "" : " not") + " detected in " + delta + " msec"); return detected; } public Collection<Object> getCycle() { long start = System.currentTimeMillis(); if (cycleDetector == null) { cycleDetector = new CycleDetector<Object, EventBean>(graph); } Set<Object> cycles = cycleDetector.findCycles(); long delta = System.currentTimeMillis() - start; // System.out.println("Cycle output took " + delta + " msec"); for (Object vertex : cycles) { vertexReferenceCount.removeAll(vertex); graph.removeVertex(vertex); } return cycles; } }