001/*
002 * Copyright (c) 2007-2016 Concurrent, 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  }