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.api.ClassAccess; 022import org.jadira.reflection.access.asm.AsmClassAccess; 023import org.jadira.reflection.access.model.ClassModel; 024import org.jadira.reflection.access.model.FieldModel; 025import org.jadira.reflection.cloning.api.CloneDriver; 026import org.jadira.reflection.cloning.api.CloneStrategy; 027 028/** 029 * A CloneStrategy that uses ASM 030 */ 031public class AsmCloneStrategy extends AbstractCloneStrategy implements CloneStrategy { 032 033 private static final char CHAR_NULL = '\u0000'; 034 035 @Override 036 public <T> T newInstance(Class<T> c) { 037 038 ClassAccess<T> classAccess = AsmClassAccess.get(c); 039 return classAccess.newInstance(); 040 } 041 042 private static AsmCloneStrategy instance = new AsmCloneStrategy(); 043 044 /** 045 * Returns a shared instance of AsmCloneStrategy 046 * @return The instance 047 */ 048 public static AsmCloneStrategy getInstance() { 049 return instance; 050 } 051 052 @Override 053 protected <T> void handleTransientField(T copy, FieldModel<T> f) { 054 055 Class<?> clazz = f.getField().getType(); 056 try { 057 if (f.isPrivate()) { 058 if (clazz.isPrimitive()) { 059 if (java.lang.Boolean.TYPE == clazz) { 060 f.getField().setBoolean(copy, false); 061 } else if (java.lang.Byte.TYPE == clazz) { 062 f.getField().setByte(copy, (byte) 0); 063 } else if (java.lang.Character.TYPE == clazz) { 064 f.getField().setChar(copy, CHAR_NULL); 065 } else if (java.lang.Short.TYPE == clazz) { 066 f.getField().setShort(copy, (short) 0); 067 } else if (java.lang.Integer.TYPE == clazz) { 068 f.getField().setInt(copy, 0); 069 } else if (java.lang.Long.TYPE == clazz) { 070 f.getField().setLong(copy, 0L); 071 } else if (java.lang.Float.TYPE == clazz) { 072 f.getField().setFloat(copy, 0.0F); 073 } else if (java.lang.Double.TYPE == clazz) { 074 f.getField().setDouble(copy, 0.0D); 075 } 076 } else { 077 f.getField().set(copy, null); 078 } 079 } else { 080 if (clazz.isPrimitive()) { 081 if (java.lang.Boolean.TYPE == clazz) { 082 f.getFieldAccess().putBooleanValue(copy, false); 083 } else if (java.lang.Byte.TYPE == clazz) { 084 f.getFieldAccess().putByteValue(copy, (byte) 0); 085 } else if (java.lang.Character.TYPE == clazz) { 086 f.getFieldAccess().putCharValue(copy, CHAR_NULL); 087 } else if (java.lang.Short.TYPE == clazz) { 088 f.getFieldAccess().putShortValue(copy, (short) 0); 089 } else if (java.lang.Integer.TYPE == clazz) { 090 f.getFieldAccess().putIntValue(copy, 0); 091 } else if (java.lang.Long.TYPE == clazz) { 092 f.getFieldAccess().putLongValue(copy, 0L); 093 } else if (java.lang.Float.TYPE == clazz) { 094 f.getFieldAccess().putFloatValue(copy, 0.0F); 095 } else if (java.lang.Double.TYPE == clazz) { 096 f.getFieldAccess().putDoubleValue(copy, 0.0D); 097 } 098 } else { 099 f.getFieldAccess().putValue(copy, null); 100 } 101 } 102 } catch (IllegalArgumentException e) { 103 throw new IllegalStateException("Problem performing clone for field {" + f.getField().getName() + "} of object {" + System.identityHashCode(copy) + "}: " + e.getMessage(), e); 104 } catch (IllegalAccessException e) { 105 throw new IllegalStateException("Problem performing clone for field {" + f.getField().getName() + "} of object {" + System.identityHashCode(copy) + "}: " + e.getMessage(), e); 106 } 107 } 108 109 @Override 110 protected <W> ClassModel<W> getClassModel(Class<W> clazz) { 111 return AsmClassAccess.get(clazz).getClassModel(); 112 } 113 114 @Override 115 protected <T> void handleClonePrimitiveField(T obj, T copy, CloneDriver driver, FieldModel<T> f, IdentityHashMap<Object, Object> referencesToReuse) { 116 117 Field field = f.getField(); 118 119 try { 120 Class<?> clazz = f.getFieldClass(); 121 122 if (f.isPrivate()) { 123 if (java.lang.Boolean.TYPE == clazz) { 124 field.setBoolean(copy, field.getBoolean(obj)); 125 } else if (java.lang.Byte.TYPE == clazz) { 126 field.setByte(copy, field.getByte(obj)); 127 } else if (java.lang.Character.TYPE == clazz) { 128 field.setChar(copy, field.getChar(obj)); 129 } else if (java.lang.Short.TYPE == clazz) { 130 field.setShort(copy, field.getShort(obj)); 131 } else if (java.lang.Integer.TYPE == clazz) { 132 field.setInt(copy, field.getInt(obj)); 133 } else if (java.lang.Long.TYPE == clazz) { 134 field.setLong(copy, field.getLong(obj)); 135 } else if (java.lang.Float.TYPE == clazz) { 136 field.setFloat(copy, field.getFloat(obj)); 137 } else if (java.lang.Double.TYPE == clazz) { 138 field.setDouble(copy, field.getDouble(obj)); 139 } else { 140 throw new IllegalStateException("Expected primitive but was :" + clazz.getName()); 141 } 142 } else { 143 if (java.lang.Boolean.TYPE == clazz) { 144 f.getFieldAccess().putBooleanValue(copy, field.getBoolean(obj)); 145 } else if (java.lang.Byte.TYPE == clazz) { 146 f.getFieldAccess().putByteValue(copy, field.getByte(obj)); 147 } else if (java.lang.Character.TYPE == clazz) { 148 f.getFieldAccess().putCharValue(copy, field.getChar(obj)); 149 } else if (java.lang.Short.TYPE == clazz) { 150 f.getFieldAccess().putShortValue(copy, field.getShort(obj)); 151 } else if (java.lang.Integer.TYPE == clazz) { 152 f.getFieldAccess().putIntValue(copy, field.getInt(obj)); 153 } else if (java.lang.Long.TYPE == clazz) { 154 f.getFieldAccess().putLongValue(copy, field.getLong(obj)); 155 } else if (java.lang.Float.TYPE == clazz) { 156 f.getFieldAccess().putFloatValue(copy, field.getFloat(obj)); 157 } else if (java.lang.Double.TYPE == clazz) { 158 f.getFieldAccess().putDoubleValue(copy, field.getDouble(obj)); 159 } else { 160 throw new IllegalStateException("Expected primitive but was :" + clazz.getName()); 161 } 162 } 163 164 } catch (IllegalArgumentException e) { 165 throw new IllegalStateException("Problem performing clone for field {" + field.getName() + "} of object {" + System.identityHashCode(obj) + "}: " + e.getMessage(), e); 166 } catch (IllegalAccessException e) { 167 throw new IllegalStateException("Problem performing clone for field {" + field.getName() + "} of object {" + System.identityHashCode(obj) + "}: " + e.getMessage(), e); 168 } 169 } 170 171 @Override 172 protected <T> Object getFieldValue(T obj, FieldModel<T> f) { 173 174 final Field field = f.getField(); 175 176 final Object fieldObject; 177 178 try { 179 if (f.isPrivate()) { 180 fieldObject = field.get(obj); 181 } else { 182 fieldObject = f.getFieldAccess().getValue(obj); 183 } 184 } catch (IllegalArgumentException e) { 185 throw new IllegalStateException("Problem performing clone for field {" + field.getName() + "} of object {" + System.identityHashCode(obj) + "}: " + e.getMessage(), e); 186 } catch (IllegalAccessException e) { 187 throw new IllegalStateException("Problem performing clone for field {" + field.getName() + "} of object {" + System.identityHashCode(obj) + "}: " + e.getMessage(), e); 188 } 189 190 return fieldObject; 191 } 192 193 @Override 194 protected <T> void putFieldValue(T obj, FieldModel<T> f, Object value) { 195 196 final Field field = f.getField(); 197 198 try { 199 if (f.isPrivate()) { 200 f.getField().set(obj, value); 201 } else { 202 f.getFieldAccess().putValue(obj, value); 203 } 204 } catch (IllegalArgumentException e) { 205 throw new IllegalStateException("Problem performing clone for field {" + field.getName() + "} of object {" + System.identityHashCode(obj) + "}: " + e.getMessage(), e); 206 } catch (IllegalAccessException e) { 207 throw new IllegalStateException("Problem performing clone for field {" + field.getName() + "} of object {" + System.identityHashCode(obj) + "}: " + e.getMessage(), e); 208 } 209 } 210}