1 package com.sun.syndication.feed.synd.impl;
2
3 import com.sun.syndication.common.CopyFrom;
4 import com.sun.syndication.common.Enum;
5
6 import java.beans.BeanInfo;
7 import java.beans.Introspector;
8 import java.beans.PropertyDescriptor;
9 import java.lang.reflect.Array;
10 import java.lang.reflect.Method;
11 import java.util.*;
12
13 /***
14 * @author Alejandro Abdelnur
15 */
16 public class SyndCopyFrom {
17 private static final Object[] NO_PARAMS = new Object[0];
18
19 private Class _beanInterfaceClass;
20 private Map _baseInterfaceMap;
21 private Map _baseImplMap;
22
23 public SyndCopyFrom(Class beanInterfaceClass,Map basePropInterfaceMap,Map basePropClassImplMap) {
24 _beanInterfaceClass = beanInterfaceClass;
25 _baseInterfaceMap = basePropInterfaceMap;
26 _baseImplMap = basePropClassImplMap;
27 }
28
29 public void copy(Object target,Object source) {
30 try {
31 BeanInfo bi = Introspector.getBeanInfo(_beanInterfaceClass);
32 PropertyDescriptor[] pds = bi.getPropertyDescriptors();
33 if (pds!=null) {
34 for (int i=0;i<pds.length;i++) {
35 String propertyName = pds[i].getName();
36 Method pReadMethod = pds[i].getReadMethod();
37 Method pWriteMethod = pds[i].getWriteMethod();
38 if (pReadMethod!=null && pWriteMethod!=null &&
39 pReadMethod.getDeclaringClass()!=Object.class &&
40 pReadMethod.getParameterTypes().length==0 &&
41 _baseInterfaceMap.containsKey(propertyName)) {
42 Object value = pReadMethod.invoke(source,NO_PARAMS);
43 if (value!=null) {
44 Class baseInterface = (Class) _baseInterfaceMap.get(propertyName);
45 value = doCopy(value,baseInterface);
46 pWriteMethod.invoke(target,new Object[]{value});
47 }
48 }
49 }
50 }
51 }
52 catch (Exception ex) {
53 System.out.println(ex);
54 ex.printStackTrace(System.out);
55 throw new RuntimeException("Could not do a copyFrom "+ex);
56 }
57 }
58
59 private CopyFrom createInstance(Class interfaceClass) throws Exception {
60 return (CopyFrom) ((Class)_baseImplMap.get(interfaceClass)).newInstance();
61 }
62
63 private Object doCopy(Object value,Class baseInterface) throws Exception {
64 if (value!=null) {
65 Class vClass = value.getClass();
66 if (vClass.isArray()) {
67 value = doCopyArray(value,baseInterface);
68 }
69 else
70 if (value instanceof Collection) {
71 value = doCopyCollection((Collection)value,baseInterface);
72 }
73 else
74 if (value instanceof Map) {
75 value = doCopyMap((Map)value,baseInterface);
76 }
77 else
78 if (isBasicType(vClass)) {
79
80 if (value instanceof Date) {
81 value = ((Date)value).clone();
82 }
83 }
84 else {
85 if (value instanceof CopyFrom) {
86 CopyFrom source = (CopyFrom)value;
87 CopyFrom target = createInstance(source.getInterface());
88 target.copyFrom(source);
89 value = target;
90 }
91 else {
92 throw new Exception("unsupported class for 'copyFrom' "+value.getClass());
93 }
94 }
95 }
96 return value;
97 }
98
99 private Object doCopyArray(Object array,Class baseInterface) throws Exception {
100 Class elementClass = array.getClass().getComponentType();
101 int length = Array.getLength(array);
102 Object newArray = Array.newInstance(elementClass,length);
103 for (int i=0;i<length;i++) {
104 Object element = doCopy(Array.get(array,i),baseInterface);
105 Array.set(newArray,i,element);
106 }
107 return newArray;
108 }
109
110 private Object doCopyCollection(Collection collection,Class baseInterface) throws Exception {
111
112 Collection newColl = (collection instanceof Set) ? (Collection)new HashSet() : (Collection)new ArrayList();
113 Iterator i = collection.iterator();
114 while (i.hasNext()) {
115 Object element = doCopy(i.next(),baseInterface);
116 newColl.add(element);
117 }
118 return newColl;
119 }
120
121 private Object doCopyMap(Map map,Class baseInterface) throws Exception {
122 Map newMap = new HashMap();
123 Iterator entries = map.entrySet().iterator();
124 while (entries.hasNext()) {
125 Map.Entry entry = (Map.Entry) entries.next();
126 Object key = entry.getKey();
127 Object element = doCopy(entry.getValue(),baseInterface);
128 newMap.put(key,element);
129 }
130 return newMap;
131 }
132
133 private static final Set BASIC_TYPES = new HashSet();
134
135 static {
136 BASIC_TYPES.add(Boolean.class);
137 BASIC_TYPES.add(Byte.class);
138 BASIC_TYPES.add(Character.class);
139 BASIC_TYPES.add(Double.class);
140 BASIC_TYPES.add(Float.class);
141 BASIC_TYPES.add(Integer.class);
142 BASIC_TYPES.add(Long.class);
143 BASIC_TYPES.add(Short.class);
144 BASIC_TYPES.add(String.class);
145 BASIC_TYPES.add(Date.class);
146 }
147
148 private boolean isBasicType(Class vClass) {
149 return BASIC_TYPES.contains(vClass) || Enum.class.isAssignableFrom(vClass);
150 }
151
152 }