    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  }