Source code: com/sun/syndication/feed/impl/CopyFromHelper.java
1 /*
2 * Copyright 2004 Sun Microsystems, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17 package com.sun.syndication.feed.impl;
18
19 import com.sun.syndication.feed.CopyFrom;
20 import com.sun.syndication.feed.impl.BeanIntrospector;
21
22 import java.beans.PropertyDescriptor;
23 import java.lang.reflect.Array;
24 import java.lang.reflect.Method;
25 import java.util.*;
26
27 /**
28 * @author Alejandro Abdelnur
29 */
30 public class CopyFromHelper {
31 private static final Object[] NO_PARAMS = new Object[0];
32
33 private Class _beanInterfaceClass;
34 private Map _baseInterfaceMap; //ENTRIES(propertyName,interface.class)
35 private Map _baseImplMap; //ENTRIES(interface.class,implementation.class)
36
37 public CopyFromHelper(Class beanInterfaceClass,Map basePropInterfaceMap,Map basePropClassImplMap) {
38 _beanInterfaceClass = beanInterfaceClass;
39 _baseInterfaceMap = basePropInterfaceMap;
40 _baseImplMap = basePropClassImplMap;
41 }
42
43 public void copy(Object target,Object source) {
44 try {
45 PropertyDescriptor[] pds = BeanIntrospector.getPropertyDescriptors(_beanInterfaceClass);
46 if (pds!=null) {
47 for (int i=0;i<pds.length;i++) {
48 String propertyName = pds[i].getName();
49 Method pReadMethod = pds[i].getReadMethod();
50 Method pWriteMethod = pds[i].getWriteMethod();
51 if (pReadMethod!=null && pWriteMethod!=null && // ensure it has getter and setter methods
52 pReadMethod.getDeclaringClass()!=Object.class && // filter Object.class getter methods
53 pReadMethod.getParameterTypes().length==0 && // filter getter methods that take parameters
54 _baseInterfaceMap.containsKey(propertyName)) { // only copies properties defined as copyFrom-able
55 Object value = pReadMethod.invoke(source,NO_PARAMS);
56 if (value!=null) {
57 Class baseInterface = (Class) _baseInterfaceMap.get(propertyName);
58 value = doCopy(value,baseInterface);
59 pWriteMethod.invoke(target,new Object[]{value});
60 }
61 }
62 }
63 }
64 }
65 catch (Exception ex) {
66 System.out.println(ex);
67 ex.printStackTrace(System.out);
68 throw new RuntimeException("Could not do a copyFrom "+ex);
69 }
70 }
71
72 private CopyFrom createInstance(Class interfaceClass) throws Exception {
73 return (CopyFrom) ((Class)_baseImplMap.get(interfaceClass)).newInstance();
74 }
75
76 private Object doCopy(Object value,Class baseInterface) throws Exception {
77 if (value!=null) {
78 Class vClass = value.getClass();
79 if (vClass.isArray()) {
80 value = doCopyArray(value,baseInterface);
81 }
82 else
83 if (value instanceof Collection) {
84 value = doCopyCollection((Collection)value,baseInterface);
85 }
86 else
87 if (value instanceof Map) {
88 value = doCopyMap((Map)value,baseInterface);
89 }
90 else
91 if (isBasicType(vClass)) {
92 // value = value; // nothing to do here
93 if (value instanceof Date) { // because Date it is not inmutable
94 value = ((Date)value).clone();
95 }
96 }
97 else { // it goes CopyFrom
98 if (value instanceof CopyFrom) {
99 CopyFrom source = (CopyFrom)value;
100 CopyFrom target = createInstance(source.getInterface());
101 target.copyFrom(source);
102 value = target;
103 }
104 else {
105 throw new Exception("unsupported class for 'copyFrom' "+value.getClass());
106 }
107 }
108 }
109 return value;
110 }
111
112 private Object doCopyArray(Object array,Class baseInterface) throws Exception {
113 Class elementClass = array.getClass().getComponentType();
114 int length = Array.getLength(array);
115 Object newArray = Array.newInstance(elementClass,length);
116 for (int i=0;i<length;i++) {
117 Object element = doCopy(Array.get(array,i),baseInterface);
118 Array.set(newArray,i,element);
119 }
120 return newArray;
121 }
122
123 private Object doCopyCollection(Collection collection,Class baseInterface) throws Exception {
124 // expecting SETs or LISTs only, going default implementation of them
125 Collection newColl = (collection instanceof Set) ? (Collection)new HashSet() : (Collection)new ArrayList();
126 Iterator i = collection.iterator();
127 while (i.hasNext()) {
128 Object element = doCopy(i.next(),baseInterface);
129 newColl.add(element);
130 }
131 return newColl;
132 }
133
134 private Object doCopyMap(Map map,Class baseInterface) throws Exception {
135 Map newMap = new HashMap();
136 Iterator entries = map.entrySet().iterator();
137 while (entries.hasNext()) {
138 Map.Entry entry = (Map.Entry) entries.next();
139 Object key = entry.getKey(); // we are assuming string KEYS
140 Object element = doCopy(entry.getValue(),baseInterface);
141 newMap.put(key,element);
142 }
143 return newMap;
144 }
145
146 private static final Set BASIC_TYPES = new HashSet();
147
148 static {
149 BASIC_TYPES.add(Boolean.class);
150 BASIC_TYPES.add(Byte.class);
151 BASIC_TYPES.add(Character.class);
152 BASIC_TYPES.add(Double.class);
153 BASIC_TYPES.add(Float.class);
154 BASIC_TYPES.add(Integer.class);
155 BASIC_TYPES.add(Long.class);
156 BASIC_TYPES.add(Short.class);
157 BASIC_TYPES.add(String.class);
158 BASIC_TYPES.add(Date.class);
159 }
160
161 private boolean isBasicType(Class vClass) {
162 return BASIC_TYPES.contains(vClass);
163 }
164
165 }