Commit 4af1a1bb authored by Liang Ding's avatar Liang Ding

c

parent 2afd5b47
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.processor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringEscapeUtils;
import org.b3log.latke.Keys;
import org.b3log.latke.annotation.RequestProcessing;
import org.b3log.latke.annotation.RequestProcessor;
import org.b3log.latke.model.User;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.Query;
import org.b3log.latke.repository.SortDirection;
import org.b3log.latke.servlet.HTTPRequestContext;
import org.b3log.latke.servlet.HTTPRequestMethod;
import org.b3log.latke.servlet.renderer.AtomRenderer;
import org.b3log.latke.servlet.renderer.RssRenderer;
import org.b3log.latke.util.Locales;
import org.b3log.latke.util.Strings;
import org.b3log.solo.SoloServletListener;
import org.b3log.solo.model.Article;
import org.b3log.solo.model.Preference;
import org.b3log.solo.model.Tag;
import org.b3log.solo.model.feed.atom.Category;
import org.b3log.solo.model.feed.atom.Entry;
import org.b3log.solo.model.feed.atom.Feed;
import org.b3log.solo.model.feed.rss.Channel;
import org.b3log.solo.model.feed.rss.Item;
import org.b3log.solo.repository.ArticleRepository;
import org.b3log.solo.repository.TagArticleRepository;
import org.b3log.solo.repository.TagRepository;
import org.b3log.solo.repository.impl.ArticleRepositoryImpl;
import org.b3log.solo.repository.impl.TagArticleRepositoryImpl;
import org.b3log.solo.repository.impl.TagRepositoryImpl;
import org.b3log.solo.service.PreferenceQueryService;
import org.b3log.solo.util.Articles;
import org.b3log.solo.util.TimeZones;
import org.b3log.solo.util.Users;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Feed (Atom/RSS) processor.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.1.0.0, May 10, 2012
* @since 0.3.1
*/
@RequestProcessor
public final class FeedProcessor {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(FeedProcessor.class.getName());
/**
* Article repository.
*/
private ArticleRepository articleRepository = ArticleRepositoryImpl.getInstance();
/**
* Preference query service.
*/
private PreferenceQueryService preferenceQueryService = PreferenceQueryService.getInstance();
/**
* Count of output entry.
*/
public static final int ENTRY_OUTPUT_CNT = 10;
/**
* Article utilities.
*/
private Articles articleUtils = Articles.getInstance();
/**
* Tag repository.
*/
private TagRepository tagRepository = TagRepositoryImpl.getInstance();
/**
* Tag-Article repository.
*/
private TagArticleRepository tagArticleRepository = TagArticleRepositoryImpl.getInstance();
/**
* Blog articles Atom output.
*
* @param context the specified context
*/
@RequestProcessing(value = {"/blog-articles-feed.do"}, method = {HTTPRequestMethod.GET, HTTPRequestMethod.HEAD})
public void blogArticlesAtom(final HTTPRequestContext context) {
final AtomRenderer renderer = new AtomRenderer();
context.setRenderer(renderer);
final Feed feed = new Feed();
try {
final JSONObject preference = preferenceQueryService.getPreference();
final String blogTitle = preference.getString(Preference.BLOG_TITLE);
final String blogSubtitle = preference.getString(Preference.BLOG_SUBTITLE);
final String blogHost = preference.getString(Preference.BLOG_HOST);
feed.setTitle(StringEscapeUtils.escapeXml(blogTitle));
feed.setSubtitle(StringEscapeUtils.escapeXml(blogSubtitle));
feed.setUpdated(TimeZones.getTime(preference.getString(Preference.TIME_ZONE_ID)));
feed.setAuthor(StringEscapeUtils.escapeXml(blogTitle));
feed.setLink("http://" + blogHost + "/blog-articles-feed.do");
feed.setId("http://" + blogHost + "/");
final Query query = new Query().setCurrentPageNum(1).
setPageSize(ENTRY_OUTPUT_CNT).
addFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true).
addSort(Article.ARTICLE_UPDATE_DATE, SortDirection.DESCENDING).
setPageCount(1);
final boolean hasMultipleUsers = Users.getInstance().hasMultipleUsers();
String authorName = "";
final JSONObject articleResult = articleRepository.get(query);
final JSONArray articles = articleResult.getJSONArray(Keys.RESULTS);
if (!hasMultipleUsers && 0 != articles.length()) {
authorName = articleUtils.getAuthor(articles.getJSONObject(0)).getString(User.USER_NAME);
}
final boolean isFullContent = "fullContent".equals(preference.getString(Preference.FEED_OUTPUT_MODE));
for (int i = 0; i < articles.length(); i++) {
final JSONObject article = articles.getJSONObject(i);
final Entry entry = new Entry();
feed.addEntry(entry);
final String title = StringEscapeUtils.escapeXml(article.getString(Article.ARTICLE_TITLE));
entry.setTitle(title);
final String summary = isFullContent ? StringEscapeUtils.escapeXml(article.getString(Article.ARTICLE_CONTENT))
: StringEscapeUtils.escapeXml(article.optString(Article.ARTICLE_ABSTRACT));
entry.setSummary(summary);
final Date updated = (Date) article.get(Article.ARTICLE_UPDATE_DATE);
entry.setUpdated(updated);
final String link = "http://" + blogHost + article.getString(Article.ARTICLE_PERMALINK);
entry.setLink(link);
entry.setId(link);
if (hasMultipleUsers) {
authorName = StringEscapeUtils.escapeXml(articleUtils.getAuthor(article).getString(User.USER_NAME));
}
entry.setAuthor(authorName);
final String tagsString = article.getString(Article.ARTICLE_TAGS_REF);
final String[] tagStrings = tagsString.split(",");
for (int j = 0; j < tagStrings.length; j++) {
final Category catetory = new Category();
entry.addCatetory(catetory);
final String tag = tagStrings[j];
catetory.setTerm(tag);
}
}
renderer.setContent(feed.toString());
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Get blog article feed error", e);
try {
context.getResponse().sendError(
HttpServletResponse.SC_SERVICE_UNAVAILABLE);
} catch (final IOException ex) {
throw new RuntimeException(ex);
}
}
}
/**
* Tag articles Atom output.
*
* @param context the specified context
* @throws IOException io exception
*/
@RequestProcessing(value = {"/tag-articles-feed.do"}, method = {HTTPRequestMethod.GET, HTTPRequestMethod.HEAD})
public void tagArticlesAtom(final HTTPRequestContext context) throws IOException {
final AtomRenderer renderer = new AtomRenderer();
context.setRenderer(renderer);
final HttpServletRequest request = context.getRequest();
final HttpServletResponse response = context.getResponse();
final String queryString = request.getQueryString();
if (Strings.isEmptyOrNull(queryString)) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
final String oIdMap = queryString.split("&")[0];
final String tagId = oIdMap.split("=")[1];
final Feed feed = new Feed();
try {
final String tagTitle = tagRepository.get(tagId).getString(Tag.TAG_TITLE);
final JSONObject preference = preferenceQueryService.getPreference();
if (null == preference) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
final String blogTitle = preference.getString(Preference.BLOG_TITLE);
final String blogSubtitle = preference.getString(Preference.BLOG_SUBTITLE) + ", " + tagTitle;
final String blogHost = preference.getString(Preference.BLOG_HOST);
feed.setTitle(StringEscapeUtils.escapeXml(blogTitle));
feed.setSubtitle(StringEscapeUtils.escapeXml(blogSubtitle));
feed.setUpdated(TimeZones.getTime(preference.getString(Preference.TIME_ZONE_ID)));
feed.setAuthor(StringEscapeUtils.escapeXml(blogTitle));
feed.setLink("http://" + blogHost + "/tag-articles-feed.do");
feed.setId("http://" + blogHost + "/");
final JSONObject tagArticleResult = tagArticleRepository.getByTagId(tagId, 1, ENTRY_OUTPUT_CNT);
final JSONArray tagArticleRelations = tagArticleResult.getJSONArray(Keys.RESULTS);
if (0 == tagArticleRelations.length()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
final List<JSONObject> articles = new ArrayList<JSONObject>();
for (int i = 0; i < tagArticleRelations.length(); i++) {
final JSONObject tagArticleRelation = tagArticleRelations.getJSONObject(i);
final String articleId = tagArticleRelation.getString(Article.ARTICLE + "_" + Keys.OBJECT_ID);
final JSONObject article = articleRepository.get(articleId);
if (article.getBoolean(Article.ARTICLE_IS_PUBLISHED)) { // Skips the unpublished article
articles.add(article);
}
}
final boolean hasMultipleUsers = Users.getInstance().hasMultipleUsers();
String authorName = "";
if (!hasMultipleUsers && !articles.isEmpty()) {
authorName = articleUtils.getAuthor(articles.get(0)).getString(User.USER_NAME);
}
final boolean isFullContent = "fullContent".equals(preference.getString(Preference.FEED_OUTPUT_MODE));
for (int i = 0; i < articles.size(); i++) {
final JSONObject article = articles.get(i);
final Entry entry = new Entry();
feed.addEntry(entry);
final String title = StringEscapeUtils.escapeXml(article.getString(Article.ARTICLE_TITLE));
entry.setTitle(title);
final String summary = isFullContent ? StringEscapeUtils.escapeXml(article.getString(Article.ARTICLE_CONTENT))
: StringEscapeUtils.escapeXml(article.optString(Article.ARTICLE_ABSTRACT));
entry.setSummary(summary);
final Date updated = (Date) article.get(Article.ARTICLE_UPDATE_DATE);
entry.setUpdated(updated);
final String link = "http://" + blogHost + article.getString(Article.ARTICLE_PERMALINK);
entry.setLink(link);
entry.setId(link);
if (hasMultipleUsers) {
authorName = StringEscapeUtils.escapeXml(articleUtils.getAuthor(article).getString(User.USER_NAME));
}
entry.setAuthor(authorName);
final String tagsString = article.getString(Article.ARTICLE_TAGS_REF);
final String[] tagStrings = tagsString.split(",");
for (int j = 0; j < tagStrings.length; j++) {
final Category catetory = new Category();
entry.addCatetory(catetory);
final String tag = tagStrings[j];
catetory.setTerm(tag);
}
}
renderer.setContent(feed.toString());
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Get tag article feed error", e);
try {
context.getResponse().sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
} catch (final IOException ex) {
throw new RuntimeException(ex);
}
}
}
/**
* Blog articles RSS output.
*
* @param context the specified context
*/
@RequestProcessing(value = {"/blog-articles-rss.do"}, method = {HTTPRequestMethod.GET, HTTPRequestMethod.HEAD})
public void blogArticlesRSS(final HTTPRequestContext context) {
final HttpServletResponse response = context.getResponse();
final RssRenderer renderer = new RssRenderer();
context.setRenderer(renderer);
final Channel channel = new Channel();
try {
final JSONObject preference = preferenceQueryService.getPreference();
if (null == preference) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
final String blogTitle = preference.getString(Preference.BLOG_TITLE);
final String blogSubtitle = preference.getString(Preference.BLOG_SUBTITLE);
final String blogHost = preference.getString(Preference.BLOG_HOST);
channel.setTitle(StringEscapeUtils.escapeXml(blogTitle));
channel.setLastBuildDate(TimeZones.getTime(preference.getString(Preference.TIME_ZONE_ID)));
channel.setLink("http://" + blogHost);
channel.setAtomLink("http://" + blogHost + "/blog-articles-rss.do");
channel.setGenerator("B3log Solo, ver " + SoloServletListener.VERSION);
final String localeString = preference.getString(Preference.LOCALE_STRING);
final String country = Locales.getCountry(localeString).toLowerCase();
final String language = Locales.getLanguage(localeString).toLowerCase();
channel.setLanguage(language + '-' + country);
channel.setDescription(blogSubtitle);
final Query query = new Query().setCurrentPageNum(1).
setPageSize(ENTRY_OUTPUT_CNT).
addFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true).
addSort(Article.ARTICLE_UPDATE_DATE, SortDirection.DESCENDING).
setPageCount(1);
final JSONObject articleResult = articleRepository.get(query);
final JSONArray articles = articleResult.getJSONArray(Keys.RESULTS);
final boolean hasMultipleUsers = Users.getInstance().hasMultipleUsers();
String authorName = "";
if (!hasMultipleUsers && 0 != articles.length()) {
authorName = articleUtils.getAuthor(articles.getJSONObject(0)).getString(User.USER_NAME);
}
final boolean isFullContent = "fullContent".equals(preference.getString(Preference.FEED_OUTPUT_MODE));
for (int i = 0; i < articles.length(); i++) {
final JSONObject article = articles.getJSONObject(i);
final Item item = new Item();
channel.addItem(item);
final String title = StringEscapeUtils.escapeXml(article.getString(Article.ARTICLE_TITLE));
item.setTitle(title);
final String description = isFullContent ? StringEscapeUtils.escapeXml(article.getString(Article.ARTICLE_CONTENT))
: StringEscapeUtils.escapeXml(article.optString(Article.ARTICLE_ABSTRACT));
item.setDescription(description);
final Date pubDate = (Date) article.get(Article.ARTICLE_UPDATE_DATE);
item.setPubDate(pubDate);
final String link = "http://" + blogHost + article.getString(Article.ARTICLE_PERMALINK);
item.setLink(link);
item.setGUID(link);
final String authorEmail = article.getString(Article.ARTICLE_AUTHOR_EMAIL);
if (hasMultipleUsers) {
authorName = StringEscapeUtils.escapeXml(articleUtils.getAuthor(article).getString(User.USER_NAME));
}
item.setAuthor(authorEmail + "(" + authorName + ")");
final String tagsString = article.getString(Article.ARTICLE_TAGS_REF);
final String[] tagStrings = tagsString.split(",");
for (int j = 0; j < tagStrings.length; j++) {
final org.b3log.solo.model.feed.rss.Category catetory = new org.b3log.solo.model.feed.rss.Category();
item.addCatetory(catetory);
final String tag = tagStrings[j];
catetory.setTerm(tag);
}
}
renderer.setContent(channel.toString());
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Get blog article rss error", e);
try {
context.getResponse().sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
} catch (final IOException ex) {
throw new RuntimeException(ex);
}
}
}
/**
* Tag articles RSS output.
*
* @param context the specified context
* @throws IOException io exception
*/
@RequestProcessing(value = {"/tag-articles-rss.do"}, method = {HTTPRequestMethod.GET, HTTPRequestMethod.HEAD})
public void tagArticlesRSS(final HTTPRequestContext context) throws IOException {
final HttpServletResponse response = context.getResponse();
final HttpServletRequest request = context.getRequest();
final RssRenderer renderer = new RssRenderer();
context.setRenderer(renderer);
final String queryString = request.getQueryString();
if (Strings.isEmptyOrNull(queryString)) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
final String oIdMap = queryString.split("&")[0];
final String tagId = oIdMap.split("=")[1];
final Channel channel = new Channel();
try {
final String tagTitle = tagRepository.get(tagId).getString(Tag.TAG_TITLE);
final JSONObject preference = preferenceQueryService.getPreference();
if (null == preference) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
final String blogTitle = preference.getString(Preference.BLOG_TITLE);
final String blogSubtitle = preference.getString(Preference.BLOG_SUBTITLE) + ", " + tagTitle;
final String blogHost = preference.getString(Preference.BLOG_HOST);
channel.setTitle(StringEscapeUtils.escapeXml(blogTitle));
channel.setLastBuildDate(TimeZones.getTime(preference.getString(Preference.TIME_ZONE_ID)));
channel.setLink("http://" + blogHost);
channel.setAtomLink("http://" + blogHost + "/tag-articles-rss.do");
channel.setGenerator("B3log Solo, ver " + SoloServletListener.VERSION);
final String localeString = preference.getString(Preference.LOCALE_STRING);
final String country = Locales.getCountry(localeString).toLowerCase();
final String language = Locales.getLanguage(localeString).toLowerCase();
channel.setLanguage(language + '-' + country);
channel.setDescription(blogSubtitle);
final JSONObject tagArticleResult = tagArticleRepository.getByTagId(tagId, 1, ENTRY_OUTPUT_CNT);
final JSONArray tagArticleRelations = tagArticleResult.getJSONArray(Keys.RESULTS);
if (0 == tagArticleRelations.length()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
final List<JSONObject> articles = new ArrayList<JSONObject>();
for (int i = 0; i < tagArticleRelations.length(); i++) {
final JSONObject tagArticleRelation = tagArticleRelations.getJSONObject(i);
final String articleId = tagArticleRelation.getString(Article.ARTICLE + "_" + Keys.OBJECT_ID);
final JSONObject article = articleRepository.get(articleId);
if (article.getBoolean(Article.ARTICLE_IS_PUBLISHED)) { // Skips the unpublished article
articles.add(article);
}
}
final boolean hasMultipleUsers = Users.getInstance().hasMultipleUsers();
String authorName = "";
if (!hasMultipleUsers && !articles.isEmpty()) {
authorName = articleUtils.getAuthor(articles.get(0)).getString(User.USER_NAME);
}
final boolean isFullContent = "fullContent".equals(preference.getString(Preference.FEED_OUTPUT_MODE));
for (int i = 0; i < articles.size(); i++) {
final JSONObject article = articles.get(i);
final Item item = new Item();
channel.addItem(item);
final String title = StringEscapeUtils.escapeXml(article.getString(Article.ARTICLE_TITLE));
item.setTitle(title);
final String description = isFullContent ? StringEscapeUtils.escapeXml(article.getString(Article.ARTICLE_CONTENT))
: StringEscapeUtils.escapeXml(article.optString(Article.ARTICLE_ABSTRACT));
item.setDescription(description);
final Date pubDate = (Date) article.get(Article.ARTICLE_UPDATE_DATE);
item.setPubDate(pubDate);
final String link = "http://" + blogHost + article.getString(Article.ARTICLE_PERMALINK);
item.setLink(link);
item.setGUID(link);
final String authorEmail = article.getString(Article.ARTICLE_AUTHOR_EMAIL);
if (hasMultipleUsers) {
authorName = StringEscapeUtils.escapeXml(articleUtils.getAuthor(article).getString(User.USER_NAME));
}
item.setAuthor(authorEmail + "(" + authorName + ")");
final String tagsString = article.getString(Article.ARTICLE_TAGS_REF);
final String[] tagStrings = tagsString.split(",");
for (int j = 0; j < tagStrings.length; j++) {
final org.b3log.solo.model.feed.rss.Category catetory = new org.b3log.solo.model.feed.rss.Category();
item.addCatetory(catetory);
final String tag = tagStrings[j];
catetory.setTerm(tag);
}
}
renderer.setContent(channel.toString());
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Get tag article rss error", e);
try {
context.getResponse().sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
} catch (final IOException ex) {
throw new RuntimeException(ex);
}
}
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.processor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringEscapeUtils;
import org.b3log.latke.Keys;
import org.b3log.latke.annotation.RequestProcessing;
import org.b3log.latke.annotation.RequestProcessor;
import org.b3log.latke.model.User;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.PropertyFilter;
import org.b3log.latke.repository.Query;
import org.b3log.latke.repository.SortDirection;
import org.b3log.latke.servlet.HTTPRequestContext;
import org.b3log.latke.servlet.HTTPRequestMethod;
import org.b3log.latke.servlet.renderer.AtomRenderer;
import org.b3log.latke.servlet.renderer.RssRenderer;
import org.b3log.latke.util.Locales;
import org.b3log.latke.util.Strings;
import org.b3log.solo.SoloServletListener;
import org.b3log.solo.model.Article;
import org.b3log.solo.model.Preference;
import org.b3log.solo.model.Tag;
import org.b3log.solo.model.feed.atom.Category;
import org.b3log.solo.model.feed.atom.Entry;
import org.b3log.solo.model.feed.atom.Feed;
import org.b3log.solo.model.feed.rss.Channel;
import org.b3log.solo.model.feed.rss.Item;
import org.b3log.solo.repository.ArticleRepository;
import org.b3log.solo.repository.TagArticleRepository;
import org.b3log.solo.repository.TagRepository;
import org.b3log.solo.repository.impl.ArticleRepositoryImpl;
import org.b3log.solo.repository.impl.TagArticleRepositoryImpl;
import org.b3log.solo.repository.impl.TagRepositoryImpl;
import org.b3log.solo.service.PreferenceQueryService;
import org.b3log.solo.util.Articles;
import org.b3log.solo.util.TimeZones;
import org.b3log.solo.util.Users;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Feed (Atom/RSS) processor.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.1.0.0, May 10, 2012
* @since 0.3.1
*/
@RequestProcessor
public final class FeedProcessor {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(FeedProcessor.class.getName());
/**
* Article repository.
*/
private ArticleRepository articleRepository = ArticleRepositoryImpl.getInstance();
/**
* Preference query service.
*/
private PreferenceQueryService preferenceQueryService = PreferenceQueryService.getInstance();
/**
* Count of output entry.
*/
public static final int ENTRY_OUTPUT_CNT = 10;
/**
* Article utilities.
*/
private Articles articleUtils = Articles.getInstance();
/**
* Tag repository.
*/
private TagRepository tagRepository = TagRepositoryImpl.getInstance();
/**
* Tag-Article repository.
*/
private TagArticleRepository tagArticleRepository = TagArticleRepositoryImpl.getInstance();
/**
* Blog articles Atom output.
*
* @param context the specified context
*/
@RequestProcessing(value = {"/blog-articles-feed.do"}, method = {HTTPRequestMethod.GET, HTTPRequestMethod.HEAD})
public void blogArticlesAtom(final HTTPRequestContext context) {
final AtomRenderer renderer = new AtomRenderer();
context.setRenderer(renderer);
final Feed feed = new Feed();
try {
final JSONObject preference = preferenceQueryService.getPreference();
final String blogTitle = preference.getString(Preference.BLOG_TITLE);
final String blogSubtitle = preference.getString(Preference.BLOG_SUBTITLE);
final String blogHost = preference.getString(Preference.BLOG_HOST);
feed.setTitle(StringEscapeUtils.escapeXml(blogTitle));
feed.setSubtitle(StringEscapeUtils.escapeXml(blogSubtitle));
feed.setUpdated(TimeZones.getTime(preference.getString(Preference.TIME_ZONE_ID)));
feed.setAuthor(StringEscapeUtils.escapeXml(blogTitle));
feed.setLink("http://" + blogHost + "/blog-articles-feed.do");
feed.setId("http://" + blogHost + "/");
final Query query = new Query().setCurrentPageNum(1).
setPageSize(ENTRY_OUTPUT_CNT).
setFilter(new PropertyFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true)).
addSort(Article.ARTICLE_UPDATE_DATE, SortDirection.DESCENDING).
setPageCount(1);
final boolean hasMultipleUsers = Users.getInstance().hasMultipleUsers();
String authorName = "";
final JSONObject articleResult = articleRepository.get(query);
final JSONArray articles = articleResult.getJSONArray(Keys.RESULTS);
if (!hasMultipleUsers && 0 != articles.length()) {
authorName = articleUtils.getAuthor(articles.getJSONObject(0)).getString(User.USER_NAME);
}
final boolean isFullContent = "fullContent".equals(preference.getString(Preference.FEED_OUTPUT_MODE));
for (int i = 0; i < articles.length(); i++) {
final JSONObject article = articles.getJSONObject(i);
final Entry entry = new Entry();
feed.addEntry(entry);
final String title = StringEscapeUtils.escapeXml(article.getString(Article.ARTICLE_TITLE));
entry.setTitle(title);
final String summary = isFullContent ? StringEscapeUtils.escapeXml(article.getString(Article.ARTICLE_CONTENT))
: StringEscapeUtils.escapeXml(article.optString(Article.ARTICLE_ABSTRACT));
entry.setSummary(summary);
final Date updated = (Date) article.get(Article.ARTICLE_UPDATE_DATE);
entry.setUpdated(updated);
final String link = "http://" + blogHost + article.getString(Article.ARTICLE_PERMALINK);
entry.setLink(link);
entry.setId(link);
if (hasMultipleUsers) {
authorName = StringEscapeUtils.escapeXml(articleUtils.getAuthor(article).getString(User.USER_NAME));
}
entry.setAuthor(authorName);
final String tagsString = article.getString(Article.ARTICLE_TAGS_REF);
final String[] tagStrings = tagsString.split(",");
for (int j = 0; j < tagStrings.length; j++) {
final Category catetory = new Category();
entry.addCatetory(catetory);
final String tag = tagStrings[j];
catetory.setTerm(tag);
}
}
renderer.setContent(feed.toString());
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Get blog article feed error", e);
try {
context.getResponse().sendError(
HttpServletResponse.SC_SERVICE_UNAVAILABLE);
} catch (final IOException ex) {
throw new RuntimeException(ex);
}
}
}
/**
* Tag articles Atom output.
*
* @param context the specified context
* @throws IOException io exception
*/
@RequestProcessing(value = {"/tag-articles-feed.do"}, method = {HTTPRequestMethod.GET, HTTPRequestMethod.HEAD})
public void tagArticlesAtom(final HTTPRequestContext context) throws IOException {
final AtomRenderer renderer = new AtomRenderer();
context.setRenderer(renderer);
final HttpServletRequest request = context.getRequest();
final HttpServletResponse response = context.getResponse();
final String queryString = request.getQueryString();
if (Strings.isEmptyOrNull(queryString)) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
final String oIdMap = queryString.split("&")[0];
final String tagId = oIdMap.split("=")[1];
final Feed feed = new Feed();
try {
final String tagTitle = tagRepository.get(tagId).getString(Tag.TAG_TITLE);
final JSONObject preference = preferenceQueryService.getPreference();
if (null == preference) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
final String blogTitle = preference.getString(Preference.BLOG_TITLE);
final String blogSubtitle = preference.getString(Preference.BLOG_SUBTITLE) + ", " + tagTitle;
final String blogHost = preference.getString(Preference.BLOG_HOST);
feed.setTitle(StringEscapeUtils.escapeXml(blogTitle));
feed.setSubtitle(StringEscapeUtils.escapeXml(blogSubtitle));
feed.setUpdated(TimeZones.getTime(preference.getString(Preference.TIME_ZONE_ID)));
feed.setAuthor(StringEscapeUtils.escapeXml(blogTitle));
feed.setLink("http://" + blogHost + "/tag-articles-feed.do");
feed.setId("http://" + blogHost + "/");
final JSONObject tagArticleResult = tagArticleRepository.getByTagId(tagId, 1, ENTRY_OUTPUT_CNT);
final JSONArray tagArticleRelations = tagArticleResult.getJSONArray(Keys.RESULTS);
if (0 == tagArticleRelations.length()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
final List<JSONObject> articles = new ArrayList<JSONObject>();
for (int i = 0; i < tagArticleRelations.length(); i++) {
final JSONObject tagArticleRelation = tagArticleRelations.getJSONObject(i);
final String articleId = tagArticleRelation.getString(Article.ARTICLE + "_" + Keys.OBJECT_ID);
final JSONObject article = articleRepository.get(articleId);
if (article.getBoolean(Article.ARTICLE_IS_PUBLISHED)) { // Skips the unpublished article
articles.add(article);
}
}
final boolean hasMultipleUsers = Users.getInstance().hasMultipleUsers();
String authorName = "";
if (!hasMultipleUsers && !articles.isEmpty()) {
authorName = articleUtils.getAuthor(articles.get(0)).getString(User.USER_NAME);
}
final boolean isFullContent = "fullContent".equals(preference.getString(Preference.FEED_OUTPUT_MODE));
for (int i = 0; i < articles.size(); i++) {
final JSONObject article = articles.get(i);
final Entry entry = new Entry();
feed.addEntry(entry);
final String title = StringEscapeUtils.escapeXml(article.getString(Article.ARTICLE_TITLE));
entry.setTitle(title);
final String summary = isFullContent ? StringEscapeUtils.escapeXml(article.getString(Article.ARTICLE_CONTENT))
: StringEscapeUtils.escapeXml(article.optString(Article.ARTICLE_ABSTRACT));
entry.setSummary(summary);
final Date updated = (Date) article.get(Article.ARTICLE_UPDATE_DATE);
entry.setUpdated(updated);
final String link = "http://" + blogHost + article.getString(Article.ARTICLE_PERMALINK);
entry.setLink(link);
entry.setId(link);
if (hasMultipleUsers) {
authorName = StringEscapeUtils.escapeXml(articleUtils.getAuthor(article).getString(User.USER_NAME));
}
entry.setAuthor(authorName);
final String tagsString = article.getString(Article.ARTICLE_TAGS_REF);
final String[] tagStrings = tagsString.split(",");
for (int j = 0; j < tagStrings.length; j++) {
final Category catetory = new Category();
entry.addCatetory(catetory);
final String tag = tagStrings[j];
catetory.setTerm(tag);
}
}
renderer.setContent(feed.toString());
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Get tag article feed error", e);
try {
context.getResponse().sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
} catch (final IOException ex) {
throw new RuntimeException(ex);
}
}
}
/**
* Blog articles RSS output.
*
* @param context the specified context
*/
@RequestProcessing(value = {"/blog-articles-rss.do"}, method = {HTTPRequestMethod.GET, HTTPRequestMethod.HEAD})
public void blogArticlesRSS(final HTTPRequestContext context) {
final HttpServletResponse response = context.getResponse();
final RssRenderer renderer = new RssRenderer();
context.setRenderer(renderer);
final Channel channel = new Channel();
try {
final JSONObject preference = preferenceQueryService.getPreference();
if (null == preference) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
final String blogTitle = preference.getString(Preference.BLOG_TITLE);
final String blogSubtitle = preference.getString(Preference.BLOG_SUBTITLE);
final String blogHost = preference.getString(Preference.BLOG_HOST);
channel.setTitle(StringEscapeUtils.escapeXml(blogTitle));
channel.setLastBuildDate(TimeZones.getTime(preference.getString(Preference.TIME_ZONE_ID)));
channel.setLink("http://" + blogHost);
channel.setAtomLink("http://" + blogHost + "/blog-articles-rss.do");
channel.setGenerator("B3log Solo, ver " + SoloServletListener.VERSION);
final String localeString = preference.getString(Preference.LOCALE_STRING);
final String country = Locales.getCountry(localeString).toLowerCase();
final String language = Locales.getLanguage(localeString).toLowerCase();
channel.setLanguage(language + '-' + country);
channel.setDescription(blogSubtitle);
final Query query = new Query().setCurrentPageNum(1).
setPageSize(ENTRY_OUTPUT_CNT).
setFilter(new PropertyFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true)).
addSort(Article.ARTICLE_UPDATE_DATE, SortDirection.DESCENDING).
setPageCount(1);
final JSONObject articleResult = articleRepository.get(query);
final JSONArray articles = articleResult.getJSONArray(Keys.RESULTS);
final boolean hasMultipleUsers = Users.getInstance().hasMultipleUsers();
String authorName = "";
if (!hasMultipleUsers && 0 != articles.length()) {
authorName = articleUtils.getAuthor(articles.getJSONObject(0)).getString(User.USER_NAME);
}
final boolean isFullContent = "fullContent".equals(preference.getString(Preference.FEED_OUTPUT_MODE));
for (int i = 0; i < articles.length(); i++) {
final JSONObject article = articles.getJSONObject(i);
final Item item = new Item();
channel.addItem(item);
final String title = StringEscapeUtils.escapeXml(article.getString(Article.ARTICLE_TITLE));
item.setTitle(title);
final String description = isFullContent ? StringEscapeUtils.escapeXml(article.getString(Article.ARTICLE_CONTENT))
: StringEscapeUtils.escapeXml(article.optString(Article.ARTICLE_ABSTRACT));
item.setDescription(description);
final Date pubDate = (Date) article.get(Article.ARTICLE_UPDATE_DATE);
item.setPubDate(pubDate);
final String link = "http://" + blogHost + article.getString(Article.ARTICLE_PERMALINK);
item.setLink(link);
item.setGUID(link);
final String authorEmail = article.getString(Article.ARTICLE_AUTHOR_EMAIL);
if (hasMultipleUsers) {
authorName = StringEscapeUtils.escapeXml(articleUtils.getAuthor(article).getString(User.USER_NAME));
}
item.setAuthor(authorEmail + "(" + authorName + ")");
final String tagsString = article.getString(Article.ARTICLE_TAGS_REF);
final String[] tagStrings = tagsString.split(",");
for (int j = 0; j < tagStrings.length; j++) {
final org.b3log.solo.model.feed.rss.Category catetory = new org.b3log.solo.model.feed.rss.Category();
item.addCatetory(catetory);
final String tag = tagStrings[j];
catetory.setTerm(tag);
}
}
renderer.setContent(channel.toString());
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Get blog article rss error", e);
try {
context.getResponse().sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
} catch (final IOException ex) {
throw new RuntimeException(ex);
}
}
}
/**
* Tag articles RSS output.
*
* @param context the specified context
* @throws IOException io exception
*/
@RequestProcessing(value = {"/tag-articles-rss.do"}, method = {HTTPRequestMethod.GET, HTTPRequestMethod.HEAD})
public void tagArticlesRSS(final HTTPRequestContext context) throws IOException {
final HttpServletResponse response = context.getResponse();
final HttpServletRequest request = context.getRequest();
final RssRenderer renderer = new RssRenderer();
context.setRenderer(renderer);
final String queryString = request.getQueryString();
if (Strings.isEmptyOrNull(queryString)) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
final String oIdMap = queryString.split("&")[0];
final String tagId = oIdMap.split("=")[1];
final Channel channel = new Channel();
try {
final String tagTitle = tagRepository.get(tagId).getString(Tag.TAG_TITLE);
final JSONObject preference = preferenceQueryService.getPreference();
if (null == preference) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
final String blogTitle = preference.getString(Preference.BLOG_TITLE);
final String blogSubtitle = preference.getString(Preference.BLOG_SUBTITLE) + ", " + tagTitle;
final String blogHost = preference.getString(Preference.BLOG_HOST);
channel.setTitle(StringEscapeUtils.escapeXml(blogTitle));
channel.setLastBuildDate(TimeZones.getTime(preference.getString(Preference.TIME_ZONE_ID)));
channel.setLink("http://" + blogHost);
channel.setAtomLink("http://" + blogHost + "/tag-articles-rss.do");
channel.setGenerator("B3log Solo, ver " + SoloServletListener.VERSION);
final String localeString = preference.getString(Preference.LOCALE_STRING);
final String country = Locales.getCountry(localeString).toLowerCase();
final String language = Locales.getLanguage(localeString).toLowerCase();
channel.setLanguage(language + '-' + country);
channel.setDescription(blogSubtitle);
final JSONObject tagArticleResult = tagArticleRepository.getByTagId(tagId, 1, ENTRY_OUTPUT_CNT);
final JSONArray tagArticleRelations = tagArticleResult.getJSONArray(Keys.RESULTS);
if (0 == tagArticleRelations.length()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
final List<JSONObject> articles = new ArrayList<JSONObject>();
for (int i = 0; i < tagArticleRelations.length(); i++) {
final JSONObject tagArticleRelation = tagArticleRelations.getJSONObject(i);
final String articleId = tagArticleRelation.getString(Article.ARTICLE + "_" + Keys.OBJECT_ID);
final JSONObject article = articleRepository.get(articleId);
if (article.getBoolean(Article.ARTICLE_IS_PUBLISHED)) { // Skips the unpublished article
articles.add(article);
}
}
final boolean hasMultipleUsers = Users.getInstance().hasMultipleUsers();
String authorName = "";
if (!hasMultipleUsers && !articles.isEmpty()) {
authorName = articleUtils.getAuthor(articles.get(0)).getString(User.USER_NAME);
}
final boolean isFullContent = "fullContent".equals(preference.getString(Preference.FEED_OUTPUT_MODE));
for (int i = 0; i < articles.size(); i++) {
final JSONObject article = articles.get(i);
final Item item = new Item();
channel.addItem(item);
final String title = StringEscapeUtils.escapeXml(article.getString(Article.ARTICLE_TITLE));
item.setTitle(title);
final String description = isFullContent ? StringEscapeUtils.escapeXml(article.getString(Article.ARTICLE_CONTENT))
: StringEscapeUtils.escapeXml(article.optString(Article.ARTICLE_ABSTRACT));
item.setDescription(description);
final Date pubDate = (Date) article.get(Article.ARTICLE_UPDATE_DATE);
item.setPubDate(pubDate);
final String link = "http://" + blogHost + article.getString(Article.ARTICLE_PERMALINK);
item.setLink(link);
item.setGUID(link);
final String authorEmail = article.getString(Article.ARTICLE_AUTHOR_EMAIL);
if (hasMultipleUsers) {
authorName = StringEscapeUtils.escapeXml(articleUtils.getAuthor(article).getString(User.USER_NAME));
}
item.setAuthor(authorEmail + "(" + authorName + ")");
final String tagsString = article.getString(Article.ARTICLE_TAGS_REF);
final String[] tagStrings = tagsString.split(",");
for (int j = 0; j < tagStrings.length; j++) {
final org.b3log.solo.model.feed.rss.Category catetory = new org.b3log.solo.model.feed.rss.Category();
item.addCatetory(catetory);
final String tag = tagStrings[j];
catetory.setTerm(tag);
}
}
renderer.setContent(channel.toString());
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Get tag article rss error", e);
try {
context.getResponse().sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
} catch (final IOException ex) {
throw new RuntimeException(ex);
}
}
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.processor;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.time.DateFormatUtils;
import org.b3log.latke.Keys;
import org.b3log.latke.annotation.RequestProcessing;
import org.b3log.latke.annotation.RequestProcessor;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.Query;
import org.b3log.latke.repository.SortDirection;
import org.b3log.latke.servlet.HTTPRequestContext;
import org.b3log.latke.servlet.HTTPRequestMethod;
import org.b3log.latke.servlet.renderer.TextXMLRenderer;
import org.b3log.solo.model.ArchiveDate;
import org.b3log.solo.model.Article;
import org.b3log.solo.model.Page;
import org.b3log.solo.model.Preference;
import org.b3log.solo.model.Tag;
import org.b3log.solo.model.sitemap.Sitemap;
import org.b3log.solo.model.sitemap.URL;
import org.b3log.solo.repository.ArchiveDateRepository;
import org.b3log.solo.repository.PageRepository;
import org.b3log.solo.repository.TagRepository;
import org.b3log.solo.repository.impl.ArchiveDateRepositoryImpl;
import org.b3log.solo.repository.impl.ArticleRepositoryImpl;
import org.b3log.solo.repository.impl.PageRepositoryImpl;
import org.b3log.solo.repository.impl.TagRepositoryImpl;
import org.b3log.solo.service.PreferenceQueryService;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Site map (sitemap) processor.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.4, Jun 11, 2012
* @since 0.3.1
*/
@RequestProcessor
public final class SitemapProcessor {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(SitemapProcessor.class.getName());
/**
* Preference query service.
*/
private PreferenceQueryService preferenceQueryService = PreferenceQueryService.getInstance();
/**
* Article repository.
*/
private ArticleRepositoryImpl articleRepository = ArticleRepositoryImpl.getInstance();
/**
* Page repository.
*/
private PageRepository pageRepository = PageRepositoryImpl.getInstance();
/**
* Tag repository.
*/
private TagRepository tagRepository = TagRepositoryImpl.getInstance();
/**
* Archive date repository.
*/
private ArchiveDateRepository archiveDateRepository = ArchiveDateRepositoryImpl.getInstance();
/**
* Returns the sitemap.
*
* @param context the specified context
*/
@RequestProcessing(value = {"/sitemap.xml"}, method = HTTPRequestMethod.GET)
public void sitemap(final HTTPRequestContext context) {
final TextXMLRenderer renderer = new TextXMLRenderer();
context.setRenderer(renderer);
final Sitemap sitemap = new Sitemap();
try {
final JSONObject preference = preferenceQueryService.getPreference();
addArticles(sitemap, preference);
addNavigations(sitemap, preference);
addTags(sitemap, preference);
addArchives(sitemap, preference);
LOGGER.log(Level.INFO, "Generating sitemap....");
final String content = sitemap.toString();
LOGGER.log(Level.INFO, "Generated sitemap");
renderer.setContent(content);
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Get blog article feed error", e);
try {
context.getResponse().sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
} catch (final IOException ex) {
throw new RuntimeException(ex);
}
}
}
/**
* Adds articles into the specified sitemap.
*
* @param sitemap the specified sitemap
* @param preference the specified preference
* @throws Exception exception
*/
private void addArticles(final Sitemap sitemap, final JSONObject preference) throws Exception {
final String host = preference.getString(Preference.BLOG_HOST);
// XXX: query all articles?
final Query query = new Query().setCurrentPageNum(1).
addFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true).
addSort(Article.ARTICLE_CREATE_DATE, SortDirection.DESCENDING);
// Closes cache avoid Java heap space out of memory while caching
// query results
articleRepository.setCacheEnabled(false);
final JSONObject articleResult = articleRepository.get(query);
articleRepository.setCacheEnabled(true); // Restores cache
final JSONArray articles = articleResult.getJSONArray(Keys.RESULTS);
for (int i = 0; i < articles.length(); i++) {
final JSONObject article = articles.getJSONObject(i);
final String permalink = article.getString(Article.ARTICLE_PERMALINK);
final URL url = new URL();
url.setLoc("http://" + host + permalink);
final Date updateDate = (Date) article.get(Article.ARTICLE_UPDATE_DATE);
final String lastMod = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(updateDate);
url.setLastMod(lastMod);
sitemap.addURL(url);
}
}
/**
* Adds navigations into the specified sitemap.
*
* @param sitemap the specified sitemap
* @param preference the specified preference
* @throws Exception exception
*/
private void addNavigations(final Sitemap sitemap, final JSONObject preference) throws Exception {
final String host = preference.getString(Preference.BLOG_HOST);
final JSONObject result = pageRepository.get(new Query());
final JSONArray pages = result.getJSONArray(Keys.RESULTS);
for (int i = 0; i < pages.length(); i++) {
final JSONObject page = pages.getJSONObject(i);
final String permalink = page.getString(Page.PAGE_PERMALINK);
final URL url = new URL();
// The navigation maybe a page or a link
// Just filters for user mistakes tolerance
if (!permalink.contains("://")) {
url.setLoc("http://" + host + permalink);
} else {
url.setLoc(permalink);
}
sitemap.addURL(url);
}
}
/**
* Adds tags (tag-articles) and tags wall (/tags.html) into the specified
* sitemap.
*
* @param sitemap the specified sitemap
* @param preference the specified preference
* @throws Exception exception
*/
private void addTags(final Sitemap sitemap, final JSONObject preference) throws Exception {
final String host = preference.getString(Preference.BLOG_HOST);
final JSONObject result = tagRepository.get(new Query());
final JSONArray tags = result.getJSONArray(Keys.RESULTS);
for (int i = 0; i < tags.length(); i++) {
final JSONObject tag = tags.getJSONObject(i);
final String link = URLEncoder.encode(tag.getString(Tag.TAG_TITLE), "UTF-8");
final URL url = new URL();
url.setLoc("http://" + host + "/tags/" + link);
sitemap.addURL(url);
}
// Tags wall
final URL url = new URL();
url.setLoc("http://" + host + "/tags.html");
sitemap.addURL(url);
}
/**
* Adds archives (archive-articles) into the specified sitemap.
*
* @param sitemap the specified sitemap
* @param preference the specified preference
* @throws Exception exception
*/
private void addArchives(final Sitemap sitemap, final JSONObject preference) throws Exception {
final String host = preference.getString(Preference.BLOG_HOST);
final JSONObject result = archiveDateRepository.get(new Query());
final JSONArray archiveDates = result.getJSONArray(Keys.RESULTS);
for (int i = 0; i < archiveDates.length(); i++) {
final JSONObject archiveDate = archiveDates.getJSONObject(i);
final long time = archiveDate.getLong(ArchiveDate.ARCHIVE_TIME);
final String dateString = ArchiveDate.DATE_FORMAT.format(time);
final URL url = new URL();
url.setLoc("http://" + host + "/archives/" + dateString);
sitemap.addURL(url);
}
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.processor;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.time.DateFormatUtils;
import org.b3log.latke.Keys;
import org.b3log.latke.annotation.RequestProcessing;
import org.b3log.latke.annotation.RequestProcessor;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.PropertyFilter;
import org.b3log.latke.repository.Query;
import org.b3log.latke.repository.SortDirection;
import org.b3log.latke.servlet.HTTPRequestContext;
import org.b3log.latke.servlet.HTTPRequestMethod;
import org.b3log.latke.servlet.renderer.TextXMLRenderer;
import org.b3log.solo.model.ArchiveDate;
import org.b3log.solo.model.Article;
import org.b3log.solo.model.Page;
import org.b3log.solo.model.Preference;
import org.b3log.solo.model.Tag;
import org.b3log.solo.model.sitemap.Sitemap;
import org.b3log.solo.model.sitemap.URL;
import org.b3log.solo.repository.ArchiveDateRepository;
import org.b3log.solo.repository.PageRepository;
import org.b3log.solo.repository.TagRepository;
import org.b3log.solo.repository.impl.ArchiveDateRepositoryImpl;
import org.b3log.solo.repository.impl.ArticleRepositoryImpl;
import org.b3log.solo.repository.impl.PageRepositoryImpl;
import org.b3log.solo.repository.impl.TagRepositoryImpl;
import org.b3log.solo.service.PreferenceQueryService;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Site map (sitemap) processor.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.4, Jun 11, 2012
* @since 0.3.1
*/
@RequestProcessor
public final class SitemapProcessor {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(SitemapProcessor.class.getName());
/**
* Preference query service.
*/
private PreferenceQueryService preferenceQueryService = PreferenceQueryService.getInstance();
/**
* Article repository.
*/
private ArticleRepositoryImpl articleRepository = ArticleRepositoryImpl.getInstance();
/**
* Page repository.
*/
private PageRepository pageRepository = PageRepositoryImpl.getInstance();
/**
* Tag repository.
*/
private TagRepository tagRepository = TagRepositoryImpl.getInstance();
/**
* Archive date repository.
*/
private ArchiveDateRepository archiveDateRepository = ArchiveDateRepositoryImpl.getInstance();
/**
* Returns the sitemap.
*
* @param context the specified context
*/
@RequestProcessing(value = {"/sitemap.xml"}, method = HTTPRequestMethod.GET)
public void sitemap(final HTTPRequestContext context) {
final TextXMLRenderer renderer = new TextXMLRenderer();
context.setRenderer(renderer);
final Sitemap sitemap = new Sitemap();
try {
final JSONObject preference = preferenceQueryService.getPreference();
addArticles(sitemap, preference);
addNavigations(sitemap, preference);
addTags(sitemap, preference);
addArchives(sitemap, preference);
LOGGER.log(Level.INFO, "Generating sitemap....");
final String content = sitemap.toString();
LOGGER.log(Level.INFO, "Generated sitemap");
renderer.setContent(content);
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Get blog article feed error", e);
try {
context.getResponse().sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
} catch (final IOException ex) {
throw new RuntimeException(ex);
}
}
}
/**
* Adds articles into the specified sitemap.
*
* @param sitemap the specified sitemap
* @param preference the specified preference
* @throws Exception exception
*/
private void addArticles(final Sitemap sitemap, final JSONObject preference) throws Exception {
final String host = preference.getString(Preference.BLOG_HOST);
// XXX: query all articles?
final Query query = new Query().setCurrentPageNum(1).
setFilter(new PropertyFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true)).
addSort(Article.ARTICLE_CREATE_DATE, SortDirection.DESCENDING);
// Closes cache avoid Java heap space out of memory while caching
// query results
articleRepository.setCacheEnabled(false);
final JSONObject articleResult = articleRepository.get(query);
articleRepository.setCacheEnabled(true); // Restores cache
final JSONArray articles = articleResult.getJSONArray(Keys.RESULTS);
for (int i = 0; i < articles.length(); i++) {
final JSONObject article = articles.getJSONObject(i);
final String permalink = article.getString(Article.ARTICLE_PERMALINK);
final URL url = new URL();
url.setLoc("http://" + host + permalink);
final Date updateDate = (Date) article.get(Article.ARTICLE_UPDATE_DATE);
final String lastMod = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(updateDate);
url.setLastMod(lastMod);
sitemap.addURL(url);
}
}
/**
* Adds navigations into the specified sitemap.
*
* @param sitemap the specified sitemap
* @param preference the specified preference
* @throws Exception exception
*/
private void addNavigations(final Sitemap sitemap, final JSONObject preference) throws Exception {
final String host = preference.getString(Preference.BLOG_HOST);
final JSONObject result = pageRepository.get(new Query());
final JSONArray pages = result.getJSONArray(Keys.RESULTS);
for (int i = 0; i < pages.length(); i++) {
final JSONObject page = pages.getJSONObject(i);
final String permalink = page.getString(Page.PAGE_PERMALINK);
final URL url = new URL();
// The navigation maybe a page or a link
// Just filters for user mistakes tolerance
if (!permalink.contains("://")) {
url.setLoc("http://" + host + permalink);
} else {
url.setLoc(permalink);
}
sitemap.addURL(url);
}
}
/**
* Adds tags (tag-articles) and tags wall (/tags.html) into the specified
* sitemap.
*
* @param sitemap the specified sitemap
* @param preference the specified preference
* @throws Exception exception
*/
private void addTags(final Sitemap sitemap, final JSONObject preference) throws Exception {
final String host = preference.getString(Preference.BLOG_HOST);
final JSONObject result = tagRepository.get(new Query());
final JSONArray tags = result.getJSONArray(Keys.RESULTS);
for (int i = 0; i < tags.length(); i++) {
final JSONObject tag = tags.getJSONObject(i);
final String link = URLEncoder.encode(tag.getString(Tag.TAG_TITLE), "UTF-8");
final URL url = new URL();
url.setLoc("http://" + host + "/tags/" + link);
sitemap.addURL(url);
}
// Tags wall
final URL url = new URL();
url.setLoc("http://" + host + "/tags.html");
sitemap.addURL(url);
}
/**
* Adds archives (archive-articles) into the specified sitemap.
*
* @param sitemap the specified sitemap
* @param preference the specified preference
* @throws Exception exception
*/
private void addArchives(final Sitemap sitemap, final JSONObject preference) throws Exception {
final String host = preference.getString(Preference.BLOG_HOST);
final JSONObject result = archiveDateRepository.get(new Query());
final JSONArray archiveDates = result.getJSONArray(Keys.RESULTS);
for (int i = 0; i < archiveDates.length(); i++) {
final JSONObject archiveDate = archiveDates.getJSONObject(i);
final long time = archiveDate.getLong(ArchiveDate.ARCHIVE_TIME);
final String dateString = ArchiveDate.DATE_FORMAT.format(time);
final URL url = new URL();
url.setLoc("http://" + host + "/archives/" + dateString);
sitemap.addURL(url);
}
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.processor.util;
import freemarker.template.Template;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringEscapeUtils;
import org.b3log.latke.repository.RepositoryException;
import org.b3log.solo.util.Articles;
import org.b3log.solo.model.Article;
import org.b3log.solo.repository.ArticleRepository;
import org.b3log.solo.repository.TagRepository;
import org.b3log.latke.Keys;
import org.b3log.latke.Latkes;
import org.b3log.latke.action.AbstractAction;
import org.b3log.latke.event.Event;
import org.b3log.latke.event.EventException;
import org.b3log.latke.event.EventManager;
import org.b3log.latke.model.Pagination;
import org.b3log.latke.model.Plugin;
import org.b3log.latke.model.User;
import org.b3log.latke.plugin.ViewLoadEventData;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.Query;
import org.b3log.latke.repository.SortDirection;
import org.b3log.latke.service.ServiceException;
import org.b3log.latke.util.*;
import org.b3log.latke.util.freemarker.Templates;
import org.b3log.solo.model.ArchiveDate;
import org.b3log.solo.model.Link;
import org.b3log.solo.model.Preference;
import org.b3log.solo.repository.CommentRepository;
import org.b3log.solo.repository.LinkRepository;
import org.b3log.solo.SoloServletListener;
import org.b3log.solo.model.*;
import org.b3log.solo.repository.ArchiveDateRepository;
import org.b3log.solo.repository.PageRepository;
import org.b3log.solo.repository.StatisticRepository;
import org.b3log.solo.repository.UserRepository;
import org.b3log.solo.repository.impl.ArchiveDateRepositoryImpl;
import org.b3log.solo.repository.impl.ArticleRepositoryImpl;
import org.b3log.solo.repository.impl.CommentRepositoryImpl;
import org.b3log.solo.repository.impl.LinkRepositoryImpl;
import org.b3log.solo.repository.impl.PageRepositoryImpl;
import org.b3log.solo.repository.impl.StatisticRepositoryImpl;
import org.b3log.solo.repository.impl.TagRepositoryImpl;
import org.b3log.solo.repository.impl.UserRepositoryImpl;
import org.b3log.solo.service.ArticleQueryService;
import org.b3log.solo.util.Tags;
import org.b3log.solo.util.Users;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Filler utilities.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.5.9, May 22, 2012
* @since 0.3.1
*/
public final class Filler {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(Filler.class.getName());
/**
* Article repository.
*/
private ArticleRepository articleRepository = ArticleRepositoryImpl.getInstance();
/**
* Comment repository.
*/
private CommentRepository commentRepository = CommentRepositoryImpl.getInstance();
/**
* Archive date repository.
*/
private ArchiveDateRepository archiveDateRepository = ArchiveDateRepositoryImpl.getInstance();
/**
* Tag repository.
*/
private TagRepository tagRepository = TagRepositoryImpl.getInstance();
/**
* Article utilities.
*/
private Articles articleUtils = Articles.getInstance();
/**
* Tag utilities.
*/
private Tags tagUtils = Tags.getInstance();
/**
* Link repository.
*/
private LinkRepository linkRepository = LinkRepositoryImpl.getInstance();
/**
* Page repository.
*/
private PageRepository pageRepository = PageRepositoryImpl.getInstance();
/**
* Statistic repository.
*/
private StatisticRepository statisticRepository = StatisticRepositoryImpl.getInstance();
/**
* User repository.
*/
private UserRepository userRepository = UserRepositoryImpl.getInstance();
/**
* Article query service.
*/
private ArticleQueryService articleQueryService = ArticleQueryService.getInstance();
/**
* {@code true} for published.
*/
private static final boolean PUBLISHED = true;
/**
* Fills articles in index.ftl.
*
* @param dataModel data model
* @param currentPageNum current page number
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillIndexArticles(final Map<String, Object> dataModel, final int currentPageNum, final JSONObject preference)
throws ServiceException {
Stopwatchs.start("Fill Index Articles");
try {
final int pageSize = preference.getInt(Preference.ARTICLE_LIST_DISPLAY_COUNT);
final int windowSize = preference.getInt(Preference.ARTICLE_LIST_PAGINATION_WINDOW_SIZE);
final JSONObject statistic = statisticRepository.get(Statistic.STATISTIC);
final int publishedArticleCnt = statistic.getInt(Statistic.STATISTIC_PUBLISHED_ARTICLE_COUNT);
final int pageCount = (int) Math.ceil((double) publishedArticleCnt / (double) pageSize);
final Query query = new Query().setCurrentPageNum(currentPageNum).setPageSize(pageSize).setPageCount(pageCount).
addFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, PUBLISHED).
addSort(Article.ARTICLE_PUT_TOP, SortDirection.DESCENDING).
index(Article.ARTICLE_PERMALINK);
if (preference.getBoolean(Preference.ENABLE_ARTICLE_UPDATE_HINT)) {
query.addSort(Article.ARTICLE_UPDATE_DATE, SortDirection.DESCENDING);
} else {
query.addSort(Article.ARTICLE_CREATE_DATE, SortDirection.DESCENDING);
}
final JSONObject result = articleRepository.get(query);
final List<Integer> pageNums = Paginator.paginate(currentPageNum, pageSize, pageCount, windowSize);
if (0 != pageNums.size()) {
dataModel.put(Pagination.PAGINATION_FIRST_PAGE_NUM, pageNums.get(0));
dataModel.put(Pagination.PAGINATION_LAST_PAGE_NUM, pageNums.get(pageNums.size() - 1));
}
dataModel.put(Pagination.PAGINATION_PAGE_COUNT, pageCount);
dataModel.put(Pagination.PAGINATION_PAGE_NUMS, pageNums);
final List<JSONObject> articles = org.b3log.latke.util.CollectionUtils.jsonArrayToList(result.getJSONArray(Keys.RESULTS));
final boolean hasMultipleUsers = Users.getInstance().hasMultipleUsers();
if (hasMultipleUsers) {
setArticlesExProperties(articles, preference);
} else {
if (!articles.isEmpty()) {
final JSONObject author = articleUtils.getAuthor(articles.get(0));
setArticlesExProperties(articles, author, preference);
}
}
dataModel.put(Article.ARTICLES, articles);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills index articles failed", e);
throw new ServiceException(e);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills index articles failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills links.
*
* @param dataModel data model
* @throws ServiceException service exception
*/
public void fillLinks(final Map<String, Object> dataModel) throws ServiceException {
Stopwatchs.start("Fill Links");
try {
final Map<String, SortDirection> sorts = new HashMap<String, SortDirection>();
sorts.put(Link.LINK_ORDER, SortDirection.ASCENDING);
final Query query = new Query().addSort(Link.LINK_ORDER, SortDirection.ASCENDING).setPageCount(1);
final JSONObject linkResult = linkRepository.get(query);
final List<JSONObject> links = org.b3log.latke.util.CollectionUtils.jsonArrayToList(linkResult.getJSONArray(Keys.RESULTS));
dataModel.put(Link.LINKS, links);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills links failed", e);
throw new ServiceException(e);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills links failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
Stopwatchs.end();
}
/**
* Fills most used tags.
*
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillMostUsedTags(final Map<String, Object> dataModel, final JSONObject preference) throws ServiceException {
Stopwatchs.start("Fill Most Used Tags");
try {
LOGGER.finer("Filling most used tags....");
final int mostUsedTagDisplayCnt = preference.getInt(Preference.MOST_USED_TAG_DISPLAY_CNT);
final List<JSONObject> tags = tagRepository.getMostUsedTags(mostUsedTagDisplayCnt);
tagUtils.removeForUnpublishedArticles(tags);
dataModel.put(Common.MOST_USED_TAGS, tags);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills most used tags failed", e);
throw new ServiceException(e);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills most used tags failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills archive dates.
*
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillArchiveDates(final Map<String, Object> dataModel, final JSONObject preference) throws ServiceException {
Stopwatchs.start("Fill Archive Dates");
try {
LOGGER.finer("Filling archive dates....");
final List<JSONObject> archiveDates = archiveDateRepository.getArchiveDates();
final String localeString = preference.getString(Preference.LOCALE_STRING);
final String language = Locales.getLanguage(localeString);
for (final JSONObject archiveDate : archiveDates) {
final long time = archiveDate.getLong(ArchiveDate.ARCHIVE_TIME);
final String dateString = ArchiveDate.DATE_FORMAT.format(time);
final String[] dateStrings = dateString.split("/");
final String year = dateStrings[0];
final String month = dateStrings[1];
archiveDate.put(ArchiveDate.ARCHIVE_DATE_YEAR, year);
archiveDate.put(ArchiveDate.ARCHIVE_DATE_MONTH, month);
if ("en".equals(language)) {
final String monthName = Dates.EN_MONTHS.get(month);
archiveDate.put(Common.MONTH_NAME, monthName);
}
}
dataModel.put(ArchiveDate.ARCHIVE_DATES, archiveDates);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills archive dates failed", e);
throw new ServiceException(e);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills archive dates failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills most view count articles.
*
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillMostViewCountArticles(final Map<String, Object> dataModel, final JSONObject preference) throws ServiceException {
Stopwatchs.start("Fill Most View Articles");
try {
LOGGER.finer("Filling the most view count articles....");
final int mostCommentArticleDisplayCnt = preference.getInt(Preference.MOST_VIEW_ARTICLE_DISPLAY_CNT);
final List<JSONObject> mostViewCountArticles = articleRepository.getMostViewCountArticles(mostCommentArticleDisplayCnt);
dataModel.put(Common.MOST_VIEW_COUNT_ARTICLES, mostViewCountArticles);
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Fills most view count articles failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills most comments articles.
*
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillMostCommentArticles(final Map<String, Object> dataModel, final JSONObject preference) throws ServiceException {
Stopwatchs.start("Fill Most CMMTs Articles");
try {
LOGGER.finer("Filling most comment articles....");
final int mostCommentArticleDisplayCnt = preference.getInt(Preference.MOST_COMMENT_ARTICLE_DISPLAY_CNT);
final List<JSONObject> mostCommentArticles = articleRepository.getMostCommentArticles(mostCommentArticleDisplayCnt);
dataModel.put(Common.MOST_COMMENT_ARTICLES, mostCommentArticles);
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Fills most comment articles failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills post articles recently.
*
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillRecentArticles(final Map<String, Object> dataModel, final JSONObject preference) throws ServiceException {
Stopwatchs.start("Fill Recent Articles");
try {
final int recentArticleDisplayCnt = preference.getInt(Preference.RECENT_ARTICLE_DISPLAY_CNT);
final List<JSONObject> recentArticles = articleRepository.getRecentArticles(recentArticleDisplayCnt);
dataModel.put(Common.RECENT_ARTICLES, recentArticles);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills recent articles failed", e);
throw new ServiceException(e);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills recent articles failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills post comments recently.
*
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillRecentComments(final Map<String, Object> dataModel, final JSONObject preference) throws ServiceException {
Stopwatchs.start("Fill Recent Comments");
try {
LOGGER.finer("Filling recent comments....");
final int recentCommentDisplayCnt = preference.getInt(Preference.RECENT_COMMENT_DISPLAY_CNT);
final List<JSONObject> recentComments = commentRepository.getRecentComments(recentCommentDisplayCnt);
for (final JSONObject comment : recentComments) {
final String content = comment.getString(Comment.COMMENT_CONTENT).replaceAll(SoloServletListener.ENTER_ESC, "&nbsp;");
comment.put(Comment.COMMENT_CONTENT, content);
comment.put(Comment.COMMENT_NAME, StringEscapeUtils.escapeHtml(comment.getString(Comment.COMMENT_NAME)));
comment.put(Comment.COMMENT_URL, StringEscapeUtils.escapeHtml(comment.getString(Comment.COMMENT_URL)));
comment.remove(Comment.COMMENT_EMAIL); // Erases email for security reason
}
dataModel.put(Common.RECENT_COMMENTS, recentComments);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills recent comments failed", e);
throw new ServiceException(e);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills recent comments failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills footer.ftl.
*
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillBlogFooter(final Map<String, Object> dataModel, final JSONObject preference) throws ServiceException {
Stopwatchs.start("Fill Footer");
try {
LOGGER.finer("Filling footer....");
final String blogTitle = preference.getString(Preference.BLOG_TITLE);
dataModel.put(Preference.BLOG_TITLE, blogTitle);
final String blogHost = preference.getString(Preference.BLOG_HOST);
dataModel.put(Preference.BLOG_HOST, blogHost);
dataModel.put(Common.VERSION, SoloServletListener.VERSION);
dataModel.put(Common.STATIC_RESOURCE_VERSION, Latkes.getStaticResourceVersion());
dataModel.put(Common.YEAR, String.valueOf(Calendar.getInstance().get(Calendar.YEAR)));
dataModel.put(Keys.Server.STATIC_SERVER, Latkes.getStaticServer());
dataModel.put(Keys.Server.SERVER, Latkes.getServer());
// Activates plugins
try {
final ViewLoadEventData data = new ViewLoadEventData();
data.setViewName("footer.ftl");
data.setDataModel(dataModel);
EventManager.getInstance().fireEventSynchronously(new Event<ViewLoadEventData>(AbstractAction.FREEMARKER_ACTION, data));
if (Strings.isEmptyOrNull((String) dataModel.get(Plugin.PLUGINS))) {
// There is no plugin for this template, fill ${plugins} with blank.
dataModel.put(Plugin.PLUGINS, "");
}
} catch (final EventException e) {
LOGGER.log(Level.WARNING, "Event[FREEMARKER_ACTION] handle failed, ignores this exception for kernel health", e);
}
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills blog footer failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills header.ftl.
*
* @param request the specified HTTP servlet request
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillBlogHeader(final HttpServletRequest request, final Map<String, Object> dataModel, final JSONObject preference)
throws ServiceException {
Stopwatchs.start("Fill Header");
try {
LOGGER.fine("Filling header....");
dataModel.put(Preference.ARTICLE_LIST_DISPLAY_COUNT, preference.getInt(Preference.ARTICLE_LIST_DISPLAY_COUNT));
dataModel.put(Preference.ARTICLE_LIST_PAGINATION_WINDOW_SIZE,
preference.getInt(Preference.ARTICLE_LIST_PAGINATION_WINDOW_SIZE));
dataModel.put(Preference.LOCALE_STRING, preference.getString(Preference.LOCALE_STRING));
dataModel.put(Preference.BLOG_TITLE, preference.getString(Preference.BLOG_TITLE));
dataModel.put(Preference.BLOG_SUBTITLE, preference.getString(Preference.BLOG_SUBTITLE));
dataModel.put(Preference.HTML_HEAD, preference.getString(Preference.HTML_HEAD));
dataModel.put(Preference.META_KEYWORDS, preference.getString(Preference.META_KEYWORDS));
dataModel.put(Preference.META_DESCRIPTION, preference.getString(Preference.META_DESCRIPTION));
dataModel.put(Common.YEAR, String.valueOf(Calendar.getInstance().get(Calendar.YEAR)));
final String noticeBoard = preference.getString(Preference.NOTICE_BOARD);
dataModel.put(Preference.NOTICE_BOARD, noticeBoard);
final Query query = new Query().setPageCount(1);
final JSONObject result = userRepository.get(query);
final JSONArray users = result.getJSONArray(Keys.RESULTS);
final List<JSONObject> userList = CollectionUtils.jsonArrayToList(users);
dataModel.put(User.USERS, userList);
for (final JSONObject user : userList) {
user.remove(User.USER_EMAIL);
}
final String skinDirName = (String) request.getAttribute(Keys.TEMAPLTE_DIR_NAME);
dataModel.put(Skin.SKIN_DIR_NAME, skinDirName);
Keys.fillServer(dataModel);
fillMinified(dataModel);
fillPageNavigations(dataModel);
fillStatistic(dataModel);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills blog header failed", e);
throw new ServiceException(e);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills blog header failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills minified directory and file postfix for static JavaScript, CSS.
*
* @param dataModel the specified data model
*/
public void fillMinified(final Map<String, Object> dataModel) {
switch (Latkes.getRuntimeMode()) {
case DEVELOPMENT:
dataModel.put(Common.MINI_POSTFIX, "");
break;
case PRODUCTION:
dataModel.put(Common.MINI_POSTFIX, Common.MINI_POSTFIX_VALUE);
break;
default:
throw new AssertionError();
}
}
/**
* Fills side.ftl.
*
* @param request the specified HTTP servlet request
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillSide(final HttpServletRequest request, final Map<String, Object> dataModel, final JSONObject preference)
throws ServiceException {
Stopwatchs.start("Fill Side");
try {
LOGGER.fine("Filling side....");
final Template template = Templates.getTemplate((String) request.getAttribute(Keys.TEMAPLTE_DIR_NAME), "side.ftl");
if (null == template) {
LOGGER.fine("The skin dose not contain [side.ftl] template");
return;
}
// TODO: fillRecentArticles(dataModel, preference);
if (Templates.hasExpression(template, "<#list links as link>")) {
fillLinks(dataModel);
}
if (Templates.hasExpression(template, "<#list recentComments as comment>")) {
fillRecentComments(dataModel, preference);
}
if (Templates.hasExpression(template, "<#list mostUsedTags as tag>")) {
fillMostUsedTags(dataModel, preference);
}
if (Templates.hasExpression(template, "<#list mostCommentArticles as article>")) {
fillMostCommentArticles(dataModel, preference);
}
if (Templates.hasExpression(template, "<#list mostViewCountArticles as article>")) {
fillMostViewCountArticles(dataModel, preference);
}
if (Templates.hasExpression(template, "<#list archiveDates as archiveDate>")) {
fillArchiveDates(dataModel, preference);
}
} catch (final ServiceException e) {
LOGGER.log(Level.SEVERE, "Fills side failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills the specified template.
*
* @param template the specified template
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillUserTemplate(final Template template, final Map<String, Object> dataModel, final JSONObject preference)
throws ServiceException {
Stopwatchs.start("Fill User Template[name=" + template.getName() + "]");
try {
LOGGER.log(Level.FINE, "Filling user template[name{0}]", template.getName());
if (Templates.hasExpression(template, "<#list links as link>")) {
fillLinks(dataModel);
}
if (Templates.hasExpression(template, "<#list recentComments as comment>")) {
fillRecentComments(dataModel, preference);
}
if (Templates.hasExpression(template, "<#list mostUsedTags as tag>")) {
fillMostUsedTags(dataModel, preference);
}
if (Templates.hasExpression(template, "<#list mostCommentArticles as article>")) {
fillMostCommentArticles(dataModel, preference);
}
if (Templates.hasExpression(template, "<#list mostViewCountArticles as article>")) {
fillMostViewCountArticles(dataModel, preference);
}
if (Templates.hasExpression(template, "<#list archiveDates as archiveDate>")) {
fillArchiveDates(dataModel, preference);
}
final String noticeBoard = preference.getString(Preference.NOTICE_BOARD);
dataModel.put(Preference.NOTICE_BOARD, noticeBoard);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills user template failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills page navigations.
*
* @param dataModel data model
* @throws ServiceException service exception
*/
private void fillPageNavigations(final Map<String, Object> dataModel) throws ServiceException {
Stopwatchs.start("Fill Navigations");
try {
LOGGER.finer("Filling page navigations....");
final List<JSONObject> pages = pageRepository.getPages();
for (final JSONObject page : pages) {
if ("page".equals(page.optString(Page.PAGE_TYPE))) {
final String permalink = page.optString(Page.PAGE_PERMALINK);
page.put(Page.PAGE_PERMALINK, Latkes.getServePath() + permalink);
}
}
dataModel.put(Common.PAGE_NAVIGATIONS, pages);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills page navigations failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills statistic.
*
* @param dataModel data model
* @throws ServiceException service exception
*/
private void fillStatistic(final Map<String, Object> dataModel) throws ServiceException {
Stopwatchs.start("Fill Statistic");
try {
LOGGER.finer("Filling statistic....");
final JSONObject statistic = statisticRepository.get(Statistic.STATISTIC);
dataModel.put(Statistic.STATISTIC, statistic);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills statistic failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Sets some extra properties into the specified article with the specified author and preference, performs content and
* abstract editor processing.
*
* <p>
* Article ext properties:
* <pre>
* {
* ....,
* "authorName": "",
* "authorId": "",
* "hasUpdated": boolean
* }
* </pre>
* </p>
*
* @param article the specified article
* @param author the specified author
* @param preference the specified preference
* @throws ServiceException service exception
* @see #setArticlesExProperties(java.util.List, org.json.JSONObject)
*/
private void setArticleExProperties(final JSONObject article, final JSONObject author, final JSONObject preference)
throws ServiceException {
try {
final String authorName = author.getString(User.USER_NAME);
article.put(Common.AUTHOR_NAME, authorName);
final String authorId = author.getString(Keys.OBJECT_ID);
article.put(Common.AUTHOR_ID, authorId);
if (preference.getBoolean(Preference.ENABLE_ARTICLE_UPDATE_HINT)) {
article.put(Common.HAS_UPDATED, articleUtils.hasUpdated(article));
} else {
article.put(Common.HAS_UPDATED, false);
}
processArticleAbstract(preference, article);
articleQueryService.markdown(article);
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Sets article extra properties failed", e);
throw new ServiceException(e);
}
}
/**
* Sets some extra properties into the specified article with the specified preference, performs content and
* abstract editor processing.
*
* <p>
* Article ext properties:
* <pre>
* {
* ....,
* "authorName": "",
* "authorId": "",
* "hasUpdated": boolean
* }
* </pre>
* </p>
*
* @param article the specified article
* @param preference the specified preference
* @throws ServiceException service exception
* @see #setArticlesExProperties(java.util.List, org.json.JSONObject)
*/
private void setArticleExProperties(final JSONObject article, final JSONObject preference) throws ServiceException {
try {
final JSONObject author = articleUtils.getAuthor(article);
final String authorName = author.getString(User.USER_NAME);
article.put(Common.AUTHOR_NAME, authorName);
final String authorId = author.getString(Keys.OBJECT_ID);
article.put(Common.AUTHOR_ID, authorId);
if (preference.getBoolean(Preference.ENABLE_ARTICLE_UPDATE_HINT)) {
article.put(Common.HAS_UPDATED, articleUtils.hasUpdated(article));
} else {
article.put(Common.HAS_UPDATED, false);
}
processArticleAbstract(preference, article);
articleQueryService.markdown(article);
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Sets article extra properties failed", e);
throw new ServiceException(e);
}
}
/**
* Sets some extra properties into the specified article with the specified
* author and preference.
*
* <p>
* The batch version of method
* {@linkplain #setArticleExProperties(org.json.JSONObject, org.json.JSONObject)}.
* </p>
*
* <p>
* Article ext properties:
* <pre>
* {
* ....,
* "authorName": "",
* "authorId": "",
* "hasUpdated": boolean
* }
* </pre>
* </p>
*
* @param articles the specified articles
* @param author the specified author
* @param preference the specified preference
* @throws ServiceException service exception
* @see #setArticleExProperties(org.json.JSONObject, org.json.JSONObject)
*/
public void setArticlesExProperties(final List<JSONObject> articles, final JSONObject author, final JSONObject preference)
throws ServiceException {
for (final JSONObject article : articles) {
setArticleExProperties(article, author, preference);
}
}
/**
* Sets some extra properties into the specified article with the specified
* preference.
*
* <p>
* The batch version of method
* {@linkplain #setArticleExProperties(org.json.JSONObject, org.json.JSONObject)}.
* </p>
*
* <p>
* Article ext properties:
* <pre>
* {
* ....,
* "authorName": "",
* "authorId": "",
* "hasUpdated": boolean
* }
* </pre>
* </p>
*
* @param articles the specified articles
* @param preference the specified preference
* @throws ServiceException service exception
* @see #setArticleExProperties(org.json.JSONObject, org.json.JSONObject)
*/
public void setArticlesExProperties(final List<JSONObject> articles, final JSONObject preference)
throws ServiceException {
for (final JSONObject article : articles) {
setArticleExProperties(article, preference);
}
}
/**
* Processes the abstract of the specified article with the specified preference.
*
* <p>
* <ul>
* <li>If the abstract is {@code null}, sets it with ""</li>
* <li>If user configured preference "titleOnly", sets the abstract with ""</li>
* <li>If user configured preference "titleAndContent", sets the abstract with the content of the article</li>
* </ul>
* </p>
*
* @param preference the specified preference
* @param article the specified article
*/
private void processArticleAbstract(final JSONObject preference, final JSONObject article) {
final String articleAbstract = article.optString(Article.ARTICLE_ABSTRACT, null);
if (null == articleAbstract) {
article.put(Article.ARTICLE_ABSTRACT, "");
}
final String articleListStyle = preference.optString(Preference.ARTICLE_LIST_STYLE);
if ("titleOnly".equals(articleListStyle)) {
article.put(Article.ARTICLE_ABSTRACT, "");
} else if ("titleAndContent".equals(articleListStyle)) {
article.put(Article.ARTICLE_ABSTRACT, article.optString(Article.ARTICLE_CONTENT));
}
}
/**
* Gets the {@link Filler} singleton.
*
* @return the singleton
*/
public static Filler getInstance() {
return SingletonHolder.SINGLETON;
}
/**
* Private default constructor.
*/
private Filler() {
}
/**
* Singleton holder.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.0, Jan 12, 2011
*/
private static final class SingletonHolder {
/**
* Singleton.
*/
private static final Filler SINGLETON = new Filler();
/**
* Private default constructor.
*/
private SingletonHolder() {
}
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.processor.util;
import freemarker.template.Template;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringEscapeUtils;
import org.b3log.latke.repository.RepositoryException;
import org.b3log.solo.util.Articles;
import org.b3log.solo.model.Article;
import org.b3log.solo.repository.ArticleRepository;
import org.b3log.solo.repository.TagRepository;
import org.b3log.latke.Keys;
import org.b3log.latke.Latkes;
import org.b3log.latke.action.AbstractAction;
import org.b3log.latke.event.Event;
import org.b3log.latke.event.EventException;
import org.b3log.latke.event.EventManager;
import org.b3log.latke.model.Pagination;
import org.b3log.latke.model.Plugin;
import org.b3log.latke.model.User;
import org.b3log.latke.plugin.ViewLoadEventData;
import org.b3log.latke.repository.*;
import org.b3log.latke.service.ServiceException;
import org.b3log.latke.util.*;
import org.b3log.latke.util.freemarker.Templates;
import org.b3log.solo.model.ArchiveDate;
import org.b3log.solo.model.Link;
import org.b3log.solo.model.Preference;
import org.b3log.solo.repository.CommentRepository;
import org.b3log.solo.repository.LinkRepository;
import org.b3log.solo.SoloServletListener;
import org.b3log.solo.model.*;
import org.b3log.solo.repository.ArchiveDateRepository;
import org.b3log.solo.repository.PageRepository;
import org.b3log.solo.repository.StatisticRepository;
import org.b3log.solo.repository.UserRepository;
import org.b3log.solo.repository.impl.ArchiveDateRepositoryImpl;
import org.b3log.solo.repository.impl.ArticleRepositoryImpl;
import org.b3log.solo.repository.impl.CommentRepositoryImpl;
import org.b3log.solo.repository.impl.LinkRepositoryImpl;
import org.b3log.solo.repository.impl.PageRepositoryImpl;
import org.b3log.solo.repository.impl.StatisticRepositoryImpl;
import org.b3log.solo.repository.impl.TagRepositoryImpl;
import org.b3log.solo.repository.impl.UserRepositoryImpl;
import org.b3log.solo.service.ArticleQueryService;
import org.b3log.solo.util.Tags;
import org.b3log.solo.util.Users;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Filler utilities.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.5.9, May 22, 2012
* @since 0.3.1
*/
public final class Filler {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(Filler.class.getName());
/**
* Article repository.
*/
private ArticleRepository articleRepository = ArticleRepositoryImpl.getInstance();
/**
* Comment repository.
*/
private CommentRepository commentRepository = CommentRepositoryImpl.getInstance();
/**
* Archive date repository.
*/
private ArchiveDateRepository archiveDateRepository = ArchiveDateRepositoryImpl.getInstance();
/**
* Tag repository.
*/
private TagRepository tagRepository = TagRepositoryImpl.getInstance();
/**
* Article utilities.
*/
private Articles articleUtils = Articles.getInstance();
/**
* Tag utilities.
*/
private Tags tagUtils = Tags.getInstance();
/**
* Link repository.
*/
private LinkRepository linkRepository = LinkRepositoryImpl.getInstance();
/**
* Page repository.
*/
private PageRepository pageRepository = PageRepositoryImpl.getInstance();
/**
* Statistic repository.
*/
private StatisticRepository statisticRepository = StatisticRepositoryImpl.getInstance();
/**
* User repository.
*/
private UserRepository userRepository = UserRepositoryImpl.getInstance();
/**
* Article query service.
*/
private ArticleQueryService articleQueryService = ArticleQueryService.getInstance();
/**
* {@code true} for published.
*/
private static final boolean PUBLISHED = true;
/**
* Fills articles in index.ftl.
*
* @param dataModel data model
* @param currentPageNum current page number
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillIndexArticles(final Map<String, Object> dataModel, final int currentPageNum, final JSONObject preference)
throws ServiceException {
Stopwatchs.start("Fill Index Articles");
try {
final int pageSize = preference.getInt(Preference.ARTICLE_LIST_DISPLAY_COUNT);
final int windowSize = preference.getInt(Preference.ARTICLE_LIST_PAGINATION_WINDOW_SIZE);
final JSONObject statistic = statisticRepository.get(Statistic.STATISTIC);
final int publishedArticleCnt = statistic.getInt(Statistic.STATISTIC_PUBLISHED_ARTICLE_COUNT);
final int pageCount = (int) Math.ceil((double) publishedArticleCnt / (double) pageSize);
final Query query = new Query().setCurrentPageNum(currentPageNum).setPageSize(pageSize).setPageCount(pageCount).
setFilter(new PropertyFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, PUBLISHED)).
addSort(Article.ARTICLE_PUT_TOP, SortDirection.DESCENDING).
index(Article.ARTICLE_PERMALINK);
if (preference.getBoolean(Preference.ENABLE_ARTICLE_UPDATE_HINT)) {
query.addSort(Article.ARTICLE_UPDATE_DATE, SortDirection.DESCENDING);
} else {
query.addSort(Article.ARTICLE_CREATE_DATE, SortDirection.DESCENDING);
}
final JSONObject result = articleRepository.get(query);
final List<Integer> pageNums = Paginator.paginate(currentPageNum, pageSize, pageCount, windowSize);
if (0 != pageNums.size()) {
dataModel.put(Pagination.PAGINATION_FIRST_PAGE_NUM, pageNums.get(0));
dataModel.put(Pagination.PAGINATION_LAST_PAGE_NUM, pageNums.get(pageNums.size() - 1));
}
dataModel.put(Pagination.PAGINATION_PAGE_COUNT, pageCount);
dataModel.put(Pagination.PAGINATION_PAGE_NUMS, pageNums);
final List<JSONObject> articles = org.b3log.latke.util.CollectionUtils.jsonArrayToList(result.getJSONArray(Keys.RESULTS));
final boolean hasMultipleUsers = Users.getInstance().hasMultipleUsers();
if (hasMultipleUsers) {
setArticlesExProperties(articles, preference);
} else {
if (!articles.isEmpty()) {
final JSONObject author = articleUtils.getAuthor(articles.get(0));
setArticlesExProperties(articles, author, preference);
}
}
dataModel.put(Article.ARTICLES, articles);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills index articles failed", e);
throw new ServiceException(e);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills index articles failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills links.
*
* @param dataModel data model
* @throws ServiceException service exception
*/
public void fillLinks(final Map<String, Object> dataModel) throws ServiceException {
Stopwatchs.start("Fill Links");
try {
final Map<String, SortDirection> sorts = new HashMap<String, SortDirection>();
sorts.put(Link.LINK_ORDER, SortDirection.ASCENDING);
final Query query = new Query().addSort(Link.LINK_ORDER, SortDirection.ASCENDING).setPageCount(1);
final JSONObject linkResult = linkRepository.get(query);
final List<JSONObject> links = org.b3log.latke.util.CollectionUtils.jsonArrayToList(linkResult.getJSONArray(Keys.RESULTS));
dataModel.put(Link.LINKS, links);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills links failed", e);
throw new ServiceException(e);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills links failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
Stopwatchs.end();
}
/**
* Fills most used tags.
*
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillMostUsedTags(final Map<String, Object> dataModel, final JSONObject preference) throws ServiceException {
Stopwatchs.start("Fill Most Used Tags");
try {
LOGGER.finer("Filling most used tags....");
final int mostUsedTagDisplayCnt = preference.getInt(Preference.MOST_USED_TAG_DISPLAY_CNT);
final List<JSONObject> tags = tagRepository.getMostUsedTags(mostUsedTagDisplayCnt);
tagUtils.removeForUnpublishedArticles(tags);
dataModel.put(Common.MOST_USED_TAGS, tags);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills most used tags failed", e);
throw new ServiceException(e);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills most used tags failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills archive dates.
*
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillArchiveDates(final Map<String, Object> dataModel, final JSONObject preference) throws ServiceException {
Stopwatchs.start("Fill Archive Dates");
try {
LOGGER.finer("Filling archive dates....");
final List<JSONObject> archiveDates = archiveDateRepository.getArchiveDates();
final String localeString = preference.getString(Preference.LOCALE_STRING);
final String language = Locales.getLanguage(localeString);
for (final JSONObject archiveDate : archiveDates) {
final long time = archiveDate.getLong(ArchiveDate.ARCHIVE_TIME);
final String dateString = ArchiveDate.DATE_FORMAT.format(time);
final String[] dateStrings = dateString.split("/");
final String year = dateStrings[0];
final String month = dateStrings[1];
archiveDate.put(ArchiveDate.ARCHIVE_DATE_YEAR, year);
archiveDate.put(ArchiveDate.ARCHIVE_DATE_MONTH, month);
if ("en".equals(language)) {
final String monthName = Dates.EN_MONTHS.get(month);
archiveDate.put(Common.MONTH_NAME, monthName);
}
}
dataModel.put(ArchiveDate.ARCHIVE_DATES, archiveDates);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills archive dates failed", e);
throw new ServiceException(e);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills archive dates failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills most view count articles.
*
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillMostViewCountArticles(final Map<String, Object> dataModel, final JSONObject preference) throws ServiceException {
Stopwatchs.start("Fill Most View Articles");
try {
LOGGER.finer("Filling the most view count articles....");
final int mostCommentArticleDisplayCnt = preference.getInt(Preference.MOST_VIEW_ARTICLE_DISPLAY_CNT);
final List<JSONObject> mostViewCountArticles = articleRepository.getMostViewCountArticles(mostCommentArticleDisplayCnt);
dataModel.put(Common.MOST_VIEW_COUNT_ARTICLES, mostViewCountArticles);
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Fills most view count articles failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills most comments articles.
*
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillMostCommentArticles(final Map<String, Object> dataModel, final JSONObject preference) throws ServiceException {
Stopwatchs.start("Fill Most CMMTs Articles");
try {
LOGGER.finer("Filling most comment articles....");
final int mostCommentArticleDisplayCnt = preference.getInt(Preference.MOST_COMMENT_ARTICLE_DISPLAY_CNT);
final List<JSONObject> mostCommentArticles = articleRepository.getMostCommentArticles(mostCommentArticleDisplayCnt);
dataModel.put(Common.MOST_COMMENT_ARTICLES, mostCommentArticles);
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Fills most comment articles failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills post articles recently.
*
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillRecentArticles(final Map<String, Object> dataModel, final JSONObject preference) throws ServiceException {
Stopwatchs.start("Fill Recent Articles");
try {
final int recentArticleDisplayCnt = preference.getInt(Preference.RECENT_ARTICLE_DISPLAY_CNT);
final List<JSONObject> recentArticles = articleRepository.getRecentArticles(recentArticleDisplayCnt);
dataModel.put(Common.RECENT_ARTICLES, recentArticles);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills recent articles failed", e);
throw new ServiceException(e);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills recent articles failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills post comments recently.
*
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillRecentComments(final Map<String, Object> dataModel, final JSONObject preference) throws ServiceException {
Stopwatchs.start("Fill Recent Comments");
try {
LOGGER.finer("Filling recent comments....");
final int recentCommentDisplayCnt = preference.getInt(Preference.RECENT_COMMENT_DISPLAY_CNT);
final List<JSONObject> recentComments = commentRepository.getRecentComments(recentCommentDisplayCnt);
for (final JSONObject comment : recentComments) {
final String content = comment.getString(Comment.COMMENT_CONTENT).replaceAll(SoloServletListener.ENTER_ESC, "&nbsp;");
comment.put(Comment.COMMENT_CONTENT, content);
comment.put(Comment.COMMENT_NAME, StringEscapeUtils.escapeHtml(comment.getString(Comment.COMMENT_NAME)));
comment.put(Comment.COMMENT_URL, StringEscapeUtils.escapeHtml(comment.getString(Comment.COMMENT_URL)));
comment.remove(Comment.COMMENT_EMAIL); // Erases email for security reason
}
dataModel.put(Common.RECENT_COMMENTS, recentComments);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills recent comments failed", e);
throw new ServiceException(e);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills recent comments failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills footer.ftl.
*
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillBlogFooter(final Map<String, Object> dataModel, final JSONObject preference) throws ServiceException {
Stopwatchs.start("Fill Footer");
try {
LOGGER.finer("Filling footer....");
final String blogTitle = preference.getString(Preference.BLOG_TITLE);
dataModel.put(Preference.BLOG_TITLE, blogTitle);
final String blogHost = preference.getString(Preference.BLOG_HOST);
dataModel.put(Preference.BLOG_HOST, blogHost);
dataModel.put(Common.VERSION, SoloServletListener.VERSION);
dataModel.put(Common.STATIC_RESOURCE_VERSION, Latkes.getStaticResourceVersion());
dataModel.put(Common.YEAR, String.valueOf(Calendar.getInstance().get(Calendar.YEAR)));
dataModel.put(Keys.Server.STATIC_SERVER, Latkes.getStaticServer());
dataModel.put(Keys.Server.SERVER, Latkes.getServer());
// Activates plugins
try {
final ViewLoadEventData data = new ViewLoadEventData();
data.setViewName("footer.ftl");
data.setDataModel(dataModel);
EventManager.getInstance().fireEventSynchronously(new Event<ViewLoadEventData>(AbstractAction.FREEMARKER_ACTION, data));
if (Strings.isEmptyOrNull((String) dataModel.get(Plugin.PLUGINS))) {
// There is no plugin for this template, fill ${plugins} with blank.
dataModel.put(Plugin.PLUGINS, "");
}
} catch (final EventException e) {
LOGGER.log(Level.WARNING, "Event[FREEMARKER_ACTION] handle failed, ignores this exception for kernel health", e);
}
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills blog footer failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills header.ftl.
*
* @param request the specified HTTP servlet request
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillBlogHeader(final HttpServletRequest request, final Map<String, Object> dataModel, final JSONObject preference)
throws ServiceException {
Stopwatchs.start("Fill Header");
try {
LOGGER.fine("Filling header....");
dataModel.put(Preference.ARTICLE_LIST_DISPLAY_COUNT, preference.getInt(Preference.ARTICLE_LIST_DISPLAY_COUNT));
dataModel.put(Preference.ARTICLE_LIST_PAGINATION_WINDOW_SIZE,
preference.getInt(Preference.ARTICLE_LIST_PAGINATION_WINDOW_SIZE));
dataModel.put(Preference.LOCALE_STRING, preference.getString(Preference.LOCALE_STRING));
dataModel.put(Preference.BLOG_TITLE, preference.getString(Preference.BLOG_TITLE));
dataModel.put(Preference.BLOG_SUBTITLE, preference.getString(Preference.BLOG_SUBTITLE));
dataModel.put(Preference.HTML_HEAD, preference.getString(Preference.HTML_HEAD));
dataModel.put(Preference.META_KEYWORDS, preference.getString(Preference.META_KEYWORDS));
dataModel.put(Preference.META_DESCRIPTION, preference.getString(Preference.META_DESCRIPTION));
dataModel.put(Common.YEAR, String.valueOf(Calendar.getInstance().get(Calendar.YEAR)));
final String noticeBoard = preference.getString(Preference.NOTICE_BOARD);
dataModel.put(Preference.NOTICE_BOARD, noticeBoard);
final Query query = new Query().setPageCount(1);
final JSONObject result = userRepository.get(query);
final JSONArray users = result.getJSONArray(Keys.RESULTS);
final List<JSONObject> userList = CollectionUtils.jsonArrayToList(users);
dataModel.put(User.USERS, userList);
for (final JSONObject user : userList) {
user.remove(User.USER_EMAIL);
}
final String skinDirName = (String) request.getAttribute(Keys.TEMAPLTE_DIR_NAME);
dataModel.put(Skin.SKIN_DIR_NAME, skinDirName);
Keys.fillServer(dataModel);
fillMinified(dataModel);
fillPageNavigations(dataModel);
fillStatistic(dataModel);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills blog header failed", e);
throw new ServiceException(e);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills blog header failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills minified directory and file postfix for static JavaScript, CSS.
*
* @param dataModel the specified data model
*/
public void fillMinified(final Map<String, Object> dataModel) {
switch (Latkes.getRuntimeMode()) {
case DEVELOPMENT:
dataModel.put(Common.MINI_POSTFIX, "");
break;
case PRODUCTION:
dataModel.put(Common.MINI_POSTFIX, Common.MINI_POSTFIX_VALUE);
break;
default:
throw new AssertionError();
}
}
/**
* Fills side.ftl.
*
* @param request the specified HTTP servlet request
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillSide(final HttpServletRequest request, final Map<String, Object> dataModel, final JSONObject preference)
throws ServiceException {
Stopwatchs.start("Fill Side");
try {
LOGGER.fine("Filling side....");
final Template template = Templates.getTemplate((String) request.getAttribute(Keys.TEMAPLTE_DIR_NAME), "side.ftl");
if (null == template) {
LOGGER.fine("The skin dose not contain [side.ftl] template");
return;
}
// TODO: fillRecentArticles(dataModel, preference);
if (Templates.hasExpression(template, "<#list links as link>")) {
fillLinks(dataModel);
}
if (Templates.hasExpression(template, "<#list recentComments as comment>")) {
fillRecentComments(dataModel, preference);
}
if (Templates.hasExpression(template, "<#list mostUsedTags as tag>")) {
fillMostUsedTags(dataModel, preference);
}
if (Templates.hasExpression(template, "<#list mostCommentArticles as article>")) {
fillMostCommentArticles(dataModel, preference);
}
if (Templates.hasExpression(template, "<#list mostViewCountArticles as article>")) {
fillMostViewCountArticles(dataModel, preference);
}
if (Templates.hasExpression(template, "<#list archiveDates as archiveDate>")) {
fillArchiveDates(dataModel, preference);
}
} catch (final ServiceException e) {
LOGGER.log(Level.SEVERE, "Fills side failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills the specified template.
*
* @param template the specified template
* @param dataModel data model
* @param preference the specified preference
* @throws ServiceException service exception
*/
public void fillUserTemplate(final Template template, final Map<String, Object> dataModel, final JSONObject preference)
throws ServiceException {
Stopwatchs.start("Fill User Template[name=" + template.getName() + "]");
try {
LOGGER.log(Level.FINE, "Filling user template[name{0}]", template.getName());
if (Templates.hasExpression(template, "<#list links as link>")) {
fillLinks(dataModel);
}
if (Templates.hasExpression(template, "<#list recentComments as comment>")) {
fillRecentComments(dataModel, preference);
}
if (Templates.hasExpression(template, "<#list mostUsedTags as tag>")) {
fillMostUsedTags(dataModel, preference);
}
if (Templates.hasExpression(template, "<#list mostCommentArticles as article>")) {
fillMostCommentArticles(dataModel, preference);
}
if (Templates.hasExpression(template, "<#list mostViewCountArticles as article>")) {
fillMostViewCountArticles(dataModel, preference);
}
if (Templates.hasExpression(template, "<#list archiveDates as archiveDate>")) {
fillArchiveDates(dataModel, preference);
}
final String noticeBoard = preference.getString(Preference.NOTICE_BOARD);
dataModel.put(Preference.NOTICE_BOARD, noticeBoard);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Fills user template failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills page navigations.
*
* @param dataModel data model
* @throws ServiceException service exception
*/
private void fillPageNavigations(final Map<String, Object> dataModel) throws ServiceException {
Stopwatchs.start("Fill Navigations");
try {
LOGGER.finer("Filling page navigations....");
final List<JSONObject> pages = pageRepository.getPages();
for (final JSONObject page : pages) {
if ("page".equals(page.optString(Page.PAGE_TYPE))) {
final String permalink = page.optString(Page.PAGE_PERMALINK);
page.put(Page.PAGE_PERMALINK, Latkes.getServePath() + permalink);
}
}
dataModel.put(Common.PAGE_NAVIGATIONS, pages);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills page navigations failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Fills statistic.
*
* @param dataModel data model
* @throws ServiceException service exception
*/
private void fillStatistic(final Map<String, Object> dataModel) throws ServiceException {
Stopwatchs.start("Fill Statistic");
try {
LOGGER.finer("Filling statistic....");
final JSONObject statistic = statisticRepository.get(Statistic.STATISTIC);
dataModel.put(Statistic.STATISTIC, statistic);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Fills statistic failed", e);
throw new ServiceException(e);
} finally {
Stopwatchs.end();
}
}
/**
* Sets some extra properties into the specified article with the specified author and preference, performs content and
* abstract editor processing.
*
* <p>
* Article ext properties:
* <pre>
* {
* ....,
* "authorName": "",
* "authorId": "",
* "hasUpdated": boolean
* }
* </pre>
* </p>
*
* @param article the specified article
* @param author the specified author
* @param preference the specified preference
* @throws ServiceException service exception
* @see #setArticlesExProperties(java.util.List, org.json.JSONObject)
*/
private void setArticleExProperties(final JSONObject article, final JSONObject author, final JSONObject preference)
throws ServiceException {
try {
final String authorName = author.getString(User.USER_NAME);
article.put(Common.AUTHOR_NAME, authorName);
final String authorId = author.getString(Keys.OBJECT_ID);
article.put(Common.AUTHOR_ID, authorId);
if (preference.getBoolean(Preference.ENABLE_ARTICLE_UPDATE_HINT)) {
article.put(Common.HAS_UPDATED, articleUtils.hasUpdated(article));
} else {
article.put(Common.HAS_UPDATED, false);
}
processArticleAbstract(preference, article);
articleQueryService.markdown(article);
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Sets article extra properties failed", e);
throw new ServiceException(e);
}
}
/**
* Sets some extra properties into the specified article with the specified preference, performs content and
* abstract editor processing.
*
* <p>
* Article ext properties:
* <pre>
* {
* ....,
* "authorName": "",
* "authorId": "",
* "hasUpdated": boolean
* }
* </pre>
* </p>
*
* @param article the specified article
* @param preference the specified preference
* @throws ServiceException service exception
* @see #setArticlesExProperties(java.util.List, org.json.JSONObject)
*/
private void setArticleExProperties(final JSONObject article, final JSONObject preference) throws ServiceException {
try {
final JSONObject author = articleUtils.getAuthor(article);
final String authorName = author.getString(User.USER_NAME);
article.put(Common.AUTHOR_NAME, authorName);
final String authorId = author.getString(Keys.OBJECT_ID);
article.put(Common.AUTHOR_ID, authorId);
if (preference.getBoolean(Preference.ENABLE_ARTICLE_UPDATE_HINT)) {
article.put(Common.HAS_UPDATED, articleUtils.hasUpdated(article));
} else {
article.put(Common.HAS_UPDATED, false);
}
processArticleAbstract(preference, article);
articleQueryService.markdown(article);
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Sets article extra properties failed", e);
throw new ServiceException(e);
}
}
/**
* Sets some extra properties into the specified article with the specified
* author and preference.
*
* <p>
* The batch version of method
* {@linkplain #setArticleExProperties(org.json.JSONObject, org.json.JSONObject)}.
* </p>
*
* <p>
* Article ext properties:
* <pre>
* {
* ....,
* "authorName": "",
* "authorId": "",
* "hasUpdated": boolean
* }
* </pre>
* </p>
*
* @param articles the specified articles
* @param author the specified author
* @param preference the specified preference
* @throws ServiceException service exception
* @see #setArticleExProperties(org.json.JSONObject, org.json.JSONObject)
*/
public void setArticlesExProperties(final List<JSONObject> articles, final JSONObject author, final JSONObject preference)
throws ServiceException {
for (final JSONObject article : articles) {
setArticleExProperties(article, author, preference);
}
}
/**
* Sets some extra properties into the specified article with the specified
* preference.
*
* <p>
* The batch version of method
* {@linkplain #setArticleExProperties(org.json.JSONObject, org.json.JSONObject)}.
* </p>
*
* <p>
* Article ext properties:
* <pre>
* {
* ....,
* "authorName": "",
* "authorId": "",
* "hasUpdated": boolean
* }
* </pre>
* </p>
*
* @param articles the specified articles
* @param preference the specified preference
* @throws ServiceException service exception
* @see #setArticleExProperties(org.json.JSONObject, org.json.JSONObject)
*/
public void setArticlesExProperties(final List<JSONObject> articles, final JSONObject preference)
throws ServiceException {
for (final JSONObject article : articles) {
setArticleExProperties(article, preference);
}
}
/**
* Processes the abstract of the specified article with the specified preference.
*
* <p>
* <ul>
* <li>If the abstract is {@code null}, sets it with ""</li>
* <li>If user configured preference "titleOnly", sets the abstract with ""</li>
* <li>If user configured preference "titleAndContent", sets the abstract with the content of the article</li>
* </ul>
* </p>
*
* @param preference the specified preference
* @param article the specified article
*/
private void processArticleAbstract(final JSONObject preference, final JSONObject article) {
final String articleAbstract = article.optString(Article.ARTICLE_ABSTRACT, null);
if (null == articleAbstract) {
article.put(Article.ARTICLE_ABSTRACT, "");
}
final String articleListStyle = preference.optString(Preference.ARTICLE_LIST_STYLE);
if ("titleOnly".equals(articleListStyle)) {
article.put(Article.ARTICLE_ABSTRACT, "");
} else if ("titleAndContent".equals(articleListStyle)) {
article.put(Article.ARTICLE_ABSTRACT, article.optString(Article.ARTICLE_CONTENT));
}
}
/**
* Gets the {@link Filler} singleton.
*
* @return the singleton
*/
public static Filler getInstance() {
return SingletonHolder.SINGLETON;
}
/**
* Private default constructor.
*/
private Filler() {
}
/**
* Singleton holder.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.0, Jan 12, 2011
*/
private static final class SingletonHolder {
/**
* Singleton.
*/
private static final Filler SINGLETON = new Filler();
/**
* Private default constructor.
*/
private SingletonHolder() {
}
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.AbstractRepository;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.Query;
import org.b3log.solo.model.Article;
import org.b3log.latke.repository.RepositoryException;
import org.b3log.latke.repository.SortDirection;
import org.b3log.solo.model.ArchiveDate;
import org.b3log.solo.repository.ArchiveDateArticleRepository;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Archive date-Article relation repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.6, Nov 9, 2011
* @since 0.3.1
*/
public final class ArchiveDateArticleRepositoryImpl extends AbstractRepository implements ArchiveDateArticleRepository {
/**
* Singleton.
*/
private static final ArchiveDateArticleRepositoryImpl SINGLETON =
new ArchiveDateArticleRepositoryImpl(ArchiveDate.ARCHIVE_DATE + "_" + Article.ARTICLE);
@Override
public JSONObject getByArchiveDateId(final String archiveDateId, final int currentPageNum, final int pageSize)
throws RepositoryException {
final Query query = new Query().addFilter(ArchiveDate.ARCHIVE_DATE + "_" + Keys.OBJECT_ID,
FilterOperator.EQUAL, archiveDateId).
addSort(Article.ARTICLE + "_" + Keys.OBJECT_ID,
SortDirection.DESCENDING).
setCurrentPageNum(currentPageNum).
setPageSize(pageSize).
setPageCount(1);
return get(query);
}
@Override
public JSONObject getByArticleId(final String articleId) throws RepositoryException {
final Query query = new Query();
query.addFilter(Article.ARTICLE + "_" + Keys.OBJECT_ID, FilterOperator.EQUAL, articleId);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
/**
* Gets the {@link ArchiveDateArticleRepositoryImpl} singleton.
*
* @return the singleton
*/
public static ArchiveDateArticleRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private ArchiveDateArticleRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.*;
import org.b3log.solo.model.Article;
import org.b3log.solo.model.ArchiveDate;
import org.b3log.solo.repository.ArchiveDateArticleRepository;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Archive date-Article relation repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.6, Nov 9, 2011
* @since 0.3.1
*/
public final class ArchiveDateArticleRepositoryImpl extends AbstractRepository implements ArchiveDateArticleRepository {
/**
* Singleton.
*/
private static final ArchiveDateArticleRepositoryImpl SINGLETON =
new ArchiveDateArticleRepositoryImpl(ArchiveDate.ARCHIVE_DATE + "_" + Article.ARTICLE);
@Override
public JSONObject getByArchiveDateId(final String archiveDateId, final int currentPageNum, final int pageSize)
throws RepositoryException {
final Query query = new Query().setFilter(new PropertyFilter(ArchiveDate.ARCHIVE_DATE + "_" + Keys.OBJECT_ID,
FilterOperator.EQUAL, archiveDateId)).
addSort(Article.ARTICLE + "_" + Keys.OBJECT_ID,
SortDirection.DESCENDING).
setCurrentPageNum(currentPageNum).
setPageSize(pageSize).
setPageCount(1);
return get(query);
}
@Override
public JSONObject getByArticleId(final String articleId) throws RepositoryException {
final Query query = new Query();
query.setFilter(new PropertyFilter(Article.ARTICLE + "_" + Keys.OBJECT_ID, FilterOperator.EQUAL, articleId));
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
/**
* Gets the {@link ArchiveDateArticleRepositoryImpl} singleton.
*
* @return the singleton
*/
public static ArchiveDateArticleRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private ArchiveDateArticleRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import java.text.ParseException;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.AbstractRepository;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.Query;
import org.b3log.latke.repository.RepositoryException;
import org.b3log.latke.repository.SortDirection;
import org.b3log.latke.util.CollectionUtils;
import org.b3log.solo.model.ArchiveDate;
import org.b3log.solo.repository.ArchiveDateRepository;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Archive date repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.6, Dec 31, 2011
* @since 0.3.1
*/
public final class ArchiveDateRepositoryImpl extends AbstractRepository implements ArchiveDateRepository {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(ArchiveDateRepositoryImpl.class.getName());
/**
* Singleton.
*/
private static final ArchiveDateRepositoryImpl SINGLETON = new ArchiveDateRepositoryImpl(ArchiveDate.ARCHIVE_DATE);
@Override
public JSONObject getByArchiveDate(final String archiveDate) throws RepositoryException {
long time = 0L;
try {
time = ArchiveDate.DATE_FORMAT.parse(archiveDate).getTime();
} catch (final ParseException e) {
LOGGER.log(Level.SEVERE, "Can not parse archive date [" + archiveDate + "]", e);
throw new RepositoryException("Can not parse archive date [" + archiveDate + "]");
}
final Query query = new Query();
query.addFilter(ArchiveDate.ARCHIVE_TIME, FilterOperator.EQUAL, time).setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public List<JSONObject> getArchiveDates() throws RepositoryException {
final org.b3log.latke.repository.Query query =
new Query().addSort(ArchiveDate.ARCHIVE_TIME, SortDirection.DESCENDING).setPageCount(1);
final JSONObject result = get(query);
final JSONArray archiveDates = result.optJSONArray(Keys.RESULTS);
final List<JSONObject> ret = CollectionUtils.jsonArrayToList(archiveDates);
removeForUnpublishedArticles(ret);
return ret;
}
/**
* Removes archive dates of unpublished articles from the specified archive
* dates.
*
* @param archiveDates the specified archive dates
* @throws RepositoryException repository exception
*/
private void removeForUnpublishedArticles(final List<JSONObject> archiveDates) throws RepositoryException {
final Iterator<JSONObject> iterator = archiveDates.iterator();
while (iterator.hasNext()) {
final JSONObject archiveDate = iterator.next();
if (0 == archiveDate.optInt(ArchiveDate.ARCHIVE_DATE_PUBLISHED_ARTICLE_COUNT)) {
iterator.remove();
}
}
}
/**
* Gets the {@link ArchiveDateRepositoryImpl} singleton.
*
* @return the singleton
*/
public static ArchiveDateRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private ArchiveDateRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import java.text.ParseException;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.*;
import org.b3log.latke.util.CollectionUtils;
import org.b3log.solo.model.ArchiveDate;
import org.b3log.solo.repository.ArchiveDateRepository;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Archive date repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.6, Dec 31, 2011
* @since 0.3.1
*/
public final class ArchiveDateRepositoryImpl extends AbstractRepository implements ArchiveDateRepository {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(ArchiveDateRepositoryImpl.class.getName());
/**
* Singleton.
*/
private static final ArchiveDateRepositoryImpl SINGLETON = new ArchiveDateRepositoryImpl(ArchiveDate.ARCHIVE_DATE);
@Override
public JSONObject getByArchiveDate(final String archiveDate) throws RepositoryException {
long time = 0L;
try {
time = ArchiveDate.DATE_FORMAT.parse(archiveDate).getTime();
} catch (final ParseException e) {
LOGGER.log(Level.SEVERE, "Can not parse archive date [" + archiveDate + "]", e);
throw new RepositoryException("Can not parse archive date [" + archiveDate + "]");
}
final Query query = new Query();
query.setFilter(new PropertyFilter(ArchiveDate.ARCHIVE_TIME, FilterOperator.EQUAL, time)).setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public List<JSONObject> getArchiveDates() throws RepositoryException {
final org.b3log.latke.repository.Query query =
new Query().addSort(ArchiveDate.ARCHIVE_TIME, SortDirection.DESCENDING).setPageCount(1);
final JSONObject result = get(query);
final JSONArray archiveDates = result.optJSONArray(Keys.RESULTS);
final List<JSONObject> ret = CollectionUtils.jsonArrayToList(archiveDates);
removeForUnpublishedArticles(ret);
return ret;
}
/**
* Removes archive dates of unpublished articles from the specified archive
* dates.
*
* @param archiveDates the specified archive dates
* @throws RepositoryException repository exception
*/
private void removeForUnpublishedArticles(final List<JSONObject> archiveDates) throws RepositoryException {
final Iterator<JSONObject> iterator = archiveDates.iterator();
while (iterator.hasNext()) {
final JSONObject archiveDate = iterator.next();
if (0 == archiveDate.optInt(ArchiveDate.ARCHIVE_DATE_PUBLISHED_ARTICLE_COUNT)) {
iterator.remove();
}
}
}
/**
* Gets the {@link ArchiveDateRepositoryImpl} singleton.
*
* @return the singleton
*/
public static ArchiveDateRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private ArchiveDateRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.b3log.solo.model.Article;
import org.b3log.solo.repository.ArticleRepository;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.*;
import org.b3log.latke.util.CollectionUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Article repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.3.9, May 8, 2012
* @since 0.3.1
*/
public final class ArticleRepositoryImpl extends AbstractRepository implements ArticleRepository {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(ArticleRepositoryImpl.class.getName());
/**
* Singleton.
*/
private static final ArticleRepositoryImpl SINGLETON = new ArticleRepositoryImpl(Article.ARTICLE);
/**
* Random range.
*/
private static final double RANDOM_RANGE = 0.1D;
@Override
public JSONObject getByAuthorEmail(final String authorEmail, final int currentPageNum, final int pageSize)
throws RepositoryException {
final Query query = new Query().addFilter(Article.ARTICLE_AUTHOR_EMAIL, FilterOperator.EQUAL, authorEmail).
addFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true).
addSort(Article.ARTICLE_UPDATE_DATE, SortDirection.DESCENDING).
setCurrentPageNum(currentPageNum).setPageSize(pageSize).setPageCount(1);
return get(query);
}
@Override
public JSONObject getByPermalink(final String permalink) throws RepositoryException {
final Query query = new Query().addFilter(Article.ARTICLE_PERMALINK, FilterOperator.EQUAL, permalink).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public List<JSONObject> getRecentArticles(final int fetchSize) throws RepositoryException {
final Query query = new Query();
query.addFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true);
query.addSort(Article.ARTICLE_UPDATE_DATE, SortDirection.DESCENDING);
query.setCurrentPageNum(1);
query.setPageSize(fetchSize);
query.setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
return CollectionUtils.jsonArrayToList(array);
}
@Override
public List<JSONObject> getMostCommentArticles(final int num) throws RepositoryException {
final Query query = new Query().addSort(Article.ARTICLE_COMMENT_COUNT, SortDirection.DESCENDING).
addSort(Article.ARTICLE_UPDATE_DATE, SortDirection.DESCENDING).
addFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true).
setCurrentPageNum(1).setPageSize(num).setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
return CollectionUtils.jsonArrayToList(array);
}
@Override
public List<JSONObject> getMostViewCountArticles(final int num) throws RepositoryException {
final Query query = new Query();
query.addSort(Article.ARTICLE_VIEW_COUNT, SortDirection.DESCENDING).
addSort(Article.ARTICLE_UPDATE_DATE, SortDirection.DESCENDING);
query.addFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true);
query.setCurrentPageNum(1);
query.setPageSize(num);
query.setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
return CollectionUtils.jsonArrayToList(array);
}
@Override
public JSONObject getPreviousArticle(final String articleId) throws RepositoryException {
final JSONObject currentArticle = get(articleId);
final Date currentArticleCreateDate = (Date) currentArticle.opt(Article.ARTICLE_CREATE_DATE);
final Query query = new Query().addFilter(Article.ARTICLE_CREATE_DATE, FilterOperator.LESS_THAN, currentArticleCreateDate).
addFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true).
addSort(Article.ARTICLE_CREATE_DATE, SortDirection.DESCENDING).setCurrentPageNum(1).
setPageSize(1).setPageCount(1).
addProjection(Article.ARTICLE_TITLE, String.class).
addProjection(Article.ARTICLE_PERMALINK, String.class);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (1 != array.length()) {
return null;
}
final JSONObject ret = new JSONObject();
final JSONObject article = array.optJSONObject(0);
try {
ret.put(Article.ARTICLE_TITLE, article.getString(Article.ARTICLE_TITLE));
ret.put(Article.ARTICLE_PERMALINK, article.getString(Article.ARTICLE_PERMALINK));
} catch (final JSONException e) {
throw new RepositoryException(e);
}
return ret;
}
@Override
public JSONObject getNextArticle(final String articleId) throws RepositoryException {
final JSONObject currentArticle = get(articleId);
final Date currentArticleCreateDate = (Date) currentArticle.opt(Article.ARTICLE_CREATE_DATE);
final Query query = new Query().addFilter(Article.ARTICLE_CREATE_DATE, FilterOperator.GREATER_THAN, currentArticleCreateDate).
addFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true).
addSort(Article.ARTICLE_CREATE_DATE, SortDirection.ASCENDING).setCurrentPageNum(1).
setPageSize(1).setPageCount(1).
addProjection(Article.ARTICLE_TITLE, String.class).
addProjection(Article.ARTICLE_PERMALINK, String.class);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (1 != array.length()) {
return null;
}
final JSONObject ret = new JSONObject();
final JSONObject article = array.optJSONObject(0);
try {
ret.put(Article.ARTICLE_TITLE, article.getString(Article.ARTICLE_TITLE));
ret.put(Article.ARTICLE_PERMALINK, article.getString(Article.ARTICLE_PERMALINK));
} catch (final JSONException e) {
throw new RepositoryException(e);
}
return ret;
}
@Override
public boolean isPublished(final String articleId) throws RepositoryException {
final JSONObject article = get(articleId);
if (null == article) {
return false;
}
return article.optBoolean(Article.ARTICLE_IS_PUBLISHED);
}
@Override
public List<JSONObject> getRandomly(final int fetchSize) throws RepositoryException {
final List<JSONObject> ret = new ArrayList<JSONObject>();
if (0 == count()) {
return ret;
}
final double mid = Math.random() + RANDOM_RANGE;
LOGGER.log(Level.FINEST, "Random mid[{0}]", mid);
Query query = new Query();
query.addFilter(Article.ARTICLE_RANDOM_DOUBLE, FilterOperator.GREATER_THAN_OR_EQUAL, mid);
query.addFilter(Article.ARTICLE_RANDOM_DOUBLE, FilterOperator.LESS_THAN_OR_EQUAL, mid);
query.addFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true);
query.setCurrentPageNum(1);
query.setPageSize(fetchSize);
query.setPageCount(1);
final JSONObject result1 = get(query);
final JSONArray array1 = result1.optJSONArray(Keys.RESULTS);
final List<JSONObject> list1 = CollectionUtils.<JSONObject>jsonArrayToList(array1);
ret.addAll(list1);
final int reminingSize = fetchSize - array1.length();
if (0 != reminingSize) { // Query for remains
query = new Query();
query.addFilter(Article.ARTICLE_RANDOM_DOUBLE, FilterOperator.GREATER_THAN_OR_EQUAL, 0D);
query.addFilter(Article.ARTICLE_RANDOM_DOUBLE, FilterOperator.LESS_THAN_OR_EQUAL, mid);
query.addFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true);
query.setCurrentPageNum(1);
query.setPageSize(reminingSize);
query.setPageCount(1);
final JSONObject result2 = get(query);
final JSONArray array2 = result2.optJSONArray(Keys.RESULTS);
final List<JSONObject> list2 = CollectionUtils.<JSONObject>jsonArrayToList(array2);
ret.addAll(list2);
}
return ret;
}
/**
* Gets the {@link ArticleRepositoryImpl} singleton.
*
* @return the singleton
*/
public static ArticleRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private ArticleRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.b3log.solo.model.Article;
import org.b3log.solo.repository.ArticleRepository;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.*;
import org.b3log.latke.util.CollectionUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Article repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.3.9, May 8, 2012
* @since 0.3.1
*/
public final class ArticleRepositoryImpl extends AbstractRepository implements ArticleRepository {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(ArticleRepositoryImpl.class.getName());
/**
* Singleton.
*/
private static final ArticleRepositoryImpl SINGLETON = new ArticleRepositoryImpl(Article.ARTICLE);
/**
* Random range.
*/
private static final double RANDOM_RANGE = 0.1D;
@Override
public JSONObject getByAuthorEmail(final String authorEmail, final int currentPageNum, final int pageSize)
throws RepositoryException {
final Query query = new Query().setFilter(CompositeFilterOperator.and(
new PropertyFilter(Article.ARTICLE_AUTHOR_EMAIL, FilterOperator.EQUAL, authorEmail),
new PropertyFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true))).
addSort(Article.ARTICLE_UPDATE_DATE, SortDirection.DESCENDING).
setCurrentPageNum(currentPageNum).setPageSize(pageSize).setPageCount(1);
return get(query);
}
@Override
public JSONObject getByPermalink(final String permalink) throws RepositoryException {
final Query query = new Query().setFilter(
new PropertyFilter(Article.ARTICLE_PERMALINK, FilterOperator.EQUAL, permalink)).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public List<JSONObject> getRecentArticles(final int fetchSize) throws RepositoryException {
final Query query = new Query();
query.setFilter(new PropertyFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true));
query.addSort(Article.ARTICLE_UPDATE_DATE, SortDirection.DESCENDING);
query.setCurrentPageNum(1);
query.setPageSize(fetchSize);
query.setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
return CollectionUtils.jsonArrayToList(array);
}
@Override
public List<JSONObject> getMostCommentArticles(final int num) throws RepositoryException {
final Query query = new Query().addSort(Article.ARTICLE_COMMENT_COUNT, SortDirection.DESCENDING).
addSort(Article.ARTICLE_UPDATE_DATE, SortDirection.DESCENDING).
setFilter(new PropertyFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true)).
setCurrentPageNum(1).setPageSize(num).setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
return CollectionUtils.jsonArrayToList(array);
}
@Override
public List<JSONObject> getMostViewCountArticles(final int num) throws RepositoryException {
final Query query = new Query();
query.addSort(Article.ARTICLE_VIEW_COUNT, SortDirection.DESCENDING).
addSort(Article.ARTICLE_UPDATE_DATE, SortDirection.DESCENDING);
query.setFilter(new PropertyFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true));
query.setCurrentPageNum(1);
query.setPageSize(num);
query.setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
return CollectionUtils.jsonArrayToList(array);
}
@Override
public JSONObject getPreviousArticle(final String articleId) throws RepositoryException {
final JSONObject currentArticle = get(articleId);
final Date currentArticleCreateDate = (Date) currentArticle.opt(Article.ARTICLE_CREATE_DATE);
final Query query = new Query().setFilter(
CompositeFilterOperator.and(
new PropertyFilter(Article.ARTICLE_CREATE_DATE, FilterOperator.LESS_THAN, currentArticleCreateDate),
new PropertyFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true))).
addSort(Article.ARTICLE_CREATE_DATE, SortDirection.DESCENDING).setCurrentPageNum(1).
setPageSize(1).setPageCount(1).
addProjection(Article.ARTICLE_TITLE, String.class).
addProjection(Article.ARTICLE_PERMALINK, String.class);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (1 != array.length()) {
return null;
}
final JSONObject ret = new JSONObject();
final JSONObject article = array.optJSONObject(0);
try {
ret.put(Article.ARTICLE_TITLE, article.getString(Article.ARTICLE_TITLE));
ret.put(Article.ARTICLE_PERMALINK, article.getString(Article.ARTICLE_PERMALINK));
} catch (final JSONException e) {
throw new RepositoryException(e);
}
return ret;
}
@Override
public JSONObject getNextArticle(final String articleId) throws RepositoryException {
final JSONObject currentArticle = get(articleId);
final Date currentArticleCreateDate = (Date) currentArticle.opt(Article.ARTICLE_CREATE_DATE);
final Query query = new Query().setFilter(
CompositeFilterOperator.and(
new PropertyFilter(Article.ARTICLE_CREATE_DATE, FilterOperator.GREATER_THAN, currentArticleCreateDate),
new PropertyFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true))).
addSort(Article.ARTICLE_CREATE_DATE, SortDirection.ASCENDING).setCurrentPageNum(1).
setPageSize(1).setPageCount(1).
addProjection(Article.ARTICLE_TITLE, String.class).
addProjection(Article.ARTICLE_PERMALINK, String.class);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (1 != array.length()) {
return null;
}
final JSONObject ret = new JSONObject();
final JSONObject article = array.optJSONObject(0);
try {
ret.put(Article.ARTICLE_TITLE, article.getString(Article.ARTICLE_TITLE));
ret.put(Article.ARTICLE_PERMALINK, article.getString(Article.ARTICLE_PERMALINK));
} catch (final JSONException e) {
throw new RepositoryException(e);
}
return ret;
}
@Override
public boolean isPublished(final String articleId) throws RepositoryException {
final JSONObject article = get(articleId);
if (null == article) {
return false;
}
return article.optBoolean(Article.ARTICLE_IS_PUBLISHED);
}
@Override
public List<JSONObject> getRandomly(final int fetchSize) throws RepositoryException {
final List<JSONObject> ret = new ArrayList<JSONObject>();
if (0 == count()) {
return ret;
}
final double mid = Math.random() + RANDOM_RANGE;
LOGGER.log(Level.FINEST, "Random mid[{0}]", mid);
Query query = new Query();
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_IS_PUBLISHED, FilterOperator.EQUAL, true)));
query.setCurrentPageNum(1);
query.setPageSize(fetchSize);
query.setPageCount(1);
final JSONObject result1 = get(query);
final JSONArray array1 = result1.optJSONArray(Keys.RESULTS);
final List<JSONObject> list1 = CollectionUtils.<JSONObject>jsonArrayToList(array1);
ret.addAll(list1);
final int reminingSize = fetchSize - array1.length();
if (0 != reminingSize) { // Query for remains
query = new Query();
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_IS_PUBLISHED, FilterOperator.EQUAL, true)));
query.setCurrentPageNum(1);
query.setPageSize(reminingSize);
query.setPageCount(1);
final JSONObject result2 = get(query);
final JSONArray array2 = result2.optJSONArray(Keys.RESULTS);
final List<JSONObject> list2 = CollectionUtils.<JSONObject>jsonArrayToList(array2);
ret.addAll(list2);
}
return ret;
}
/**
* Gets the {@link ArticleRepositoryImpl} singleton.
*
* @return the singleton
*/
public static ArticleRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private ArticleRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.b3log.latke.Keys;
import org.b3log.latke.cache.Cache;
import org.b3log.latke.repository.AbstractRepository;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.Query;
import org.b3log.latke.repository.RepositoryException;
import org.b3log.latke.repository.SortDirection;
import org.b3log.solo.model.Comment;
import org.b3log.solo.repository.CommentRepository;
import org.b3log.latke.util.CollectionUtils;
import org.b3log.solo.model.Article;
import org.b3log.solo.repository.ArticleRepository;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Comment repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.8, Oct 18, 2011
* @since 0.3.1
*/
public final class CommentRepositoryImpl extends AbstractRepository implements CommentRepository {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(CommentRepositoryImpl.class.getName());
/**
* Singleton.
*/
private static final CommentRepositoryImpl SINGLETON = new CommentRepositoryImpl(Comment.COMMENT);
/**
* Article repository.
*/
private ArticleRepository articleRepository = ArticleRepositoryImpl.getInstance();
/**
* Recent comments query results cache key.
*/
public static final String RECENT_CMTS_CACHE_KEY = "recentCMTs";
@Override
public int removeComments(final String onId) throws RepositoryException {
final List<JSONObject> comments = getComments(onId, 1, Integer.MAX_VALUE);
for (final JSONObject comment : comments) {
final String commentId = comment.optString(Keys.OBJECT_ID);
remove(commentId);
}
LOGGER.log(Level.FINER, "Removed comments[onId={0}, removedCnt={1}]", new Object[]{onId, comments.size()});
return comments.size();
}
@Override
public List<JSONObject> getComments(final String onId, final int currentPageNum, final int pageSize)
throws RepositoryException {
final Query query = new Query().addSort(Keys.OBJECT_ID, SortDirection.DESCENDING).
addFilter(Comment.COMMENT_ON_ID, FilterOperator.EQUAL, onId).
setCurrentPageNum(currentPageNum).
setPageSize(pageSize).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
return CollectionUtils.jsonArrayToList(array);
}
@Override
@SuppressWarnings("unchecked")
public List<JSONObject> getRecentComments(final int num) throws RepositoryException {
if (isCacheEnabled()) {
final Cache<String, Serializable> cache = getCache();
final Object ret = cache.get(RECENT_CMTS_CACHE_KEY);
if (null != ret) {
return (List<JSONObject>) ret;
}
}
final Query query = new Query().addSort(Keys.OBJECT_ID, SortDirection.DESCENDING).
setCurrentPageNum(1).
setPageSize(num).setPageCount(1);
List<JSONObject> ret;
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
ret = CollectionUtils.jsonArrayToList(array);
// Removes unpublished article related comments
removeForUnpublishedArticles(ret);
if (isCacheEnabled()) {
final Cache<String, Serializable> cache = getCache();
cache.put(RECENT_CMTS_CACHE_KEY, (Serializable) ret);
}
return ret;
}
/**
* Removes comments of unpublished articles for the specified comments.
*
* @param comments the specified comments
* @throws RepositoryException repository exception
*/
private void removeForUnpublishedArticles(final List<JSONObject> comments) throws RepositoryException {
LOGGER.finer("Removing unpublished articles' comments....");
final Iterator<JSONObject> iterator = comments.iterator();
while (iterator.hasNext()) {
final JSONObject comment = iterator.next();
final String commentOnType = comment.optString(Comment.COMMENT_ON_TYPE);
if (Article.ARTICLE.equals(commentOnType)) {
final String articleId = comment.optString(Comment.COMMENT_ON_ID);
if (!articleRepository.isPublished(articleId)) {
iterator.remove();
}
}
}
LOGGER.finer("Removed unpublished articles' comments....");
}
/**
* Gets the {@link CommentRepositoryImpl} singleton.
*
* @return the singleton
*/
public static CommentRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private CommentRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.b3log.latke.Keys;
import org.b3log.latke.cache.Cache;
import org.b3log.latke.repository.*;
import org.b3log.solo.model.Comment;
import org.b3log.solo.repository.CommentRepository;
import org.b3log.latke.util.CollectionUtils;
import org.b3log.solo.model.Article;
import org.b3log.solo.repository.ArticleRepository;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Comment repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.8, Oct 18, 2011
* @since 0.3.1
*/
public final class CommentRepositoryImpl extends AbstractRepository implements CommentRepository {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(CommentRepositoryImpl.class.getName());
/**
* Singleton.
*/
private static final CommentRepositoryImpl SINGLETON = new CommentRepositoryImpl(Comment.COMMENT);
/**
* Article repository.
*/
private ArticleRepository articleRepository = ArticleRepositoryImpl.getInstance();
/**
* Recent comments query results cache key.
*/
public static final String RECENT_CMTS_CACHE_KEY = "recentCMTs";
@Override
public int removeComments(final String onId) throws RepositoryException {
final List<JSONObject> comments = getComments(onId, 1, Integer.MAX_VALUE);
for (final JSONObject comment : comments) {
final String commentId = comment.optString(Keys.OBJECT_ID);
remove(commentId);
}
LOGGER.log(Level.FINER, "Removed comments[onId={0}, removedCnt={1}]", new Object[]{onId, comments.size()});
return comments.size();
}
@Override
public List<JSONObject> getComments(final String onId, final int currentPageNum, final int pageSize)
throws RepositoryException {
final Query query = new Query().addSort(Keys.OBJECT_ID, SortDirection.DESCENDING).
setFilter(new PropertyFilter(Comment.COMMENT_ON_ID, FilterOperator.EQUAL, onId)).
setCurrentPageNum(currentPageNum).
setPageSize(pageSize).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
return CollectionUtils.jsonArrayToList(array);
}
@Override
@SuppressWarnings("unchecked")
public List<JSONObject> getRecentComments(final int num) throws RepositoryException {
if (isCacheEnabled()) {
final Cache<String, Serializable> cache = getCache();
final Object ret = cache.get(RECENT_CMTS_CACHE_KEY);
if (null != ret) {
return (List<JSONObject>) ret;
}
}
final Query query = new Query().addSort(Keys.OBJECT_ID, SortDirection.DESCENDING).
setCurrentPageNum(1).
setPageSize(num).setPageCount(1);
List<JSONObject> ret;
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
ret = CollectionUtils.jsonArrayToList(array);
// Removes unpublished article related comments
removeForUnpublishedArticles(ret);
if (isCacheEnabled()) {
final Cache<String, Serializable> cache = getCache();
cache.put(RECENT_CMTS_CACHE_KEY, (Serializable) ret);
}
return ret;
}
/**
* Removes comments of unpublished articles for the specified comments.
*
* @param comments the specified comments
* @throws RepositoryException repository exception
*/
private void removeForUnpublishedArticles(final List<JSONObject> comments) throws RepositoryException {
LOGGER.finer("Removing unpublished articles' comments....");
final Iterator<JSONObject> iterator = comments.iterator();
while (iterator.hasNext()) {
final JSONObject comment = iterator.next();
final String commentOnType = comment.optString(Comment.COMMENT_ON_TYPE);
if (Article.ARTICLE.equals(commentOnType)) {
final String articleId = comment.optString(Comment.COMMENT_ON_ID);
if (!articleRepository.isPublished(articleId)) {
iterator.remove();
}
}
}
LOGGER.finer("Removed unpublished articles' comments....");
}
/**
* Gets the {@link CommentRepositoryImpl} singleton.
*
* @return the singleton
*/
public static CommentRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private CommentRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import java.util.logging.Logger;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.AbstractRepository;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.Query;
import org.b3log.latke.repository.RepositoryException;
import org.b3log.latke.repository.SortDirection;
import org.b3log.solo.model.Link;
import org.b3log.solo.repository.LinkRepository;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Link repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.5, Nov 10, 2011
* @since 0.3.1
*/
public final class LinkRepositoryImpl extends AbstractRepository implements LinkRepository {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(LinkRepositoryImpl.class.getName());
/**
* Singleton.
*/
private static final LinkRepositoryImpl SINGLETON = new LinkRepositoryImpl(Link.LINK);
@Override
public JSONObject getByAddress(final String address) throws RepositoryException {
final Query query = new Query().addFilter(Link.LINK_ADDRESS, FilterOperator.EQUAL, address).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public int getMaxOrder() throws RepositoryException {
final Query query = new Query();
query.addSort(Link.LINK_ORDER, SortDirection.DESCENDING);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return -1;
}
return array.optJSONObject(0).optInt(Link.LINK_ORDER);
}
@Override
public JSONObject getByOrder(final int order) throws RepositoryException {
final Query query = new Query();
query.addFilter(Link.LINK_ORDER, FilterOperator.EQUAL, order);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public JSONObject getUpper(final String id) throws RepositoryException {
final JSONObject link = get(id);
if (null == link) {
return null;
}
final Query query = new Query();
query.addFilter(Link.LINK_ORDER, FilterOperator.LESS_THAN, link.optInt(Link.LINK_ORDER)).
addSort(Link.LINK_ORDER, SortDirection.DESCENDING);
query.setCurrentPageNum(1);
query.setPageSize(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (1 != array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public JSONObject getUnder(final String id) throws RepositoryException {
final JSONObject link = get(id);
if (null == link) {
return null;
}
final Query query = new Query();
query.addFilter(Link.LINK_ORDER, FilterOperator.GREATER_THAN, link.optInt(Link.LINK_ORDER)).
addSort(Link.LINK_ORDER, SortDirection.ASCENDING);
query.setCurrentPageNum(1);
query.setPageSize(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (1 != array.length()) {
return null;
}
return array.optJSONObject(0);
}
/**
* Gets the {@link LinkRepositoryImpl} singleton.
*
* @return the singleton
*/
public static LinkRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private LinkRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import java.util.logging.Logger;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.*;
import org.b3log.solo.model.Link;
import org.b3log.solo.repository.LinkRepository;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Link repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.5, Nov 10, 2011
* @since 0.3.1
*/
public final class LinkRepositoryImpl extends AbstractRepository implements LinkRepository {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(LinkRepositoryImpl.class.getName());
/**
* Singleton.
*/
private static final LinkRepositoryImpl SINGLETON = new LinkRepositoryImpl(Link.LINK);
@Override
public JSONObject getByAddress(final String address) throws RepositoryException {
final Query query = new Query().setFilter(
new PropertyFilter(Link.LINK_ADDRESS, FilterOperator.EQUAL, address)).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public int getMaxOrder() throws RepositoryException {
final Query query = new Query();
query.addSort(Link.LINK_ORDER, SortDirection.DESCENDING);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return -1;
}
return array.optJSONObject(0).optInt(Link.LINK_ORDER);
}
@Override
public JSONObject getByOrder(final int order) throws RepositoryException {
final Query query = new Query();
query.setFilter(new PropertyFilter(Link.LINK_ORDER, FilterOperator.EQUAL, order));
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public JSONObject getUpper(final String id) throws RepositoryException {
final JSONObject link = get(id);
if (null == link) {
return null;
}
final Query query = new Query();
query.setFilter(
new PropertyFilter(Link.LINK_ORDER, FilterOperator.LESS_THAN, link.optInt(Link.LINK_ORDER))).
addSort(Link.LINK_ORDER, SortDirection.DESCENDING);
query.setCurrentPageNum(1);
query.setPageSize(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (1 != array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public JSONObject getUnder(final String id) throws RepositoryException {
final JSONObject link = get(id);
if (null == link) {
return null;
}
final Query query = new Query();
query.setFilter(new PropertyFilter(Link.LINK_ORDER, FilterOperator.GREATER_THAN, link.optInt(Link.LINK_ORDER))).
addSort(Link.LINK_ORDER, SortDirection.ASCENDING);
query.setCurrentPageNum(1);
query.setPageSize(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (1 != array.length()) {
return null;
}
return array.optJSONObject(0);
}
/**
* Gets the {@link LinkRepositoryImpl} singleton.
*
* @return the singleton
*/
public static LinkRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private LinkRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import java.util.List;
import java.util.logging.Logger;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.AbstractRepository;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.Query;
import org.b3log.latke.repository.RepositoryException;
import org.b3log.latke.repository.SortDirection;
import org.b3log.latke.util.CollectionUtils;
import org.b3log.solo.model.Page;
import org.b3log.solo.repository.PageRepository;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Page repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.9, Dec 31, 2011
* @since 0.3.1
*/
public final class PageRepositoryImpl extends AbstractRepository implements PageRepository {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(PageRepositoryImpl.class.getName());
/**
* Singleton.
*/
private static final PageRepositoryImpl SINGLETON = new PageRepositoryImpl(Page.PAGE);
@Override
public JSONObject getByPermalink(final String permalink) throws RepositoryException {
final Query query = new Query().addFilter(Page.PAGE_PERMALINK, FilterOperator.EQUAL, permalink).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public int getMaxOrder() throws RepositoryException {
final Query query = new Query().addSort(Page.PAGE_ORDER, SortDirection.DESCENDING).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return -1;
}
return array.optJSONObject(0).optInt(Page.PAGE_ORDER);
}
@Override
public JSONObject getUpper(final String id) throws RepositoryException {
final JSONObject page = get(id);
if (null == page) {
return null;
}
final Query query = new Query().addFilter(Page.PAGE_ORDER, FilterOperator.LESS_THAN, page.optInt(Page.PAGE_ORDER)).
addSort(Page.PAGE_ORDER, SortDirection.DESCENDING).
setCurrentPageNum(1).setPageSize(1).setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (1 != array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public JSONObject getUnder(final String id) throws RepositoryException {
final JSONObject page = get(id);
if (null == page) {
return null;
}
final Query query = new Query().addFilter(Page.PAGE_ORDER, FilterOperator.GREATER_THAN, page.optInt(Page.PAGE_ORDER)).
addSort(Page.PAGE_ORDER, SortDirection.ASCENDING).setCurrentPageNum(1).
setPageSize(1).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (1 != array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public JSONObject getByOrder(final int order) throws RepositoryException {
final Query query = new Query().addFilter(Page.PAGE_ORDER, FilterOperator.EQUAL, order).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public List<JSONObject> getPages() throws RepositoryException {
final Query query = new Query().addSort(
Page.PAGE_ORDER, SortDirection.ASCENDING).setPageCount(1);
final JSONObject result = get(query);
return CollectionUtils.jsonArrayToList(result.optJSONArray(Keys.RESULTS));
}
/**
* Gets the {@link PageRepositoryImpl} singleton.
*
* @return the singleton
*/
public static PageRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private PageRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import java.util.List;
import java.util.logging.Logger;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.*;
import org.b3log.latke.util.CollectionUtils;
import org.b3log.solo.model.Page;
import org.b3log.solo.repository.PageRepository;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Page repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.9, Dec 31, 2011
* @since 0.3.1
*/
public final class PageRepositoryImpl extends AbstractRepository implements PageRepository {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(PageRepositoryImpl.class.getName());
/**
* Singleton.
*/
private static final PageRepositoryImpl SINGLETON = new PageRepositoryImpl(Page.PAGE);
@Override
public JSONObject getByPermalink(final String permalink) throws RepositoryException {
final Query query = new Query().setFilter(
new PropertyFilter(Page.PAGE_PERMALINK, FilterOperator.EQUAL, permalink)).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public int getMaxOrder() throws RepositoryException {
final Query query = new Query().addSort(Page.PAGE_ORDER, SortDirection.DESCENDING).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return -1;
}
return array.optJSONObject(0).optInt(Page.PAGE_ORDER);
}
@Override
public JSONObject getUpper(final String id) throws RepositoryException {
final JSONObject page = get(id);
if (null == page) {
return null;
}
final Query query = new Query().setFilter(
new PropertyFilter(Page.PAGE_ORDER, FilterOperator.LESS_THAN, page.optInt(Page.PAGE_ORDER))).
addSort(Page.PAGE_ORDER, SortDirection.DESCENDING).
setCurrentPageNum(1).setPageSize(1).setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (1 != array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public JSONObject getUnder(final String id) throws RepositoryException {
final JSONObject page = get(id);
if (null == page) {
return null;
}
final Query query = new Query().setFilter(
new PropertyFilter(Page.PAGE_ORDER, FilterOperator.GREATER_THAN, page.optInt(Page.PAGE_ORDER))).
addSort(Page.PAGE_ORDER, SortDirection.ASCENDING).setCurrentPageNum(1).
setPageSize(1).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (1 != array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public JSONObject getByOrder(final int order) throws RepositoryException {
final Query query = new Query().setFilter(
new PropertyFilter(Page.PAGE_ORDER, FilterOperator.EQUAL, order)).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public List<JSONObject> getPages() throws RepositoryException {
final Query query = new Query().addSort(
Page.PAGE_ORDER, SortDirection.ASCENDING).setPageCount(1);
final JSONObject result = get(query);
return CollectionUtils.jsonArrayToList(result.optJSONArray(Keys.RESULTS));
}
/**
* Gets the {@link PageRepositoryImpl} singleton.
*
* @return the singleton
*/
public static PageRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private PageRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import java.util.List;
import java.util.logging.Logger;
import org.b3log.solo.model.Article;
import org.b3log.solo.model.Tag;
import org.b3log.solo.repository.TagArticleRepository;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.AbstractRepository;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.Query;
import org.b3log.latke.repository.RepositoryException;
import org.b3log.latke.repository.SortDirection;
import org.b3log.latke.util.CollectionUtils;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Tag-Article relation repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.9, Nov 9, 2011
* @since 0.3.1
*/
public final class TagArticleRepositoryImpl extends AbstractRepository implements TagArticleRepository {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(TagArticleRepositoryImpl.class.getName());
/**
* Singleton.
*/
private static final TagArticleRepositoryImpl SINGLETON = new TagArticleRepositoryImpl(Tag.TAG + "_" + Article.ARTICLE);
@Override
public List<JSONObject> getByArticleId(final String articleId) throws RepositoryException {
final Query query = new Query().addFilter(Article.ARTICLE + "_" + Keys.OBJECT_ID, FilterOperator.EQUAL, articleId).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
return CollectionUtils.jsonArrayToList(array);
}
@Override
public JSONObject getByTagId(final String tagId, final int currentPageNum, final int pageSize)
throws RepositoryException {
final Query query = new Query().addFilter(Tag.TAG + "_" + Keys.OBJECT_ID, FilterOperator.EQUAL, tagId).
addSort(Article.ARTICLE + "_" + Keys.OBJECT_ID, SortDirection.DESCENDING).
setCurrentPageNum(currentPageNum).
setPageSize(pageSize).
setPageCount(1);
return get(query);
}
/**
* Gets the {@link TagArticleRepositoryImpl} singleton.
*
* @return the singleton
*/
public static TagArticleRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private TagArticleRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import java.util.List;
import java.util.logging.Logger;
import org.b3log.solo.model.Article;
import org.b3log.solo.model.Tag;
import org.b3log.solo.repository.TagArticleRepository;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.*;
import org.b3log.latke.util.CollectionUtils;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Tag-Article relation repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.9, Nov 9, 2011
* @since 0.3.1
*/
public final class TagArticleRepositoryImpl extends AbstractRepository implements TagArticleRepository {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(TagArticleRepositoryImpl.class.getName());
/**
* Singleton.
*/
private static final TagArticleRepositoryImpl SINGLETON = new TagArticleRepositoryImpl(Tag.TAG + "_" + Article.ARTICLE);
@Override
public List<JSONObject> getByArticleId(final String articleId) throws RepositoryException {
final Query query = new Query().setFilter(
new PropertyFilter(Article.ARTICLE + "_" + Keys.OBJECT_ID, FilterOperator.EQUAL, articleId)).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
return CollectionUtils.jsonArrayToList(array);
}
@Override
public JSONObject getByTagId(final String tagId, final int currentPageNum, final int pageSize)
throws RepositoryException {
final Query query = new Query().setFilter(
new PropertyFilter(Tag.TAG + "_" + Keys.OBJECT_ID, FilterOperator.EQUAL, tagId)).
addSort(Article.ARTICLE + "_" + Keys.OBJECT_ID, SortDirection.DESCENDING).
setCurrentPageNum(currentPageNum).
setPageSize(pageSize).
setPageCount(1);
return get(query);
}
/**
* Gets the {@link TagArticleRepositoryImpl} singleton.
*
* @return the singleton
*/
public static TagArticleRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private TagArticleRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.b3log.solo.model.Tag;
import org.b3log.solo.repository.TagRepository;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.AbstractRepository;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.Query;
import org.b3log.latke.repository.RepositoryException;
import org.b3log.latke.repository.SortDirection;
import org.b3log.latke.util.CollectionUtils;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Tag repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.1.1, Nov 29, 2011
* @since 0.3.1
*/
public final class TagRepositoryImpl extends AbstractRepository implements TagRepository {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(TagRepositoryImpl.class.getName());
/**
* Singleton.
*/
private static final TagRepositoryImpl SINGLETON = new TagRepositoryImpl(Tag.TAG);
/**
* Tag-Article relation repository.
*/
private TagArticleRepositoryImpl tagArticleRepository = TagArticleRepositoryImpl.getInstance();
@Override
public JSONObject getByTitle(final String tagTitle) throws RepositoryException {
final Query query = new Query().addFilter(Tag.TAG_TITLE, FilterOperator.EQUAL, tagTitle).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public List<JSONObject> getMostUsedTags(final int num) throws RepositoryException {
final Query query = new Query().addSort(Tag.TAG_PUBLISHED_REFERENCE_COUNT, SortDirection.DESCENDING).
setCurrentPageNum(1).
setPageSize(num).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
return CollectionUtils.jsonArrayToList(array);
}
@Override
public List<JSONObject> getByArticleId(final String articleId) throws RepositoryException {
final List<JSONObject> ret = new ArrayList<JSONObject>();
final List<JSONObject> tagArticleRelations = tagArticleRepository.getByArticleId(articleId);
for (final JSONObject tagArticleRelation : tagArticleRelations) {
final String tagId = tagArticleRelation.optString(Tag.TAG + "_" + Keys.OBJECT_ID);
final JSONObject tag = get(tagId);
ret.add(tag);
}
return ret;
}
/**
* Gets the {@link TagRepositoryImpl} singleton.
*
* @return the singleton
*/
public static TagRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private TagRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.b3log.solo.model.Tag;
import org.b3log.solo.repository.TagRepository;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.*;
import org.b3log.latke.util.CollectionUtils;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Tag repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.1.1, Nov 29, 2011
* @since 0.3.1
*/
public final class TagRepositoryImpl extends AbstractRepository implements TagRepository {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(TagRepositoryImpl.class.getName());
/**
* Singleton.
*/
private static final TagRepositoryImpl SINGLETON = new TagRepositoryImpl(Tag.TAG);
/**
* Tag-Article relation repository.
*/
private TagArticleRepositoryImpl tagArticleRepository = TagArticleRepositoryImpl.getInstance();
@Override
public JSONObject getByTitle(final String tagTitle) throws RepositoryException {
final Query query = new Query().setFilter(
new PropertyFilter(Tag.TAG_TITLE, FilterOperator.EQUAL, tagTitle)).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public List<JSONObject> getMostUsedTags(final int num) throws RepositoryException {
final Query query = new Query().addSort(Tag.TAG_PUBLISHED_REFERENCE_COUNT, SortDirection.DESCENDING).
setCurrentPageNum(1).
setPageSize(num).
setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
return CollectionUtils.jsonArrayToList(array);
}
@Override
public List<JSONObject> getByArticleId(final String articleId) throws RepositoryException {
final List<JSONObject> ret = new ArrayList<JSONObject>();
final List<JSONObject> tagArticleRelations = tagArticleRepository.getByArticleId(articleId);
for (final JSONObject tagArticleRelation : tagArticleRelations) {
final String tagId = tagArticleRelation.optString(Tag.TAG + "_" + Keys.OBJECT_ID);
final JSONObject tag = get(tagId);
ret.add(tag);
}
return ret;
}
/**
* Gets the {@link TagRepositoryImpl} singleton.
*
* @return the singleton
*/
public static TagRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private TagRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import java.util.logging.Logger;
import org.b3log.latke.Keys;
import org.b3log.latke.model.Role;
import org.b3log.latke.model.User;
import org.b3log.latke.repository.AbstractRepository;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.Query;
import org.b3log.latke.repository.RepositoryException;
import org.b3log.solo.repository.UserRepository;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* User repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.8, Nov 10, 2011
* @since 0.3.1
*/
public final class UserRepositoryImpl extends AbstractRepository implements UserRepository {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(UserRepositoryImpl.class.getName());
/**
* Singleton.
*/
private static final UserRepositoryImpl SINGLETON = new UserRepositoryImpl(User.USER);
@Override
public JSONObject getByEmail(final String email) throws RepositoryException {
final Query query = new Query().setPageCount(1);
query.addFilter(User.USER_EMAIL, FilterOperator.EQUAL, email.toLowerCase().trim());
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public JSONObject getAdmin() throws RepositoryException {
final Query query = new Query().addFilter(User.USER_ROLE, FilterOperator.EQUAL, Role.ADMIN_ROLE).setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public boolean isAdminEmail(final String email) throws RepositoryException {
final JSONObject user = getByEmail(email);
if (null == user) {
return false;
}
return Role.ADMIN_ROLE.equals(user.optString(User.USER_ROLE));
}
/**
* Gets the {@link UserRepositoryImpl} singleton.
*
* @return the singleton
*/
public static UserRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private UserRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import java.util.logging.Logger;
import org.b3log.latke.Keys;
import org.b3log.latke.model.Role;
import org.b3log.latke.model.User;
import org.b3log.latke.repository.*;
import org.b3log.solo.repository.UserRepository;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* User repository.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.8, Nov 10, 2011
* @since 0.3.1
*/
public final class UserRepositoryImpl extends AbstractRepository implements UserRepository {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(UserRepositoryImpl.class.getName());
/**
* Singleton.
*/
private static final UserRepositoryImpl SINGLETON = new UserRepositoryImpl(User.USER);
@Override
public JSONObject getByEmail(final String email) throws RepositoryException {
final Query query = new Query().setPageCount(1);
query.setFilter(
new PropertyFilter(User.USER_EMAIL, FilterOperator.EQUAL, email.toLowerCase().trim()));
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public JSONObject getAdmin() throws RepositoryException {
final Query query = new Query().setFilter(
new PropertyFilter(User.USER_ROLE, FilterOperator.EQUAL, Role.ADMIN_ROLE)).setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
return array.optJSONObject(0);
}
@Override
public boolean isAdminEmail(final String email) throws RepositoryException {
final JSONObject user = getByEmail(email);
if (null == user) {
return false;
}
return Role.ADMIN_ROLE.equals(user.optString(User.USER_ROLE));
}
/**
* Gets the {@link UserRepositoryImpl} singleton.
*
* @return the singleton
*/
public static UserRepositoryImpl getInstance() {
return SINGLETON;
}
/**
* Private constructor.
*
* @param name the specified name
*/
private UserRepositoryImpl(final String name) {
super(name);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.service;
import org.b3log.solo.repository.ArchiveDateArticleRepository;
import org.b3log.solo.repository.impl.ArchiveDateArticleRepositoryImpl;
import java.util.Set;
import org.b3log.solo.model.Sign;
import org.b3log.solo.model.Tag;
import java.util.Date;
import org.b3log.latke.model.User;
import org.b3log.solo.model.Common;
import org.b3log.solo.util.Articles;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.SortDirection;
import org.b3log.latke.repository.Query;
import org.b3log.latke.model.Pagination;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.RepositoryException;
import org.b3log.latke.service.ServiceException;
import org.b3log.latke.util.CollectionUtils;
import org.b3log.latke.util.Paginator;
import org.b3log.latke.util.Stopwatchs;
import org.b3log.latke.util.Strings;
import org.b3log.solo.model.Article;
import org.b3log.solo.model.Preference;
import org.b3log.solo.repository.ArticleRepository;
import org.b3log.solo.repository.TagArticleRepository;
import org.b3log.solo.repository.TagRepository;
import org.b3log.solo.repository.impl.ArticleRepositoryImpl;
import org.b3log.solo.repository.impl.TagArticleRepositoryImpl;
import org.b3log.solo.repository.impl.TagRepositoryImpl;
import org.b3log.solo.util.Statistics;
import org.b3log.solo.util.comparator.Comparators;
import org.json.JSONArray;
import org.json.JSONObject;
import static org.b3log.solo.model.Article.*;
import org.b3log.solo.util.Markdowns;
/**
* Article query service.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.1.0, May 10, 2012
* @since 0.3.5
*/
public final class ArticleQueryService {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(ArticleQueryService.class.getName());
/**
* Article repository.
*/
private ArticleRepository articleRepository = ArticleRepositoryImpl.getInstance();
/**
* Preference query service.
*/
private PreferenceQueryService preferenceQueryService = PreferenceQueryService.getInstance();
/**
* Tag repository.
*/
private TagRepository tagRepository = TagRepositoryImpl.getInstance();
/**
* Tag-Article repository.
*/
private TagArticleRepository tagArticleRepository = TagArticleRepositoryImpl.getInstance();
/**
* Archive date-Article repository.
*/
private ArchiveDateArticleRepository archiveDateArticleRepository = ArchiveDateArticleRepositoryImpl.getInstance();
/**
* Statistic utilities.
*/
private Statistics statistics = Statistics.getInstance();
/**
* Article utilities.
*/
private static Articles articleUtils = Articles.getInstance();
/**
* Gets the recent articles with the specified fetch size.
*
* @param fetchSize the specified fetch size
* @return a list of json object, its size less or equal to the specified
* fetch size
* @throws ServiceException service exception
*/
public List<JSONObject> getRecentArticles(final int fetchSize) throws ServiceException {
try {
return articleRepository.getRecentArticles(fetchSize);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Gets recent articles failed", e);
return Collections.emptyList();
}
}
/**
* Gets an article by the specified article id.
*
* <p>
* <b>Note</b>: The article content and abstract is raw (no editor type processing).
* </p>
*
* @param articleId the specified article id
* @return for example,
* <pre>
* {
* "article": {
* "oId": "",
* "articleTitle": "",
* "articleAbstract": "",
* "articleContent": "",
* "articlePermalink": "",
* "articleHadBeenPublished": boolean,
* "articleCreateDate": java.util.Date,
* "articleTags": [{
* "oId": "",
* "tagTitle": ""
* }, ....],
* "articleSignId": "",
* "articleViewPwd": "",
* "articleEditorType": "",
* "signs": [{
* "oId": "",
* "signHTML": ""
* }, ....]
* }
* }
* </pre>, returns {@code null} if not found
* @throws ServiceException service exception
*/
public JSONObject getArticle(final String articleId) throws ServiceException {
try {
final JSONObject ret = new JSONObject();
final JSONObject article = articleRepository.get(articleId);
if (null == article) {
return null;
}
ret.put(ARTICLE, article);
// Tags
final JSONArray tags = new JSONArray();
final List<JSONObject> tagArticleRelations = tagArticleRepository.getByArticleId(articleId);
for (int i = 0; i < tagArticleRelations.size(); i++) {
final JSONObject tagArticleRelation = tagArticleRelations.get(i);
final String tagId = tagArticleRelation.getString(Tag.TAG + "_" + Keys.OBJECT_ID);
final JSONObject tag = tagRepository.get(tagId);
tags.put(tag);
}
article.put(ARTICLE_TAGS_REF, tags);
// Signs
final JSONObject preference = preferenceQueryService.getPreference();
article.put(Sign.SIGNS, new JSONArray(preference.getString(Preference.SIGNS)));
// Remove unused properties
article.remove(ARTICLE_AUTHOR_EMAIL);
article.remove(ARTICLE_COMMENT_COUNT);
article.remove(ARTICLE_IS_PUBLISHED);
article.remove(ARTICLE_PUT_TOP);
article.remove(ARTICLE_UPDATE_DATE);
article.remove(ARTICLE_VIEW_COUNT);
article.remove(ARTICLE_RANDOM_DOUBLE);
LOGGER.log(Level.FINER, "Got an article[id={0}]", articleId);
return ret;
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Gets an article failed", e);
throw new ServiceException(e);
}
}
/**
* Gets articles(by crate date descending) by the specified request json
* object.
*
* <p>
* If the property "articleIsPublished" of the specified request json object is {@code true}, the returned articles all are published,
* {@code false} otherwise.
* </p>
*
* <p>
* Specified the "excludes" for results properties exclusion.
* </p>
*
* @param requestJSONObject the specified request json object, for example,
* <pre>
* {
* "paginationCurrentPageNum": 1,
* "paginationPageSize": 20,
* "paginationWindowSize": 10,
* "articleIsPublished": boolean,
* "excludes": ["", ....] // Optional
* }, see {@link Pagination} for more details
* </pre>
* @return for example,
* <pre>
* {
* "pagination": {
* "paginationPageCount": 100,
* "paginationPageNums": [1, 2, 3, 4, 5]
* },
* "articles": [{
* "oId": "",
* "articleTitle": "",
* "articleCommentCount": int,
* "articleCreateTime"; long,
* "articleViewCount": int,
* "articleTags": "tag1, tag2, ....",
* "articlePutTop": boolean,
* "articleSignId": "",
* "articleViewPwd": "",
* "articleEditorType": "",
* .... // Specified by the "excludes"
* }, ....]
* }
* </pre>, order by article update date and sticky(put top).
* @throws ServiceException service exception
* @see Pagination
*/
public JSONObject getArticles(final JSONObject requestJSONObject) throws ServiceException {
final JSONObject ret = new JSONObject();
try {
final int currentPageNum = requestJSONObject.getInt(Pagination.PAGINATION_CURRENT_PAGE_NUM);
final int pageSize = requestJSONObject.getInt(Pagination.PAGINATION_PAGE_SIZE);
final int windowSize = requestJSONObject.getInt(Pagination.PAGINATION_WINDOW_SIZE);
final boolean articleIsPublished = requestJSONObject.optBoolean(ARTICLE_IS_PUBLISHED, true);
final Query query = new Query().setCurrentPageNum(currentPageNum).
setPageSize(pageSize).
addSort(ARTICLE_PUT_TOP, SortDirection.DESCENDING).
addSort(ARTICLE_CREATE_DATE, SortDirection.DESCENDING).
addFilter(ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, articleIsPublished);
int articleCount = statistics.getBlogArticleCount();
if (!articleIsPublished) {
articleCount -= statistics.getPublishedBlogArticleCount();
}
final int pageCount = (int) Math.ceil((double) articleCount / (double) pageSize);
query.setPageCount(pageCount);
final JSONObject result = articleRepository.get(query);
final JSONObject pagination = new JSONObject();
ret.put(Pagination.PAGINATION, pagination);
final List<Integer> pageNums = Paginator.paginate(currentPageNum, pageSize, pageCount, windowSize);
pagination.put(Pagination.PAGINATION_PAGE_COUNT, pageCount);
pagination.put(Pagination.PAGINATION_PAGE_NUMS, pageNums);
final JSONArray articles = result.getJSONArray(Keys.RESULTS);
JSONArray excludes = requestJSONObject.optJSONArray(Keys.EXCLUDES);
excludes = null == excludes ? new JSONArray() : excludes;
for (int i = 0; i < articles.length(); i++) {
final JSONObject article = articles.getJSONObject(i);
final JSONObject author = articleUtils.getAuthor(article);
final String authorName = author.getString(User.USER_NAME);
article.put(Common.AUTHOR_NAME, authorName);
article.put(ARTICLE_CREATE_TIME, ((Date) article.get(ARTICLE_CREATE_DATE)).getTime());
// Markdown to HTML for content and abstract
markdown(article);
// Remove unused properties
for (int j = 0; j < excludes.length(); j++) {
article.remove(excludes.optString(j));
}
}
ret.put(ARTICLES, articles);
return ret;
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Gets articles failed", e);
throw new ServiceException(e);
}
}
/**
* Gets a list of published articles with the specified tag id, current page number and page size.
*
* @param tagId the specified tag id
* @param currentPageNum the specified current page number
* @param pageSize the specified page size
* @return a list of articles, returns an empty list if not found
* @throws ServiceException service exception
*/
public List<JSONObject> getArticlesByTag(final String tagId, final int currentPageNum, final int pageSize)
throws ServiceException {
try {
JSONObject result = tagArticleRepository.getByTagId(tagId, currentPageNum, pageSize);
final JSONArray tagArticleRelations = result.getJSONArray(Keys.RESULTS);
if (0 == tagArticleRelations.length()) {
return Collections.emptyList();
}
final Set<String> articleIds = new HashSet<String>();
for (int i = 0; i < tagArticleRelations.length(); i++) {
final JSONObject tagArticleRelation = tagArticleRelations.getJSONObject(i);
final String articleId = tagArticleRelation.getString(Article.ARTICLE + "_" + Keys.OBJECT_ID);
articleIds.add(articleId);
}
final List<JSONObject> ret = new ArrayList<JSONObject>();
final Query query = new Query().addFilter(Keys.OBJECT_ID, FilterOperator.IN, articleIds).
setPageCount(1).index(Article.ARTICLE_PERMALINK);
result = articleRepository.get(query);
final JSONArray articles = result.getJSONArray(Keys.RESULTS);
for (int i = 0; i < articles.length(); i++) {
final JSONObject article = articles.getJSONObject(i);
if (!article.getBoolean(Article.ARTICLE_IS_PUBLISHED)) {
// Skips the unpublished article
continue;
}
// Markdown to HTML for content and abstract
markdown(article);
ret.add(article);
}
return ret;
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Gets articles by tag[id=" + tagId + "] failed", e);
throw new ServiceException(e);
}
}
/**
* Gets a list of published articles with the specified archive date id, current page number and page size.
*
* @param archiveDateId the specified archive date id
* @param currentPageNum the specified current page number
* @param pageSize the specified page size
* @return a list of articles, returns an empty list if not found
* @throws ServiceException service exception
*/
public List<JSONObject> getArticlesByArchiveDate(final String archiveDateId, final int currentPageNum, final int pageSize)
throws ServiceException {
try {
JSONObject result = archiveDateArticleRepository.getByArchiveDateId(archiveDateId, currentPageNum, pageSize);
final JSONArray relations = result.getJSONArray(Keys.RESULTS);
if (0 == relations.length()) {
return Collections.emptyList();
}
final Set<String> articleIds = new HashSet<String>();
for (int i = 0; i < relations.length(); i++) {
final JSONObject relation = relations.getJSONObject(i);
final String articleId = relation.getString(Article.ARTICLE + "_" + Keys.OBJECT_ID);
articleIds.add(articleId);
}
final List<JSONObject> ret = new ArrayList<JSONObject>();
final Query query = new Query().addFilter(Keys.OBJECT_ID, FilterOperator.IN, articleIds).
setPageCount(1).index(Article.ARTICLE_PERMALINK);
result = articleRepository.get(query);
final JSONArray articles = result.getJSONArray(Keys.RESULTS);
for (int i = 0; i < articles.length(); i++) {
final JSONObject article = articles.getJSONObject(i);
if (!article.getBoolean(Article.ARTICLE_IS_PUBLISHED)) {
// Skips the unpublished article
continue;
}
// Markdown to HTML for content and abstract
markdown(article);
ret.add(article);
}
return ret;
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Gets articles by archive date[id=" + archiveDateId + "] failed", e);
throw new ServiceException(e);
}
}
/**
* Gets a list of articles randomly with the specified fetch size.
*
* <p>
* <b>Note</b>: The article content and abstract is raw (no editor type processing).
* </p>
*
* @param fetchSize the specified fetch size
* @return a list of json objects, its size less or equal to the specified
* fetch size
* @throws ServiceException service exception
*/
public List<JSONObject> getArticlesRandomly(final int fetchSize) throws ServiceException {
try {
final List<JSONObject> ret = articleRepository.getRandomly(fetchSize);
removeUnusedProperties(ret);
return ret;
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Gets articles randomly failed[fetchSize=" + fetchSize + "]", e);
throw new ServiceException(e);
}
}
/**
* Gets the relevant published articles of the specified article.
*
* <p>
* <b>Note</b>: The article content and abstract is raw (no editor type processing).
* </p>
*
* @param article the specified article
* @param preference the specified preference
* @return a list of articles, returns an empty list if not found
* @throws ServiceException service exception
*/
public List<JSONObject> getRelevantArticles(final JSONObject article, final JSONObject preference)
throws ServiceException {
try {
final int displayCnt = preference.getInt(Preference.RELEVANT_ARTICLES_DISPLAY_CNT);
final String[] tagTitles = article.getString(Article.ARTICLE_TAGS_REF).split(",");
final int maxTagCnt = displayCnt > tagTitles.length ? tagTitles.length : displayCnt;
final String articleId = article.getString(Keys.OBJECT_ID);
final List<JSONObject> articles = new ArrayList<JSONObject>();
for (int i = 0; i < maxTagCnt; i++) { // XXX: should average by tag?
final String tagTitle = tagTitles[i];
final JSONObject tag = tagRepository.getByTitle(tagTitle);
final String tagId = tag.getString(Keys.OBJECT_ID);
final JSONObject result = tagArticleRepository.getByTagId(tagId, 1, displayCnt);
final JSONArray tagArticleRelations = result.getJSONArray(Keys.RESULTS);
final int relationSize = displayCnt < tagArticleRelations.length() ? displayCnt : tagArticleRelations.length();
for (int j = 0; j < relationSize; j++) {
final JSONObject tagArticleRelation = tagArticleRelations.getJSONObject(j);
final String relatedArticleId = tagArticleRelation.getString(Article.ARTICLE + "_" + Keys.OBJECT_ID);
if (articleId.equals(relatedArticleId)) {
continue;
}
final JSONObject relevant = articleRepository.get(relatedArticleId);
if (!relevant.getBoolean(Article.ARTICLE_IS_PUBLISHED)) {
continue;
}
boolean existed = false;
for (final JSONObject relevantArticle : articles) {
if (relevantArticle.getString(Keys.OBJECT_ID).
equals(relevant.getString(Keys.OBJECT_ID))) {
existed = true;
}
}
if (!existed) {
articles.add(relevant);
}
}
}
Collections.sort(articles, Comparators.ARTICLE_UPDATE_DATE_COMPARATOR);
removeUnusedProperties(articles);
if (displayCnt > articles.size()) {
return articles;
}
final List<Integer> randomIntegers = CollectionUtils.getRandomIntegers(0, articles.size() - 1, displayCnt);
final List<JSONObject> ret = new ArrayList<JSONObject>();
for (final int index : randomIntegers) {
ret.add(articles.get(index));
}
return ret;
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Gets relevant articles failed", e);
throw new ServiceException(e);
}
}
/**
* Determines an article specified by the given article id is published.
*
* @param articleId the given article id
* @return {@code true} if it is published
* @throws ServiceException service exception
*/
public boolean isArticlePublished(final String articleId) throws ServiceException {
try {
return articleRepository.isPublished(articleId);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Determines the article publish status failed[articleId=" + articleId + "]", e);
throw new ServiceException(e);
}
}
/**
* Gets the next article(by create date) by the specified article id.
*
* <p>
* <b>Note</b>: The article content and abstract is raw (no editor type processing).
* </p>
*
* @param articleId the specified article id
* @return the previous article,
* <pre>
* {
* "articleTitle": "",
* "articlePermalink": ""
* }
* </pre>
* returns {@code null} if not found
* @throws ServiceException service exception
*/
public JSONObject getNextArticle(final String articleId) throws ServiceException {
try {
return articleRepository.getNextArticle(articleId);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Gets the next article failed[articleId=" + articleId + "]", e);
throw new ServiceException(e);
}
}
/**
* Gets the previous article(by create date) by the specified article id.
*
* <p>
* <b>Note</b>: The article content and abstract is raw (no editor type processing).
* </p>
*
* @param articleId the specified article id
* @return the previous article,
* <pre>
* {
* "articleTitle": "",
* "articlePermalink": ""
* }
* </pre>
* returns {@code null} if not found
* @throws ServiceException service exception
*/
public JSONObject getPreviousArticle(final String articleId) throws ServiceException {
try {
return articleRepository.getPreviousArticle(articleId);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Gets the previous article failed[articleId=" + articleId + "]", e);
throw new ServiceException(e);
}
}
/**
* Gets an article by the specified article id.
*
* <p>
* <b>Note</b>: The article content and abstract is raw (no editor type processing).
* </p>
*
* @param articleId the specified article id
* @return an article, returns {@code null} if not found
* @throws ServiceException service exception
*/
public JSONObject getArticleById(final String articleId) throws ServiceException {
try {
return articleRepository.get(articleId);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Gets an article[articleId=" + articleId + "] failed", e);
throw new ServiceException(e);
}
}
/**
* Gets <em>published</em> articles by the specified author email, current page number and page size.
*
* @param authorEmail the specified author email
* @param currentPageNum the specified current page number
* @param pageSize the specified page size
* @return a list of articles, returns an empty list if not found
* @throws ServiceException service exception
*/
public List<JSONObject> getArticlesByAuthorEmail(final String authorEmail, final int currentPageNum, final int pageSize)
throws ServiceException {
try {
final JSONObject result = articleRepository.getByAuthorEmail(authorEmail, currentPageNum, pageSize);
final JSONArray articles = result.getJSONArray(Keys.RESULTS);
final List<JSONObject> ret = new ArrayList<JSONObject>();
for (int i = 0; i < articles.length(); i++) {
final JSONObject article = articles.getJSONObject(i);
// Markdown to HTML for content and abstract
markdown(article);
ret.add(article);
}
return ret;
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Gets articles by author email failed[authorEmail="
+ authorEmail + ", currentPageNum=" + currentPageNum + ", pageSize=" + pageSize + "]", e);
throw new ServiceException(e);
}
}
/**
* Gets article contents with the specified article id.
*
* <p>
* Invoking this method dose not effect on article view count.
* </p>
*
* @param articleId the specified article id
* @return article contents, returns {@code null} if not found
* @throws ServiceException service exception
*/
public String getArticleContent(final String articleId) throws ServiceException {
if (Strings.isEmptyOrNull(articleId)) {
return null;
}
try {
final JSONObject article = articleRepository.get(articleId);
if (null == article) {
return null;
}
// Markdown to HTML for content and abstract
if ("CodeMirror-Markdown".equals(article.optString(ARTICLE_EDITOR_TYPE))) {
Stopwatchs.start("Get Article Content [Markdown]");
final String content = article.optString(ARTICLE_CONTENT);
article.put(ARTICLE_CONTENT, Markdowns.toHTML(content));
Stopwatchs.end();
}
return article.getString(Article.ARTICLE_CONTENT);
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Gets article content failed[articleId=" + articleId + "]", e);
throw new ServiceException(e);
}
}
/**
* Converts the content and abstract for each of the specified articles to HTML if that is saved by Markdown editor.
*
* @param articles the specified articles
* @throws Exception exception
*/
public void markdowns(final List<JSONObject> articles) throws Exception {
for (final JSONObject article : articles) {
markdown(article);
}
}
/**
* Converts the content and abstract for the specified article to HTML if it is saved by Markdown editor.
*
* @param article the specified article
* @throws Exception exception
*/
public void markdown(final JSONObject article) throws Exception {
if ("CodeMirror-Markdown".equals(article.optString(ARTICLE_EDITOR_TYPE))) {
Stopwatchs.start("Markdown Article[id=" + article.optString(Keys.OBJECT_ID) + "]");
Stopwatchs.start("Content");
final String content = article.optString(ARTICLE_CONTENT);
article.put(ARTICLE_CONTENT, Markdowns.toHTML(content));
Stopwatchs.end();
final String abstractContent = article.optString(ARTICLE_ABSTRACT);
if (!Strings.isEmptyOrNull(abstractContent)) {
Stopwatchs.start("Abstract");
article.put(ARTICLE_ABSTRACT, Markdowns.toHTML(abstractContent));
Stopwatchs.end();
}
Stopwatchs.end();
}
}
/**
* Removes unused properties of each article in the specified articles.
*
* <p>
* Remains the following properties:
* <ul>
* <li>{@link Article#ARTICLE_TITLE article title}</li>
* <li>{@link Article#ARTICLE_PERMALINK article permalink}</li>
* </ul>
* </p>
*
* <p>
* The batch version of method {@link #removeUnusedProperties(org.json.JSONObject)}.
* </p>
*
* @param articles the specified articles
* @see #removeUnusedProperties(org.json.JSONObject)
*/
public void removeUnusedProperties(final List<JSONObject> articles) {
for (final JSONObject article : articles) {
removeUnusedProperties(article);
}
}
/**
* Removes unused properties of the specified article.
*
* <p>
* Remains the following properties:
* <ul>
* <li>{@link Article#ARTICLE_TITLE article title}</li>
* <li>{@link Article#ARTICLE_PERMALINK article permalink}</li>
* </ul>
* </p>
*
* @param article the specified article
* @see #removeUnusedProperties(java.util.List)
*/
public void removeUnusedProperties(final JSONObject article) {
article.remove(Keys.OBJECT_ID);
article.remove(Article.ARTICLE_AUTHOR_EMAIL);
article.remove(Article.ARTICLE_ABSTRACT);
article.remove(Article.ARTICLE_COMMENT_COUNT);
article.remove(Article.ARTICLE_CONTENT);
article.remove(Article.ARTICLE_CREATE_DATE);
article.remove(Article.ARTICLE_TAGS_REF);
article.remove(Article.ARTICLE_UPDATE_DATE);
article.remove(Article.ARTICLE_VIEW_COUNT);
article.remove(Article.ARTICLE_RANDOM_DOUBLE);
article.remove(Article.ARTICLE_IS_PUBLISHED);
article.remove(Article.ARTICLE_PUT_TOP);
article.remove(Article.ARTICLE_HAD_BEEN_PUBLISHED);
}
/**
* Gets the {@link ArticleQueryService} singleton.
*
* @return the singleton
*/
public static ArticleQueryService getInstance() {
return SingletonHolder.SINGLETON;
}
/**
* Private constructor.
*/
private ArticleQueryService() {
}
/**
* Singleton holder.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.0, Oct 3, 2011
*/
private static final class SingletonHolder {
/**
* Singleton.
*/
private static final ArticleQueryService SINGLETON = new ArticleQueryService();
/**
* Private default constructor.
*/
private SingletonHolder() {
}
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.service;
import org.b3log.solo.repository.ArchiveDateArticleRepository;
import org.b3log.solo.repository.impl.ArchiveDateArticleRepositoryImpl;
import java.util.Set;
import org.b3log.solo.model.Sign;
import org.b3log.solo.model.Tag;
import java.util.Date;
import org.b3log.latke.model.User;
import org.b3log.solo.model.Common;
import org.b3log.solo.util.Articles;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.SortDirection;
import org.b3log.latke.repository.Query;
import org.b3log.latke.model.Pagination;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.*;
import org.b3log.latke.service.ServiceException;
import org.b3log.latke.util.CollectionUtils;
import org.b3log.latke.util.Paginator;
import org.b3log.latke.util.Stopwatchs;
import org.b3log.latke.util.Strings;
import org.b3log.solo.model.Article;
import org.b3log.solo.model.Preference;
import org.b3log.solo.repository.ArticleRepository;
import org.b3log.solo.repository.TagArticleRepository;
import org.b3log.solo.repository.TagRepository;
import org.b3log.solo.repository.impl.ArticleRepositoryImpl;
import org.b3log.solo.repository.impl.TagArticleRepositoryImpl;
import org.b3log.solo.repository.impl.TagRepositoryImpl;
import org.b3log.solo.util.Statistics;
import org.b3log.solo.util.comparator.Comparators;
import org.json.JSONArray;
import org.json.JSONObject;
import static org.b3log.solo.model.Article.*;
import org.b3log.solo.util.Markdowns;
/**
* Article query service.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.1.0, May 10, 2012
* @since 0.3.5
*/
public final class ArticleQueryService {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(ArticleQueryService.class.getName());
/**
* Article repository.
*/
private ArticleRepository articleRepository = ArticleRepositoryImpl.getInstance();
/**
* Preference query service.
*/
private PreferenceQueryService preferenceQueryService = PreferenceQueryService.getInstance();
/**
* Tag repository.
*/
private TagRepository tagRepository = TagRepositoryImpl.getInstance();
/**
* Tag-Article repository.
*/
private TagArticleRepository tagArticleRepository = TagArticleRepositoryImpl.getInstance();
/**
* Archive date-Article repository.
*/
private ArchiveDateArticleRepository archiveDateArticleRepository = ArchiveDateArticleRepositoryImpl.getInstance();
/**
* Statistic utilities.
*/
private Statistics statistics = Statistics.getInstance();
/**
* Article utilities.
*/
private static Articles articleUtils = Articles.getInstance();
/**
* Gets the recent articles with the specified fetch size.
*
* @param fetchSize the specified fetch size
* @return a list of json object, its size less or equal to the specified
* fetch size
* @throws ServiceException service exception
*/
public List<JSONObject> getRecentArticles(final int fetchSize) throws ServiceException {
try {
return articleRepository.getRecentArticles(fetchSize);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Gets recent articles failed", e);
return Collections.emptyList();
}
}
/**
* Gets an article by the specified article id.
*
* <p>
* <b>Note</b>: The article content and abstract is raw (no editor type processing).
* </p>
*
* @param articleId the specified article id
* @return for example,
* <pre>
* {
* "article": {
* "oId": "",
* "articleTitle": "",
* "articleAbstract": "",
* "articleContent": "",
* "articlePermalink": "",
* "articleHadBeenPublished": boolean,
* "articleCreateDate": java.util.Date,
* "articleTags": [{
* "oId": "",
* "tagTitle": ""
* }, ....],
* "articleSignId": "",
* "articleViewPwd": "",
* "articleEditorType": "",
* "signs": [{
* "oId": "",
* "signHTML": ""
* }, ....]
* }
* }
* </pre>, returns {@code null} if not found
* @throws ServiceException service exception
*/
public JSONObject getArticle(final String articleId) throws ServiceException {
try {
final JSONObject ret = new JSONObject();
final JSONObject article = articleRepository.get(articleId);
if (null == article) {
return null;
}
ret.put(ARTICLE, article);
// Tags
final JSONArray tags = new JSONArray();
final List<JSONObject> tagArticleRelations = tagArticleRepository.getByArticleId(articleId);
for (int i = 0; i < tagArticleRelations.size(); i++) {
final JSONObject tagArticleRelation = tagArticleRelations.get(i);
final String tagId = tagArticleRelation.getString(Tag.TAG + "_" + Keys.OBJECT_ID);
final JSONObject tag = tagRepository.get(tagId);
tags.put(tag);
}
article.put(ARTICLE_TAGS_REF, tags);
// Signs
final JSONObject preference = preferenceQueryService.getPreference();
article.put(Sign.SIGNS, new JSONArray(preference.getString(Preference.SIGNS)));
// Remove unused properties
article.remove(ARTICLE_AUTHOR_EMAIL);
article.remove(ARTICLE_COMMENT_COUNT);
article.remove(ARTICLE_IS_PUBLISHED);
article.remove(ARTICLE_PUT_TOP);
article.remove(ARTICLE_UPDATE_DATE);
article.remove(ARTICLE_VIEW_COUNT);
article.remove(ARTICLE_RANDOM_DOUBLE);
LOGGER.log(Level.FINER, "Got an article[id={0}]", articleId);
return ret;
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Gets an article failed", e);
throw new ServiceException(e);
}
}
/**
* Gets articles(by crate date descending) by the specified request json
* object.
*
* <p>
* If the property "articleIsPublished" of the specified request json object is {@code true}, the returned articles all are published,
* {@code false} otherwise.
* </p>
*
* <p>
* Specified the "excludes" for results properties exclusion.
* </p>
*
* @param requestJSONObject the specified request json object, for example,
* <pre>
* {
* "paginationCurrentPageNum": 1,
* "paginationPageSize": 20,
* "paginationWindowSize": 10,
* "articleIsPublished": boolean,
* "excludes": ["", ....] // Optional
* }, see {@link Pagination} for more details
* </pre>
* @return for example,
* <pre>
* {
* "pagination": {
* "paginationPageCount": 100,
* "paginationPageNums": [1, 2, 3, 4, 5]
* },
* "articles": [{
* "oId": "",
* "articleTitle": "",
* "articleCommentCount": int,
* "articleCreateTime"; long,
* "articleViewCount": int,
* "articleTags": "tag1, tag2, ....",
* "articlePutTop": boolean,
* "articleSignId": "",
* "articleViewPwd": "",
* "articleEditorType": "",
* .... // Specified by the "excludes"
* }, ....]
* }
* </pre>, order by article update date and sticky(put top).
* @throws ServiceException service exception
* @see Pagination
*/
public JSONObject getArticles(final JSONObject requestJSONObject) throws ServiceException {
final JSONObject ret = new JSONObject();
try {
final int currentPageNum = requestJSONObject.getInt(Pagination.PAGINATION_CURRENT_PAGE_NUM);
final int pageSize = requestJSONObject.getInt(Pagination.PAGINATION_PAGE_SIZE);
final int windowSize = requestJSONObject.getInt(Pagination.PAGINATION_WINDOW_SIZE);
final boolean articleIsPublished = requestJSONObject.optBoolean(ARTICLE_IS_PUBLISHED, true);
final Query query = new Query().setCurrentPageNum(currentPageNum).
setPageSize(pageSize).
addSort(ARTICLE_PUT_TOP, SortDirection.DESCENDING).
addSort(ARTICLE_CREATE_DATE, SortDirection.DESCENDING).
setFilter(
new PropertyFilter(ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, articleIsPublished));
int articleCount = statistics.getBlogArticleCount();
if (!articleIsPublished) {
articleCount -= statistics.getPublishedBlogArticleCount();
}
final int pageCount = (int) Math.ceil((double) articleCount / (double) pageSize);
query.setPageCount(pageCount);
final JSONObject result = articleRepository.get(query);
final JSONObject pagination = new JSONObject();
ret.put(Pagination.PAGINATION, pagination);
final List<Integer> pageNums = Paginator.paginate(currentPageNum, pageSize, pageCount, windowSize);
pagination.put(Pagination.PAGINATION_PAGE_COUNT, pageCount);
pagination.put(Pagination.PAGINATION_PAGE_NUMS, pageNums);
final JSONArray articles = result.getJSONArray(Keys.RESULTS);
JSONArray excludes = requestJSONObject.optJSONArray(Keys.EXCLUDES);
excludes = null == excludes ? new JSONArray() : excludes;
for (int i = 0; i < articles.length(); i++) {
final JSONObject article = articles.getJSONObject(i);
final JSONObject author = articleUtils.getAuthor(article);
final String authorName = author.getString(User.USER_NAME);
article.put(Common.AUTHOR_NAME, authorName);
article.put(ARTICLE_CREATE_TIME, ((Date) article.get(ARTICLE_CREATE_DATE)).getTime());
// Markdown to HTML for content and abstract
markdown(article);
// Remove unused properties
for (int j = 0; j < excludes.length(); j++) {
article.remove(excludes.optString(j));
}
}
ret.put(ARTICLES, articles);
return ret;
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Gets articles failed", e);
throw new ServiceException(e);
}
}
/**
* Gets a list of published articles with the specified tag id, current page number and page size.
*
* @param tagId the specified tag id
* @param currentPageNum the specified current page number
* @param pageSize the specified page size
* @return a list of articles, returns an empty list if not found
* @throws ServiceException service exception
*/
public List<JSONObject> getArticlesByTag(final String tagId, final int currentPageNum, final int pageSize)
throws ServiceException {
try {
JSONObject result = tagArticleRepository.getByTagId(tagId, currentPageNum, pageSize);
final JSONArray tagArticleRelations = result.getJSONArray(Keys.RESULTS);
if (0 == tagArticleRelations.length()) {
return Collections.emptyList();
}
final Set<String> articleIds = new HashSet<String>();
for (int i = 0; i < tagArticleRelations.length(); i++) {
final JSONObject tagArticleRelation = tagArticleRelations.getJSONObject(i);
final String articleId = tagArticleRelation.getString(Article.ARTICLE + "_" + Keys.OBJECT_ID);
articleIds.add(articleId);
}
final List<JSONObject> ret = new ArrayList<JSONObject>();
final Query query = new Query().setFilter(
new PropertyFilter(Keys.OBJECT_ID, FilterOperator.IN, articleIds)).
setPageCount(1).index(Article.ARTICLE_PERMALINK);
result = articleRepository.get(query);
final JSONArray articles = result.getJSONArray(Keys.RESULTS);
for (int i = 0; i < articles.length(); i++) {
final JSONObject article = articles.getJSONObject(i);
if (!article.getBoolean(Article.ARTICLE_IS_PUBLISHED)) {
// Skips the unpublished article
continue;
}
// Markdown to HTML for content and abstract
markdown(article);
ret.add(article);
}
return ret;
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Gets articles by tag[id=" + tagId + "] failed", e);
throw new ServiceException(e);
}
}
/**
* Gets a list of published articles with the specified archive date id, current page number and page size.
*
* @param archiveDateId the specified archive date id
* @param currentPageNum the specified current page number
* @param pageSize the specified page size
* @return a list of articles, returns an empty list if not found
* @throws ServiceException service exception
*/
public List<JSONObject> getArticlesByArchiveDate(final String archiveDateId, final int currentPageNum, final int pageSize)
throws ServiceException {
try {
JSONObject result = archiveDateArticleRepository.getByArchiveDateId(archiveDateId, currentPageNum, pageSize);
final JSONArray relations = result.getJSONArray(Keys.RESULTS);
if (0 == relations.length()) {
return Collections.emptyList();
}
final Set<String> articleIds = new HashSet<String>();
for (int i = 0; i < relations.length(); i++) {
final JSONObject relation = relations.getJSONObject(i);
final String articleId = relation.getString(Article.ARTICLE + "_" + Keys.OBJECT_ID);
articleIds.add(articleId);
}
final List<JSONObject> ret = new ArrayList<JSONObject>();
final Query query = new Query().setFilter(
new PropertyFilter(Keys.OBJECT_ID, FilterOperator.IN, articleIds)).
setPageCount(1).index(Article.ARTICLE_PERMALINK);
result = articleRepository.get(query);
final JSONArray articles = result.getJSONArray(Keys.RESULTS);
for (int i = 0; i < articles.length(); i++) {
final JSONObject article = articles.getJSONObject(i);
if (!article.getBoolean(Article.ARTICLE_IS_PUBLISHED)) {
// Skips the unpublished article
continue;
}
// Markdown to HTML for content and abstract
markdown(article);
ret.add(article);
}
return ret;
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Gets articles by archive date[id=" + archiveDateId + "] failed", e);
throw new ServiceException(e);
}
}
/**
* Gets a list of articles randomly with the specified fetch size.
*
* <p>
* <b>Note</b>: The article content and abstract is raw (no editor type processing).
* </p>
*
* @param fetchSize the specified fetch size
* @return a list of json objects, its size less or equal to the specified
* fetch size
* @throws ServiceException service exception
*/
public List<JSONObject> getArticlesRandomly(final int fetchSize) throws ServiceException {
try {
final List<JSONObject> ret = articleRepository.getRandomly(fetchSize);
removeUnusedProperties(ret);
return ret;
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Gets articles randomly failed[fetchSize=" + fetchSize + "]", e);
throw new ServiceException(e);
}
}
/**
* Gets the relevant published articles of the specified article.
*
* <p>
* <b>Note</b>: The article content and abstract is raw (no editor type processing).
* </p>
*
* @param article the specified article
* @param preference the specified preference
* @return a list of articles, returns an empty list if not found
* @throws ServiceException service exception
*/
public List<JSONObject> getRelevantArticles(final JSONObject article, final JSONObject preference)
throws ServiceException {
try {
final int displayCnt = preference.getInt(Preference.RELEVANT_ARTICLES_DISPLAY_CNT);
final String[] tagTitles = article.getString(Article.ARTICLE_TAGS_REF).split(",");
final int maxTagCnt = displayCnt > tagTitles.length ? tagTitles.length : displayCnt;
final String articleId = article.getString(Keys.OBJECT_ID);
final List<JSONObject> articles = new ArrayList<JSONObject>();
for (int i = 0; i < maxTagCnt; i++) { // XXX: should average by tag?
final String tagTitle = tagTitles[i];
final JSONObject tag = tagRepository.getByTitle(tagTitle);
final String tagId = tag.getString(Keys.OBJECT_ID);
final JSONObject result = tagArticleRepository.getByTagId(tagId, 1, displayCnt);
final JSONArray tagArticleRelations = result.getJSONArray(Keys.RESULTS);
final int relationSize = displayCnt < tagArticleRelations.length() ? displayCnt : tagArticleRelations.length();
for (int j = 0; j < relationSize; j++) {
final JSONObject tagArticleRelation = tagArticleRelations.getJSONObject(j);
final String relatedArticleId = tagArticleRelation.getString(Article.ARTICLE + "_" + Keys.OBJECT_ID);
if (articleId.equals(relatedArticleId)) {
continue;
}
final JSONObject relevant = articleRepository.get(relatedArticleId);
if (!relevant.getBoolean(Article.ARTICLE_IS_PUBLISHED)) {
continue;
}
boolean existed = false;
for (final JSONObject relevantArticle : articles) {
if (relevantArticle.getString(Keys.OBJECT_ID).
equals(relevant.getString(Keys.OBJECT_ID))) {
existed = true;
}
}
if (!existed) {
articles.add(relevant);
}
}
}
Collections.sort(articles, Comparators.ARTICLE_UPDATE_DATE_COMPARATOR);
removeUnusedProperties(articles);
if (displayCnt > articles.size()) {
return articles;
}
final List<Integer> randomIntegers = CollectionUtils.getRandomIntegers(0, articles.size() - 1, displayCnt);
final List<JSONObject> ret = new ArrayList<JSONObject>();
for (final int index : randomIntegers) {
ret.add(articles.get(index));
}
return ret;
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Gets relevant articles failed", e);
throw new ServiceException(e);
}
}
/**
* Determines an article specified by the given article id is published.
*
* @param articleId the given article id
* @return {@code true} if it is published
* @throws ServiceException service exception
*/
public boolean isArticlePublished(final String articleId) throws ServiceException {
try {
return articleRepository.isPublished(articleId);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Determines the article publish status failed[articleId=" + articleId + "]", e);
throw new ServiceException(e);
}
}
/**
* Gets the next article(by create date) by the specified article id.
*
* <p>
* <b>Note</b>: The article content and abstract is raw (no editor type processing).
* </p>
*
* @param articleId the specified article id
* @return the previous article,
* <pre>
* {
* "articleTitle": "",
* "articlePermalink": ""
* }
* </pre>
* returns {@code null} if not found
* @throws ServiceException service exception
*/
public JSONObject getNextArticle(final String articleId) throws ServiceException {
try {
return articleRepository.getNextArticle(articleId);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Gets the next article failed[articleId=" + articleId + "]", e);
throw new ServiceException(e);
}
}
/**
* Gets the previous article(by create date) by the specified article id.
*
* <p>
* <b>Note</b>: The article content and abstract is raw (no editor type processing).
* </p>
*
* @param articleId the specified article id
* @return the previous article,
* <pre>
* {
* "articleTitle": "",
* "articlePermalink": ""
* }
* </pre>
* returns {@code null} if not found
* @throws ServiceException service exception
*/
public JSONObject getPreviousArticle(final String articleId) throws ServiceException {
try {
return articleRepository.getPreviousArticle(articleId);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Gets the previous article failed[articleId=" + articleId + "]", e);
throw new ServiceException(e);
}
}
/**
* Gets an article by the specified article id.
*
* <p>
* <b>Note</b>: The article content and abstract is raw (no editor type processing).
* </p>
*
* @param articleId the specified article id
* @return an article, returns {@code null} if not found
* @throws ServiceException service exception
*/
public JSONObject getArticleById(final String articleId) throws ServiceException {
try {
return articleRepository.get(articleId);
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Gets an article[articleId=" + articleId + "] failed", e);
throw new ServiceException(e);
}
}
/**
* Gets <em>published</em> articles by the specified author email, current page number and page size.
*
* @param authorEmail the specified author email
* @param currentPageNum the specified current page number
* @param pageSize the specified page size
* @return a list of articles, returns an empty list if not found
* @throws ServiceException service exception
*/
public List<JSONObject> getArticlesByAuthorEmail(final String authorEmail, final int currentPageNum, final int pageSize)
throws ServiceException {
try {
final JSONObject result = articleRepository.getByAuthorEmail(authorEmail, currentPageNum, pageSize);
final JSONArray articles = result.getJSONArray(Keys.RESULTS);
final List<JSONObject> ret = new ArrayList<JSONObject>();
for (int i = 0; i < articles.length(); i++) {
final JSONObject article = articles.getJSONObject(i);
// Markdown to HTML for content and abstract
markdown(article);
ret.add(article);
}
return ret;
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Gets articles by author email failed[authorEmail="
+ authorEmail + ", currentPageNum=" + currentPageNum + ", pageSize=" + pageSize + "]", e);
throw new ServiceException(e);
}
}
/**
* Gets article contents with the specified article id.
*
* <p>
* Invoking this method dose not effect on article view count.
* </p>
*
* @param articleId the specified article id
* @return article contents, returns {@code null} if not found
* @throws ServiceException service exception
*/
public String getArticleContent(final String articleId) throws ServiceException {
if (Strings.isEmptyOrNull(articleId)) {
return null;
}
try {
final JSONObject article = articleRepository.get(articleId);
if (null == article) {
return null;
}
// Markdown to HTML for content and abstract
if ("CodeMirror-Markdown".equals(article.optString(ARTICLE_EDITOR_TYPE))) {
Stopwatchs.start("Get Article Content [Markdown]");
final String content = article.optString(ARTICLE_CONTENT);
article.put(ARTICLE_CONTENT, Markdowns.toHTML(content));
Stopwatchs.end();
}
return article.getString(Article.ARTICLE_CONTENT);
} catch (final Exception e) {
LOGGER.log(Level.SEVERE, "Gets article content failed[articleId=" + articleId + "]", e);
throw new ServiceException(e);
}
}
/**
* Converts the content and abstract for each of the specified articles to HTML if that is saved by Markdown editor.
*
* @param articles the specified articles
* @throws Exception exception
*/
public void markdowns(final List<JSONObject> articles) throws Exception {
for (final JSONObject article : articles) {
markdown(article);
}
}
/**
* Converts the content and abstract for the specified article to HTML if it is saved by Markdown editor.
*
* @param article the specified article
* @throws Exception exception
*/
public void markdown(final JSONObject article) throws Exception {
if ("CodeMirror-Markdown".equals(article.optString(ARTICLE_EDITOR_TYPE))) {
Stopwatchs.start("Markdown Article[id=" + article.optString(Keys.OBJECT_ID) + "]");
Stopwatchs.start("Content");
final String content = article.optString(ARTICLE_CONTENT);
article.put(ARTICLE_CONTENT, Markdowns.toHTML(content));
Stopwatchs.end();
final String abstractContent = article.optString(ARTICLE_ABSTRACT);
if (!Strings.isEmptyOrNull(abstractContent)) {
Stopwatchs.start("Abstract");
article.put(ARTICLE_ABSTRACT, Markdowns.toHTML(abstractContent));
Stopwatchs.end();
}
Stopwatchs.end();
}
}
/**
* Removes unused properties of each article in the specified articles.
*
* <p>
* Remains the following properties:
* <ul>
* <li>{@link Article#ARTICLE_TITLE article title}</li>
* <li>{@link Article#ARTICLE_PERMALINK article permalink}</li>
* </ul>
* </p>
*
* <p>
* The batch version of method {@link #removeUnusedProperties(org.json.JSONObject)}.
* </p>
*
* @param articles the specified articles
* @see #removeUnusedProperties(org.json.JSONObject)
*/
public void removeUnusedProperties(final List<JSONObject> articles) {
for (final JSONObject article : articles) {
removeUnusedProperties(article);
}
}
/**
* Removes unused properties of the specified article.
*
* <p>
* Remains the following properties:
* <ul>
* <li>{@link Article#ARTICLE_TITLE article title}</li>
* <li>{@link Article#ARTICLE_PERMALINK article permalink}</li>
* </ul>
* </p>
*
* @param article the specified article
* @see #removeUnusedProperties(java.util.List)
*/
public void removeUnusedProperties(final JSONObject article) {
article.remove(Keys.OBJECT_ID);
article.remove(Article.ARTICLE_AUTHOR_EMAIL);
article.remove(Article.ARTICLE_ABSTRACT);
article.remove(Article.ARTICLE_COMMENT_COUNT);
article.remove(Article.ARTICLE_CONTENT);
article.remove(Article.ARTICLE_CREATE_DATE);
article.remove(Article.ARTICLE_TAGS_REF);
article.remove(Article.ARTICLE_UPDATE_DATE);
article.remove(Article.ARTICLE_VIEW_COUNT);
article.remove(Article.ARTICLE_RANDOM_DOUBLE);
article.remove(Article.ARTICLE_IS_PUBLISHED);
article.remove(Article.ARTICLE_PUT_TOP);
article.remove(Article.ARTICLE_HAD_BEEN_PUBLISHED);
}
/**
* Gets the {@link ArticleQueryService} singleton.
*
* @return the singleton
*/
public static ArticleQueryService getInstance() {
return SingletonHolder.SINGLETON;
}
/**
* Private constructor.
*/
private ArticleQueryService() {
}
/**
* Singleton holder.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.0, Oct 3, 2011
*/
private static final class SingletonHolder {
/**
* Singleton.
*/
private static final ArticleQueryService SINGLETON = new ArticleQueryService();
/**
* Private default constructor.
*/
private SingletonHolder() {
}
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.util;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.b3log.solo.model.Article;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.Query;
import org.b3log.latke.repository.RepositoryException;
import org.b3log.latke.repository.SortDirection;
import org.b3log.latke.service.ServiceException;
import org.b3log.latke.user.UserService;
import org.b3log.latke.user.UserServiceFactory;
import org.b3log.latke.util.CollectionUtils;
import org.b3log.latke.util.Strings;
import org.b3log.solo.model.Common;
import org.b3log.solo.model.Preference;
import org.b3log.solo.repository.ArticleRepository;
import org.b3log.solo.repository.UserRepository;
import org.b3log.solo.repository.impl.ArticleRepositoryImpl;
import org.b3log.solo.repository.impl.UserRepositoryImpl;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Article utilities.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.2.8, May 6, 2012
* @since 0.3.1
*/
public final class Articles {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(Articles.class.getName());
/**
* Article repository.
*/
private ArticleRepository articleRepository = ArticleRepositoryImpl.getInstance();
/**
* User repository.
*/
private UserRepository userRepository = UserRepositoryImpl.getInstance();
/**
* User service.
*/
private UserService userService = UserServiceFactory.getUserService();
/**
* Builds article view password form parameters with the specified article.
*
* @param article the specified article
* @return parameters string, for example,
* <pre>
* "?articleId=xxx&articleTitle=xxx&articlePermalink=xxx&articleAbstract=xxx"
* </pre>
* @throws UnsupportedEncodingException if can not encode the arguments
*/
public String buildArticleViewPwdFormParameters(final JSONObject article) throws UnsupportedEncodingException {
final StringBuilder parametersBuilder =
new StringBuilder("?articleId=").append(article.optString(Keys.OBJECT_ID)).
append("&articleTitle=").append(URLEncoder.encode(article.optString(Article.ARTICLE_TITLE), "UTF-8")).
append("&articlePermalink=").append(URLEncoder.encode(article.optString(Article.ARTICLE_PERMALINK), "UTF-8")).
append("&articleAbstract=").append(URLEncoder.encode(article.optString(Article.ARTICLE_ABSTRACT, " "), "UTF-8"));
return parametersBuilder.toString();
}
/**
* Checks whether need password to view the specified article with the specified request.
*
* <p>
* Checks session, if not represents, checks article property {@link Article#ARTICLE_VIEW_PWD view password}.
* </p>
*
* <p>
* The blogger itself dose not need view password never.
* </p>
*
* @param request the specified request
* @param article the specified article
* @return {@code true} if need, returns {@code false} otherwise
*/
public boolean needViewPwd(final HttpServletRequest request, final JSONObject article) {
final String articleViewPwd = article.optString(Article.ARTICLE_VIEW_PWD);
if (Strings.isEmptyOrNull(articleViewPwd)) {
return false;
}
final HttpSession session = request.getSession(false);
if (null != session) {
@SuppressWarnings("unchecked")
Map<String, String> viewPwds = (Map<String, String>) session.getAttribute(Common.ARTICLES_VIEW_PWD);
if (null == viewPwds) {
viewPwds = new HashMap<String, String>();
}
if (articleViewPwd.equals(viewPwds.get(article.optString(Keys.OBJECT_ID)))) {
return false;
}
}
if (null != userService.getCurrentUser(request)) {
return false;
}
return true;
}
/**
* Gets the specified article's author.
*
* <p>
* The specified article has a property
* {@value Article#ARTICLE_AUTHOR_EMAIL}, this method will use this property
* to get a user from users.
* </p>
*
* <p>
* If can't find the specified article's author (i.e. the author has been
* removed by administrator), returns administrator.
* </p>
*
* @param article the specified article
* @return user, {@code null} if not found
* @throws ServiceException service exception
*/
public JSONObject getAuthor(final JSONObject article) throws ServiceException {
try {
final String email = article.getString(Article.ARTICLE_AUTHOR_EMAIL);
JSONObject ret = userRepository.getByEmail(email);
if (null == ret) {
LOGGER.log(Level.WARNING,
"Gets author of article failed, assumes the administrator is the author of this article[id={0}]",
article.getString(Keys.OBJECT_ID));
// This author may be deleted by admin, use admin as the author
// of this article
ret = userRepository.getAdmin();
}
return ret;
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Gets author of article[id={0}] failed", article.optString(Keys.OBJECT_ID));
throw new ServiceException(e);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Gets author of article[id={0}] failed", article.optString(Keys.OBJECT_ID));
throw new ServiceException(e);
}
}
/**
* Article comment count +1 for an article specified by the given article id.
*
* @param articleId the given article id
* @throws JSONException json exception
* @throws RepositoryException repository exception
*/
public void incArticleCommentCount(final String articleId) throws JSONException, RepositoryException {
final JSONObject article = articleRepository.get(articleId);
final JSONObject newArticle = new JSONObject(article, JSONObject.getNames(article));
final int commentCnt = article.getInt(Article.ARTICLE_COMMENT_COUNT);
newArticle.put(Article.ARTICLE_COMMENT_COUNT, commentCnt + 1);
articleRepository.update(articleId, newArticle);
}
/**
* Gets the sign of an article specified by the sign id.
*
* @param signId the specified article id
* @param preference the specified preference
* @return article sign, returns the default sign (which oId is "1") if not found
* @throws RepositoryException repository exception
* @throws JSONException json exception
*/
public JSONObject getSign(final String signId, final JSONObject preference) throws JSONException, RepositoryException {
final JSONArray signs = new JSONArray(preference.getString(Preference.SIGNS));
JSONObject defaultSign = null;
for (int i = 0; i < signs.length(); i++) {
final JSONObject ret = signs.getJSONObject(i);
if (signId.equals(ret.optString(Keys.OBJECT_ID))) {
return ret;
}
if ("1".equals(ret.optString(Keys.OBJECT_ID))) {
defaultSign = ret;
}
}
LOGGER.log(Level.WARNING, "Can not find the sign[id={0}], returns a default sign[id=1]", signId);
if (null == defaultSign) {
throw new IllegalStateException("Can not find the default sign which id equals to 1");
}
return defaultSign;
}
/**
* Determines the specified article has updated.
*
* @param article the specified article
* @return {@code true} if it has updated, {@code false} otherwise
* @throws JSONException json exception
*/
public boolean hasUpdated(final JSONObject article) throws JSONException {
final Date updateDate = (Date) article.get(Article.ARTICLE_UPDATE_DATE);
final Date createDate = (Date) article.get(Article.ARTICLE_CREATE_DATE);
return !createDate.equals(updateDate);
}
/**
* Determines the specified article had been published.
*
* @param article the specified article
* @return {@code true} if it had been published, {@code false} otherwise
* @throws JSONException json exception
*/
public boolean hadBeenPublished(final JSONObject article) throws JSONException {
return article.getBoolean(Article.ARTICLE_HAD_BEEN_PUBLISHED);
}
/**
* Gets all unpublished articles.
*
* @return articles all unpublished articles
* @throws RepositoryException repository exception
* @throws JSONException json exception
*/
public List<JSONObject> getUnpublishedArticles() throws RepositoryException, JSONException {
final Map<String, SortDirection> sorts = new HashMap<String, SortDirection>();
sorts.put(Article.ARTICLE_CREATE_DATE, SortDirection.DESCENDING);
sorts.put(Article.ARTICLE_PUT_TOP, SortDirection.DESCENDING);
final Query query = new Query().addFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true);
final JSONObject result = articleRepository.get(query);
final JSONArray articles = result.getJSONArray(Keys.RESULTS);
return CollectionUtils.jsonArrayToList(articles);
}
/**
* Gets the {@link Articles} singleton.
*
* @return the singleton
*/
public static Articles getInstance() {
return SingletonHolder.SINGLETON;
}
/**
* Private default constructor.
*/
private Articles() {
}
/**
* Singleton holder.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.0, Jan 12, 2011
*/
private static final class SingletonHolder {
/**
* Singleton.
*/
private static final Articles SINGLETON = new Articles();
/**
* Private default constructor.
*/
private SingletonHolder() {
}
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.util;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.b3log.solo.model.Article;
import org.b3log.latke.Keys;
import org.b3log.latke.repository.*;
import org.b3log.latke.service.ServiceException;
import org.b3log.latke.user.UserService;
import org.b3log.latke.user.UserServiceFactory;
import org.b3log.latke.util.CollectionUtils;
import org.b3log.latke.util.Strings;
import org.b3log.solo.model.Common;
import org.b3log.solo.model.Preference;
import org.b3log.solo.repository.ArticleRepository;
import org.b3log.solo.repository.UserRepository;
import org.b3log.solo.repository.impl.ArticleRepositoryImpl;
import org.b3log.solo.repository.impl.UserRepositoryImpl;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Article utilities.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.2.8, May 6, 2012
* @since 0.3.1
*/
public final class Articles {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(Articles.class.getName());
/**
* Article repository.
*/
private ArticleRepository articleRepository = ArticleRepositoryImpl.getInstance();
/**
* User repository.
*/
private UserRepository userRepository = UserRepositoryImpl.getInstance();
/**
* User service.
*/
private UserService userService = UserServiceFactory.getUserService();
/**
* Builds article view password form parameters with the specified article.
*
* @param article the specified article
* @return parameters string, for example,
* <pre>
* "?articleId=xxx&articleTitle=xxx&articlePermalink=xxx&articleAbstract=xxx"
* </pre>
* @throws UnsupportedEncodingException if can not encode the arguments
*/
public String buildArticleViewPwdFormParameters(final JSONObject article) throws UnsupportedEncodingException {
final StringBuilder parametersBuilder =
new StringBuilder("?articleId=").append(article.optString(Keys.OBJECT_ID)).
append("&articleTitle=").append(URLEncoder.encode(article.optString(Article.ARTICLE_TITLE), "UTF-8")).
append("&articlePermalink=").append(URLEncoder.encode(article.optString(Article.ARTICLE_PERMALINK), "UTF-8")).
append("&articleAbstract=").append(URLEncoder.encode(article.optString(Article.ARTICLE_ABSTRACT, " "), "UTF-8"));
return parametersBuilder.toString();
}
/**
* Checks whether need password to view the specified article with the specified request.
*
* <p>
* Checks session, if not represents, checks article property {@link Article#ARTICLE_VIEW_PWD view password}.
* </p>
*
* <p>
* The blogger itself dose not need view password never.
* </p>
*
* @param request the specified request
* @param article the specified article
* @return {@code true} if need, returns {@code false} otherwise
*/
public boolean needViewPwd(final HttpServletRequest request, final JSONObject article) {
final String articleViewPwd = article.optString(Article.ARTICLE_VIEW_PWD);
if (Strings.isEmptyOrNull(articleViewPwd)) {
return false;
}
final HttpSession session = request.getSession(false);
if (null != session) {
@SuppressWarnings("unchecked")
Map<String, String> viewPwds = (Map<String, String>) session.getAttribute(Common.ARTICLES_VIEW_PWD);
if (null == viewPwds) {
viewPwds = new HashMap<String, String>();
}
if (articleViewPwd.equals(viewPwds.get(article.optString(Keys.OBJECT_ID)))) {
return false;
}
}
if (null != userService.getCurrentUser(request)) {
return false;
}
return true;
}
/**
* Gets the specified article's author.
*
* <p>
* The specified article has a property
* {@value Article#ARTICLE_AUTHOR_EMAIL}, this method will use this property
* to get a user from users.
* </p>
*
* <p>
* If can't find the specified article's author (i.e. the author has been
* removed by administrator), returns administrator.
* </p>
*
* @param article the specified article
* @return user, {@code null} if not found
* @throws ServiceException service exception
*/
public JSONObject getAuthor(final JSONObject article) throws ServiceException {
try {
final String email = article.getString(Article.ARTICLE_AUTHOR_EMAIL);
JSONObject ret = userRepository.getByEmail(email);
if (null == ret) {
LOGGER.log(Level.WARNING,
"Gets author of article failed, assumes the administrator is the author of this article[id={0}]",
article.getString(Keys.OBJECT_ID));
// This author may be deleted by admin, use admin as the author
// of this article
ret = userRepository.getAdmin();
}
return ret;
} catch (final RepositoryException e) {
LOGGER.log(Level.SEVERE, "Gets author of article[id={0}] failed", article.optString(Keys.OBJECT_ID));
throw new ServiceException(e);
} catch (final JSONException e) {
LOGGER.log(Level.SEVERE, "Gets author of article[id={0}] failed", article.optString(Keys.OBJECT_ID));
throw new ServiceException(e);
}
}
/**
* Article comment count +1 for an article specified by the given article id.
*
* @param articleId the given article id
* @throws JSONException json exception
* @throws RepositoryException repository exception
*/
public void incArticleCommentCount(final String articleId) throws JSONException, RepositoryException {
final JSONObject article = articleRepository.get(articleId);
final JSONObject newArticle = new JSONObject(article, JSONObject.getNames(article));
final int commentCnt = article.getInt(Article.ARTICLE_COMMENT_COUNT);
newArticle.put(Article.ARTICLE_COMMENT_COUNT, commentCnt + 1);
articleRepository.update(articleId, newArticle);
}
/**
* Gets the sign of an article specified by the sign id.
*
* @param signId the specified article id
* @param preference the specified preference
* @return article sign, returns the default sign (which oId is "1") if not found
* @throws RepositoryException repository exception
* @throws JSONException json exception
*/
public JSONObject getSign(final String signId, final JSONObject preference) throws JSONException, RepositoryException {
final JSONArray signs = new JSONArray(preference.getString(Preference.SIGNS));
JSONObject defaultSign = null;
for (int i = 0; i < signs.length(); i++) {
final JSONObject ret = signs.getJSONObject(i);
if (signId.equals(ret.optString(Keys.OBJECT_ID))) {
return ret;
}
if ("1".equals(ret.optString(Keys.OBJECT_ID))) {
defaultSign = ret;
}
}
LOGGER.log(Level.WARNING, "Can not find the sign[id={0}], returns a default sign[id=1]", signId);
if (null == defaultSign) {
throw new IllegalStateException("Can not find the default sign which id equals to 1");
}
return defaultSign;
}
/**
* Determines the specified article has updated.
*
* @param article the specified article
* @return {@code true} if it has updated, {@code false} otherwise
* @throws JSONException json exception
*/
public boolean hasUpdated(final JSONObject article) throws JSONException {
final Date updateDate = (Date) article.get(Article.ARTICLE_UPDATE_DATE);
final Date createDate = (Date) article.get(Article.ARTICLE_CREATE_DATE);
return !createDate.equals(updateDate);
}
/**
* Determines the specified article had been published.
*
* @param article the specified article
* @return {@code true} if it had been published, {@code false} otherwise
* @throws JSONException json exception
*/
public boolean hadBeenPublished(final JSONObject article) throws JSONException {
return article.getBoolean(Article.ARTICLE_HAD_BEEN_PUBLISHED);
}
/**
* Gets all unpublished articles.
*
* @return articles all unpublished articles
* @throws RepositoryException repository exception
* @throws JSONException json exception
*/
public List<JSONObject> getUnpublishedArticles() throws RepositoryException, JSONException {
final Map<String, SortDirection> sorts = new HashMap<String, SortDirection>();
sorts.put(Article.ARTICLE_CREATE_DATE, SortDirection.DESCENDING);
sorts.put(Article.ARTICLE_PUT_TOP, SortDirection.DESCENDING);
final Query query = new Query().setFilter(
new PropertyFilter(Article.ARTICLE_IS_PUBLISHED, FilterOperator.EQUAL, true));
final JSONObject result = articleRepository.get(query);
final JSONArray articles = result.getJSONArray(Keys.RESULTS);
return CollectionUtils.jsonArrayToList(articles);
}
/**
* Gets the {@link Articles} singleton.
*
* @return the singleton
*/
public static Articles getInstance() {
return SingletonHolder.SINGLETON;
}
/**
* Private default constructor.
*/
private Articles() {
}
/**
* Singleton holder.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.0, Jan 12, 2011
*/
private static final class SingletonHolder {
/**
* Singleton.
*/
private static final Articles SINGLETON = new Articles();
/**
* Private default constructor.
*/
private SingletonHolder() {
}
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import org.b3log.latke.Keys;
import org.b3log.latke.model.Role;
import org.b3log.latke.model.User;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.Query;
import org.b3log.latke.repository.Transaction;
import org.b3log.solo.AbstractTestCase;
import org.b3log.solo.model.UserExt;
import org.b3log.solo.repository.UserRepository;
import org.json.JSONArray;
import org.json.JSONObject;
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* {@link UserRepositoryImpl} test case.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.1, Feb 21, 2012
*/
@Test(suiteName = "repository")
public final class UserRepositoryImplTestCase extends AbstractTestCase {
/**
* Tests.
*
* @throws Exception exception
*/
@Test
public void test() throws Exception {
final UserRepository userRepository = getUserRepository();
final JSONObject another = new JSONObject();
another.put(User.USER_NAME, "test1");
another.put(User.USER_EMAIL, "test1@gmail.com");
another.put(User.USER_PASSWORD, "pass1");
another.put(User.USER_ROLE, Role.DEFAULT_ROLE);
another.put(UserExt.USER_ARTICLE_COUNT, 0);
another.put(UserExt.USER_PUBLISHED_ARTICLE_COUNT, 0);
Transaction transaction = userRepository.beginTransaction();
userRepository.add(another);
transaction.commit();
Assert.assertNull(userRepository.getAdmin());
JSONObject admin = new JSONObject();
admin.put(User.USER_NAME, "test");
admin.put(User.USER_EMAIL, "test@gmail.com");
admin.put(User.USER_PASSWORD, "pass");
admin.put(User.USER_ROLE, Role.ADMIN_ROLE);
admin.put(UserExt.USER_ARTICLE_COUNT, 0);
admin.put(UserExt.USER_PUBLISHED_ARTICLE_COUNT, 0);
transaction = userRepository.beginTransaction();
userRepository.add(admin);
transaction.commit();
Assert.assertTrue(userRepository.isAdminEmail("test@gmail.com"));
Assert.assertFalse(userRepository.isAdminEmail("notFound@gmail.com"));
admin = userRepository.getAdmin();
Assert.assertNotNull(admin);
Assert.assertEquals("test", admin.optString(User.USER_NAME));
final JSONObject result =
userRepository.get(new Query().addFilter(User.USER_NAME,
FilterOperator.EQUAL,
"test1"));
final JSONArray users = result.getJSONArray(Keys.RESULTS);
Assert.assertEquals(users.length(), 1);
Assert.assertEquals(users.getJSONObject(0).getString(User.USER_EMAIL),
"test1@gmail.com");
final JSONObject notFound =
userRepository.getByEmail("not.found@gmail.com");
Assert.assertNull(notFound);
final JSONObject found = userRepository.getByEmail("test1@gmail.com");
Assert.assertNotNull(found);
Assert.assertEquals(found.getString(User.USER_PASSWORD), "pass1");
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.repository.impl;
import org.b3log.latke.Keys;
import org.b3log.latke.model.Role;
import org.b3log.latke.model.User;
import org.b3log.latke.repository.FilterOperator;
import org.b3log.latke.repository.PropertyFilter;
import org.b3log.latke.repository.Query;
import org.b3log.latke.repository.Transaction;
import org.b3log.solo.AbstractTestCase;
import org.b3log.solo.model.UserExt;
import org.b3log.solo.repository.UserRepository;
import org.json.JSONArray;
import org.json.JSONObject;
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* {@link UserRepositoryImpl} test case.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.1, Feb 21, 2012
*/
@Test(suiteName = "repository")
public final class UserRepositoryImplTestCase extends AbstractTestCase {
/**
* Tests.
*
* @throws Exception exception
*/
@Test
public void test() throws Exception {
final UserRepository userRepository = getUserRepository();
final JSONObject another = new JSONObject();
another.put(User.USER_NAME, "test1");
another.put(User.USER_EMAIL, "test1@gmail.com");
another.put(User.USER_PASSWORD, "pass1");
another.put(User.USER_ROLE, Role.DEFAULT_ROLE);
another.put(UserExt.USER_ARTICLE_COUNT, 0);
another.put(UserExt.USER_PUBLISHED_ARTICLE_COUNT, 0);
Transaction transaction = userRepository.beginTransaction();
userRepository.add(another);
transaction.commit();
Assert.assertNull(userRepository.getAdmin());
JSONObject admin = new JSONObject();
admin.put(User.USER_NAME, "test");
admin.put(User.USER_EMAIL, "test@gmail.com");
admin.put(User.USER_PASSWORD, "pass");
admin.put(User.USER_ROLE, Role.ADMIN_ROLE);
admin.put(UserExt.USER_ARTICLE_COUNT, 0);
admin.put(UserExt.USER_PUBLISHED_ARTICLE_COUNT, 0);
transaction = userRepository.beginTransaction();
userRepository.add(admin);
transaction.commit();
Assert.assertTrue(userRepository.isAdminEmail("test@gmail.com"));
Assert.assertFalse(userRepository.isAdminEmail("notFound@gmail.com"));
admin = userRepository.getAdmin();
Assert.assertNotNull(admin);
Assert.assertEquals("test", admin.optString(User.USER_NAME));
final JSONObject result =
userRepository.get(new Query().setFilter(
new PropertyFilter(User.USER_NAME, FilterOperator.EQUAL, "test1")));
final JSONArray users = result.getJSONArray(Keys.RESULTS);
Assert.assertEquals(users.length(), 1);
Assert.assertEquals(users.getJSONObject(0).getString(User.USER_EMAIL),
"test1@gmail.com");
final JSONObject notFound =
userRepository.getByEmail("not.found@gmail.com");
Assert.assertNull(notFound);
final JSONObject found = userRepository.getByEmail("test1@gmail.com");
Assert.assertNotNull(found);
Assert.assertEquals(found.getString(User.USER_PASSWORD), "pass1");
}
}
#
# Copyright (C) 2009, 2010, 2011, B3log Team
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# Description: ease skin (mock for test).
# Version: 1.0.0.0, Jun 27, 2012
# Author: Liang Ding
#
name=ease
version=1.0.1
forSolo=0.4.6
memo=\u56de\u5f52\u606c\u9759
<?xml version="1.0" encoding="UTF-8"?>
<!--
Description: B3log Solo parent POM.
Version: 2.0.2.0, Jun 19, 2012
Version: 2.0.2.1, Jun 27, 2012
Author: Liang Ding
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
......@@ -32,7 +32,7 @@
<org.b3log.latke.version>0.5.0-SNAPSHOT</org.b3log.latke.version>
<org.b3log.latke-gae.version>0.5.0-SNAPSHOT</org.b3log.latke-gae.version>
<org.b3log.latke-repository-mysql.version>0.5.0-SNAPSHOT</org.b3log.latke-repository-mysql.version>
<gae.version>1.6.5</gae.version>
<gae.version>1.7.0</gae.version>
<freemarker-gae.version>2.3.19</freemarker-gae.version>
<jsoup.version>1.5.2</jsoup.version>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment