    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  }