001 // Copyright 2006, 2007, 2008, 2010, 2011, 2012 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 import org.apache.tapestry5.plastic.PlasticUtils; 018 019 /** 020 * An immutable object that represents a mapping from one type to another. This is also the contribution type when 021 * building the {@link org.apache.tapestry5.ioc.services.TypeCoercer} service. Wraps a 022 * {@link org.apache.tapestry5.ioc.services.Coercion} object that performs the work with additional properties that 023 * describe 024 * the input and output types of the coercion, needed when searching for an appropriate coercion (or sequence of 025 * coercions). 026 * 027 * @param <S> 028 * source (input) type 029 * @param <T> 030 * target (output) type 031 */ 032 public final class CoercionTuple<S, T> 033 { 034 private final Class<S> sourceType; 035 036 private final Class<T> targetType; 037 038 private final Coercion<S, T> coercion; 039 040 /** 041 * Wraps an arbitrary coercion with an implementation of toString() that identifies the source and target types. 042 */ 043 private class CoercionWrapper<WS, WT> implements Coercion<WS, WT> 044 { 045 private final Coercion<WS, WT> coercion; 046 047 public CoercionWrapper(Coercion<WS, WT> coercion) 048 { 049 this.coercion = coercion; 050 } 051 052 public WT coerce(WS input) 053 { 054 return coercion.coerce(input); 055 } 056 057 @Override 058 public String toString() 059 { 060 return String.format("%s --> %s", convert(sourceType), convert(targetType)); 061 } 062 } 063 064 private String convert(Class type) 065 { 066 if (Void.class.equals(type)) 067 return "null"; 068 069 String name = PlasticUtils.toTypeName(type); 070 071 int dotx = name.lastIndexOf('.'); 072 073 // Strip off a package name of "java.lang" 074 075 if (dotx > 0 && name.substring(0, dotx).equals("java.lang")) 076 return name.substring(dotx + 1); 077 078 return name; 079 } 080 081 /** 082 * Standard constructor, which defaults wrap to true. 083 */ 084 public CoercionTuple(Class<S> sourceType, Class<T> targetType, Coercion<S, T> coercion) 085 { 086 this(sourceType, targetType, coercion, true); 087 } 088 089 /** 090 * Convenience constructor to help with generics. 091 * 092 * @since 5.2.0 093 */ 094 public static <S, T> CoercionTuple<S, T> create(Class<S> sourceType, Class<T> targetType, Coercion<S, T> coercion) 095 { 096 return new CoercionTuple<S, T>(sourceType, targetType, coercion); 097 } 098 099 /** 100 * Internal-use constructor. 101 * 102 * @param sourceType 103 * the source (or input) type of the coercion, may be Void.class to indicate a coercion from null 104 * @param targetType 105 * the target (or output) type of the coercion 106 * @param coercion 107 * the object that performs the coercion 108 * @param wrap 109 * if true, the coercion is wrapped to provide a useful toString() 110 */ 111 @SuppressWarnings("unchecked") 112 public CoercionTuple(Class<S> sourceType, Class<T> targetType, Coercion<S, T> coercion, boolean wrap) 113 { 114 assert sourceType != null; 115 assert targetType != null; 116 assert coercion != null; 117 118 this.sourceType = PlasticUtils.toWrapperType(sourceType); 119 this.targetType = PlasticUtils.toWrapperType(targetType); 120 this.coercion = wrap ? new CoercionWrapper<S, T>(coercion) : coercion; 121 } 122 123 @Override 124 public String toString() 125 { 126 return coercion.toString(); 127 } 128 129 public Coercion<S, T> getCoercion() 130 { 131 return coercion; 132 } 133 134 public Class<S> getSourceType() 135 { 136 return sourceType; 137 } 138 139 public Class<T> getTargetType() 140 { 141 return targetType; 142 } 143 144 }