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 }