@Test public void debate_max_level() throws Exception { Account debater = savedAccountCitizen("debater1"); FlakeId parentId = Debate.NO_PARENT; Debate last = null; for (int i = 0; i < 10; i++) { last = service.debate(article.getArticleId(), parentId, debater, "nested"); parentId = last.getDebateId(); } assertTrue(last.isMaxLevel()); try { service.debate(article.getArticleId(), parentId, debater, "failed"); fail("IllegalArgumentException expected"); } catch (IllegalArgumentException expected) { } }
@Override public Debate debate(FlakeId articleId, @Nullable FlakeId parentDebateId, Authorization debaterAuth, String content) { Article article = articleDao.loadArticleWithoutCache(articleId); ZoneInfo zoneInfo = zoneDao.loadZoneWithoutCache(article.getZone()); Account debater = accountDao.strongVerifyAccount(debaterAuth) .filter(zoneInfo::canDebate) .orElseThrow(() -> new AccessDeniedException("no write to debate at zone:" + article.getZone())); Debate parent = Optional.ofNullable(parentDebateId).flatMap(debateDao::findDebate).orElse(null); Debate debate = debateDao.create(article, parent, content, debater, Instant.now(clock)); articleDao.increaseDebateCount(article); if (zoneInfo.getDebateAuthority() == Authority.CITIZEN) { accountDao.increaseDebateCount(debater); } if (!debate.getReplyToAccountId().equals(debater.getAccountId())) { feedService.createReplyFeed(debate.getDebateId(), debate.getReplyToAccountId()); } return debate; }
ArticleServiceImpl implements ArticleService { @Override public Debate debate(FlakeId articleId, @Nullable FlakeId parentDebateId, Authorization debaterAuth, String content) { Article article = articleDao.loadArticleWithoutCache(articleId); ZoneInfo zoneInfo = zoneDao.loadZoneWithoutCache(article.getZone()); Account debater = accountDao.strongVerifyAccount(debaterAuth) .filter(zoneInfo::canDebate) .orElseThrow(() -> new AccessDeniedException("no write to debate at zone:" + article.getZone())); Debate parent = Optional.ofNullable(parentDebateId).flatMap(debateDao::findDebate).orElse(null); Debate debate = debateDao.create(article, parent, content, debater, Instant.now(clock)); articleDao.increaseDebateCount(article); if (zoneInfo.getDebateAuthority() == Authority.CITIZEN) { accountDao.increaseDebateCount(debater); } if (!debate.getReplyToAccountId().equals(debater.getAccountId())) { feedService.createReplyFeed(debate.getDebateId(), debate.getReplyToAccountId()); } return debate; } }
ArticleServiceImpl implements ArticleService { @Override public Debate debate(FlakeId articleId, @Nullable FlakeId parentDebateId, Authorization debaterAuth, String content) { Article article = articleDao.loadArticleWithoutCache(articleId); ZoneInfo zoneInfo = zoneDao.loadZoneWithoutCache(article.getZone()); Account debater = accountDao.strongVerifyAccount(debaterAuth) .filter(zoneInfo::canDebate) .orElseThrow(() -> new AccessDeniedException("no write to debate at zone:" + article.getZone())); Debate parent = Optional.ofNullable(parentDebateId).flatMap(debateDao::findDebate).orElse(null); Debate debate = debateDao.create(article, parent, content, debater, Instant.now(clock)); articleDao.increaseDebateCount(article); if (zoneInfo.getDebateAuthority() == Authority.CITIZEN) { accountDao.increaseDebateCount(debater); } if (!debate.getReplyToAccountId().equals(debater.getAccountId())) { feedService.createReplyFeed(debate.getDebateId(), debate.getReplyToAccountId()); } return debate; }  }
ArticleServiceImpl implements ArticleService { @Override public Debate debate(FlakeId articleId, @Nullable FlakeId parentDebateId, Authorization debaterAuth, String content) { Article article = articleDao.loadArticleWithoutCache(articleId); ZoneInfo zoneInfo = zoneDao.loadZoneWithoutCache(article.getZone()); Account debater = accountDao.strongVerifyAccount(debaterAuth) .filter(zoneInfo::canDebate) .orElseThrow(() -> new AccessDeniedException("no write to debate at zone:" + article.getZone())); Debate parent = Optional.ofNullable(parentDebateId).flatMap(debateDao::findDebate).orElse(null); Debate debate = debateDao.create(article, parent, content, debater, Instant.now(clock)); articleDao.increaseDebateCount(article); if (zoneInfo.getDebateAuthority() == Authority.CITIZEN) { accountDao.increaseDebateCount(debater); } if (!debate.getReplyToAccountId().equals(debater.getAccountId())) { feedService.createReplyFeed(debate.getDebateId(), debate.getReplyToAccountId()); } return debate; }  @Override Article createExternalLink(Authorization authorization,
      Zone zone,
      String title,
      String link); @Override boolean canCreateArticle(Zone zone, Authorization auth); @Override Article createSpeak(Authorization authorization, Zone zone, String title, String content); @Override Optional<Article> findArticle(FlakeId articleId); @Override List<Article> listLatestZoneArticles(Zone zone, @Nullable FlakeId startArticleId); @Override Article loadArticle(FlakeId articleId); @Override String loadEditableDebateContent(FlakeId debateId, Authorization editor); @Override String updateDebateContent(FlakeId debateId, Authorization editorAuth, String content); @Override Debate debate(FlakeId articleId,
      @Nullable FlakeId parentDebateId,
      Authorization debaterAuth,
      String content); @Override DebateTree listBestDebates(FlakeId articleId, @Nullable FlakeId parentDebateId); @Override List<Article> listHotZoneArticles(Zone zone, FlakeId startArticleId); @Override @Cacheable(value = "rssHotArticles") List<Article> listRssHotZoneArticlesWithCache(Zone zone); @Override @Cacheable(value = "rssHotArticles") List<Article> listRssTopArticlesWithCache(); @Override List<Article> listLatestArticles(@Nullable FlakeId startArticleId); @Override List<Article> listTopArticles(@Nullable FlakeId startArticleId); @Override Debate loadDebateWithoutCache(FlakeId debateId); @Override Debate loadDebateWithCache(FlakeId debateId); @Override List<Debate> listReplyToDebates(Authorization authorization,
      @Nullable FlakeId startDebateId); @Override List<Debate> listLatestDebates(@Nullable FlakeId startDebateId); @Override List<Debate> listLatestZoneDebates(Zone zone, @Nullable FlakeId startDebateId); @Override List<Article> listArticlesByDebatesWithCache(List<FlakeId> debateIds); @Override List<Debate> listDebatesByIdWithCache(List<FlakeId> debateIds); @Override List<Article> listArticlesByAuthor(String username, @Nullable FlakeId startArticleId); @Override List<Debate> listDebatesByDebater(String username, @Nullable FlakeId startDebateId); @Override boolean isExternalLinkExist(Zone zone, String externalLink); @Override List<Article> listArticlesByExternalLink(Zone zone, String externalLink); @Override void deleteArticle(Authorization authorization, FlakeId articleId); @Override boolean canDeleteArticle(String username, FlakeId articleId); }
ArticleServiceImpl implements ArticleService { @Override public Debate debate(FlakeId articleId, @Nullable FlakeId parentDebateId, Authorization debaterAuth, String content) { Article article = articleDao.loadArticleWithoutCache(articleId); ZoneInfo zoneInfo = zoneDao.loadZoneWithoutCache(article.getZone()); Account debater = accountDao.strongVerifyAccount(debaterAuth) .filter(zoneInfo::canDebate) .orElseThrow(() -> new AccessDeniedException("no write to debate at zone:" + article.getZone())); Debate parent = Optional.ofNullable(parentDebateId).flatMap(debateDao::findDebate).orElse(null); Debate debate = debateDao.create(article, parent, content, debater, Instant.now(clock)); articleDao.increaseDebateCount(article); if (zoneInfo.getDebateAuthority() == Authority.CITIZEN) { accountDao.increaseDebateCount(debater); } if (!debate.getReplyToAccountId().equals(debater.getAccountId())) { feedService.createReplyFeed(debate.getDebateId(), debate.getReplyToAccountId()); } return debate; }  @Override Article createExternalLink(Authorization authorization,
      Zone zone,
      String title,
      String link); @Override boolean canCreateArticle(Zone zone, Authorization auth); @Override Article createSpeak(Authorization authorization, Zone zone, String title, String content); @Override Optional<Article> findArticle(FlakeId articleId); @Override List<Article> listLatestZoneArticles(Zone zone, @Nullable FlakeId startArticleId); @Override Article loadArticle(FlakeId articleId); @Override String loadEditableDebateContent(FlakeId debateId, Authorization editor); @Override String updateDebateContent(FlakeId debateId, Authorization editorAuth, String content); @Override Debate debate(FlakeId articleId,
      @Nullable FlakeId parentDebateId,
      Authorization debaterAuth,
      String content); @Override DebateTree listBestDebates(FlakeId articleId, @Nullable FlakeId parentDebateId); @Override List<Article> listHotZoneArticles(Zone zone, FlakeId startArticleId); @Override @Cacheable(value = "rssHotArticles") List<Article> listRssHotZoneArticlesWithCache(Zone zone); @Override @Cacheable(value = "rssHotArticles") List<Article> listRssTopArticlesWithCache(); @Override List<Article> listLatestArticles(@Nullable FlakeId startArticleId); @Override List<Article> listTopArticles(@Nullable FlakeId startArticleId); @Override Debate loadDebateWithoutCache(FlakeId debateId); @Override Debate loadDebateWithCache(FlakeId debateId); @Override List<Debate> listReplyToDebates(Authorization authorization,
      @Nullable FlakeId startDebateId); @Override List<Debate> listLatestDebates(@Nullable FlakeId startDebateId); @Override List<Debate> listLatestZoneDebates(Zone zone, @Nullable FlakeId startDebateId); @Override List<Article> listArticlesByDebatesWithCache(List<FlakeId> debateIds); @Override List<Debate> listDebatesByIdWithCache(List<FlakeId> debateIds); @Override List<Article> listArticlesByAuthor(String username, @Nullable FlakeId startArticleId); @Override List<Debate> listDebatesByDebater(String username, @Nullable FlakeId startDebateId); @Override boolean isExternalLinkExist(Zone zone, String externalLink); @Override List<Article> listArticlesByExternalLink(Zone zone, String externalLink); @Override void deleteArticle(Authorization authorization, FlakeId articleId); @Override boolean canDeleteArticle(String username, FlakeId articleId);  }