public void addNewPastMeeting(Set<Contact> contacts, Calendar date, String text) {
   Calendar now = new GregorianCalendar();
   if (contacts.isEmpty() || !contactSet.containsAll(contacts)) {
     throw new IllegalArgumentException("One or more Contacts do not exist OR set is empty");
   } else if (contacts == null || date == null || text == null) {
     throw new NullPointerException("One or more arguments are null");
   } else if (date.after(now)) {
     throw new IllegalArgumentException("Cannot create a past meeting with a future date!");
   } else // an exception hasn't been thrown, so we can add the meeting
   {
     PastMeeting pastMeeting = new PastMeetingImpl(meetingIdAssigner(), contacts, date);
     /**
      * @see PastMeetingImpl#addNotes(String) use this method to add notes to avoid unnecessary
      *     code duplication
      */
     ((PastMeetingImpl) pastMeeting).addNotes(text);
     meetingSet.add(pastMeeting); // add to main meeting set AFTER notes are added
     pastMeetings.add(pastMeeting); // add to list of past meetings AFTER notes are added
   }
 }
  /**
   * This method is used EITHER: when a future meeting happens, and is then converted to a past
   * meeting (with notes), OR: to add notes to a past meeting at a date after its creation.
   */
  public void addMeetingNotes(int id, String text) {
    Meeting meeting = getMeeting(id); // find meeting by id - will be null if doesn't exist

    if (meeting == null) {
      throw new IllegalArgumentException("Specified meeting does not exist!");
    } else if (text == null) {
      throw new NullPointerException("Cannot add null string of notes");
    } else if (((MeetingImpl) meeting).inFuture() == true) {
      throw new IllegalStateException(
          "Meeting set for date in the future - not eligible for conversion!");
    } else if (meeting instanceof FutureMeeting) // we know it's a future meeting needing conversion
    {
      /**
       * @param convertedMeeting name to indicate the original FutureMeeting type is now a
       *     PastMeeting the 0 id field (an impossible id) is a flag to let us know whether or not
       *     it goes through the for loop if statement
       */
      Set<Contact> set =
          new HashSet<
              Contact>(); // to use for our empty convertedMeeting, to avoid a NullPointerException
      PastMeeting convertedMeeting = new PastMeetingImpl(0, set, null);
      for (FutureMeeting fm : futureMeetings) {
        if (fm.getId() == id) {
          /**
           * convertedMeeting is now re-constructed with proper values, which shows that we have an
           * id match
           */
          convertedMeeting = new PastMeetingImpl(fm.getId(), fm.getContacts(), fm.getDate());
        }
      }
      if (convertedMeeting.getId()
          == 0) // i.e. we haven't had an id match (got into the for loop if statement)
      {
        throw new IllegalArgumentException("Couldn't find meeting in list of meetings!");
      } else // we know that convertedMeeting has been through the for loop if statement, so can add
      // it to our sets/lists
      {
        meetingSet.remove(meeting); // remove the old FutureMeeting from main meeting set
        futureMeetings.remove(meeting); // remove the old FutureMeeting from list of future meetings
        pastMeetings.add(convertedMeeting); // add the new PastMeeting to list of past meetings
        meetingSet.add(convertedMeeting); // add the new PastMeeting to main meeting set
        /**
         * here we call this method again to add the notes to our new PastMeeting object, knowing it
         * will drop through to the else if below (as it is now an instanceof PastMeeting)
         */
        addMeetingNotes(convertedMeeting.getId(), text);
      }
    } else if (meeting
        instanceof
        PastMeeting) // this will catch cases where we just want to add notes to a PastMeeting
    // (including the convertedMeeting)
    {
      for (PastMeeting pm : pastMeetings) {
        if (pm.getId() == id) {
          meetingSet.remove(
              meeting); // remove the old PastMeeting (without new note) from list of past meetings
          pastMeetings.remove(
              pm); // add the new PastMeeting (without new note) from list of past meetings
          /**
           * @see PastMeetingImpl#addNotes(String) use this method to actually add notes to avoid
           *     unnecessary code duplication
           */
          ((PastMeetingImpl) pm).addNotes(text);
          pastMeetings.add(pm); // add the new PastMeeting (with new note) to list of past meetings
          meetingSet.add(pm); // add the new PastMeeting (with new note) to main meeting set
        } else {
          throw new IllegalArgumentException("Couldn't find meeting in list of meetings!");
        }
      }
    }
  }