001 // Copyright 2006, 2007, 2008, 2010, 2011 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.tapestry5.ioc.services; 016 017 /** 018 * An immutable object that represents a mapping from one type to another. This is also the contribution type when 019 * building the {@link org.apache.tapestry5.ioc.services.TypeCoercer} service. Wraps a 020 * {@link org.apache.tapestry5.ioc.services.Coercion} object that performs the work with additional properties that 021 * describe 022 * the input and output types of the coercion, needed when searching for an appropriate coercion (or sequence of 023 * coercions). 024 * 025 * @param <S> 026 * source (input) type 027 * @param <T> 028 * target (output) type 029 */ 030 public final class CoercionTuple<S, T> 031 { 032 private final Class<S> sourceType; 033 034 private final Class<T> targetType; 035 036 private final Coercion<S, T> coercion; 037 038 /** 039 * Wraps an arbitrary coercion with an implementation of toString() that identifies the source and target types. 040 */ 041 private class CoercionWrapper<WS, WT> implements Coercion<WS, WT> 042 { 043 private final Coercion<WS, WT> coercion; 044 045 public CoercionWrapper(Coercion<WS, WT> coercion) 046 { 047 this.coercion = coercion; 048 } 049 050 public WT coerce(WS input) 051 { 052 return coercion.coerce(input); 053 } 054 055 @Override 056 public String toString() 057 { 058 return String.format("%s --> %s", convert(sourceType), convert(targetType)); 059 } 060 } 061 062 private String convert(Class type) 063 { 064 if (void.class.equals(type)) 065 return "null"; 066 067 String name = ClassFabUtils.toJavaClassName(type); 068 069 int dotx = name.lastIndexOf('.'); 070 071 // Strip off a package name of "java.lang" 072 073 if (dotx > 0 && name.substring(0, dotx).equals("java.lang")) 074 return name.substring(dotx + 1); 075 076 return name; 077 } 078 079 /** 080 * Standard constructor, which defaults wrap to true. 081 */ 082 public CoercionTuple(Class<S> sourceType, Class<T> targetType, Coercion<S, T> coercion) 083 { 084 this(sourceType, targetType, coercion, true); 085 } 086 087 /** 088 * Convenience constructor to help with generics. 089 * 090 * @since 5.2.0 091 */ 092 public static <S, T> CoercionTuple<S, T> create(Class<S> sourceType, Class<T> targetType, Coercion<S, T> coercion) 093 { 094 return new CoercionTuple<S, T>(sourceType, targetType, coercion); 095 } 096 097 /** 098 * Internal-use constructor. 099 * 100 * @param sourceType 101 * the source (or input) type of the coercion 102 * @param targetType 103 * the target (or output) type of the coercion 104 * @param coercion 105 * the object that performs the coercion 106 * @param wrap 107 * if true, the coercion is wrapped to provide a useful toString() 108 */ 109 @SuppressWarnings("unchecked") 110 public CoercionTuple(Class<S> sourceType, Class<T> targetType, Coercion<S, T> coercion, boolean wrap) 111 { 112 assert sourceType != null; 113 assert targetType != null; 114 assert coercion != null; 115 116 this.sourceType = ClassFabUtils.getWrapperType(sourceType); 117 this.targetType = ClassFabUtils.getWrapperType(targetType); 118 this.coercion = wrap ? new CoercionWrapper<S, T>(coercion) : coercion; 119 } 120 121 @Override 122 public String toString() 123 { 124 return coercion.toString(); 125 } 126 127 public Coercion<S, T> getCoercion() 128 { 129 return coercion; 130 } 131 132 public Class<S> getSourceType() 133 { 134 return sourceType; 135 } 136 137 public Class<T> getTargetType() 138 { 139 return targetType; 140 } 141 142 }