/* * Copyright 2004 Sun Microsystems, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.sun.syndication.feed.impl; import com.sun.syndication.feed.CopyFrom; import com.sun.syndication.feed.impl.BeanIntrospector; import java.beans.PropertyDescriptor; import java.lang.reflect.Array; import java.lang.reflect.Method; import java.util.*; /** * @author Alejandro Abdelnur */ public class CopyFromHelper { private static final Object[] NO_PARAMS = new Object[0]; private Class _beanInterfaceClass; private Map _baseInterfaceMap; //ENTRIES(propertyName,interface.class) private Map _baseImplMap; //ENTRIES(interface.class,implementation.class) public CopyFromHelper(Class beanInterfaceClass,Map basePropInterfaceMap,Map basePropClassImplMap) { _beanInterfaceClass = beanInterfaceClass; _baseInterfaceMap = basePropInterfaceMap; _baseImplMap = basePropClassImplMap; } public void copy(Object target,Object source) { try { PropertyDescriptor[] pds = BeanIntrospector.getPropertyDescriptors(_beanInterfaceClass); if (pds!=null) { for (int i=0;i<pds.length;i++) { String propertyName = pds[i].getName(); Method pReadMethod = pds[i].getReadMethod(); Method pWriteMethod = pds[i].getWriteMethod(); if (pReadMethod!=null && pWriteMethod!=null && // ensure it has getter and setter methods pReadMethod.getDeclaringClass()!=Object.class && // filter Object.class getter methods pReadMethod.getParameterTypes().length==0 && // filter getter methods that take parameters _baseInterfaceMap.containsKey(propertyName)) { // only copies properties defined as copyFrom-able Object value = pReadMethod.invoke(source,NO_PARAMS); if (value!=null) { Class baseInterface = (Class) _baseInterfaceMap.get(propertyName); value = doCopy(value,baseInterface); pWriteMethod.invoke(target,new Object[]{value}); } } } } } catch (Exception ex) { throw new RuntimeException("Could not do a copyFrom "+ex, ex); } } private CopyFrom createInstance(Class interfaceClass) throws Exception { if( _baseImplMap.get(interfaceClass) == null ){ return null; } else { return (CopyFrom) ((Class)_baseImplMap.get(interfaceClass)).newInstance(); } } private Object doCopy(Object value,Class baseInterface) throws Exception { if (value!=null) { Class vClass = value.getClass(); if (vClass.isArray()) { value = doCopyArray(value,baseInterface); } else if (value instanceof Collection) { value = doCopyCollection((Collection)value,baseInterface); } else if (value instanceof Map) { value = doCopyMap((Map)value,baseInterface); } else if (isBasicType(vClass)) { // value = value; // nothing to do here if (value instanceof Date) { // because Date it is not inmutable value = ((Date)value).clone(); } } else { // it goes CopyFrom if (value instanceof CopyFrom) { CopyFrom source = (CopyFrom) value; CopyFrom target = createInstance(source.getInterface()); target = target == null ? (CopyFrom) value.getClass().newInstance() : target; target.copyFrom(source); value = target; } else { throw new Exception("unsupported class for 'copyFrom' "+value.getClass()); } } } return value; } private Object doCopyArray(Object array,Class baseInterface) throws Exception { Class elementClass = array.getClass().getComponentType(); int length = Array.getLength(array); Object newArray = Array.newInstance(elementClass,length); for (int i=0;i<length;i++) { Object element = doCopy(Array.get(array,i),baseInterface); Array.set(newArray,i,element); } return newArray; } private Object doCopyCollection(Collection collection,Class baseInterface) throws Exception { // expecting SETs or LISTs only, going default implementation of them Collection newColl = (collection instanceof Set) ? (Collection)new HashSet() : (Collection)new ArrayList(); Iterator i = collection.iterator(); while (i.hasNext()) { Object element = doCopy(i.next(),baseInterface); newColl.add(element); } return newColl; } private Object doCopyMap(Map map,Class baseInterface) throws Exception { Map newMap = new HashMap(); Iterator entries = map.entrySet().iterator(); while (entries.hasNext()) { Map.Entry entry = (Map.Entry) entries.next(); Object key = entry.getKey(); // we are assuming string KEYS Object element = doCopy(entry.getValue(),baseInterface); newMap.put(key,element); } return newMap; } private static final Set BASIC_TYPES = new HashSet(); static { BASIC_TYPES.add(Boolean.class); BASIC_TYPES.add(Byte.class); BASIC_TYPES.add(Character.class); BASIC_TYPES.add(Double.class); BASIC_TYPES.add(Float.class); BASIC_TYPES.add(Integer.class); BASIC_TYPES.add(Long.class); BASIC_TYPES.add(Short.class); BASIC_TYPES.add(String.class); BASIC_TYPES.add(Date.class); } private boolean isBasicType(Class vClass) { return BASIC_TYPES.contains(vClass); } }