001 // Copyright 2006, 2007, 2008 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 static org.apache.tapestry5.ioc.internal.util.Defense.notNull;
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 {@link
022 * org.apache.tapestry5.ioc.services.Coercion} object that performs the work with additional properties that describe
023 * the input and output types of the coercion, needed when searching for an appropriate coercion (or sequence of
024 * coercions).
025 *
026 * @param <S> source (input) type
027 * @param <T> target (output) type
028 */
029 public final class CoercionTuple<S, T>
030 {
031 private final Class<S> sourceType;
032
033 private final Class<T> targetType;
034
035 private final Coercion<S, T> coercion;
036
037 /**
038 * Wraps an arbitrary coercion with an implementation of toString() that identifies the source and target types.
039 */
040 private class CoercionWrapper<WS, WT> implements Coercion<WS, WT>
041 {
042 private final Coercion<WS, WT> coercion;
043
044 public CoercionWrapper(Coercion<WS, WT> coercion)
045 {
046 this.coercion = coercion;
047 }
048
049 public WT coerce(WS input)
050 {
051 return coercion.coerce(input);
052 }
053
054 @Override
055 public String toString()
056 {
057 return String.format("%s --> %s", convert(sourceType), convert(targetType));
058 }
059 }
060
061 private String convert(Class type)
062 {
063 if (void.class.equals(type)) return "null";
064
065 String name = ClassFabUtils.toJavaClassName(type);
066
067 int dotx = name.lastIndexOf('.');
068
069 // Strip off a package name of "java.lang"
070
071 if (dotx > 0 && name.substring(0, dotx).equals("java.lang"))
072 return name.substring(dotx + 1);
073
074 return name;
075 }
076
077 /**
078 * Standard constructor, which defaults wrap to true.
079 */
080 public CoercionTuple(Class<S> sourceType, Class<T> targetType, Coercion<S, T> coercion)
081 {
082 this(sourceType, targetType, coercion, true);
083 }
084
085 /**
086 * Internal-use constructor.
087 *
088 * @param sourceType the source (or input) type of the coercion
089 * @param targetType the target (or output) type of the coercion
090 * @param coercion the object that performs the coercion
091 * @param wrap if true, the coercion is wrapped to provide a useful toString()
092 */
093 public CoercionTuple(Class<S> sourceType, Class<T> targetType, Coercion<S, T> coercion,
094 boolean wrap)
095 {
096 notNull(sourceType, "sourceType");
097 notNull(targetType, "targetType");
098 notNull(coercion, "coercion");
099
100 this.sourceType = sourceType;
101 this.targetType = targetType;
102 this.coercion = wrap ? new CoercionWrapper<S, T>(coercion) : coercion;
103 }
104
105 @Override
106 public String toString()
107 {
108 return coercion.toString();
109 }
110
111 public Coercion<S, T> getCoercion()
112 {
113 return coercion;
114 }
115
116 public Class<S> getSourceType()
117 {
118 return sourceType;
119 }
120
121 public Class<T> getTargetType()
122 {
123 return targetType;
124 }
125
126 }