001/*
002 * Copyright (c) 2016 Chris K Wensel <chris@wensel.net>. All Rights Reserved.
003 * Copyright (c) 2007-2017 Xplenty, Inc. All Rights Reserved.
004 *
005 * Project and contact information: http://www.cascading.org/
006 *
007 * This file is part of the Cascading project.
008 *
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *     http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 */
021
022package cascading.flow.planner.rule;
023
024import cascading.flow.planner.PlannerContext;
025import cascading.flow.planner.graph.ElementGraph;
026import cascading.flow.planner.iso.transformer.ContractedTransformer;
027import cascading.flow.planner.iso.transformer.GraphTransformer;
028import cascading.flow.planner.iso.transformer.RecursiveGraphTransformer;
029import cascading.flow.planner.iso.transformer.SubGraphTransformer;
030import cascading.flow.planner.iso.transformer.Transformed;
031import cascading.flow.planner.rule.util.LogLevel;
032
033import static cascading.flow.planner.rule.util.RuleLogUtil.enableLogging;
034import static cascading.flow.planner.rule.util.RuleLogUtil.restoreLogging;
035
036/**
037 * The RuleTransformer class is responsible for transforming an element graph into a new graph.
038 */
039public class RuleTransformer extends GraphTransformer<ElementGraph, ElementGraph> implements Rule
040  {
041  private final LogLevel logLevel;
042  private final PlanPhase phase;
043  protected final RuleExpression ruleExpression;
044  protected final ContractedTransformer contractedTransformer;
045  protected final SubGraphTransformer subGraphTransformer;
046
047  protected RecursiveGraphTransformer<ElementGraph> graphTransformer;
048
049  public RuleTransformer( PlanPhase phase, RuleExpression ruleExpression )
050    {
051    this( null, phase, ruleExpression );
052    }
053
054  public RuleTransformer( LogLevel logLevel, PlanPhase phase, RuleExpression ruleExpression )
055    {
056    this.logLevel = logLevel;
057    this.phase = phase;
058    this.ruleExpression = ruleExpression;
059
060    if( ruleExpression.getContractionExpression() != null )
061      contractedTransformer = new ContractedTransformer( ruleExpression.getContractionExpression() );
062    else
063      contractedTransformer = null;
064
065    if( ruleExpression.getContractedMatchExpression() != null )
066      {
067      if( contractedTransformer == null )
068        throw new IllegalArgumentException( "must have contracted expression if given contracted match expression" );
069
070      subGraphTransformer = new SubGraphTransformer( contractedTransformer, ruleExpression.getContractedMatchExpression() );
071      }
072    else
073      {
074      subGraphTransformer = null;
075      }
076    }
077
078  @Override
079  public PlanPhase getRulePhase()
080    {
081    return phase;
082    }
083
084  @Override
085  public String getRuleName()
086    {
087    return getClass().getSimpleName().replaceAll( "^(.*)[]A-Z][a-z]*Rule$", "$1" );
088    }
089
090  @Override
091  public Transformed<ElementGraph> transform( PlannerContext plannerContext, ElementGraph rootGraph )
092    {
093    String[] logLevels = enableLogging( logLevel );
094
095    try
096      {
097      return performTransform( plannerContext, rootGraph );
098      }
099    finally
100      {
101      restoreLogging( logLevels );
102      }
103    }
104
105  public Transformed<ElementGraph> performTransform( PlannerContext plannerContext, ElementGraph rootGraph )
106    {
107    Transformed<ElementGraph> result = new Transformed<>( plannerContext, this, rootGraph );
108
109    ElementGraph graphCopy = rootGraph.copyElementGraph();
110
111    Transformed<ElementGraph> transformed = graphTransformer.transform( plannerContext, graphCopy );
112
113    result.addChildTransform( transformed );
114
115    if( transformed.getEndGraph() != null && !rootGraph.equals( transformed.getEndGraph() ) )
116      result.setEndGraph( transformed.getEndGraph() );
117
118    return result;
119    }
120
121  @Override
122  public String toString()
123    {
124    return getRuleName();
125    }
126  }