private Function<Object, Object> getFieldAccessor(Class<?> entityClass, String fieldName) { return getAccessorByPublicField(entityClass, fieldName) .orElseGet(() -> getAccessorByPropertyDescriptor(entityClass, fieldName) .orElseGet(() -> getAccessorByPrivateField(entityClass, fieldName).orElse(null))); }
private Class<?> getAccessorTarget(Class<?> entityClass, String fieldName) { try { return entityClass.getDeclaredField(fieldName).getType(); } catch (NoSuchFieldException | SecurityException e) { if (entityClass.getSuperclass() != Object.class) { return getAccessorTarget(entityClass.getSuperclass(), fieldName); } traceError(fieldName, entityClass, e); return null; } }
public Function<Object, Object> getAccessor(Class<?> entityClass, String fieldPath) { if (!fieldPath.contains(".")) { return getFieldAccessor(entityClass, fieldPath); } return getComposedAccessor(entityClass, fieldPath); }
private Optional<Function<Object, Object>> getAccessorByPublicField(Class<?> entityClass, String fieldName) { try { Field field = entityClass.getField(fieldName); if (field.isAccessible()) { return newAccessorByField(field); } } catch (NoSuchFieldException | SecurityException e) { traceAccess(fieldName, entityClass, e); } return Optional.empty(); }
@Test public void mainFieldAccessTest() { Function<Object, Object> accessorId = factory.getAccessor(Person.class, "id"); assertEquals(1L, accessorId.apply(person)); Function<Object, Object> accessorName = factory.getAccessor(Person.class, "name"); assertEquals("Sherlock Holmes", accessorName.apply(person)); }
private Optional<Function<Object, Object>> getAccessorByPrivateField(Class<?> entityClass, String fieldName) { try { Field field = entityClass.getDeclaredField(fieldName); field.setAccessible(true); return newAccessorByField(field); } catch (NoSuchFieldException | SecurityException e) { if (entityClass.getSuperclass() != Object.class) { return getAccessorByPrivateField(entityClass.getSuperclass(), fieldName); } traceAccess(fieldName, entityClass, e); } return Optional.empty(); }
public EntityInfo inspect() { JpaFieldsInspector fieldsInspector = new JpaFieldsInspector(); List<FieldInfo> fieldsFromClass = fieldsInspector.getFieldsFromClass(entityClass); EntityFieldAccesorFactory factory = new EntityFieldAccesorFactory(); List<ColumnInfo> columns = fieldsFromClass.stream().map(field -> { Function<Object, Object> accessor = factory.getAccessor(entityClass, field.getFieldName()); return new ColumnInfo(field.getColumnName(), field.getFieldType(), accessor); }).collect(Collectors.toList()); return new EntityInfo(entityClass, getTableName(), columns); }
private Function<Object, Object> getComposedAccessor(Class<?> entityClass, String fieldNameSeq) { String[] fieldSeq = fieldNameSeq.split("\\."); ComposedEntityFieldAccessor head = new ComposedEntityFieldAccessor(); ComposedEntityFieldAccessor composed = head; for (int i = 0; i < fieldSeq.length; i++) { String fieldName = fieldSeq[i]; Function<Object, Object> accessor = getFieldAccessor(entityClass, fieldName); if (i < fieldSeq.length - 1) { composed = composed.andThenApply(accessor); entityClass = getAccessorTarget(entityClass, fieldName); if (entityClass == null) { return null; } } else { composed.andFinally(accessor); } } return head; }
private Optional<Function<Object, Object>> newAccessorByField(Field field) { return Optional.of(obj -> { try { return field.get(obj); } catch (IllegalArgumentException | IllegalAccessException e) { traceAccess(field.getName(), field.getDeclaringClass(), e); return null; } }); }
@Test public void embeddedFieldAccessTest() { Function<Object, Object> accessorStreet = factory.getAccessor(Person.class, "address.street"); assertEquals("221b Baker St", accessorStreet.apply(person)); Function<Object, Object> accessorCity = factory.getAccessor(Person.class, "address.city"); assertEquals("London", accessorCity.apply(person)); }
@Test public void parentFieldOnHierarchy() { Function<Object, Object> accessor = factory.getAccessor(ChildClass.class, "beanField"); assertEquals("bean value", accessor.apply(instanceChild)); }
@Test public void beanFieldOnPublicClassTest() { Function<Object, Object> accessor = factory.getAccessor(PublicClass.class, "beanField"); assertEquals("bean", accessor.apply(instancePublic)); }
@Test public void parentPublicFieldOnHierarchy() { Function<Object, Object> accessor = factory.getAccessor(ChildClass.class, "publicField"); assertEquals("public one", accessor.apply(instanceChild)); }
@Test public void beanFieldOnPackageClassTest() { Function<Object, Object> accessor = factory.getAccessor(PackageClass.class, "beanField"); assertEquals("bean", accessor.apply(instancePackage)); }
@Test public void publicFieldOnPrivateClassTest() { Function<Object, Object> accessor = factory.getAccessor(PrivateClass.class, "publicField"); assertEquals("public", accessor.apply(instancePrivate)); }
@Test public void privateFieldOnPublicClassTest() { Function<Object, Object> accessor = factory.getAccessor(PublicClass.class, "privateField"); assertEquals("private", accessor.apply(instancePublic)); }
@Test public void privateFieldOnPackageClassTest() { Function<Object, Object> accessor = factory.getAccessor(PackageClass.class, "privateField"); assertEquals("private", accessor.apply(instancePackage)); }
@Test public void childFieldOnHierarchy() { Function<Object, Object> accessor = factory.getAccessor(ChildClass.class, "otherField"); assertEquals(1, accessor.apply(instanceChild)); }
@Test public void composedField() { Function<Object, Object> accessor = factory.getAccessor(ManyToOneClass.class, "reference.privateField"); assertEquals("private", accessor.apply(intanceManyToOne)); }
@Test public void publicFieldOnPublicClassTest() { Function<Object, Object> accessor = factory.getAccessor(PublicClass.class, "publicField"); assertEquals("public", accessor.apply(instancePublic)); }