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 015package org.apache.tapestry5.ioc.services; 016 017import 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 */ 032public 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 @Override 053 public WT coerce(WS input) 054 { 055 return coercion.coerce(input); 056 } 057 058 @Override 059 public String toString() 060 { 061 return String.format("%s --> %s", convert(sourceType), convert(targetType)); 062 } 063 } 064 065 private String convert(Class type) 066 { 067 if (Void.class.equals(type)) 068 return "null"; 069 070 String name = PlasticUtils.toTypeName(type); 071 072 int dotx = name.lastIndexOf('.'); 073 074 // Strip off a package name of "java.lang" 075 076 if (dotx > 0 && name.substring(0, dotx).equals("java.lang")) 077 return name.substring(dotx + 1); 078 079 return name; 080 } 081 082 /** 083 * Standard constructor, which defaults wrap to true. 084 */ 085 public CoercionTuple(Class<S> sourceType, Class<T> targetType, Coercion<S, T> coercion) 086 { 087 this(sourceType, targetType, coercion, true); 088 } 089 090 /** 091 * Convenience constructor to help with generics. 092 * 093 * @since 5.2.0 094 */ 095 public static <S, T> CoercionTuple<S, T> create(Class<S> sourceType, Class<T> targetType, Coercion<S, T> coercion) 096 { 097 return new CoercionTuple<S, T>(sourceType, targetType, coercion); 098 } 099 100 /** 101 * Internal-use constructor. 102 * 103 * @param sourceType 104 * the source (or input) type of the coercion, may be Void.class to indicate a coercion from null 105 * @param targetType 106 * the target (or output) type of the coercion 107 * @param coercion 108 * the object that performs the coercion 109 * @param wrap 110 * if true, the coercion is wrapped to provide a useful toString() 111 */ 112 @SuppressWarnings("unchecked") 113 public CoercionTuple(Class<S> sourceType, Class<T> targetType, Coercion<S, T> coercion, boolean wrap) 114 { 115 assert sourceType != null; 116 assert targetType != null; 117 assert coercion != null; 118 119 this.sourceType = PlasticUtils.toWrapperType(sourceType); 120 this.targetType = PlasticUtils.toWrapperType(targetType); 121 this.coercion = wrap ? new CoercionWrapper<S, T>(coercion) : coercion; 122 } 123 124 @Override 125 public String toString() 126 { 127 return coercion.toString(); 128 } 129 130 public Coercion<S, T> getCoercion() 131 { 132 return coercion; 133 } 134 135 public Class<S> getSourceType() 136 { 137 return sourceType; 138 } 139 140 public Class<T> getTargetType() 141 { 142 return targetType; 143 } 144 145}