001/* 002 * Copyright (c) 2007-2017 Xplenty, Inc. All Rights Reserved. 003 * 004 * Project and contact information: http://www.cascading.org/ 005 * 006 * This file is part of the Cascading project. 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020 021package cascading.flow.planner.iso.finder; 022 023import java.util.Collection; 024import java.util.Collections; 025import java.util.Iterator; 026import java.util.LinkedHashMap; 027import java.util.Map; 028import java.util.Set; 029 030import cascading.flow.FlowElement; 031import cascading.flow.planner.Scope; 032import cascading.flow.planner.graph.ElementGraph; 033import cascading.flow.planner.graph.ElementGraphs; 034import cascading.flow.planner.graph.ElementSubGraph; 035import cascading.flow.planner.iso.expression.ElementCapture; 036import cascading.flow.planner.iso.expression.ElementExpression; 037import cascading.flow.planner.iso.expression.ExpressionGraph; 038import cascading.util.EnumMultiMap; 039import cascading.util.Util; 040 041/** 042 * 043 */ 044public class Match 045 { 046 protected final ExpressionGraph matchGraph; 047 protected final ElementGraph elementGraph; 048 protected final Map<ElementExpression, FlowElement> vertexMapping; 049 protected final Collection<FlowElement> foundElements; 050 protected final Collection<Scope> foundScopes; 051 protected EnumMultiMap<FlowElement> captureMap; 052 053 private ElementSubGraph matchedGraph; 054 055 public Match( ExpressionGraph matchGraph, ElementGraph elementGraph, Map<ElementExpression, FlowElement> vertexMapping, Collection<FlowElement> foundElements, Collection<Scope> foundScopes ) 056 { 057 this( matchGraph, elementGraph, vertexMapping, foundElements, foundScopes, null ); 058 } 059 060 public Match( ExpressionGraph matchGraph, ElementGraph elementGraph, Map<ElementExpression, FlowElement> vertexMapping, Collection<FlowElement> foundElements, Collection<Scope> foundScopes, EnumMultiMap<FlowElement> captureMap ) 061 { 062 this.matchGraph = matchGraph; 063 this.elementGraph = elementGraph; 064 this.vertexMapping = vertexMapping == null ? Collections.<ElementExpression, FlowElement>emptyMap() : vertexMapping; 065 this.foundElements = foundElements; 066 this.foundScopes = foundScopes; 067 this.captureMap = captureMap; 068 } 069 070 public ElementGraph getElementGraph() 071 { 072 return elementGraph; 073 } 074 075 public ExpressionGraph getMatchGraph() 076 { 077 return matchGraph; 078 } 079 080 public boolean foundMatch() 081 { 082 return !vertexMapping.values().isEmpty(); 083 } 084 085 public Map<ElementExpression, FlowElement> getVertexMapping() 086 { 087 return vertexMapping; 088 } 089 090 public Collection<FlowElement> getFoundElements() 091 { 092 return foundElements; 093 } 094 095 public ElementSubGraph getMatchedGraph() 096 { 097 if( matchedGraph == null ) 098 matchedGraph = new ElementSubGraph( elementGraph, foundElements, foundScopes ); 099 100 return matchedGraph; 101 } 102 103 public Set<FlowElement> getIncludedElements() 104 { 105 return getCapturedElements( ElementCapture.Include ); 106 } 107 108 public Set<FlowElement> getCapturedElements( ElementCapture... captures ) 109 { 110 return getCaptureMap().getAllValues( captures ); 111 } 112 113 public EnumMultiMap<FlowElement> getCaptureMap() 114 { 115 if( captureMap != null ) 116 return captureMap; 117 118 captureMap = new EnumMultiMap<>(); 119 120 Map<FlowElement, ElementExpression> reversed = new LinkedHashMap<>(); 121 122 if( Util.reverseMap( vertexMapping, reversed ) ) 123 throw new IllegalStateException( "duplicates found in mapping" ); 124 125 // returns a Set ordered topologically by the matched graph. retains this first, this second ordering for simple cases 126 Iterator<FlowElement> iterator = ElementGraphs.getTopologicalIterator( getMatchedGraph() ); 127 128 while( iterator.hasNext() ) 129 { 130 FlowElement next = iterator.next(); 131 ElementExpression elementExpression = reversed.get( next ); 132 133 // matchedGraph may be a super-set of what's in the mapping, so elementExpression may be null 134 if( elementExpression == null ) 135 continue; 136 137 captureMap.addAll( elementExpression.getCapture(), next ); 138 } 139 140 return captureMap; 141 } 142 143 @Override 144 public String toString() 145 { 146 final StringBuilder sb = new StringBuilder( "Match{" ); 147// sb.append( "matcherGraph=" ).append( matcherGraph ); 148// sb.append( ", mapping=" ).append( mapping ); 149 sb.append( getMatchedGraph() ); 150 sb.append( '}' ); 151 return sb.toString(); 152 } 153 }