How to calculate the count of null field from the model dynamically using java



How to calculate profile completion percentage? Refer to the below Profile model file, Each attribute is another model(EX: BasicInfo has some 15 elements, need to take the count of this and then finally adding the count of this one to Profile total count) . I need to get BasicInfo count dynamically without adding if condition check for all fields. Refer the below code

Logic:

  1. Each attribute has a weight of 1
  2. There are 13 elements in Profile
  3. Each attribute has many elements (assuming BasicInfo has 15 and user has filled 10), then you should return 10/15 = 0.67
  4. Then sum all of the attributes and divide by 13.

// model sample

Profile.java

    private BasicInfo basicInfo;

    private ReligionInfo religionInfo;

    private LocationInfo locationInfo;

    private ProfessionalInfo professionalInfo;

    private FamilyInfo familyInfo;

    private LifestyleInfo lifestyleInfo;

    private Configuration configuration;

    private BasicPreferences basicPreferences;

    private ReligionPreferences religionPreferences;

    private LocationPreferences locationPreferences;

    private ProfessionalPreferences professionalPreferences;

// What I tried

public long getProfileList(String id) {
   Profile profile = findById(id);
    int count = getBasicInfo(profile);
   
    
    return count;
    }
  
  private int getBasicInfo(Profile profile) {
      
        int counter = 0;
        if (ObjectUtils.isEmpty(profile.getBasicInfo().getBirthDate())) {
            counter++;
        }

        if (ObjectUtils.isEmpty(profile.getBasicInfo().getDobt())) {
            counter++;
        }
        
        return counter;
    }

Answer

Have you tried reflection? You can get all the declared fields of a class. I coded a tiny method to filter nulls as you asked

import java.util.*;
import java.util.stream.*;
import java.lang.reflect.Field;

class Example {
   private String emptyField;
   private String emptyField2;
   private String nonNullField = "non null";
}

public class Main {

    static boolean isFieldNull(Field field, Object obj) {
        try {
            return Objects.isNull(field.get(obj));
        } catch(IllegalAccessException ignored) {
            return false;
        }
    }

    public static void main (String[] args) {
        Example main = new Example();
        Field[] fields = Example.class.getDeclaredFields();

        //For getting access to private fields
        Arrays.stream(fields).forEach(f -> f.setAccessible(true));

        System.out.println(Arrays.stream(fields)
            .filter(f -> isFieldNull(f, main))
            .count());

    }

Here’s the output of this code

   java -classpath .:/run_dir/junit-4.12.jar:target/dependency/* Main
   2


Source: stackoverflow