/core/src/main/java/org/b3log/solo/service/PageMgmtService.java
Java | 414 lines | 212 code | 61 blank | 141 comment | 30 complexity | c779e5499d650faa41aac974c6121eb0 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1
1/* 2 * Copyright (c) 2009, 2010, 2011, 2012, B3log Team 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package org.b3log.solo.service; 17 18import java.util.List; 19import java.util.logging.Level; 20import java.util.logging.Logger; 21import org.b3log.latke.Keys; 22import org.b3log.latke.repository.RepositoryException; 23import org.b3log.latke.repository.Transaction; 24import org.b3log.latke.service.LangPropsService; 25import org.b3log.latke.service.ServiceException; 26import org.b3log.latke.util.Ids; 27import org.b3log.latke.util.Strings; 28import org.b3log.solo.model.Comment; 29import org.b3log.solo.model.Page; 30import org.b3log.solo.model.Preference; 31import org.b3log.solo.repository.CommentRepository; 32import org.b3log.solo.repository.PageRepository; 33import org.b3log.solo.repository.impl.CommentRepositoryImpl; 34import org.b3log.solo.repository.impl.PageRepositoryImpl; 35import org.b3log.solo.util.Comments; 36import org.b3log.solo.util.Permalinks; 37import org.b3log.solo.util.Statistics; 38import org.json.JSONException; 39import org.json.JSONObject; 40 41/** 42 * Page management service. 43 * 44 * @author <a href="mailto:DL88250@gmail.com">Liang Ding</a> 45 * @version 1.0.0.7, Jun 8, 2012 46 * @since 0.4.0 47 */ 48public final class PageMgmtService { 49 50 /** 51 * Logger. 52 */ 53 private static final Logger LOGGER = Logger.getLogger(PageMgmtService.class.getName()); 54 /** 55 * Page repository. 56 */ 57 private PageRepository pageRepository = PageRepositoryImpl.getInstance(); 58 /** 59 * Comment repository. 60 */ 61 private CommentRepository commentRepository = CommentRepositoryImpl.getInstance(); 62 /** 63 * Statistic utilities. 64 */ 65 private Statistics statistics = Statistics.getInstance(); 66 /** 67 * Language service. 68 */ 69 private LangPropsService langPropsService = LangPropsService.getInstance(); 70 /** 71 * Permalink utilities. 72 */ 73 private Permalinks permalinks = Permalinks.getInstance(); 74 /** 75 * Preference query service. 76 */ 77 private PreferenceQueryService preferenceQueryService = PreferenceQueryService.getInstance(); 78 79 /** 80 * Updates a page by the specified request json object. 81 * 82 * @param requestJSONObject the specified request json object, for example, 83 * <pre> 84 * { 85 * "page": { 86 * "oId": "", 87 * "pageTitle": "", 88 * "pageContent": "", 89 * "pageOrder": int, 90 * "pageCommentCount": int, 91 * "pagePermalink": "", 92 * "pageCommentable": boolean, 93 * "pageType": "", 94 * "pageOpenTarget": "" 95 * } 96 * }, see {@link Page} for more details 97 * </pre> 98 * @throws ServiceException service exception 99 */ 100 public void updatePage(final JSONObject requestJSONObject) throws ServiceException { 101 102 final Transaction transaction = pageRepository.beginTransaction(); 103 try { 104 final JSONObject page = requestJSONObject.getJSONObject(Page.PAGE); 105 final String pageId = page.getString(Keys.OBJECT_ID); 106 final JSONObject oldPage = pageRepository.get(pageId); 107 final JSONObject newPage = new JSONObject(page, JSONObject.getNames(page)); 108 newPage.put(Page.PAGE_ORDER, oldPage.getInt(Page.PAGE_ORDER)); 109 newPage.put(Page.PAGE_COMMENT_COUNT, oldPage.getInt(Page.PAGE_COMMENT_COUNT)); 110 String permalink = page.optString(Page.PAGE_PERMALINK).trim(); 111 112 final String oldPermalink = oldPage.getString(Page.PAGE_PERMALINK); 113 if (!oldPermalink.equals(permalink)) { 114 if (Strings.isEmptyOrNull(permalink)) { 115 permalink = "/pages/" + pageId + ".html"; 116 } 117 118 if (Page.PAGE.equals(page.getString(Page.PAGE_TYPE))) { 119 if (!permalink.startsWith("/")) { 120 permalink = "/" + permalink; 121 } 122 123 if (Permalinks.invalidPagePermalinkFormat(permalink)) { 124 if (transaction.isActive()) { 125 transaction.rollback(); 126 } 127 128 throw new ServiceException(langPropsService.get("invalidPermalinkFormatLabel")); 129 } 130 131 if (!oldPermalink.equals(permalink) 132 && permalinks.exist(permalink)) { 133 if (transaction.isActive()) { 134 transaction.rollback(); 135 } 136 137 throw new ServiceException(langPropsService.get("duplicatedPermalinkLabel")); 138 } 139 } 140 } 141 142 // TODO: SBC case 143 newPage.put(Page.PAGE_PERMALINK, permalink.replaceAll(" ", "-")); 144 145 if (!oldPage.getString(Page.PAGE_PERMALINK).equals(permalink)) { // The permalink has been updated 146 // Updates related comments' links 147 processCommentsForPageUpdate(newPage); 148 } 149 150 // Editor type 151 final JSONObject preference = preferenceQueryService.getPreference(); 152 newPage.put(Page.PAGE_EDITOR_TYPE, preference.optString(Preference.EDITOR_TYPE)); 153 154 pageRepository.update(pageId, newPage); 155 156 transaction.commit(); 157 158 LOGGER.log(Level.FINER, "Updated a page[id={0}]", pageId); 159 } catch (final Exception e) { 160 LOGGER.log(Level.SEVERE, e.getMessage(), e); 161 if (transaction.isActive()) { 162 transaction.rollback(); 163 } 164 165 throw new ServiceException(e); 166 } 167 } 168 169 /** 170 * Removes a page specified by the given page id. 171 * 172 * @param pageId the given page id 173 * @throws ServiceException service exception 174 */ 175 public void removePage(final String pageId) throws ServiceException { 176 final Transaction transaction = pageRepository.beginTransaction(); 177 try { 178 LOGGER.log(Level.FINER, "Removing a page[id={0}]", pageId); 179 removePageComments(pageId); 180 pageRepository.remove(pageId); 181 182 transaction.commit(); 183 184 } catch (final Exception e) { 185 if (transaction.isActive()) { 186 transaction.rollback(); 187 } 188 189 LOGGER.log(Level.SEVERE, "Removes a page[id=" + pageId + "] failed", e); 190 191 throw new ServiceException(e); 192 } 193 } 194 195 /** 196 * Adds a page with the specified request json object. 197 * 198 * @param requestJSONObject the specified request json object, for example, 199 * <pre> 200 * { 201 * "page": { 202 * "pageTitle": "", 203 * "pageContent": "", 204 * "pageOpenTarget": "", 205 * "pageCommentable": boolean, 206 * "pageType": "", 207 * "pagePermalink": "" // optional 208 * } 209 * }, see {@link Page} for more details 210 * </pre> 211 * @return generated page id 212 * @throws ServiceException if permalink format checks failed or persists 213 * failed 214 */ 215 public String addPage(final JSONObject requestJSONObject) throws ServiceException { 216 final Transaction transaction = pageRepository.beginTransaction(); 217 try { 218 final JSONObject page = requestJSONObject.getJSONObject(Page.PAGE); 219 page.put(Page.PAGE_COMMENT_COUNT, 0); 220 final int maxOrder = pageRepository.getMaxOrder(); 221 page.put(Page.PAGE_ORDER, maxOrder + 1); 222 223 String permalink = page.optString(Page.PAGE_PERMALINK); 224 if (Strings.isEmptyOrNull(permalink)) { 225 permalink = "/pages/" + Ids.genTimeMillisId() + ".html"; 226 } 227 228 if (Page.PAGE.equals(page.getString(Page.PAGE_TYPE))) { 229 if (!permalink.startsWith("/")) { 230 permalink = "/" + permalink; 231 } 232 233 if (Permalinks.invalidPagePermalinkFormat(permalink)) { 234 if (transaction.isActive()) { 235 transaction.rollback(); 236 } 237 238 throw new ServiceException(langPropsService.get("invalidPermalinkFormatLabel")); 239 } 240 241 if (permalinks.exist(permalink)) { 242 if (transaction.isActive()) { 243 transaction.rollback(); 244 } 245 246 throw new ServiceException(langPropsService.get("duplicatedPermalinkLabel")); 247 } 248 } 249 250 // TODO: SBC case 251 page.put(Page.PAGE_PERMALINK, permalink.replaceAll(" ", "-")); 252 253 // Editor type 254 final JSONObject preference = preferenceQueryService.getPreference(); 255 page.put(Page.PAGE_EDITOR_TYPE, preference.optString(Preference.EDITOR_TYPE)); 256 257 final String ret = pageRepository.add(page); 258 259 transaction.commit(); 260 261 return ret; 262 } catch (final JSONException e) { 263 LOGGER.log(Level.SEVERE, e.getMessage(), e); 264 if (transaction.isActive()) { 265 transaction.rollback(); 266 } 267 268 throw new ServiceException(e); 269 } catch (final RepositoryException e) { 270 LOGGER.log(Level.SEVERE, e.getMessage(), e); 271 if (transaction.isActive()) { 272 transaction.rollback(); 273 } 274 275 throw new ServiceException(e); 276 } 277 } 278 279 /** 280 * Changes the order of a page specified by the given page id with 281 * the specified direction. 282 * 283 * @param pageId the given page id 284 * @param direction the specified direction, "up"/"down" 285 * @throws ServiceException service exception 286 */ 287 public void changeOrder(final String pageId, final String direction) throws ServiceException { 288 289 final Transaction transaction = pageRepository.beginTransaction(); 290 try { 291 final JSONObject srcPage = pageRepository.get(pageId); 292 final int srcPageOrder = srcPage.getInt(Page.PAGE_ORDER); 293 294 JSONObject targetPage = null; 295 if ("up".equals(direction)) { 296 targetPage = pageRepository.getUpper(pageId); 297 } else { // Down 298 targetPage = pageRepository.getUnder(pageId); 299 } 300 301 if (null == targetPage) { 302 if (transaction.isActive()) { 303 transaction.rollback(); 304 } 305 306 LOGGER.log(Level.WARNING, "Cant not find the target page of source page[order={0}]", srcPageOrder); 307 return; 308 } 309 310 // Swaps 311 srcPage.put(Page.PAGE_ORDER, targetPage.getInt(Page.PAGE_ORDER)); 312 targetPage.put(Page.PAGE_ORDER, srcPageOrder); 313 314 pageRepository.update(srcPage.getString(Keys.OBJECT_ID), srcPage); 315 pageRepository.update(targetPage.getString(Keys.OBJECT_ID), targetPage); 316 317 transaction.commit(); 318 } catch (final Exception e) { 319 if (transaction.isActive()) { 320 transaction.rollback(); 321 } 322 323 LOGGER.log(Level.SEVERE, "Changes page's order failed", e); 324 325 throw new ServiceException(e); 326 } 327 } 328 329 /** 330 * Gets the {@link PageMgmtService} singleton. 331 * 332 * @return the singleton 333 */ 334 public static PageMgmtService getInstance() { 335 return SingletonHolder.SINGLETON; 336 } 337 338 /** 339 * Removes page comments by the specified page id. 340 * 341 * <p> 342 * Removes related comments, sets page/blog comment statistic count. 343 * </p> 344 * 345 * @param pageId the specified page id 346 * @throws JSONException json exception 347 * @throws RepositoryException repository exception 348 */ 349 private void removePageComments(final String pageId) throws JSONException, RepositoryException { 350 final int removedCnt = commentRepository.removeComments(pageId); 351 352 int blogCommentCount = statistics.getBlogCommentCount(); 353 blogCommentCount -= removedCnt; 354 statistics.setBlogCommentCount(blogCommentCount); 355 356 int publishedBlogCommentCount = statistics.getPublishedBlogCommentCount(); 357 publishedBlogCommentCount -= removedCnt; 358 statistics.setPublishedBlogCommentCount(publishedBlogCommentCount); 359 } 360 361 /** 362 * Processes comments for page update. 363 * 364 * @param page the specified page to update 365 * @throws Exception exception 366 */ 367 public void processCommentsForPageUpdate(final JSONObject page) throws Exception { 368 final String pageId = page.getString(Keys.OBJECT_ID); 369 370 final List<JSONObject> comments = commentRepository.getComments(pageId, 1, Integer.MAX_VALUE); 371 372 for (final JSONObject comment : comments) { 373 final String commentId = comment.getString(Keys.OBJECT_ID); 374 final String sharpURL = Comments.getCommentSharpURLForPage(page, commentId); 375 376 comment.put(Comment.COMMENT_SHARP_URL, sharpURL); 377 378 if (Strings.isEmptyOrNull(comment.optString(Comment.COMMENT_ORIGINAL_COMMENT_ID))) { 379 comment.put(Comment.COMMENT_ORIGINAL_COMMENT_ID, ""); 380 } 381 if (Strings.isEmptyOrNull(comment.optString(Comment.COMMENT_ORIGINAL_COMMENT_NAME))) { 382 comment.put(Comment.COMMENT_ORIGINAL_COMMENT_NAME, ""); 383 } 384 385 commentRepository.update(commentId, comment); 386 } 387 } 388 389 /** 390 * Private constructor. 391 */ 392 private PageMgmtService() { 393 } 394 395 /** 396 * Singleton holder. 397 * 398 * @author <a href="mailto:DL88250@gmail.com">Liang Ding</a> 399 * @version 1.0.0.0, Oct 27, 2011 400 */ 401 private static final class SingletonHolder { 402 403 /** 404 * Singleton. 405 */ 406 private static final PageMgmtService SINGLETON = new PageMgmtService(); 407 408 /** 409 * Private default constructor. 410 */ 411 private SingletonHolder() { 412 } 413 } 414}