001/* 002 * Copyright 2013 Christopher 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 OObject 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.access.portable; 017 018import java.lang.reflect.Field; 019 020import org.jadira.reflection.access.api.FieldAccess; 021 022/** 023 * FieldAccess implementation which should be portable across most JVMs. 024 * @param <C> The Class to be accessed 025 */ 026public class PortableFieldAccess<C> implements FieldAccess<C> { 027 028 private Field field; 029 private Class<C> declaringClass; 030 private Class<?> type; 031 032 @SuppressWarnings("unchecked") 033 private PortableFieldAccess(Field f) { 034 this.field = f; 035 if (!field.isAccessible()) { 036 field.setAccessible(true); 037 } 038 this.declaringClass = (Class<C>) f.getDeclaringClass(); 039 this.type = (Class<?>) f.getType(); 040 } 041 042 @Override 043 public Class<C> declaringClass() { 044 return declaringClass; 045 } 046 047 @Override 048 public Class<?> fieldClass() { 049 return type; 050 } 051 052 @Override 053 public Field field() { 054 return field; 055 } 056 057 @Override 058 public Object getValue(C parent) { 059 try { 060 return (Object) field.get(parent); 061 } catch (IllegalArgumentException e) { 062 throw new IllegalStateException("Problem target object {" + field.getName() + "} of object {" 063 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 064 } catch (IllegalAccessException e) { 065 throw new IllegalStateException("Problem accessing {" + field.getName() + "} of object {" 066 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 067 } 068 } 069 070 @Override 071 public boolean getBooleanValue(C parent) { 072 throw new UnsupportedOperationException("Not supported for this field type"); 073 } 074 075 @Override 076 public byte getByteValue(C parent) { 077 throw new UnsupportedOperationException("Not supported for this field type"); 078 } 079 080 @Override 081 public char getCharValue(C parent) { 082 throw new UnsupportedOperationException("Not supported for this field type"); 083 } 084 085 @Override 086 public short getShortValue(C parent) { 087 throw new UnsupportedOperationException("Not supported for this field type"); 088 } 089 090 @Override 091 public int getIntValue(C parent) { 092 throw new UnsupportedOperationException("Not supported for this field type"); 093 } 094 095 @Override 096 public long getLongValue(C parent) { 097 throw new UnsupportedOperationException("Not supported for this field type"); 098 } 099 100 @Override 101 public float getFloatValue(C parent) { 102 throw new UnsupportedOperationException("Not supported for this field type"); 103 } 104 105 @Override 106 public double getDoubleValue(C parent) { 107 throw new UnsupportedOperationException("Not supported for this field type"); 108 } 109 110 @Override 111 public void putValue(C parent, Object newFieldValue) { 112 try { 113 field.set(parent, newFieldValue); 114 } catch (IllegalArgumentException e) { 115 throw new IllegalStateException("Problem argument for field {" + field.getName() + "} of object {" 116 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 117 } catch (IllegalAccessException e) { 118 throw new IllegalStateException("Problem accessing for field {" + field.getName() + "} of object {" 119 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 120 } 121 } 122 123 @Override 124 public void putBooleanValue(C parent, boolean newFieldValue) { 125 throw new UnsupportedOperationException("Not supported for this field type"); 126 } 127 128 @Override 129 public void putByteValue(C parent, byte newFieldValue) { 130 throw new UnsupportedOperationException("Not supported for this field type"); 131 } 132 133 @Override 134 public void putCharValue(C parent, char newFieldValue) { 135 throw new UnsupportedOperationException("Not supported for this field type"); 136 } 137 138 @Override 139 public void putShortValue(C parent, short newFieldValue) { 140 throw new UnsupportedOperationException("Not supported for this field type"); 141 } 142 143 @Override 144 public void putIntValue(C parent, int newFieldValue) { 145 throw new UnsupportedOperationException("Not supported for this field type"); 146 } 147 148 @Override 149 public void putLongValue(C parent, long newFieldValue) { 150 throw new UnsupportedOperationException("Not supported for this field type"); 151 } 152 153 @Override 154 public void putFloatValue(C parent, float newFieldValue) { 155 throw new UnsupportedOperationException("Not supported for this field type"); 156 } 157 158 @Override 159 public void putDoubleValue(C parent, double newFieldValue) { 160 throw new UnsupportedOperationException("Not supported for this field type"); 161 } 162 163 /** 164 * Get a new instance that can access the given Field 165 * @param f Field to be accessed 166 * @param <C> The type of class being accessed 167 * @return New PortableFieldAccess instance 168 */ 169 public static <C> PortableFieldAccess<C> get(Field f) { 170 171 Class<?> type = (Class<?>) f.getType(); 172 173 if (type.isPrimitive()) { 174 if (java.lang.Boolean.TYPE == type) { 175 return (PortableFieldAccess<C>) new PortableBooleanFieldAccess<C>(f); 176 } else if (java.lang.Byte.TYPE == type) { 177 return (PortableFieldAccess<C>) new PortableByteFieldAccess<C>(f); 178 } else if (java.lang.Character.TYPE == type) { 179 return (PortableFieldAccess<C>) new PortableCharFieldAccess<C>(f); 180 } else if (java.lang.Short.TYPE == type) { 181 return (PortableFieldAccess<C>) new PortableShortFieldAccess<C>(f); 182 } else if (java.lang.Integer.TYPE == type) { 183 return (PortableFieldAccess<C>) new PortableIntFieldAccess<C>(f); 184 } else if (java.lang.Long.TYPE == type) { 185 return (PortableFieldAccess<C>) new PortableLongFieldAccess<C>(f); 186 } else if (java.lang.Float.TYPE == type) { 187 return (PortableFieldAccess<C>) new PortableFloatFieldAccess<C>(f); 188 } else if (java.lang.Double.TYPE == type) { 189 return (PortableFieldAccess<C>) new PortableDoubleFieldAccess<C>(f); 190 } 191 } 192 return new PortableFieldAccess<C>(f); 193 } 194 195 /** 196 * PortableFieldAccess implementation suitable for accessing boolean fields 197 * @param <C> The Class containing the Field to be accessed 198 */ 199 public static class PortableBooleanFieldAccess<C> extends PortableFieldAccess<C> { 200 201 /** 202 * Construct a new instance for the given Field 203 * @param f The Field to be accessed 204 */ 205 public PortableBooleanFieldAccess(Field f) { 206 super(f); 207 } 208 209 @Override 210 public boolean getBooleanValue(C parent) { 211 try { 212 return super.field.getBoolean(parent); 213 } catch (IllegalArgumentException e) { 214 throw new IllegalStateException("Problem target object {" + super.field.getName() + "} of object {" 215 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 216 } catch (IllegalAccessException e) { 217 throw new IllegalStateException("Problem accessing {" + super.field.getName() + "} of object {" 218 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 219 } 220 } 221 222 @Override 223 public void putBooleanValue(C parent, boolean newFieldValue) { 224 try { 225 super.field.setBoolean(parent, newFieldValue); 226 } catch (IllegalArgumentException e) { 227 throw new IllegalStateException("Problem argument for field {" + super.field.getName() + "} of object {" 228 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 229 } catch (IllegalAccessException e) { 230 throw new IllegalStateException("Problem accessing for field {" + super.field.getName() + "} of object {" 231 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 232 } 233 } 234 } 235 236 /** 237 * PortableFieldAccess implementation suitable for accessing byte fields 238 * @param <C> The Class containing the Field to be accessed 239 */ 240 public static class PortableByteFieldAccess<C> extends PortableFieldAccess<C> { 241 242 /** 243 * Construct a new instance for the given Field 244 * @param f The Field to be accessed 245 */ 246 public PortableByteFieldAccess(Field f) { 247 super(f); 248 } 249 250 @Override 251 public byte getByteValue(C parent) { 252 try { 253 return super.field.getByte(parent); 254 } catch (IllegalArgumentException e) { 255 throw new IllegalStateException("Problem target object {" + super.field.getName() + "} of object {" 256 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 257 } catch (IllegalAccessException e) { 258 throw new IllegalStateException("Problem accessing {" + super.field.getName() + "} of object {" 259 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 260 } 261 } 262 263 @Override 264 public void putByteValue(C parent, byte newFieldValue) { 265 try { 266 super.field.setByte(parent, newFieldValue); 267 } catch (IllegalArgumentException e) { 268 throw new IllegalStateException("Problem argument for field {" + super.field.getName() + "} of object {" 269 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 270 } catch (IllegalAccessException e) { 271 throw new IllegalStateException("Problem accessing for field {" + super.field.getName() + "} of object {" 272 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 273 } 274 } 275 } 276 277 /** 278 * PortableFieldAccess implementation suitable for accessing char fields 279 * @param <C> The Class containing the Field to be accessed 280 */ 281 public static class PortableCharFieldAccess<C> extends PortableFieldAccess<C> { 282 283 /** 284 * Construct a new instance for the given Field 285 * @param f The Field to be accessed 286 */ 287 public PortableCharFieldAccess(Field f) { 288 super(f); 289 } 290 291 @Override 292 public char getCharValue(C parent) { 293 try { 294 return super.field.getChar(parent); 295 } catch (IllegalArgumentException e) { 296 throw new IllegalStateException("Problem target object {" + super.field.getName() + "} of object {" 297 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 298 } catch (IllegalAccessException e) { 299 throw new IllegalStateException("Problem accessing {" + super.field.getName() + "} of object {" 300 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 301 } 302 303 } 304 305 @Override 306 public void putCharValue(C parent, char newFieldValue) { 307 try { 308 super.field.setChar(parent, newFieldValue); 309 } catch (IllegalArgumentException e) { 310 throw new IllegalStateException("Problem argument for field {" + super.field.getName() + "} of object {" 311 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 312 } catch (IllegalAccessException e) { 313 throw new IllegalStateException("Problem accessing for field {" + super.field.getName() + "} of object {" 314 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 315 } 316 } 317 } 318 319 /** 320 * PortableFieldAccess implementation suitable for accessing short fields 321 * @param <C> The Class containing the Field to be accessed 322 */ 323 public static class PortableShortFieldAccess<C> extends PortableFieldAccess<C> { 324 325 /** 326 * Construct a new instance for the given Field 327 * @param f The Field to be accessed 328 */ 329 public PortableShortFieldAccess(Field f) { 330 super(f); 331 } 332 333 @Override 334 public short getShortValue(C parent) { 335 try { 336 return super.field.getShort(parent); 337 } catch (IllegalArgumentException e) { 338 throw new IllegalStateException("Problem target object {" + super.field.getName() + "} of object {" 339 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 340 } catch (IllegalAccessException e) { 341 throw new IllegalStateException("Problem accessing {" + super.field.getName() + "} of object {" 342 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 343 } 344 345 } 346 347 @Override 348 public void putShortValue(C parent, short newFieldValue) { 349 try { 350 super.field.setShort(parent, newFieldValue); 351 } catch (IllegalArgumentException e) { 352 throw new IllegalStateException("Problem argument for field {" + super.field.getName() + "} of object {" 353 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 354 } catch (IllegalAccessException e) { 355 throw new IllegalStateException("Problem accessing for field {" + super.field.getName() + "} of object {" 356 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 357 } 358 } 359 } 360 361 /** 362 * PortableFieldAccess implementation suitable for accessing int fields 363 * @param <C> The Class containing the Field to be accessed 364 */ 365 public static class PortableIntFieldAccess<C> extends PortableFieldAccess<C> { 366 367 /** 368 * Construct a new instance for the given Field 369 * @param f The Field to be accessed 370 */ 371 public PortableIntFieldAccess(Field f) { 372 super(f); 373 } 374 375 @Override 376 public int getIntValue(C parent) { 377 try { 378 return super.field.getInt(parent); 379 } catch (IllegalArgumentException e) { 380 throw new IllegalStateException("Problem target object {" + super.field.getName() + "} of object {" 381 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 382 } catch (IllegalAccessException e) { 383 throw new IllegalStateException("Problem accessing {" + super.field.getName() + "} of object {" 384 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 385 } 386 387 } 388 389 @Override 390 public void putIntValue(C parent, int newFieldValue) { 391 try { 392 super.field.setInt(parent, newFieldValue); 393 } catch (IllegalArgumentException e) { 394 throw new IllegalStateException("Problem argument for field {" + super.field.getName() + "} of object {" 395 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 396 } catch (IllegalAccessException e) { 397 throw new IllegalStateException("Problem accessing for field {" + super.field.getName() + "} of object {" 398 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 399 } 400 } 401 } 402 403 /** 404 * PortableFieldAccess implementation suitable for accessing long fields 405 * @param <C> The Class containing the Field to be accessed 406 */ 407 public static class PortableLongFieldAccess<C> extends PortableFieldAccess<C> { 408 409 /** 410 * Construct a new instance for the given Field 411 * @param f The Field to be accessed 412 */ 413 public PortableLongFieldAccess(Field f) { 414 super(f); 415 } 416 417 @Override 418 public long getLongValue(C parent) { 419 try { 420 return super.field.getLong(parent); 421 } catch (IllegalArgumentException e) { 422 throw new IllegalStateException("Problem target object {" + super.field.getName() + "} of object {" 423 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 424 } catch (IllegalAccessException e) { 425 throw new IllegalStateException("Problem accessing {" + super.field.getName() + "} of object {" 426 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 427 } 428 429 } 430 431 @Override 432 public void putLongValue(C parent, long newFieldValue) { 433 try { 434 super.field.setLong(parent, newFieldValue); 435 } catch (IllegalArgumentException e) { 436 throw new IllegalStateException("Problem argument for field {" + super.field.getName() + "} of object {" 437 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 438 } catch (IllegalAccessException e) { 439 throw new IllegalStateException("Problem accessing for field {" + super.field.getName() + "} of object {" 440 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 441 } 442 } 443 } 444 445 /** 446 * PortableFieldAccess implementation suitable for accessing float fields 447 * @param <C> The Class containing the Field to be accessed 448 */ 449 public static class PortableFloatFieldAccess<C> extends PortableFieldAccess<C> { 450 451 /** 452 * Construct a new instance for the given Field 453 * @param f The Field to be accessed 454 */ 455 public PortableFloatFieldAccess(Field f) { 456 super(f); 457 } 458 459 @Override 460 public float getFloatValue(C parent) { 461 try { 462 return super.field.getFloat(parent); 463 } catch (IllegalArgumentException e) { 464 throw new IllegalStateException("Problem target object {" + super.field.getName() + "} of object {" 465 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 466 } catch (IllegalAccessException e) { 467 throw new IllegalStateException("Problem accessing {" + super.field.getName() + "} of object {" 468 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 469 } 470 471 } 472 473 @Override 474 public void putFloatValue(C parent, float newFieldValue) { 475 try { 476 super.field.setFloat(parent, newFieldValue); 477 } catch (IllegalArgumentException e) { 478 throw new IllegalStateException("Problem argument for field {" + super.field.getName() + "} of object {" 479 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 480 } catch (IllegalAccessException e) { 481 throw new IllegalStateException("Problem accessing for field {" + super.field.getName() + "} of object {" 482 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 483 } 484 } 485 } 486 487 /** 488 * PortableFieldAccess implementation suitable for accessing double fields 489 * @param <C> The Class containing the Field to be accessed 490 */ 491 public static class PortableDoubleFieldAccess<C> extends PortableFieldAccess<C> { 492 493 /** 494 * Construct a new instance for the given Field 495 * @param f The Field to be accessed 496 */ 497 public PortableDoubleFieldAccess(Field f) { 498 super(f); 499 } 500 501 @Override 502 public double getDoubleValue(C parent) { 503 try { 504 return super.field.getDouble(parent); 505 } catch (IllegalArgumentException e) { 506 throw new IllegalStateException("Problem target object {" + super.field.getName() + "} of object {" 507 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 508 } catch (IllegalAccessException e) { 509 throw new IllegalStateException("Problem accessing {" + super.field.getName() + "} of object {" 510 + System.identityHashCode(parent) + "}: " + e.getMessage(), e); 511 } 512 513 } 514 515 @Override 516 public void putDoubleValue(C parent, double newFieldValue) { 517 try { 518 super.field.setDouble(parent, newFieldValue); 519 } catch (IllegalArgumentException e) { 520 throw new IllegalStateException("Problem argument for field {" + super.field.getName() + "} of object {" 521 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 522 } catch (IllegalAccessException e) { 523 throw new IllegalStateException("Problem accessing for field {" + super.field.getName() + "} of object {" 524 + System.identityHashCode(newFieldValue) + "}: " + e.getMessage(), e); 525 } 526 } 527 } 528}