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.expression; 022 023import cascading.flow.FlowElement; 024import cascading.flow.planner.PlannerContext; 025import cascading.flow.planner.graph.ElementGraph; 026 027/** 028 * 029 */ 030public class TypeExpression<Type> extends ElementExpression 031 { 032 public enum Topo 033 { 034 Ignore, 035 Head, 036 Tail, 037 Linear, 038 LinearIn, 039 LinearOut, 040 Splice, 041 Split, 042 SpliceOnly, 043 SplitOnly, 044 SpliceSplit 045 } 046 047 boolean exact = false; 048 Class<? extends Type> type; 049 Topo topo = Topo.Ignore; 050 051 public TypeExpression( ElementCapture capture, boolean exact, Class<? extends Type> type, Topo topo ) 052 { 053 super( capture ); 054 this.exact = exact; 055 this.type = type; 056 this.topo = topo; 057 } 058 059 public TypeExpression( ElementCapture capture, boolean exact, Class<? extends Type> type ) 060 { 061 super( capture ); 062 this.exact = exact; 063 this.type = type; 064 } 065 066 public TypeExpression( ElementCapture capture, Class<? extends Type> type, Topo topo ) 067 { 068 super( capture ); 069 this.type = type; 070 this.topo = topo; 071 } 072 073 public TypeExpression( ElementCapture capture, Class<? extends Type> type ) 074 { 075 super( capture ); 076 this.type = type; 077 } 078 079 public TypeExpression( boolean exact, Class<? extends Type> type, Topo topo ) 080 { 081 this.exact = exact; 082 this.type = type; 083 this.topo = topo; 084 } 085 086 public TypeExpression( boolean exact, Class<? extends Type> type ) 087 { 088 this.exact = exact; 089 this.type = type; 090 } 091 092 public TypeExpression( Class<? extends Type> type, Topo topo ) 093 { 094 this.type = type; 095 this.topo = topo; 096 } 097 098 public TypeExpression( Class<? extends Type> type ) 099 { 100 this.type = type; 101 } 102 103 protected Class<? extends Type> getType( FlowElement flowElement ) 104 { 105 return (Class<? extends Type>) flowElement.getClass(); 106 } 107 108 @Override 109 public boolean applies( PlannerContext plannerContext, ElementGraph elementGraph, FlowElement flowElement ) 110 { 111 boolean typeApplies = typeApplies( flowElement ); 112 113 if( !typeApplies ) 114 return false; 115 116 if( topo == Topo.Ignore ) 117 return true; 118 119 // todo: make lazy 120 boolean isHead = elementGraph.inDegreeOf( flowElement ) == 0; 121 boolean isTail = elementGraph.outDegreeOf( flowElement ) == 0; 122 boolean isSplice = elementGraph.inDegreeOf( flowElement ) > 1; 123 boolean isSplit = elementGraph.outDegreeOf( flowElement ) > 1; 124 125 switch( topo ) 126 { 127 case Head: 128 return isHead; 129 case Tail: 130 return isTail; 131 case Linear: 132 return !isSplice && !isSplit; 133 case LinearIn: 134 return !isSplice; 135 case LinearOut: 136 return !isSplit; 137 case Splice: 138 return isSplice; 139 case Split: 140 return isSplit; 141 case SpliceOnly: 142 return isSplice && !isSplit; 143 case SplitOnly: 144 return !isSplice && isSplit; 145 case SpliceSplit: 146 return isSplice && isSplit; 147 } 148 149 throw new IllegalStateException( "unknown switch, got: " + topo ); 150 } 151 152 private boolean typeApplies( FlowElement flowElement ) 153 { 154 Class<? extends Type> givenType = getType( flowElement ); 155 156 if( givenType == null ) 157 return false; 158 159 if( exact ) 160 return givenType == type; 161 162 return type.isAssignableFrom( givenType ); 163 } 164 165 @Override 166 public String toString() 167 { 168 final StringBuilder sb = new StringBuilder( getClass().getSimpleName() ).append( "{" ); 169 sb.append( "exact=" ).append( exact ); 170 sb.append( ", type=" ).append( type ); 171 sb.append( ", topo=" ).append( topo ); 172 sb.append( '}' ); 173 return sb.toString(); 174 } 175 }