content: /*
   * Symphony - A modern community (forum/BBS/SNS/blog) platform written in Java.
   * Copyright (C) 2012-present, b3log.org
   *
   * This program is free software: you can redistribute it and/or modify
   * it under the terms of the GNU Affero General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU Affero General Public License for more details.
   *
   * You should have received a copy of the GNU Affero General Public License
   * along with this program.  If not, see <https://www.gnu.org/licenses/>.
   */
  package org.b3log.symphony.repository;
  
  import org.b3log.latke.Keys;
  import org.b3log.latke.ioc.Inject;
  import org.b3log.latke.repository.*;
  import org.b3log.latke.repository.annotation.Repository;
  import org.b3log.symphony.cache.ArticleCache;
  import org.b3log.symphony.model.Article;
  import org.json.JSONObject;
  
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * Article repository.
   *
   * @author <a href="http://88250.b3log.org">Liang Ding</a>
   * @author <a href="https://qiankunpingtai.cn">qiankunpingtai</a>
   * @version 1.1.1.9, Jun 6, 2019
   * @since 0.2.0
   */
  @Repository
  public class ArticleRepository extends AbstractRepository {
  
      /**
       * Article cache.
       */
      @Inject
      private ArticleCache articleCache;
  
      /**
       * Public constructor.
       */
      public ArticleRepository() {
          super(Article.ARTICLE);
      }
  
      @Override
      public void remove(final String id) throws RepositoryException {
          super.remove(id);
  
          articleCache.removeArticle(id);
      }
  
      @Override
      public JSONObject get(final String id) throws RepositoryException {
          JSONObject ret = articleCache.getArticle(id);
          if (null != ret) {
              return ret;
          }
  
          ret = super.get(id);
          if (null == ret) {
              return null;
          }
  
          articleCache.putArticle(ret);
  
          return ret;
      }
  
      @Override
      public void update(final String id, final JSONObject article, final String... propertyNames) throws RepositoryException {
          super.update(id, article, propertyNames);
  
          article.put(Keys.OBJECT_ID, id);
          articleCache.putArticle(article);
      }
  
      @Override
      public List<JSONObject> getRandomly(final int fetchSize) throws RepositoryException {
          final List<JSONObject> ret = new ArrayList<>();
  
          final double mid = Math.random();
          Query query = new Query().
                  setFilter(CompositeFilterOperator.and(new PropertyFilter(Article.ARTICLE_RANDOM_DOUBLE, FilterOperator.GREATER_THAN_OR_EQUAL, mid),
                          new PropertyFilter(Article.ARTICLE_RANDOM_DOUBLE, FilterOperator.LESS_THAN_OR_EQUAL, mid),
                          new PropertyFilter(Article.ARTICLE_STATUS, FilterOperator.NOT_EQUAL, Article.ARTICLE_STATUS_C_INVALID),
                          new PropertyFilter(Article.ARTICLE_TYPE, FilterOperator.NOT_EQUAL, Article.ARTICLE_TYPE_C_DISCUSSION),
                          new PropertyFilter(Article.ARTICLE_SHOW_IN_LIST, FilterOperator.NOT_EQUAL, Article.ARTICLE_SHOW_IN_LIST_C_NOT))).
                  select(Article.ARTICLE_TITLE, Article.ARTICLE_PERMALINK, Article.ARTICLE_AUTHOR_ID).
                  setPage(1, fetchSize).setPageCount(1);
          final List<JSONObject> list1 = getList(query);
          ret.addAll(list1);
  
          final int reminingSize = fetchSize - list1.size();
          if (0 != reminingSize) { // Query for remains
              query = new Query().
                      setFilter(CompositeFilterOperator.and(new PropertyFilter(Article.ARTICLE_RANDOM_DOUBLE, FilterOperator.GREATER_THAN_OR_EQUAL, 0D),
                              new PropertyFilter(Article.ARTICLE_RANDOM_DOUBLE, FilterOperator.LESS_THAN_OR_EQUAL, mid),
                              new PropertyFilter(Article.ARTICLE_STATUS, FilterOperator.NOT_EQUAL, Article.ARTICLE_STATUS_C_INVALID),
                              new PropertyFilter(Article.ARTICLE_TYPE, FilterOperator.NOT_EQUAL, Article.ARTICLE_TYPE_C_DISCUSSION),
                              new PropertyFilter(Article.ARTICLE_SHOW_IN_LIST, FilterOperator.NOT_EQUAL, Article.ARTICLE_SHOW_IN_LIST_C_NOT))).
                      select(Article.ARTICLE_TITLE, Article.ARTICLE_PERMALINK, Article.ARTICLE_AUTHOR_ID).
                      setPage(1, reminingSize).setPageCount(1);
              final List<JSONObject> list2 = getList(query);
  
              ret.addAll(list2);
          }
  
          return ret;
      }
  
      /**
       * Gets an article by the specified article title.
       *
       * @param articleTitle the specified article title
       * @return an article, {@code null} if not found
       * @throws RepositoryException repository exception
       */
      public JSONObject getByTitle(final String articleTitle) throws RepositoryException {
          final Query query = new Query().setFilter(new PropertyFilter(Article.ARTICLE_TITLE,
                  FilterOperator.EQUAL, articleTitle)).setPageCount(1);
          return getFirst(query);
      }
  }
  