public ElementSubGraph getMatched() { return match.getMatchedGraph(); }
protected Match findFirstMatch( FinderContext finderContext, PlannerContext plannerContext, ElementGraph elementGraph ) { Map<ElementExpression, FlowElement> mapping = findMapping( finderContext, plannerContext, elementGraph ); return new Match( matchExpression, elementGraph, mapping, mapping.values(), getCapturedEdges( plannerContext, elementGraph, mapping ) ); }
@Override public boolean hasNext() { if( match == null ) { match = graphFinder.findMatchesOnPrimary( plannerContext, getContractedGraph(), firstOnly, elementExcludes ); if( match.foundMatch() ) { matches.add( match ); elementExcludes.addAll( match.getCapturedElements( ElementCapture.Primary ) ); // idempotent count++; } } return match.foundMatch(); }
if( !current.foundMatch() ) break; captureMap.addAll( current.getCaptureMap() ); Set<FlowElement> anchoredElements = current.getCapturedElements( ElementCapture.Primary ); Map<ElementExpression, FlowElement> vertexMapping = current.getVertexMapping(); break; Set<FlowElement> includedElements = current.getIncludedElements(); Map<ElementExpression, FlowElement> mapping = match == null ? null : match.getVertexMapping(); return new Match( matchExpression, elementGraph, mapping, finderContext.getMatchedElements(), finderContext.getMatchedScopes(), captureMap );
public Transformed<ElementSubGraph> transform( PlannerContext plannerContext, ElementGraph rootGraph ) { Transformed<ElementSubGraph> transformed = new Transformed<>( plannerContext, this, subGraphMatcher, rootGraph ); try { Transformed contractedTransformed = graphTransformer.transform( plannerContext, rootGraph ); // contracted graph transform transformed.addChildTransform( contractedTransformed ); // apply contracted sub-graph matcher to get the bounded sub-graph of the original graph ElementGraph contractedGraph = contractedTransformed.getEndGraph(); Match match = findAllPrimaries ? subGraphFinder.findAllMatches( plannerContext, contractedGraph ) : subGraphFinder.findFirstMatch( plannerContext, contractedGraph ); if( !match.foundMatch() ) return transformed; ElementGraph contractedSubGraph = match.getMatchedGraph(); ElementSubGraph resultSubGraph = asSubGraphOf( rootGraph, contractedSubGraph ); // the bounded sub-graph of the rootGraph transformed.setEndGraph( resultSubGraph ); return transformed; } catch( Throwable throwable ) { throw new TransformException( throwable, transformed ); } }
public Set<FlowElement> getIncludedElements() { return getCapturedElements( ElementCapture.Include ); }
public Set<FlowElement> getCapturedElements( ElementCapture... captures ) { return getCaptureMap().getAllValues( captures ); }
public Set<FlowElement> getAnchors() { return match.getCapturedElements( ElementCapture.Primary ); }
@Override public String toString() { final StringBuilder sb = new StringBuilder( "Match{" ); // sb.append( "matcherGraph=" ).append( matcherGraph ); // sb.append( ", mapping=" ).append( mapping ); sb.append( getMatchedGraph() ); sb.append( '}' ); return sb.toString(); } }
@Override protected boolean transformGraphInPlaceUsing( Transformed<ElementGraph> transformed, ElementGraph graph, Match match ) { Set<FlowElement> remove = match.getCapturedElements( ElementCapture.Primary ); if( remove.isEmpty() ) return false; for( FlowElement flowElement : remove ) ElementGraphs.removeAndContract( graph, flowElement ); return true; } }
public EnumMultiMap<FlowElement> getCaptureMap() { if( captureMap != null ) return captureMap; captureMap = new EnumMultiMap<>(); Map<FlowElement, ElementExpression> reversed = new LinkedHashMap<>(); if( Util.reverseMap( vertexMapping, reversed ) ) throw new IllegalStateException( "duplicates found in mapping" ); // returns a Set ordered topologically by the matched graph. retains this first, this second ordering for simple cases Iterator<FlowElement> iterator = ElementGraphs.getTopologicalIterator( getMatchedGraph() ); while( iterator.hasNext() ) { FlowElement next = iterator.next(); ElementExpression elementExpression = reversed.get( next ); // matchedGraph may be a super-set of what's in the mapping, so elementExpression may be null if( elementExpression == null ) continue; captureMap.addAll( elementExpression.getCapture(), next ); } return captureMap; }
@Override protected boolean transformGraphInPlaceUsing( Transformed<ElementGraph> transformed, ElementGraph graph, Match match ) { Set<FlowElement> remove = match.getCapturedElements( ElementCapture.Primary ); if( remove.isEmpty() ) return false; for( FlowElement flowElement : remove ) ElementGraphs.removeAndContract( graph, flowElement ); return true; } }
@Override public ElementGraph next() { try { if( !hasNext() ) throw new NoSuchElementException(); ElementGraph contractedMatchedGraph = match.getMatchedGraph(); Set<FlowElement> excludes = getContractedGraph().vertexSetCopy(); excludes.removeAll( contractedMatchedGraph.vertexSet() ); return asSubGraph( elementGraph, contractedMatchedGraph, excludes ); } finally { match = null; } }
public String getMessage() { String result = message; for( ElementCapture capture : ElementCapture.values() ) { Iterator<FlowElement> iterator = match.getCapturedElements( capture ).iterator(); while( result.contains( "{" + capture + "}" ) && iterator.hasNext() ) result = result.replaceFirst( "\\{" + capture + "\\}", iterator.next().toString() ); } return result; }
@Override public void writeDOTs( String path ) { int count = 0; beginGraph.writeDOT( new File( path, makeFileName( count++, "element-graph" ) ).toString() ); if( graphPartitioner instanceof ExpressionGraphPartitioner ) { ExpressionGraphPartitioner expressionGraphPartitioner = (ExpressionGraphPartitioner) graphPartitioner; ExpressionGraph contractionGraph = expressionGraphPartitioner.getContractionGraph(); if( contractionGraph != null ) contractionGraph.writeDOT( new File( path, makeFileName( count++, "contraction-graph", contractionGraph ) ).toString() ); ExpressionGraph expressionGraph = expressionGraphPartitioner.getExpressionGraph(); if( expressionGraph != null ) expressionGraph.writeDOT( new File( path, makeFileName( count++, "expression-graph", expressionGraph ) ).toString() ); } if( contractedGraph != null ) contractedGraph.writeDOT( new File( path, makeFileName( count++, "contracted-graph" ) ).toString() ); List<ElementGraph> subGraphs = getSubGraphs(); for( int i = 0; i < subGraphs.size(); i++ ) { ElementGraph subGraph = subGraphs.get( i ); // want to write annotations with elements new ElementMultiGraph( subGraph, annotatedSubGraphs.get( subGraph ) ).writeDOT( new File( path, makeFileName( count, i, "partition-result-sub-graph" ) ).toString() ); if( i < contractedMatches.size() ) contractedMatches.get( i ).getMatchedGraph().writeDOT( new File( path, makeFileName( count, i, "partition-contracted-graph" ) ).toString() ); } }
@Override protected boolean transformGraphInPlaceUsing( Transformed<ElementGraph> transformed, ElementGraph graph, Match match ) { Set<FlowElement> replace = match.getCapturedElements( ElementCapture.Primary ); Set<FlowElement> replaceWith = match.getCapturedElements( ElementCapture.Secondary ); if( replace.isEmpty() || replaceWith.isEmpty() ) return false; if( replace.size() != 1 ) throw new IllegalStateException( "too many captured elements" ); if( replaceWith.size() != 1 ) throw new IllegalStateException( "too many target elements" ); ElementGraphs.replaceElementWith( graph, Util.getFirst( replace ), Util.getFirst( replaceWith ) ); return true; } }
@Test public void testFind2() { ElementGraph graph = new HashJoinSameSourceGraph(); graph = new ContractedTransformer( new SyncPipeExpressionGraph() ).transform( graph ).getEndGraph(); FlowElementExpression sharedTap = new FlowElementExpression( Tap.class, TypeExpression.Topo.SplitOnly ); FlowElementExpression sharedHashJoin = new FlowElementExpression( HashJoin.class ); ExpressionGraph expressionGraph = new ExpressionGraph() .arc( sharedTap, ScopeExpression.ALL, sharedHashJoin ); GraphFinder graphFinder = new GraphFinder( expressionGraph ); Match match = graphFinder.findFirstMatch( graph ); match.getMatchedGraph().writeDOT( getPlanPath() + "/match.dot" ); }
@Override protected boolean transformGraphInPlaceUsing( Transformed<ElementGraph> transformed, ElementGraph graph, Match match ) { ElementFactory elementFactory = transformed.getPlannerContext().getElementFactoryFor( factoryName ); if( elementFactory == null ) return false; Set<FlowElement> captured = match.getCapturedElements( ElementCapture.Primary ); if( captured.isEmpty() ) return false; else if( captured.size() != 1 ) throw new IllegalStateException( "expected one, but found multiple flow elements in the match expression: " + captured ); FlowElement replace = captured.iterator().next(); FlowElement replaceWith = elementFactory.create( graph, replace ); ElementGraphs.replaceElementWith( graph, replace, replaceWith ); return true; } }
@Test public void testFind() { ElementGraph graph = new HashJoinSameSourceGraph(); graph = new ContractedTransformer( new SyncPipeExpressionGraph() ).transform( graph ).getEndGraph(); FlowElementExpression SHARED_TAP = new FlowElementExpression( Tap.class, TypeExpression.Topo.SplitOnly ); FlowElementExpression SHARED_HASHJOIN = new FlowElementExpression( HashJoin.class ); ExpressionGraph expressionGraph = new ExpressionGraph() .arcs( SHARED_TAP, SHARED_HASHJOIN ) .arcs( SHARED_TAP, SHARED_HASHJOIN ); GraphFinder graphFinder = new GraphFinder( expressionGraph ); Match match = graphFinder.findFirstMatch( graph ); match.getMatchedGraph().writeDOT( getPlanPath() + "/match.dot" ); }
@Override protected boolean transformGraphInPlaceUsing( Transformed<ElementGraph> transformed, ElementGraph graph, Match match ) { Set<FlowElement> primary = match.getCapturedElements( ElementCapture.Primary ); Set<FlowElement> secondary = match.getCapturedElements( ElementCapture.Secondary ); if( primary.isEmpty() ) return false; if( secondary.isEmpty() ) { for( FlowElement flowElement : primary ) { boolean found = ElementGraphs.removeBranchContaining( graph, flowElement ); if( !found ) throw new IllegalStateException( "no branch found at: " + flowElement ); } } else { // RemoveStreamedBranchTransformer uses a Secondary match to identify a branch but is currently unused if( secondary.size() != 1 ) throw new IllegalStateException( "too many captured secondary elements" ); boolean found = ElementGraphs.removeBranchBetween( graph, Util.getFirst( primary ), Util.getFirst( secondary ), false ); if( !found ) throw new IllegalStateException( "no branch found between: " + Util.getFirst( primary ) + " and " + Util.getFirst( secondary ) ); } return true; } }