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.rule;
022
023import cascading.flow.planner.PlannerContext;
024import cascading.flow.planner.graph.ElementGraph;
025import cascading.flow.planner.iso.transformer.ContractedTransformer;
026import cascading.flow.planner.iso.transformer.GraphTransformer;
027import cascading.flow.planner.iso.transformer.RecursiveGraphTransformer;
028import cascading.flow.planner.iso.transformer.SubGraphTransformer;
029import cascading.flow.planner.iso.transformer.Transformed;
030
031/**
032 * The RuleTransformer class is responsible for transforming an element graph into a new graph.
033 */
034public class RuleTransformer extends GraphTransformer<ElementGraph, ElementGraph> implements Rule
035  {
036  private final PlanPhase phase;
037  protected final RuleExpression ruleExpression;
038  protected final ContractedTransformer contractedTransformer;
039  protected final SubGraphTransformer subGraphTransformer;
040
041  protected RecursiveGraphTransformer<ElementGraph> graphTransformer;
042
043  public RuleTransformer( PlanPhase phase, RuleExpression ruleExpression )
044    {
045    this.phase = phase;
046    this.ruleExpression = ruleExpression;
047
048    if( ruleExpression.getContractionExpression() != null )
049      contractedTransformer = new ContractedTransformer( ruleExpression.getContractionExpression() );
050    else
051      contractedTransformer = null;
052
053    if( ruleExpression.getContractedMatchExpression() != null )
054      {
055      if( contractedTransformer == null )
056        throw new IllegalArgumentException( "must have contracted expression if given contracted match expression" );
057
058      subGraphTransformer = new SubGraphTransformer( contractedTransformer, ruleExpression.getContractedMatchExpression() );
059      }
060    else
061      {
062      subGraphTransformer = null;
063      }
064    }
065
066  @Override
067  public PlanPhase getRulePhase()
068    {
069    return phase;
070    }
071
072  @Override
073  public String getRuleName()
074    {
075    return getClass().getSimpleName().replaceAll( "^(.*)[]A-Z][a-z]*Rule$", "$1" );
076    }
077
078  @Override
079  public Transformed<ElementGraph> transform( PlannerContext plannerContext, ElementGraph rootGraph )
080    {
081    Transformed<ElementGraph> result = new Transformed<>( plannerContext, this, rootGraph );
082
083    ElementGraph graphCopy = rootGraph.copyElementGraph();
084
085    Transformed<ElementGraph> transformed = graphTransformer.transform( plannerContext, graphCopy );
086
087    result.addChildTransform( transformed );
088
089    if( transformed.getEndGraph() != null && !rootGraph.equals( transformed.getEndGraph() ) )
090      result.setEndGraph( transformed.getEndGraph() );
091
092    return result;
093    }
094
095  @Override
096  public String toString()
097    {
098    return getRuleName();
099    }
100  }