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 }