@Override
  public List<ParagraphInfo> getParagraphList(String user, String noteId)
      throws IOException, TException, ServiceException{
      // Check READER permission
      Set<String> userAndRoles = new HashSet<>();
      userAndRoles.add(user);
      boolean isAllowed = authorizationService.isReader(noteId, userAndRoles);
      Set<String> allowed = authorizationService.getReaders(noteId);
      if (!isAllowed) {
        String errorMsg = "Insufficient privileges to READER note. " +
            "Allowed users or roles: " + allowed;
        throw new ServiceException(errorMsg);
      }
      return getNotebook().processNote(noteId,
        note -> {
          if (null == note) {
            throw new IOException("Not found this note : " + noteId);
          }
          // Convert Paragraph to ParagraphInfo
          List<ParagraphInfo> paragraphInfos = new ArrayList<>();
          List<Paragraph> paragraphs = note.getParagraphs();
          for (Paragraph paragraph : paragraphs) {
            ParagraphInfo paraInfo = new ParagraphInfo();
            paraInfo.setNoteId(noteId);
            paraInfo.setParagraphId(paragraph.getId());
            paraInfo.setParagraphTitle(paragraph.getTitle());
            paraInfo.setParagraphText(paragraph.getText());
            paragraphInfos.add(paraInfo);
          }
          return paragraphInfos;
        });
  }
@Test
  void testGetParagraphList() throws IOException {
    String noteId = null;

    try {
      noteId = notebook.createNote("note1", anonymous);
      notebook.processNote(noteId,
        note -> {
          Paragraph p1 = note.addNewParagraph(anonymous);
          p1.setText("%md start remote interpreter process");
          p1.setAuthenticationInfo(anonymous);
          notebook.saveNote(note, anonymous);
          return null;
        });

      String user1Id = "user1", user2Id = "user2";

      // test user1 can get anonymous's note
      List<ParagraphInfo> paragraphList0 = null;
      try {
        paragraphList0 = notebookServer.getParagraphList(user1Id, noteId);
      } catch (ServiceException e) {
        e.printStackTrace();
      } catch (TException e) {
        e.printStackTrace();
      }
      assertNotNull(paragraphList0, user1Id + " can get anonymous's note");

      // test user1 cannot get user2's note
      authorizationService.setOwners(noteId, new HashSet<>(Arrays.asList(user2Id)));
      authorizationService.setReaders(noteId, new HashSet<>(Arrays.asList(user2Id)));
      authorizationService.setRunners(noteId, new HashSet<>(Arrays.asList(user2Id)));
      authorizationService.setWriters(noteId, new HashSet<>(Arrays.asList(user2Id)));
      List<ParagraphInfo> paragraphList1 = null;
      try {
        paragraphList1 = notebookServer.getParagraphList(user1Id, noteId);
      } catch (ServiceException e) {
        e.printStackTrace();
      } catch (TException e) {
        e.printStackTrace();
      }
      assertNull(paragraphList1, user1Id + " cannot get " + user2Id + "'s note");

      // test user1 can get user2's shared note
      authorizationService.setOwners(noteId, new HashSet<>(Arrays.asList(user2Id)));
      authorizationService.setReaders(noteId, new HashSet<>(Arrays.asList(user1Id, user2Id)));
      authorizationService.setRunners(noteId, new HashSet<>(Arrays.asList(user2Id)));
      authorizationService.setWriters(noteId, new HashSet<>(Arrays.asList(user2Id)));
      List<ParagraphInfo> paragraphList2 = null;
      try {
        paragraphList2 = notebookServer.getParagraphList(user1Id, noteId);
      } catch (ServiceException e) {
        e.printStackTrace();
      } catch (TException e) {
        e.printStackTrace();
      }
      assertNotNull(paragraphList2, user1Id + " can get " + user2Id + "'s shared note");
    } finally {
      if (null != noteId) {
        notebook.removeNote(noteId, anonymous);
      }
    }
  }