gt:         if (questionDescription == null) {
context: package teammates.common.datatransfer;
  
  import java.util.ArrayList;
  import java.util.Date;
  import java.util.List;
  
  import org.json.JSONException;
  import org.json.JSONObject;
  
  import teammates.common.util.Const;
  import teammates.common.util.FieldValidator;
  import teammates.common.util.JsonUtils;
  import teammates.common.util.Sanitizer;
  import teammates.storage.entity.FeedbackQuestion;
  
  import com.google.appengine.api.datastore.Text;
  
  public class FeedbackQuestionAttributes extends EntityAttributes implements Comparable<FeedbackQuestionAttributes> {
      public String feedbackSessionName;
      public String courseId;
      public String creatorEmail;
      /** 
       * Contains the JSON formatted string that holds the information of the question details <br>
       * Don't use directly unless for storing/loading from data store <br>
       * To get the question text use {@code getQuestionDetails().questionText}
       */
      public Text questionMetaData;
      public Text questionDescription;
      public int questionNumber;
      public FeedbackQuestionType questionType;
      public FeedbackParticipantType giverType;
      public FeedbackParticipantType recipientType;
      public int numberOfEntitiesToGiveFeedbackTo;
      public List<FeedbackParticipantType> showResponsesTo;
      public List<FeedbackParticipantType> showGiverNameTo;
      public List<FeedbackParticipantType> showRecipientNameTo;
      protected transient Date createdAt;
      protected transient Date updatedAt;
      private String feedbackQuestionId;
  
      public FeedbackQuestionAttributes() {
          // attributes to be set after construction
      }
  
      public FeedbackQuestionAttributes(FeedbackQuestion fq) {
          this.feedbackQuestionId = fq.getId();
          this.feedbackSessionName = fq.getFeedbackSessionName();
          this.courseId = fq.getCourseId();
          this.creatorEmail = fq.getCreatorEmail();
          this.questionMetaData = fq.getQuestionMetaData();
          this.questionDescription = Sanitizer.sanitizeForRichText(fq.getQuestionDescription());
          this.questionNumber = fq.getQuestionNumber();
          this.questionType = fq.getQuestionType();
          this.giverType = fq.getGiverType();
          this.recipientType = fq.getRecipientType();
          this.numberOfEntitiesToGiveFeedbackTo = fq.getNumberOfEntitiesToGiveFeedbackTo();
          this.showResponsesTo = new ArrayList<FeedbackParticipantType>(fq.getShowResponsesTo());
          this.showGiverNameTo = new ArrayList<FeedbackParticipantType>(fq.getShowGiverNameTo());
          this.showRecipientNameTo = new ArrayList<FeedbackParticipantType>(fq.getShowRecipientNameTo());
          
          this.createdAt = fq.getCreatedAt();
          this.updatedAt = fq.getUpdatedAt();
          
          removeIrrelevantVisibilityOptions();
      }
  
      private FeedbackQuestionAttributes(FeedbackQuestionAttributes other) {
          this.feedbackQuestionId = other.getId();
          this.feedbackSessionName = other.getFeedbackSessionName();
          this.courseId = other.getCourseId();
          this.creatorEmail = other.getCreatorEmail();
          this.questionMetaData = other.getQuestionMetaData();
          this.questionNumber = other.getQuestionNumber();
          this.questionType = other.getQuestionType();
          this.giverType = other.getGiverType();
          this.recipientType = other.getRecipientType();
          this.numberOfEntitiesToGiveFeedbackTo = other.getNumberOfEntitiesToGiveFeedbackTo();
          this.showResponsesTo = new ArrayList<FeedbackParticipantType>(other.getShowResponsesTo());
          this.showGiverNameTo = new ArrayList<FeedbackParticipantType>(other.getShowGiverNameTo());
          this.showRecipientNameTo = new ArrayList<FeedbackParticipantType>(other.getShowRecipientNameTo());
          
          this.createdAt = other.getCreatedAt();
          this.updatedAt = other.getUpdatedAt();
          
          removeIrrelevantVisibilityOptions();
      }
      
      public FeedbackQuestionAttributes getCopy() {
          return new FeedbackQuestionAttributes(this);
      }
  
      public Date getCreatedAt() {
          return createdAt == null ? Const.TIME_REPRESENTS_DEFAULT_TIMESTAMP : createdAt;
      }
      
      public Date getUpdatedAt() {
          return updatedAt == null ? Const.TIME_REPRESENTS_DEFAULT_TIMESTAMP : updatedAt;
      }
      
      public String getId() {
          return feedbackQuestionId;
      }
  
      /** NOTE: Only use this to match and search for the ID of a known existing question entity. */
      public void setId(String id) {
          this.feedbackQuestionId = id;
      }
  
      @Override
      public FeedbackQuestion toEntity() {
          return new FeedbackQuestion(feedbackSessionName, courseId, creatorEmail,
                                      questionMetaData, questionDescription, questionNumber, questionType, giverType,
                                      recipientType, numberOfEntitiesToGiveFeedbackTo,
                                      showResponsesTo, showGiverNameTo, showRecipientNameTo);
      }
  
      @Override
      public String toString() {
          return "FeedbackQuestionAttributes [feedbackSessionName="
                 + feedbackSessionName + ", courseId=" + courseId
                 + ", creatorEmail=" + creatorEmail + ", questionText="
                 + questionMetaData + ", questionDescription=" + questionDescription
                 + ", questionNumber=" + questionNumber
                 + ", questionType=" + questionType + ", giverType=" + giverType
                 + ", recipientType=" + recipientType
                 + ", numberOfEntitiesToGiveFeedbackTo="
                 + numberOfEntitiesToGiveFeedbackTo + ", showResponsesTo="
                 + showResponsesTo + ", showGiverNameTo=" + showGiverNameTo
                 + ", showRecipientNameTo=" + showRecipientNameTo + "]";
      }
  
      @Override
      public String getIdentificationString() {
          return this.questionNumber + ". " + this.questionMetaData.toString() + "/"
                 + this.feedbackSessionName + "/" + this.courseId;
      }
  
      @Override
      public String getEntityTypeAsString() {
          return "Feedback Question";
      }
  
      @Override
      public String getBackupIdentifier() {
          return Const.SystemParams.COURSE_BACKUP_LOG_MSG + courseId;
      }
  
      @Override
      public String getJsonString() {
          return JsonUtils.toJson(this, FeedbackQuestionAttributes.class);
      }
  
      @Override
      public List<String> getInvalidityInfo() {
          FieldValidator validator = new FieldValidator();
          List<String> errors = new ArrayList<String>();
          String error;
  
          error = validator.getInvalidityInfoForFeedbackSessionName(feedbackSessionName);
          if (!error.isEmpty()) {
              errors.add(error);
          }
  
          error = validator.getInvalidityInfoForCourseId(courseId);
          if (!error.isEmpty()) {
              errors.add(error);
          }
  
          error = validator.getInvalidityInfoForEmail(creatorEmail);
          if (!error.isEmpty()) {
              errors.add("Invalid creator's email: " + error);
          }
  
          errors.addAll(validator.getValidityInfoForFeedbackParticipantType(giverType, recipientType));
  
          errors.addAll(validator.getValidityInfoForFeedbackResponseVisibility(showResponsesTo,
                                                                               showGiverNameTo,
                                                                               showRecipientNameTo));
  
          return errors;
      }
  
      // TODO: move following methods to PageData?
      // Answer: OK to move to the respective PageData class. Unit test this thoroughly.
      public List<String> getVisibilityMessage() {
          List<String> message = new ArrayList<String>();
  
          for (FeedbackParticipantType participant : showResponsesTo) {
              StringBuilder line = new StringBuilder(100);
  
              // Exceptional case: self feedback
              if (participant == FeedbackParticipantType.RECEIVER
                      && recipientType == FeedbackParticipantType.SELF) {
                  message.add("You can see your own feedback in the results page later on.");
                  continue;
              }
  
              // Front fragment: e.g. Other students in the course..., The receiving.., etc.
              line.append(participant.toVisibilityString()).append(' ');
  
              // Recipient fragment: e.g. student, instructor, etc.
              if (participant == FeedbackParticipantType.RECEIVER) {
                  line.append(recipientType.toSingularFormString());
  
                  if (numberOfEntitiesToGiveFeedbackTo > 1) {
                      line.append('s');
                  }
  
                  line.append(' ');
              }
  
              line.append("can see your response");
  
              // Visibility fragment: e.g. can see your name, but not...
              if (showRecipientNameTo.contains(participant)) {
                  if (participant != FeedbackParticipantType.RECEIVER
                          && recipientType != FeedbackParticipantType.NONE) {
                      line.append(", the name of the recipient");
                  }
  
                  if (showGiverNameTo.contains(participant)) {
                      line.append(", and your name");
                  } else {
                      line.append(", but not your name");
                  }
              } else {
                  if (showGiverNameTo.contains(participant)) {
                      line.append(", and your name");
                  }
  
                  if (recipientType == FeedbackParticipantType.NONE) {
                      if (!showGiverNameTo.contains(participant)) {
                          line.append(", but not your name");
                      }
                  } else {
                      line.append(", but not the name of the recipient");
                      
                      if (!showGiverNameTo.contains(participant)) {
                          line.append(", or your name");
                      }
                  }
  
              }
  
              line.append('.');
              message.add(line.toString());
          }
  
          if (message.isEmpty()) {
              message.add("No-one can see your responses.");
          }
  
          return message;
      }
  
      @Override
      public boolean isValid() {
          return getInvalidityInfo().isEmpty();
      }
  
      public boolean isGiverAStudent() {
          return giverType == FeedbackParticipantType.SELF
                 || giverType == FeedbackParticipantType.STUDENTS;
      }
  
      public boolean isRecipientNameHidden() {
          return recipientType == FeedbackParticipantType.NONE
                 || recipientType == FeedbackParticipantType.SELF;
      }
  
      public boolean isRecipientAStudent() {
          return recipientType == FeedbackParticipantType.SELF
                 || recipientType == FeedbackParticipantType.STUDENTS
                 || recipientType == FeedbackParticipantType.OWN_TEAM_MEMBERS
                 || recipientType == FeedbackParticipantType.OWN_TEAM_MEMBERS_INCLUDING_SELF;
      }
  
      public boolean isResponseVisibleTo(FeedbackParticipantType userType) {
          return showResponsesTo.contains(userType);
      }
  
      /**
       * Checks if updating this question to the {@code newAttributes} will
       * require the responses to be deleted for consistency.
       * Does not check if any responses exist.
       * 
       * @param newAttributes
       * @return
       */
      public boolean isChangesRequiresResponseDeletion(FeedbackQuestionAttributes newAttributes) {
          if (!newAttributes.giverType.equals(this.giverType)
                  || !newAttributes.recipientType.equals(this.recipientType)) {
              return true;
          }
  
          if (!this.showResponsesTo.containsAll(newAttributes.showResponsesTo)
                  || !this.showGiverNameTo.containsAll(newAttributes.showGiverNameTo)
                  || !this.showRecipientNameTo.containsAll(newAttributes.showRecipientNameTo)) {
              return true;
          }
  
          return this.getQuestionDetails().isChangesRequiresResponseDeletion(newAttributes.getQuestionDetails());
      }
  
      @Override
      public int compareTo(FeedbackQuestionAttributes o) {
          if (o == null) {
              return 1;
          }
          
          if (this.questionNumber != o.questionNumber) {
              return Integer.compare(this.questionNumber, o.questionNumber);
          }
          /**
           * Although question numbers ought to be unique in a feedback session,
           * eventual consistency can result in duplicate questions numbers.
           * Therefore, to ensure that the question order is always consistent to the user,
           * compare feedbackQuestionId, which is guaranteed to be unique,
           * when the questionNumbers are the same.
           */
          return this.feedbackQuestionId.compareTo(o.feedbackQuestionId);
      }
  
      @Override
      public int hashCode() {
          final int prime = 31;
          int result = 1;
  
          result = prime * result + (courseId == null ? 0 : courseId.hashCode());
  
          result = prime * result + (creatorEmail == null ? 0 : creatorEmail.hashCode());
  
          result = prime * result + (feedbackSessionName == null ? 0 : feedbackSessionName.hashCode());
  
          result = prime * result + (giverType == null ? 0 : giverType.hashCode());
  
          result = prime * result + numberOfEntitiesToGiveFeedbackTo;
  
          result = prime * result + questionNumber;
  
          result = prime * result + (questionMetaData == null ? 0 : questionMetaData.hashCode());
  
          result = prime * result + (questionDescription == null ? 0 : questionDescription.hashCode());
  
          result = prime * result + (questionType == null ? 0 : questionType.hashCode());
  
          result = prime * result + (recipientType == null ? 0 : recipientType.hashCode());
  
          result = prime * result + (showGiverNameTo == null ? 0 : showGiverNameTo.hashCode());
  
          result = prime * result + (showRecipientNameTo == null ? 0 : showRecipientNameTo.hashCode());
  
          result = prime * result + (showResponsesTo == null ? 0 : showResponsesTo.hashCode());
  
          return result;
      }
  
      @Override
      public boolean equals(Object obj) {
          if (this == obj) {
              return true;
          }
  
          if (obj == null) {
              return false;
          }
  
          if (getClass() != obj.getClass()) {
              return false;
          }
  
          FeedbackQuestionAttributes other = (FeedbackQuestionAttributes) obj;
  
          if (courseId == null) {
              if (other.courseId != null) {
                  return false;
              }
          } else if (!courseId.equals(other.courseId)) {
              return false;
          }
  
          if (creatorEmail == null) {
              if (other.creatorEmail != null) {
                  return false;
              }
          } else if (!creatorEmail.equals(other.creatorEmail)) {
              return false;
          }
  
          if (feedbackSessionName == null) {
              if (other.feedbackSessionName != null) {
                  return false;
              }
          } else if (!feedbackSessionName.equals(other.feedbackSessionName)) {
              return false;
          }
  
          if (giverType != other.giverType) {
              return false;
          }
  
          if (numberOfEntitiesToGiveFeedbackTo != other.numberOfEntitiesToGiveFeedbackTo) {
              return false;
          }
  
          if (questionNumber != other.questionNumber) {
              return false;
          }
  
          if (questionMetaData == null) {
              if (other.questionMetaData != null) {
                  return false;
              }
          } else if (!questionMetaData.equals(other.questionMetaData)) {
              return false;
          }
  
  