View Javadoc

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              throw new RuntimeException("Could not do a copyFrom "+ex, ex);
67          }
68      }
69  
70      private CopyFrom createInstance(Class interfaceClass) throws Exception {
71          if( _baseImplMap.get(interfaceClass) == null ){
72              return null;
73          }
74          else {
75              return (CopyFrom) ((Class)_baseImplMap.get(interfaceClass)).newInstance();
76          }
77      }
78  
79      private Object doCopy(Object value,Class baseInterface) throws Exception {
80          if (value!=null) {
81              Class vClass = value.getClass();
82              if (vClass.isArray()) {
83                  value = doCopyArray(value,baseInterface);
84              }
85              else
86              if (value instanceof Collection) {
87                  value = doCopyCollection((Collection)value,baseInterface);
88              }
89              else
90              if (value instanceof Map) {
91                  value = doCopyMap((Map)value,baseInterface);
92              }
93              else
94              if (isBasicType(vClass)) {
95                  // value = value; // nothing to do here
96                  if (value instanceof Date) { // because Date it is not inmutable
97                      value = ((Date)value).clone();
98                  }
99              }
100             else { // it goes CopyFrom
101                 if (value instanceof CopyFrom) {
102                     CopyFrom source = (CopyFrom) value;
103                     CopyFrom target = createInstance(source.getInterface());
104                     target = target == null ?  (CopyFrom) value.getClass().newInstance() : target;
105                     target.copyFrom(source);
106                     value = target;
107                 }
108                 else {
109                     throw new Exception("unsupported class for 'copyFrom' "+value.getClass());
110                 }
111             }
112         }
113         return value;
114     }
115 
116     private Object doCopyArray(Object array,Class baseInterface) throws Exception {
117         Class elementClass = array.getClass().getComponentType();
118         int length = Array.getLength(array);
119         Object newArray = Array.newInstance(elementClass,length);
120         for (int i=0;i<length;i++) {
121             Object element = doCopy(Array.get(array,i),baseInterface);
122             Array.set(newArray,i,element);
123         }
124         return newArray;
125     }
126 
127     private Object doCopyCollection(Collection collection,Class baseInterface) throws Exception {
128         // expecting SETs or LISTs only, going default implementation of them
129         Collection newColl = (collection instanceof Set) ? (Collection)new HashSet() : (Collection)new ArrayList();
130         Iterator i = collection.iterator();
131         while (i.hasNext()) {
132             Object element = doCopy(i.next(),baseInterface);
133             newColl.add(element);
134         }
135         return newColl;
136     }
137 
138     private Object doCopyMap(Map map,Class baseInterface) throws Exception {
139         Map newMap = new HashMap();
140         Iterator entries = map.entrySet().iterator();
141         while (entries.hasNext()) {
142             Map.Entry entry = (Map.Entry) entries.next();
143             Object key = entry.getKey(); // we are assuming string KEYS
144             Object element = doCopy(entry.getValue(),baseInterface);
145             newMap.put(key,element);
146         }
147         return newMap;
148     }
149 
150     private static final Set BASIC_TYPES = new HashSet();
151 
152     static {
153         BASIC_TYPES.add(Boolean.class);
154         BASIC_TYPES.add(Byte.class);
155         BASIC_TYPES.add(Character.class);
156         BASIC_TYPES.add(Double.class);
157         BASIC_TYPES.add(Float.class);
158         BASIC_TYPES.add(Integer.class);
159         BASIC_TYPES.add(Long.class);
160         BASIC_TYPES.add(Short.class);
161         BASIC_TYPES.add(String.class);
162         BASIC_TYPES.add(Date.class);
163     }
164 
165     private boolean isBasicType(Class vClass) {
166         return BASIC_TYPES.contains(vClass);
167     }
168 
169 }