gt:         return isAllowedInSectionLevel(sectionName, privilegeName);
context: package teammates.common.datatransfer;
  
  import java.util.Arrays;
  import java.util.LinkedHashMap;
  import java.util.LinkedHashSet;
  import java.util.Map;
  import java.util.Set;
  
  import teammates.common.util.Assumption;
  import teammates.common.util.Const;
  
  /**
   * Representation of instructor privileges. Store the privileges of the instructor
   */
  public final class InstructorPrivileges {
  
      private static final Map<String, Boolean> PRIVILEGES_COOWNER = new LinkedHashMap<>();
      private static final Map<String, Boolean> PRIVILEGES_MANAGER = new LinkedHashMap<>();
      private static final Map<String, Boolean> PRIVILEGES_OBSERVER = new LinkedHashMap<>();
      private static final Map<String, Boolean> PRIVILEGES_TUTOR = new LinkedHashMap<>();
      private static final Map<String, Boolean> PRIVILEGES_CUSTOM = new LinkedHashMap<>();
  
      static {
          PRIVILEGES_COOWNER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_COURSE, true);
          PRIVILEGES_COOWNER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_INSTRUCTOR, true);
          PRIVILEGES_COOWNER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_SESSION, true);
          PRIVILEGES_COOWNER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_STUDENT, true);
          PRIVILEGES_COOWNER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_STUDENT_IN_SECTIONS, true);
          PRIVILEGES_COOWNER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_SESSION_IN_SECTIONS, true);
          PRIVILEGES_COOWNER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_SUBMIT_SESSION_IN_SECTIONS, true);
          PRIVILEGES_COOWNER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_SESSION_COMMENT_IN_SECTIONS, true);
  
          PRIVILEGES_MANAGER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_COURSE, false);
          PRIVILEGES_MANAGER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_INSTRUCTOR, true);
          PRIVILEGES_MANAGER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_SESSION, true);
          PRIVILEGES_MANAGER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_STUDENT, true);
          PRIVILEGES_MANAGER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_STUDENT_IN_SECTIONS, true);
          PRIVILEGES_MANAGER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_SESSION_IN_SECTIONS, true);
          PRIVILEGES_MANAGER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_SUBMIT_SESSION_IN_SECTIONS, true);
          PRIVILEGES_MANAGER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_SESSION_COMMENT_IN_SECTIONS, true);
  
          PRIVILEGES_OBSERVER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_COURSE, false);
          PRIVILEGES_OBSERVER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_INSTRUCTOR, false);
          PRIVILEGES_OBSERVER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_SESSION, false);
          PRIVILEGES_OBSERVER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_STUDENT, false);
          PRIVILEGES_OBSERVER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_STUDENT_IN_SECTIONS, true);
          PRIVILEGES_OBSERVER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_SESSION_IN_SECTIONS, true);
          PRIVILEGES_OBSERVER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_SUBMIT_SESSION_IN_SECTIONS, false);
          PRIVILEGES_OBSERVER.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_SESSION_COMMENT_IN_SECTIONS, false);
  
          PRIVILEGES_TUTOR.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_COURSE, false);
          PRIVILEGES_TUTOR.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_INSTRUCTOR, false);
          PRIVILEGES_TUTOR.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_SESSION, false);
          PRIVILEGES_TUTOR.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_STUDENT, false);
          PRIVILEGES_TUTOR.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_STUDENT_IN_SECTIONS, true);
          PRIVILEGES_TUTOR.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_SESSION_IN_SECTIONS, true);
          PRIVILEGES_TUTOR.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_SUBMIT_SESSION_IN_SECTIONS, true);
          PRIVILEGES_TUTOR.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_SESSION_COMMENT_IN_SECTIONS, false);
  
          PRIVILEGES_CUSTOM.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_COURSE, false);
          PRIVILEGES_CUSTOM.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_INSTRUCTOR, false);
          PRIVILEGES_CUSTOM.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_SESSION, false);
          PRIVILEGES_CUSTOM.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_STUDENT, false);
          PRIVILEGES_CUSTOM.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_STUDENT_IN_SECTIONS, false);
          PRIVILEGES_CUSTOM.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_SESSION_IN_SECTIONS, false);
          PRIVILEGES_CUSTOM.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_SUBMIT_SESSION_IN_SECTIONS, false);
          PRIVILEGES_CUSTOM.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_SESSION_COMMENT_IN_SECTIONS, false);
      }
  
      private static final String[] COURSE_LEVEL_ONLY_LIST = new String[] {
              Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_COURSE,
              Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_INSTRUCTOR,
              Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_SESSION,
              Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_STUDENT
      };
  
      private static final String[] SECTION_LEVEL_ONLY_LIST = new String[] {
              Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_STUDENT_IN_SECTIONS,
      };
  
      private static final String[] SESSION_LEVEL_ONLY_LIST = new String[] {
              Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_SESSION_IN_SECTIONS,
              Const.ParamsNames.INSTRUCTOR_PERMISSION_SUBMIT_SESSION_IN_SECTIONS,
              Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_SESSION_COMMENT_IN_SECTIONS
      };
  
      private static final Set<String> COURSE_LEVEL_ONLY_PRIVILEGES =
              new LinkedHashSet<String>(Arrays.asList(COURSE_LEVEL_ONLY_LIST));
      private static final Set<String> SECTION_LEVEL_ONLY_PRIVILEGES =
              new LinkedHashSet<String>(Arrays.asList(SECTION_LEVEL_ONLY_LIST));
      private static final Set<String> SESSION_LEVEL_ONLY_PRIVILEGES =
              new LinkedHashSet<String>(Arrays.asList(SESSION_LEVEL_ONLY_LIST));
  
      private Map<String, Boolean> courseLevel;
      private Map<String, Map<String, Boolean>> sectionLevel;
      private Map<String, Map<String, Map<String, Boolean>>> sessionLevel;
  
      public InstructorPrivileges() {
          this.courseLevel = new LinkedHashMap<String, Boolean>();
          this.sectionLevel = new LinkedHashMap<String, Map<String, Boolean>>();
          this.sessionLevel = new LinkedHashMap<String, Map<String, Map<String, Boolean>>>();
      }
  
      public InstructorPrivileges(String instrRole) {
          this();
          switch (instrRole) {
          case Const.InstructorPermissionRoleNames.INSTRUCTOR_PERMISSION_ROLE_COOWNER:
              setDefaultPrivilegesForCoowner();
              break;
          case Const.InstructorPermissionRoleNames.INSTRUCTOR_PERMISSION_ROLE_MANAGER:
              setDefaultPrivilegesForManager();
              break;
          case Const.InstructorPermissionRoleNames.INSTRUCTOR_PERMISSION_ROLE_OBSERVER:
              setDefaultPrivilegesForObserver();
              break;
          case Const.InstructorPermissionRoleNames.INSTRUCTOR_PERMISSION_ROLE_TUTOR:
              setDefaultPrivilegesForTutor();
              break;
          case Const.InstructorPermissionRoleNames.INSTRUCTOR_PERMISSION_ROLE_CUSTOM:
              setDefaultPrivilegesForCustom();
              break;
          default:
              setDefaultPrivilegesForCustom();
              break;
          }
      }
  
      public static boolean isPrivilegeNameValid(String privilegeName) {
          return COURSE_LEVEL_ONLY_PRIVILEGES.contains(privilegeName)
                  || SECTION_LEVEL_ONLY_PRIVILEGES.contains(privilegeName)
                  || SESSION_LEVEL_ONLY_PRIVILEGES.contains(privilegeName);
      }
  
      public static boolean isPrivilegeNameValidForSectionLevel(String privilegeName) {
          return SECTION_LEVEL_ONLY_PRIVILEGES.contains(privilegeName)
                  || SESSION_LEVEL_ONLY_PRIVILEGES.contains(privilegeName);
      }
  
      public static boolean isPrivilegeNameValidForSessionLevel(String privilegeName) {
          return SESSION_LEVEL_ONLY_PRIVILEGES.contains(privilegeName);
      }
  
      public void setDefaultPrivilegesForCoowner() {
          setDefaultPrivileges(PRIVILEGES_COOWNER);
      }
  
      public void setDefaultPrivilegesForManager() {
          setDefaultPrivileges(PRIVILEGES_MANAGER);
      }
  
      public void setDefaultPrivilegesForObserver() {
          setDefaultPrivileges(PRIVILEGES_OBSERVER);
      }
  
      public void setDefaultPrivilegesForTutor() {
          setDefaultPrivileges(PRIVILEGES_TUTOR);
      }
  
      public void setDefaultPrivilegesForCustom() {
          setDefaultPrivileges(PRIVILEGES_CUSTOM);
      }
  
      private void setDefaultPrivileges(Map<String, Boolean> defaultPrivileges) {
          for (Map.Entry<String, Boolean> entry : defaultPrivileges.entrySet()) {
              courseLevel.put(entry.getKey(), entry.getValue());
          }
      }
  
      public Map<String, Boolean> getOverallPrivilegesForSections() {
          Map<String, Boolean> privileges = new LinkedHashMap<String, Boolean>();
  
          privileges.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_STUDENT_IN_SECTIONS,
                  isAllowedInCourseLevel(Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_STUDENT_IN_SECTIONS));
  
          privileges.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_SESSION_IN_SECTIONS,
                  isAllowedInCourseLevel(Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_SESSION_IN_SECTIONS));
          privileges.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_SUBMIT_SESSION_IN_SECTIONS,
                  isAllowedInCourseLevel(Const.ParamsNames.INSTRUCTOR_PERMISSION_SUBMIT_SESSION_IN_SECTIONS));
          privileges.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_SESSION_COMMENT_IN_SECTIONS,
                  isAllowedInCourseLevel(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_SESSION_COMMENT_IN_SECTIONS));
  
          return privileges;
      }
  
      public Map<String, Boolean> getOverallPrivilegesForSessionsInSection(String sectionName) {
          Map<String, Boolean> privileges = new LinkedHashMap<String, Boolean>();
  
          privileges.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_SESSION_IN_SECTIONS,
                  isAllowedInSectionLevel(sectionName, Const.ParamsNames.INSTRUCTOR_PERMISSION_VIEW_SESSION_IN_SECTIONS));
          privileges.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_SUBMIT_SESSION_IN_SECTIONS,
                  isAllowedInSectionLevel(sectionName, Const.ParamsNames.INSTRUCTOR_PERMISSION_SUBMIT_SESSION_IN_SECTIONS));
          privileges.put(Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_SESSION_COMMENT_IN_SECTIONS,
                  isAllowedInSectionLevel(sectionName,
                                          Const.ParamsNames.INSTRUCTOR_PERMISSION_MODIFY_SESSION_COMMENT_IN_SECTIONS));
  
          return privileges;
      }
  
      /**
       * Sets privilege for the privilege specified by privilegeName.
       */
      public void updatePrivilege(String privilegeName, boolean isAllowed) {
          updatePrivilegeInCourseLevel(privilegeName, isAllowed);
      }
  
      /**
       * Sets privilege for the privilege specified by privilegeName for sectionName.
       */
      public void updatePrivilege(String sectionName, String privilegeName, boolean isAllowed) {
          updatePrivilegeInSectionLevel(sectionName, privilegeName, isAllowed);
      }
  
      /**
       * Sets privilege for the privilege specified by privilegeName for sessionName in sectionName.
       */
      public void updatePrivilege(String sectionName, String sessionName, String privilegeName, boolean isAllowed) {
          updatePrivilegeInSessionLevel(sectionName, sessionName, privilegeName, isAllowed);
      }
  
      private void updatePrivilegeInCourseLevel(String privilegeName, boolean isAllowed) {
          if (!isPrivilegeNameValid(privilegeName)) {
              return;
          }
          this.courseLevel.put(privilegeName, isAllowed);
      }
  
      private void updatePrivilegeInSectionLevel(String sectionName, String privilegeName, boolean isAllowed) {
          if (!isPrivilegeNameValidForSectionLevel(privilegeName)) {
              return;
          }
          if (!this.sectionLevel.containsKey(sectionName)) {
              sectionLevel.put(sectionName, new LinkedHashMap<String, Boolean>());
          }
          sectionLevel.get(sectionName).put(privilegeName, isAllowed);
      }
  
      private void updatePrivilegeInSessionLevel(String sectionName, String sessionName,
                                                 String privilegeName, boolean isAllowed) {
          if (!isPrivilegeNameValidForSessionLevel(privilegeName)) {
              return;
          }
          verifyExistenceOfsectionName(sectionName);
          if (!this.sessionLevel.get(sectionName).containsKey(sessionName)) {
              this.sessionLevel.get(sectionName).put(sessionName, new LinkedHashMap<String, Boolean>());
          }
          this.sessionLevel.get(sectionName).get(sessionName).put(privilegeName, isAllowed);
      }
  
      public void updatePrivileges(String sectionName, Map<String, Boolean> privileges) {
          updatePrivilegesInSectionLevel(sectionName, privileges);
      }
  
      public void updatePrivileges(String sectionName, String sessionName, Map<String, Boolean> privileges) {
          updatePrivilegesInSessionLevel(sectionName, sessionName, privileges);
      }
  
      private void updatePrivilegesInSectionLevel(String sectionName, Map<String, Boolean> privileges) {
          for (String privilegeName : privileges.keySet()) {
              if (!isPrivilegeNameValidForSectionLevel(privilegeName)) {
                  return;
              }
          }
          sectionLevel.put(sectionName, new LinkedHashMap<String, Boolean>(privileges));
      }
  
      private void updatePrivilegesInSessionLevel(String sectionName, String sessionName,
                                                  Map<String, Boolean> privileges) {
          for (String privilegeName : privileges.keySet()) {
              if (!isPrivilegeNameValidForSessionLevel(privilegeName)) {
                  return;
              }
          }
          verifyExistenceOfsectionName(sectionName);
          this.sessionLevel.get(sectionName).put(sessionName, new LinkedHashMap<String, Boolean>(privileges));
      }
  
      private void verifyExistenceOfsectionName(String sectionName) {
          if (!this.sessionLevel.containsKey(sectionName)) {
              addSectionWithDefaultPrivileges(sectionName);
              this.sessionLevel.put(sectionName, new LinkedHashMap<String, Map<String, Boolean>>());
          }
      }
  
      public void addSectionWithDefaultPrivileges(String sectionName) {
          if (this.sectionLevel.containsKey(sectionName)) {
              return;
          }
          this.sectionLevel.put(sectionName, getOverallPrivilegesForSections());
      }
  
      public void addSessionWithDefaultPrivileges(String sectionName, String sessionName) {
          verifyExistenceOfsectionName(sectionName);
          if (this.sessionLevel.get(sectionName).containsKey(sessionName)) {
              return;
          }
          this.sessionLevel.get(sectionName).put(sessionName, getOverallPrivilegesForSessionsInSection(sectionName));
      }
  
      /**
       * Returns true if it is allowed for the privilege specified by privilegeName.
       */
      public boolean isAllowedForPrivilege(String privilegeName) {
          return isAllowedInCourseLevel(privilegeName);
      }
  
      /**
       * Returns true if it is allowed for the privilege specified by privilegeName in sectionName.
       */
      public boolean isAllowedForPrivilege(String sectionName, String privilegeName) {
  