001 /* 002 Copyright (C) 2003 Laurent Martelli <laurent@aopsys.com> 003 004 This program is free software; you can redistribute it and/or modify 005 it under the terms of the GNU Lesser General Public License as 006 published by the Free Software Foundation; either version 2 of the 007 License, or (at your option) any later version. 008 009 This program is distributed in the hope that it will be useful, but 010 WITHOUT ANY WARRANTY; without even the implied warranty of 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 Lesser General Public License for more details. 013 014 You should have received a copy of the GNU Lesser General Public 015 License along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 017 USA */ 018 019 package org.objectweb.jac.core; 020 021 import java.lang.reflect.Modifier; 022 import java.util.Collection; 023 import java.util.Iterator; 024 import org.apache.log4j.Logger; 025 import org.objectweb.jac.core.rtti.ClassItem; 026 import org.objectweb.jac.core.rtti.ClassRepository; 027 import org.objectweb.jac.core.rtti.CollectionItem; 028 import org.objectweb.jac.core.rtti.FieldItem; 029 import org.objectweb.jac.core.rtti.MethodItem; 030 import org.objectweb.jac.core.rtti.NoSuchMethodException; 031 import org.objectweb.jac.core.rtti.RttiAC; 032 import org.objectweb.jac.util.ExtArrays; 033 034 public class Utils { 035 static Logger logger = Logger.getLogger("clone"); 036 037 /** 038 * "Semantic" clone. Same as <code>clone(o,null)</code> 039 * 040 * @param o the object to clone 041 * @return the cloned object 042 * 043 * @see #clone(Object,FieldItem) 044 */ 045 public static Object clone(Object o) 046 throws InstantiationException, IllegalAccessException, Exception 047 { 048 return clone(o,(FieldItem)null); 049 } 050 051 /** 052 * "Semantic" clone. Collections marked as aggregation are 053 * recursively cloned (objects in the collection are cloned), 054 * otherwise the collection of the cloned objet will contains the 055 * same objects as the source object. 056 * 057 * @param o the object to clone 058 * @param ignoredRelation do not clone this relation and leave it 059 * empty. If null, all relations are cloned. 060 * @return the cloned object 061 * 062 * @see #clone(Object) 063 */ 064 public static Object clone(Object o, FieldItem ignoredRelation) 065 throws InstantiationException, IllegalAccessException, Exception 066 { 067 logger.debug("Cloning "+o); 068 ClassRepository cr = ClassRepository.get(); 069 ClassItem cli = cr.getClass(o); 070 Object clone = cli.newInstance(); 071 Iterator i = cli.getAllFields().iterator(); 072 while (i.hasNext()) { 073 FieldItem field = (FieldItem)i.next(); 074 if (field.isCalculated() || ignoredRelation==field) 075 continue; 076 if (field.isPrimitive()) { 077 logger.debug(" copying value of fied "+field.getName()); 078 try { 079 Object fieldValue = field.getThroughAccessor(o); 080 081 // Cloneable is useless in this generic context 082 try { 083 MethodItem mClone = cr.getClass(fieldValue).getMethod("clone()"); 084 if (mClone!=null && Modifier.isPublic(mClone.getModifiers())) 085 fieldValue = mClone.invoke(fieldValue, ExtArrays.emptyObjectArray); 086 } catch(NoSuchMethodException e) { 087 } 088 field.setThroughWriter(clone,fieldValue); 089 } catch (Exception e) { 090 logger.error("clone("+o+"): failed to clone field "+field,e); 091 } 092 } else if (field instanceof CollectionItem) { 093 CollectionItem collection = (CollectionItem)field; 094 logger.debug(" copying collection "+field.getName()); 095 if (collection.isMap()) { 096 } else { 097 Iterator j = ((Collection)collection.getThroughAccessor(o)).iterator(); 098 while(j.hasNext()) { 099 Object item = j.next(); 100 if (collection.isAggregation()) { 101 item = clone(item,(FieldItem)field.getAttribute(RttiAC.OPPOSITE_ROLE)); 102 } 103 collection.addThroughAdder(clone,item); 104 } 105 } 106 } else { 107 field.setThroughWriter(clone,field.getThroughAccessor(o)); 108 } 109 } 110 logger.debug(o+" cloned"); 111 return clone; 112 } 113 114 public static Object clone(Object o, String ignoredRelation) 115 throws InstantiationException, IllegalAccessException, Exception 116 { 117 return clone(o,ClassRepository.get().getClass(o).getField(ignoredRelation)); 118 } 119 }