001package gu.sql2java;
002import java.lang.reflect.ParameterizedType;
003import java.lang.reflect.Type;
004import java.util.ArrayList;
005import java.util.Collection;
006import java.util.HashMap;
007import java.util.List;
008import java.util.Map;
009import java.util.Map.Entry;
010
011/**
012 * 
013 * @author guyadong
014 *
015 * @param <L> left type
016 * @param <R> right type
017 */
018public interface IBeanConverter<L,R> {
019
020    /**
021     * Default abstract implementation of {@link IBeanConverter}<br>
022     * 
023     * @author guyadong
024     *
025     * @param <L> left type
026     * @param <R> right type
027     */
028    public static abstract class  AbstractHandle <L,R>implements IBeanConverter<L, R> {
029        /** L type  */
030        protected final Class<?> leftType;
031        /** R type  */
032        protected final Class<?> rightType;
033        private static Class<?> getRawClass(Type type){
034            if(type instanceof Class<?>){
035                return (Class<?>) type;
036            } else if(type instanceof ParameterizedType){
037                return getRawClass(((ParameterizedType) type).getRawType());
038            } else{
039                throw new IllegalArgumentException("invalid type");
040            }
041        }
042        public AbstractHandle() {
043            Type superClass = getClass().getGenericSuperclass();
044            this.leftType = getRawClass(((ParameterizedType) superClass).getActualTypeArguments()[0]);
045            this.rightType = getRawClass(((ParameterizedType) superClass).getActualTypeArguments()[1]);
046        }
047        public AbstractHandle(Class<L> leftClass,Class<R> rightClass) {
048            this.leftType = leftClass;
049            this.rightType = rightClass;
050        }
051        /** 
052         * copy right TO left, left and right must not be null
053         * @param left
054         * @param right
055         */
056        protected abstract void doFromRight(L left, R right);
057        /** 
058         * copy left TO right, left and right must not be null 
059         * @param left
060         * @param right
061         */
062        protected abstract void doToRight(L left, R right);
063        /**
064         *  Creates a new  L instance by calling constructor with an empty argument list<br>
065         *  you must override the method if the L class haven't default constructor.
066         * @return
067         */
068        @SuppressWarnings("unchecked")
069        protected L newInstanceL(){ return (L) newInstance(this.leftType); }
070        /**
071         *  Creates a new R instance by calling constructor with an empty argument list<br>
072         *  you must override the method if the R class haven't default constructor.
073         * @return
074         */
075        @SuppressWarnings("unchecked")
076        protected R newInstanceR(){ return (R) newInstance(this.rightType); }
077        
078        protected  static<T> T newInstance(Class<T>clazz){
079            try {
080                return (T) clazz.newInstance();
081            } catch (InstantiationException e) {
082                throw new RuntimeException(e);
083            } catch (IllegalAccessException e) {
084                throw new RuntimeException(e);
085            }
086        }
087        @Override
088        public L fromRight(L left, R right) {
089            if(null != right && null != left){
090                this.doFromRight(left, right);
091            }            
092            return left;
093        }
094
095        @Override
096        public R toRight(L left, R right) {
097            if(null != left && null != right){
098                this.doToRight(left, right);
099            }
100            return right;
101        }
102
103        @Override
104        public L fromRight(R bean) {
105            return null == bean? null : fromRight(newInstanceL(),bean);
106        }
107
108        @Override
109        public R toRight(L bean) {
110            return null == bean? null : toRight(bean,newInstanceR());
111        }
112
113        @Override
114        public R[] toRight(L[] lefts, R[] rights) {
115            if(null != lefts && null != rights){
116                if( lefts.length != rights.length){
117                    throw new IllegalArgumentException("mismatched length between left and right array");
118                }
119                for(int i=0;i<lefts.length;++i){
120                    this.toRight(lefts[i],rights[i]);
121                }
122            }
123            return rights;
124        }
125
126        @Override
127        public L[] fromRight(L[] lefts, R[] rights) {
128            if(null != rights && null != lefts){
129                if( lefts.length != rights.length){
130                    throw new IllegalArgumentException("mismatched length between left and right array");
131                }
132                for(int i=0;i<lefts.length;++i){
133                    this.fromRight(lefts[i],rights[i]);
134                }
135            }
136            return lefts;
137        }
138        
139        @SuppressWarnings("unchecked")
140        @Override
141        public R[] toRight(L[] lefts) {
142            R[] rights = null;
143            if(null != lefts){
144                rights = (R[])java.lang.reflect.Array.newInstance(rightType,lefts.length) ;
145                for(int i=0;i<lefts.length;++i){
146                    rights[i] = toRight(lefts[i]);
147                }
148            }
149            return rights;
150        }
151
152        @SuppressWarnings("unchecked")
153        @Override
154        public L[] fromRight(R[] rights) {
155            L[] lefts = null;
156            if(null != rights){
157                lefts = (L[])java.lang.reflect.Array.newInstance(leftType,rights.length) ;
158                for(int i=0;i<rights.length;++i){
159                    lefts[i] = fromRight(rights[i]);
160                }
161            }
162            return lefts;
163        }
164
165        @Override
166        public List<R> toRight(Collection<L> beans) {
167            if(null==beans){
168                return null;
169            }
170            ArrayList<R> rights = new ArrayList<R>(beans.size());
171            for(L g:beans){
172                rights.add(this.toRight(g));
173            }
174            return rights;
175        }
176
177        @Override
178        public List<L> fromRight(Collection<R> beans) {
179            if(null==beans){
180                return null;
181            }
182            ArrayList<L> lefts = new ArrayList<L>(beans.size());
183            for(R n:beans){
184                lefts.add(this.fromRight(n));
185            }
186            return lefts;
187        }
188
189        @Override
190        public List<R> toRight(List<L> lefts, List<R> rights) {
191            if(null != lefts && null != rights){
192                if( lefts.size() != rights.size()){
193                    throw new IllegalArgumentException("mismatched length between left and right list");
194                }
195                for(int i=0;i<lefts.size();++i){
196                    this.toRight(lefts.get(i),rights.get(i));
197                }
198            }
199            return rights;
200        }
201
202        @Override
203        public List<L> fromRight(List<L> lefts, List<R> rights) {
204            if(null != rights && null != lefts){
205                if( lefts.size() != rights.size()){
206                    throw new IllegalArgumentException("mismatched length between left and right list");
207                }
208                for(int i=0;i<lefts.size();++i){
209                    this.fromRight(lefts.get(i),rights.get(i));
210                }
211            }
212            return lefts;
213        }
214
215        @Override
216        public List<R> toRight(List<L> lefts) {
217            List<R> rights = null;
218            if(null != lefts ){
219                rights  = new ArrayList<>();
220                for(L l:lefts){
221                    rights.add(toRight(l));
222                }
223            }
224            return rights;    
225        }
226
227        @Override
228        public List<L> fromRight(List<R> rights) {
229            List<L> lefts = null;
230            if(null != rights ){
231                lefts  = new ArrayList<>();
232                for(R r:rights){
233                    lefts.add(fromRight(r));
234                }
235            }
236            return lefts;            
237        }
238        @Override
239        public<V> Map<R,V> toRightKey(Map<L,V> lmap) {
240            if(null == lmap){
241                return null;
242            }
243            HashMap<R,V> rmap = new HashMap<R,V>(16);
244            for(Entry<L, V> entry:lmap.entrySet()){
245                rmap.put(this.toRight(entry.getKey()),entry.getValue());
246            }
247            return rmap;
248        }
249        @Override
250        public<K> Map<K,R> toRightValue(Map<K,L> lmap) {
251            if(null == lmap){
252                return null;
253            }
254            HashMap<K, R> rmap = new HashMap<K, R>(16);
255            for(Entry<K, L> entry:lmap.entrySet()){
256                rmap.put(entry.getKey(), this.toRight(entry.getValue()));
257            }
258            return rmap;
259        }
260        @Override
261        public<V> Map<L,V> fromRightKey(Map<R,V> rmap) {
262            if(null == rmap){
263                return null;
264            }
265            HashMap<L,V> lmap = new HashMap<L,V>(16);
266            for(Entry<R, V> entry:rmap.entrySet()){
267                lmap.put(this.fromRight(entry.getKey()),entry.getValue());
268            }
269            return lmap;
270        }
271        @Override
272        public<K> Map<K,L> fromRightValue(Map<K,R> rmap) {
273            if(null == rmap){
274                return null;
275            }
276            HashMap<K, L> lmap = new HashMap<K, L>(16);
277            for(Entry<K, R> entry:rmap.entrySet()){
278                lmap.put(entry.getKey(), this.fromRight(entry.getValue()));
279            }
280            return lmap;
281        }
282        @Override
283        public Map<R,R> toRight(Map<L,L> lmap) {
284            if(null == lmap){
285                return null;
286            }
287            HashMap<R,R> rmap = new HashMap<R,R>(16);
288            for(Entry<L, L> entry:lmap.entrySet()){
289                rmap.put(this.toRight(entry.getKey()),this.toRight(entry.getValue()));
290            }
291            return rmap;
292        }
293        @Override
294        public Map<L,L> fromRight(Map<R,R> rmap) {
295            if(null == rmap){
296                return null;
297            }
298            HashMap<L,L> lmap = new HashMap<L,L>(16);
299            for(Entry<R, R> entry:rmap.entrySet()){
300                lmap.put(this.fromRight(entry.getKey()),this.fromRight(entry.getValue()));
301            }
302            return lmap;
303        }
304    }
305
306    /**
307     * copy right TO left
308     * @param left
309     * @param right
310     * @return left,or new instance if left is null
311     */
312    public L fromRight(L left, R right);
313    
314    /**
315     * copy left TO right
316     * @param left
317     * @param right
318     * @return right,or new instance if right is null
319     */
320    public R toRight(L left, R right);
321    /**
322     * return an new instance converted from R bean
323     * @param bean
324     * @return L bean
325     */
326    public L fromRight(R bean);
327    /**
328     * return an new instance converted from L bean
329     * @param bean
330     * @return R bean
331     */
332    public R toRight( L bean);
333    /**
334     * copy rights TO lefts
335     * @param lefts
336     * @param rights
337     * @return lefts,or new array if lefts is null
338     */
339    public L[] fromRight(L[] lefts,R[] rights);
340    /**
341     * copy lefts TO rights
342     * @param lefts
343     * @param rights
344     * @return rights,or new array if rights is null
345     */
346    public R[] toRight(L[] lefts,R[] rights);
347    /**
348     * return an new array converted from R beans
349     * @param beans
350     * @return L bean array
351     */
352    public L[] fromRight(R[] beans);
353    /**
354     * an new array converted from L beans
355     * @param beans
356     * @return R bean array
357     */
358    public R[] toRight(L[] beans);
359    /**
360     * copy rights TO lefts
361     * @param lefts
362     * @param rights
363     * @return lefts,or new array if lefts is null
364     */
365    public List<L> fromRight(List<L> lefts,List<R> rights);
366    /**
367     * copy lefts TO rights
368     * @param lefts
369     * @param rights
370     * @return rights,or new array if rights is null
371     */
372    public List<R> toRight(List<L> lefts,List<R> rights);
373    /**
374     * return an new list converted from R beans
375     * @param beans
376     * @return L bean list
377     */
378    public List<L> fromRight(List<R> beans);
379    /**
380     * return an new list converted from L beans
381     * @param beans
382     * @return R bean list
383     */
384    public List<R> toRight(List<L> beans);
385    /**
386     * return an new list converted from R beans
387     * @param beans
388     * @return L bean list
389     */
390    public List<L> fromRight(Collection<R> beans);
391    /**
392     * an new list converted from L beans
393     * @param beans
394     * @return R bean list
395     */
396    public List<R> toRight(Collection<L> beans);
397    
398    /**
399     * return an new map with R key converted from map with L key
400     * @param lmap
401     * @return Map with R key
402     */
403    public <V> Map<R,V> toRightKey(Map<L,V> lmap);
404    /**
405     * return an new map with R value converted from map with L value
406     * @param lmap
407     * @return Map with R value
408     */
409    public <K> Map<K,R> toRightValue(Map<K,L> lmap);
410    /**
411     * return an new map with L key converted from map with R key
412     * @param rmap
413     * @return Map with L key
414     */
415    public <V> Map<L,V> fromRightKey(Map<R,V> rmap);
416    /**
417     * return an new map with L value converted from map with R value
418     * @param rmap
419     * @return Map with L value
420     */
421    public <K> Map<K,L> fromRightValue(Map<K,R> rmap);
422    /**
423     * an new map with R key and  R value converted from map with L key and L value
424     * @param lmap
425     * @return Map with R key and value
426     */
427    public Map<R,R> toRight(Map<L,L> lmap);
428    /**
429     * return an new map with L key and  L value converted from map with R key and R value
430     * @param rmap
431     * @return Map with L key and value
432     */
433    public Map<L,L> fromRight(Map<R,R> rmap);
434}