To recover from [yesterdays disaster][1], I re-read the SOLID principles and refactored my code. Hopfully I did a better job than yesterday. I wanted to keep my Student class immutable, but that meant I would have to change the class everytime a new Student type was introduced, that violated the S in SOLID. Here is what I came up with.

    public interface StudentStatus {
    	Collection<String> retrieveDocuments();
    	StudentType retrieveStatus();
    }

    public final class Student {
	
	   private final String ID;
	   private final String firstname;
	   private final String lastname;
	   private final StudentStatus status;
	
	   public Student(String iD, String firstname, String lastname, StudentStatus status) {
		   ID = iD;
		   this.firstname = firstname;
		   this.lastname = lastname;
		   this.status = status;
	   }

	   public Collection<String> retrieveDocuments() {
		   return status.retrieveDocuments();
	   }

	   public StudentType retrieveStatus() {
		  return status.retrieveStatus();
	   }

My requirements are:

 - Domestic students don't require documentation
 - International student do require documentation (passports, etc..)

Domestic Implementation:

        public final class Domestic implements StudentStatus {
    
    	   private final StudentType type;
    	   private final Collection<String> documents;
    
    	   public Domestic() {
    		   this.type = StudentType.Domestic;
    		   this.documents = Collections.emptyList();
    	   }
    	
    	   @Override
    	   public Collection<String> retrieveDocuments() {
    		   return this.documents;
    	   }
    
    	   @Override
    	   public StudentType retrieveStatus() {
    		   return type;
    	   }
       }
International Implementation:

        public final class International implements StudentStatus {
    	    	
    	   private final StudentType type;
    	   private Collection<String> documents;
    	
    	   public International(Collection<String> documents) {
    		
    		   this.type = StudentType.International;
    		   this.documents = Collections.unmodifiableCollection(documents);
    	   }
    
    	   @Override
    	   public Collection<String> retrieveDocuments() {
    		   return Collections.unmodifiableCollection(documents);
    	   }
    
    	   @Override
    	   public StudentType retrieveStatus() {
    		  return type;
    	   }
        }
If there is any new type of status, it can be added my implementing `StudentStatus`, no need to modify the `Student` class. 

Use:

            List<String> documents = new ArrayList<String>();
    		documents.add("Passport");
    		documents.add("Drivers License");
    		
    		StudentStatus domestic = new Domestic();
    		StudentStatus international = new International(documents);
    		
    		List<Student> students = new ArrayList<Student>();
    		students.add(new Student("123456789","Susan","Ceesharp", domestic));
    		students.add(new Student("987654321","Bill","Finalclass", international));
    		
    		for(Student display : students) {
    			System.out.println(display.getID() + " " + display.retrieveStatus());
    		}

I'm aware none of my classes have validation, I kept these out to keep my code clear and concise. 

**Goal:**
Keep the Student immutable without violating SOLID. 

  [1]: https://codereview.stackexchange.com/questions/178874/creating-immutable-student-object