001package net.gdface.utils;
002
003import java.lang.reflect.Array;
004import java.net.MalformedURLException;
005import java.net.URI;
006import java.net.URL;
007import java.nio.ByteBuffer;
008import java.util.Arrays;
009import java.util.Date;
010import java.util.List;
011import java.util.Map;
012import java.util.Map.Entry;
013import java.util.Set;
014
015import com.google.common.base.Function;
016import com.google.common.collect.HashBasedTable;
017import com.google.common.collect.ImmutableMap;
018import com.google.common.collect.Iterables;
019import com.google.common.collect.Lists;
020import com.google.common.collect.Maps;
021import com.google.common.collect.Maps.EntryTransformer;
022import com.google.common.collect.Sets;
023import com.google.common.collect.Table;
024import com.google.common.primitives.Booleans;
025import com.google.common.primitives.Doubles;
026import com.google.common.primitives.Floats;
027import com.google.common.primitives.Ints;
028import com.google.common.primitives.Longs;
029import com.google.common.primitives.Shorts;
030
031import static com.google.common.base.Preconditions.*;
032/**
033 * 类型转换工具类
034 * @author guyadong
035 * @deprecated be replaced by {@link BaseTypeTransformer} 
036 *
037 */
038public class TypeTransformer {
039        /**
040         * 返回buffer中所有字节(position~limit),不改变buffer状态
041         * @param buffer
042         * @return buffer 为 null 时返回 null 
043         */
044        public static final byte[] getBytesInBuffer(ByteBuffer buffer){
045                if(null == buffer){
046                        return null;
047                }
048                int pos = buffer.position();
049                try{
050                        byte[] bytes = new byte[buffer.remaining()];
051                        buffer.get(bytes);
052                        return bytes;
053                }finally{
054                        buffer.position(pos);
055                }
056        }
057        @SuppressWarnings("rawtypes")
058        private final Function sameTypeFun = new Function(){
059                @Override
060                public Object apply(Object input) {
061                        return input;
062                }};
063        private final Function<byte[],ByteBuffer> byteArray2ByteBufferFun = new Function<byte[],ByteBuffer>(){
064                @Override
065                public ByteBuffer apply(byte[] input) {
066                        return null == input ? null :ByteBuffer.wrap(input);
067                }};
068        private final Function<ByteBuffer,byte[]> byteBuffer2ByteArrayFun = new Function<ByteBuffer,byte[]>(){
069                @Override
070                public byte[] apply(ByteBuffer input) {
071                        return getBytesInBuffer(input);
072                }};
073        private final Function<Float,Double> float2DoubleFun = new Function<Float,Double>(){
074                @Override
075                public Double apply(Float input) {
076                        return null == input ? null : input.doubleValue();
077                }};
078        private final Function<Double,Float> double2FloatFun = new Function<Double,Float>(){
079                @Override
080                public Float apply(Double input) {
081                        return null == input ? null : input.floatValue();
082                }};
083        private final Function<Date,Long> date2LongFunction = new Function<Date,Long>(){
084                @Override
085                public Long apply(Date input) {
086                        return null == input ? null : input.getTime();
087                }};
088        private final Function<Long,Date> long2DateFun = new Function<Long,Date>(){
089                @Override
090                public Date apply(Long input) {
091                        return null == input ? null : new Date(input);
092                }};
093        private final Function<Long,java.sql.Date> long2SqlDateFun = new Function<Long,java.sql.Date>(){
094                @Override
095                public java.sql.Date apply(Long input) {
096                        return null == input ? null : new java.sql.Date(input);
097                }};
098        private final Function<Long,java.sql.Time> long2SqlTimeFun = new Function<Long,java.sql.Time>(){
099                @Override
100                public java.sql.Time apply(Long input) {
101                        return null == input ? null : new java.sql.Time(input);
102                }};
103        private final Function<URL,String> url2StringFun = new Function<URL,String>(){
104                @Override
105                public String apply(URL input) {
106                        return null == input ? null : input.toString();
107                }};
108        private final Function<URI,String> uri2StringFun = new Function<URI,String>(){
109                @Override
110                public String apply(URI input) {
111                        return null == input ? null : input.toString();
112                }};
113        private final Function<String,URL> string2UrlFun = new Function<String,URL>(){
114                @Override
115                public URL apply(String input) {
116                        try {
117                                return null == input ? null : new URL(input);
118                        } catch (MalformedURLException e) {
119                                throw new RuntimeException(e);
120                        }
121                }};
122        private final Function<String,URI> string2UriFun = new Function<String,URI>(){
123                @Override
124                public URI apply(String input) {
125                        return null == input ? null : URI.create(input);
126                }};
127        private final Function<int[],List<Integer>> intArray2List = new Function<int[],List<Integer>>(){
128                @Override
129                public List<Integer> apply(int[] input) {
130                        return null == input ? null : Ints.asList(input);
131                }};
132        private final Function<long[],List<Long>> longArray2List = new Function<long[],List<Long>>(){
133                @Override
134                public List<Long> apply(long[] input) {
135                        return null == input ? null : Longs.asList(input);
136                }};
137        private final Function<double[],List<Double>> doubleArray2List = new Function<double[],List<Double>>(){
138                @Override
139                public List<Double> apply(double[] input) {
140                        return null == input ? null : Doubles.asList(input);
141                }};
142        private final Function<float[],List<Double>> floatArray2List = new Function<float[],List<Double>>(){
143                @Override
144                public List<Double> apply(float[] input) {                      
145                        return null == input 
146                                        ? null 
147                                        : Lists.transform(Floats.asList(input),(Function<Float,Double>)float2DoubleFun);
148                }};
149        private final Function<short[],List<Short>> shortArray2List = new Function<short[],List<Short>>(){
150                @Override
151                public List<Short> apply(short[] input) {
152                        return null == input ? null : Shorts.asList(input);
153                }};
154        private final Function<boolean[],List<Boolean>> booleanArray2List = new Function<boolean[],List<Boolean>>(){
155                @Override
156                public List<Boolean> apply(boolean[] input) {
157                        return null == input ? null : Booleans.asList(input);
158                }};
159        private final Function<List<Integer>,int[]> list2intArray = new Function<List<Integer>,int[]>(){
160                @Override
161                public int[] apply(List<Integer> input) {
162                        return null == input ? null : Ints.toArray(input);
163                }};
164        private final Function<List<Long>,long[]> list2longArray = new Function<List<Long>,long[]>(){
165                @Override
166                public long[] apply(List<Long> input) {
167                        return null == input ? null : Longs.toArray(input);
168                }};
169        private final Function<List<Double>,double[]> list2doubleArray = new Function<List<Double>,double[]>(){
170                @Override
171                public double[] apply(List<Double> input) {
172                        return null == input ? null : Doubles.toArray(input);
173                }};
174        private final Function<List<Double>,float[]> list2floatArray = new Function<List<Double>,float[]>(){
175                @Override
176                public float[] apply(List<Double> input) {
177                        return null == input ? null : Floats.toArray(input);
178                }};
179        private final Function<List<Short>,short[]> list2shortArray = new Function<List<Short>,short[]>(){
180                @Override
181                public short[] apply(List<Short> input) {
182                        return null == input ? null : Shorts.toArray(input);
183                }};
184        private final Function<List<Boolean>,boolean[]> list2booleanArray = new Function<List<Boolean>,boolean[]>(){
185                @Override
186                public boolean[] apply(List<Boolean> input) {
187                        return null == input ? null : Booleans.toArray(input);
188                }};
189        protected final Table<Class<?>,Class<?>,Function<?,?>> transTable = HashBasedTable.create();
190        public TypeTransformer() {
191                transTable.put(byte[].class,ByteBuffer.class,byteArray2ByteBufferFun);
192                transTable.put(ByteBuffer.class,byte[].class,byteBuffer2ByteArrayFun);
193                transTable.put(Float.class,Double.class,float2DoubleFun);
194                transTable.put(Double.class,Float.class,double2FloatFun);
195                transTable.put(float.class,double.class,float2DoubleFun);
196                transTable.put(double.class,float.class,double2FloatFun);
197                transTable.put(Date.class, Long.class, date2LongFunction);
198                transTable.put(java.sql.Date.class, Long.class, date2LongFunction);
199                transTable.put(java.sql.Time.class,Long.class,date2LongFunction);
200                transTable.put(Long.class,Date.class,long2DateFun);
201                transTable.put(Long.class,java.sql.Date.class,long2SqlDateFun);
202                transTable.put(Long.class,java.sql.Time.class,long2SqlTimeFun);
203                transTable.put(URL.class,String.class,url2StringFun);
204                transTable.put(URI.class,String.class,uri2StringFun);
205                transTable.put(String.class,URL.class,string2UrlFun);
206                transTable.put(String.class,URI.class,string2UriFun);
207                transTable.put(int[].class,List.class,intArray2List);
208                transTable.put(long[].class,List.class,longArray2List);
209                transTable.put(double[].class,List.class,doubleArray2List);
210                transTable.put(float[].class,List.class,floatArray2List);
211                transTable.put(short[].class,List.class,shortArray2List);
212                transTable.put(boolean[].class,List.class,booleanArray2List);
213                transTable.put(List.class,int[].class,list2intArray);
214                transTable.put(List.class,long[].class,list2longArray);
215                transTable.put(List.class,double[].class,list2doubleArray);
216                transTable.put(List.class,float[].class,list2floatArray);
217                transTable.put(List.class,short[].class,list2shortArray);
218                transTable.put(List.class,boolean[].class,list2booleanArray);
219        }
220        /**
221         * 设置{@code left -> right}的转换器,参数不可为{@code null}
222         * @param left
223         * @param right
224         * @param trans 转换器对象
225         * @return
226         */
227        public <L,R>TypeTransformer setTransformer(Class<L> left, Class<R> right, Function<L, R> trans){
228                checkArgument(null != left && null != right && null != trans,"left, right, trans must not be null");
229                synchronized (this.transTable) {
230                        transTable.put(left,right,trans);
231                        return this;
232                }
233        }
234        /**
235         * 返回{@code left & right}指定的转换器,参数不可为{@code null}
236         * @param left
237         * @param right
238         * @return
239         */
240        @SuppressWarnings({ "unchecked" })
241        public <L,R>Function<L,R> getTransformer(Class<L>left,Class<R>right){
242                checkArgument(null != left && null != right,"left, right must not be null");
243                if(right.isAssignableFrom(left)){
244                        // 相同类型转换
245                        return (Function<L,R>)this.sameTypeFun;
246                }
247                Function<L, R> result = (Function<L, R>) this.transTable.get(left, right);
248                return result;
249        }
250        public <L,R>Function<L,R> getTransformerChecked(Class<L>left,Class<R>right){
251                return checkNotNull(getTransformer(left,right),"not found transformer for %s to %s",left,right);
252        }
253
254        /**
255         * 将{@code value}转换为{@code right}指定的类型
256         * @param value
257         * @param left {@code value}的原类型
258         * @param right 目标类型
259         * @return
260         */
261        @SuppressWarnings("unchecked")
262        public <L,R> R to (L value,Class<L>left,Class<R> right){
263                if(null == value){
264                        return null;
265                }
266                checkArgument(null != right,"right is null");
267                if(right.isInstance(value)){
268                        return (R) value;
269                }
270                return this.getTransformerChecked(left, right).apply(value);
271        }
272        /**
273         * 将 List 中的元素转换为{@code right}指定的类型
274         * @param input
275         * @param left 列表元素原类型
276         * @param right 列表元素目标类型
277         * @return
278         */
279        public <L,R>List<R> to(List<L> input,Class<L> left, Class<R> right){
280                return null == input 
281                                ? null 
282                                : Lists.transform(input, this.getTransformerChecked(left, right));
283        }
284        /**
285         * 将 Set 中的元素转换为{@code right}指定的类型
286         * @param input
287         * @param left 集合元素原类型
288         * @param right 集合元素目标类型
289         * @return
290         */
291        public <L,R> Set<R> to(Set<L> input,Class<L> left, Class<R> right){
292                return null == input 
293                                ? null 
294                                : Sets.newHashSet(Iterables.transform(input, this.getTransformerChecked(left, right)));
295        }
296        /**
297         * 将 数组 中的元素转换为{@code right}指定的类型
298         * @param input
299         * @param left 数组元素原类型
300         * @param right 数组元素目标类型
301         * @return
302         */
303        public <L,R> List<R> to(L[] input,Class<L> left,Class<R> right){
304                if(null == input){
305                        return null;
306                }
307                return to(Arrays.asList(input),left,right);
308        }
309        /**
310         * 将 int[] 转换为列表
311         * @param input
312         * @param left 
313         * @param right 
314         * @return
315         */
316        public List<Integer> to(int[] input,Class<Integer>left,Class<Integer> right){
317                return intArray2List.apply(input);
318        }
319        /**
320         * 将 long[] 转换为列表
321         * @param input
322         * @param left 
323         * @param right 
324         * @return
325         */
326        public List<Long> to(long[] input,Class<Long>left,Class<Long> right){
327                return longArray2List.apply(input);
328        }
329        /**
330         * 将 double[] 转换为列表
331         * @param input
332         * @param left 
333         * @param right 
334         * @return
335         */
336        public List<Double> to(double[] input,Class<Double>left,Class<Double> right){
337                return doubleArray2List.apply(input);
338        }
339        /**
340         * 将 float[] 转换为Double列表
341         * @param input
342         * @param left 
343         * @param right 
344         * @return
345         */
346        public List<Double> to(float[] input,Class<Float>left,Class<Double> right){
347                return floatArray2List.apply(input);
348        }
349        /**
350         * 将 short[] 转换为列表
351         * @param input
352         * @param left 
353         * @param right 
354         * @return
355         */
356        public List<Short> to(short[] input,Class<Short>left,Class<Short> right){
357                return shortArray2List.apply(input);
358        }
359        /**
360         * 将 boolean[] 转换为列表
361         * @param input
362         * @param left 
363         * @param right 
364         * @return
365         */
366        public List<Boolean> to(boolean[] input,Class<Boolean>left,Class<Boolean> right){
367                return booleanArray2List.apply(input);
368        }
369        /**
370         * 将 列表 转换为数组
371         * @param input
372         * @param left 列表元素类型
373         * @param right 数组元素类型
374         * @return
375         */
376        @SuppressWarnings("unchecked")
377        public <L,R> R[] toArray(List<L> input,Class<L> left,Class<R> right){
378                if(null == input){
379                        return null;
380                }
381                List<R> r = to(input,left,right);
382                return r.toArray((R[]) Array.newInstance(right, r.size()));
383        }
384        /**
385         * 将 Integer 列表 转换为数组
386         * @param input
387         * @param left 
388         * @param right 
389         * @return
390         */
391        public  int[] tointArray(List<Integer> input,Class<Integer> left,Class<Integer> right){
392                return list2intArray.apply(input);
393        }
394        /**
395         * 将 Long 列表 转换为数组
396         * @param input
397         * @param left 
398         * @param right 
399         * @return
400         */
401        public  long[] tolongArray(List<Long> input,Class<Long> left,Class<Long> right){
402                return list2longArray.apply(input);
403        }
404        /**
405         * 将 Double 列表 转换为数组
406         * @param input
407         * @param left 
408         * @param right 
409         * @return
410         */
411        public double[] todoubleArray(List<Double>input,Class<Double> left,Class<Double> right){
412                return list2doubleArray.apply(input);   
413        }
414        /**
415         * 将 Double 列表 转换为float数组
416         * @param input
417         * @param left 
418         * @param right 
419         * @return
420         */
421        public float[] tofloatArray(List<Double>input,Class<Double> left,Class<Float> right){
422                return list2floatArray.apply(input);
423        }
424        /**
425         * 将 Short 列表 转换为数组
426         * @param input
427         * @param left 
428         * @param right 
429         * @return
430         */
431        public short[] toshortArray(List<Short>input,Class<Short> left,Class<Short> right){
432                return list2shortArray.apply(input);    
433        }
434        /**
435         * 将 Boolean 列表 转换为数组
436         * @param input
437         * @param left 
438         * @param right 
439         * @return
440         */
441        public boolean[] tobooleanArray(List<Boolean>input,Class<Boolean> left,Class<Boolean> right){
442                return list2booleanArray.apply(input);
443        }
444        /**
445         * 将{@code Map<K1,V1>}转换为{@code Map<K2,V2>}
446         * @param input
447         * @param k1
448         * @param v1
449         * @param k2
450         * @param v2
451         * @return
452         */
453        @SuppressWarnings("unchecked")
454        public <K1,V1,K2,V2> Map<K2,V2> to(Map<K1,V1>input,Class<K1>k1,Class<V1>v1,Class<K2> k2,Class<V2> v2){
455                checkArgument(null != k1 && null != v1 && null != k2 && null != v2,"k1,v1,k2,v2 must not be null");
456                if(k1 == k2){
457                        if(v1 == v2){
458                                return (Map<K2, V2>) input;
459                        }
460                        return (Map<K2, V2>) Maps.transformValues(input, this.getTransformerChecked(v1, v2));
461                }else{
462                        Map<K2, V1> k2v1 = transform(input,this.getTransformerChecked(k1, k2));
463                        if(v1 == v2){
464                                return (Map<K2, V2>) k2v1;
465                        }else{
466                                return Maps.transformValues(k2v1, this.getTransformerChecked(v1, v2));
467                        }
468                }               
469        }
470        /** 
471     * convert {@code Map<K1,V>} to {@code Map<K2,V>}   
472     * @return {@linkplain ImmutableMap}
473     */
474    private static final <K1,K2,V>Map<K2,V> transform(Map<K1,V>fromMap,final Function<K1,K2>transformer){
475        checkNotNull(fromMap,"fromMap is null");
476        checkNotNull(transformer,"transformer is null");
477        // 新的Map对象Key类型已经是K2了,只是Value类型成了Entry
478        ImmutableMap<K2, Entry<K1, V>> k2Entry = Maps.uniqueIndex(fromMap.entrySet(), new Function<Entry<K1, V>,K2>(){
479            @Override
480            public K2 apply(Entry<K1, V> input) {               
481                return transformer.apply(input.getKey());
482            }});
483        // 再做一次转换将Entry<K1, V>转换成V,这个过程并没有创建新的Map,只是创建了k2Entry的代理对象
484        Map<K2, V> k2V = Maps.transformEntries(k2Entry, new EntryTransformer<K2,Entry<K1,V>,V>(){
485            @Override
486            public V transformEntry(K2 key, Entry<K1, V> value) {
487                return value.getValue();
488            }});
489        return k2V;
490    }
491}