001/* 002 * Copyright 2013 Chris Pheby 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.jadira.reflection.cloning.implementor; 017 018import java.lang.reflect.Field; 019import java.util.IdentityHashMap; 020 021import org.jadira.reflection.access.model.ClassModel; 022import org.jadira.reflection.access.model.FieldModel; 023import org.jadira.reflection.access.portable.PortableClassAccess; 024import org.jadira.reflection.cloning.api.CloneDriver; 025import org.jadira.reflection.cloning.api.CloneStrategy; 026import org.objenesis.Objenesis; 027import org.objenesis.ObjenesisStd; 028 029/** 030 * A CloneStrategy that uses reflection 031 */ 032public class PortableCloneStrategy extends AbstractCloneStrategy implements CloneStrategy { 033 034 private static final char CHAR_NULL = '\u0000'; 035 036 private static final Objenesis objenesis = new ObjenesisStd(); 037 038 @Override 039 public <T> T newInstance(Class<T> c) { 040 return (T) objenesis.newInstance(c); 041 } 042 043 private static PortableCloneStrategy instance = new PortableCloneStrategy(); 044 045 /** 046 * Creates a new instance 047 */ 048 public PortableCloneStrategy() { 049 } 050 051 /** 052 * Returns a shared instance of PortableCloneStrategy 053 * @return The instance 054 */ 055 public static PortableCloneStrategy getInstance() { 056 return instance; 057 } 058 059 @Override 060 protected <T> void handleTransientField(T copy, FieldModel<T> f) { 061 062 Class<?> clazz = f.getField().getType(); 063 try { 064 if (clazz.isPrimitive()) { 065 if (java.lang.Boolean.TYPE == clazz) { 066 f.getField().setBoolean(copy, false); 067 } else if (java.lang.Byte.TYPE == clazz) { 068 f.getField().setByte(copy, (byte) 0); 069 } else if (java.lang.Character.TYPE == clazz) { 070 f.getField().setChar(copy, CHAR_NULL); 071 } else if (java.lang.Short.TYPE == clazz) { 072 f.getField().setShort(copy, (short) 0); 073 } else if (java.lang.Integer.TYPE == clazz) { 074 f.getField().setInt(copy, 0); 075 } else if (java.lang.Long.TYPE == clazz) { 076 f.getField().setLong(copy, 0L); 077 } else if (java.lang.Float.TYPE == clazz) { 078 f.getField().setFloat(copy, 0.0F); 079 } else if (java.lang.Double.TYPE == clazz) { 080 f.getField().setDouble(copy, 0.0D); 081 } 082 } else { 083 f.getField().set(copy, null); 084 } 085 } catch (IllegalArgumentException e) { 086 throw new IllegalStateException("Problem performing clone for field {" + f.getField().getName() + "} of object {" + System.identityHashCode(copy) + "}: " + e.getMessage(), e); 087 } catch (IllegalAccessException e) { 088 throw new IllegalStateException("Problem performing clone for field {" + f.getField().getName() + "} of object {" + System.identityHashCode(copy) + "}: " + e.getMessage(), e); 089 } 090 } 091 092 @Override 093 protected <W> ClassModel<W> getClassModel(Class<W> clazz) { 094 return PortableClassAccess.get(clazz).getClassModel(); 095 } 096 097 @Override 098 protected <T> void handleClonePrimitiveField(T obj, T copy, CloneDriver driver, FieldModel<T> f, IdentityHashMap<Object, Object> referencesToReuse) { 099 100 Field field = f.getField(); 101 102 try { 103 Class<?> clazz = f.getFieldClass(); 104 105 if (java.lang.Boolean.TYPE == clazz) { 106 field.setBoolean(copy, field.getBoolean(obj)); 107 } else if (java.lang.Byte.TYPE == clazz) { 108 field.setByte(copy, field.getByte(obj)); 109 } else if (java.lang.Character.TYPE == clazz) { 110 field.setChar(copy, field.getChar(obj)); 111 } else if (java.lang.Short.TYPE == clazz) { 112 field.setShort(copy, field.getShort(obj)); 113 } else if (java.lang.Integer.TYPE == clazz) { 114 field.setInt(copy, field.getInt(obj)); 115 } else if (java.lang.Long.TYPE == clazz) { 116 field.setLong(copy, field.getLong(obj)); 117 } else if (java.lang.Float.TYPE == clazz) { 118 field.setFloat(copy, field.getFloat(obj)); 119 } else if (java.lang.Double.TYPE == clazz) { 120 field.setDouble(copy, field.getDouble(obj)); 121 } else { 122 throw new IllegalStateException("Expected primitive but was :" + clazz.getName()); 123 } 124 125 } catch (IllegalArgumentException e) { 126 throw new IllegalStateException("Problem performing clone for field {" + field.getName() + "} of object {" + System.identityHashCode(obj) + "}: " + e.getMessage(), e); 127 } catch (IllegalAccessException e) { 128 throw new IllegalStateException("Problem performing clone for field {" + field.getName() + "} of object {" + System.identityHashCode(obj) + "}: " + e.getMessage(), e); 129 } 130 } 131 132 @Override 133 protected <T> Object getFieldValue(T obj, FieldModel<T> f) { 134 135 final Field field = f.getField(); 136 137 final Object fieldObject; 138 139 try { 140 fieldObject = field.get(obj); 141 142 } catch (IllegalArgumentException e) { 143 throw new IllegalStateException("Problem performing clone for field {" + field.getName() + "} of object {" + System.identityHashCode(obj) + "}: " + e.getMessage(), e); 144 } catch (IllegalAccessException e) { 145 throw new IllegalStateException("Problem performing clone for field {" + field.getName() + "} of object {" + System.identityHashCode(obj) + "}: " + e.getMessage(), e); 146 } 147 148 return fieldObject; 149 } 150 151 @Override 152 protected <T> void putFieldValue(T obj, FieldModel<T> f, Object value) { 153 154 final Field field = f.getField(); 155 156 try { 157 field.set(obj, value); 158 159 } catch (IllegalArgumentException e) { 160 throw new IllegalStateException("Problem performing clone for field {" + field.getName() + "} of object {" + System.identityHashCode(obj) + "}: " + e.getMessage(), e); 161 } catch (IllegalAccessException e) { 162 throw new IllegalStateException("Problem performing clone for field {" + field.getName() + "} of object {" + System.identityHashCode(obj) + "}: " + e.getMessage(), e); 163 } 164 } 165}