/src/main/java/com/google/ie/business/service/impl/IdeaServiceImpl.java
Java | 987 lines | 660 code | 84 blank | 243 comment | 146 complexity | 1972b874933bef23a7b2315dae144883 MD5 | raw file
1/* Copyright 2010 Google Inc. 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS. 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License 14 */ 15 16package com.google.ie.business.service.impl; 17 18import com.google.ie.business.dao.AdminRequestDao; 19import com.google.ie.business.dao.IdeaDao; 20import com.google.ie.business.dao.impl.DaoConstants; 21import com.google.ie.business.domain.AdminRequest; 22import com.google.ie.business.domain.EntityIndex; 23import com.google.ie.business.domain.Idea; 24import com.google.ie.business.domain.Project; 25import com.google.ie.business.domain.Tag; 26import com.google.ie.business.domain.User; 27import com.google.ie.business.service.EntityIndexService; 28import com.google.ie.business.service.IdeaService; 29import com.google.ie.business.service.ProjectService; 30import com.google.ie.business.service.ServiceConstants; 31import com.google.ie.business.service.ShardedCounterService; 32import com.google.ie.business.service.TagService; 33import com.google.ie.business.service.UserService; 34import com.google.ie.common.audit.AuditManager; 35import com.google.ie.common.cache.CacheConstants; 36import com.google.ie.common.cache.CacheHelper; 37import com.google.ie.common.constants.IdeaExchangeConstants; 38import com.google.ie.common.constants.IdeaExchangeErrorCodes; 39import com.google.ie.common.exception.SystemException; 40import com.google.ie.common.objectionable.ObjectionableManager; 41import com.google.ie.common.taskqueue.IndexQueueUpdater; 42import com.google.ie.common.taskqueue.TagWeightUpdationManager; 43import com.google.ie.dto.RetrievalInfo; 44 45import org.apache.commons.lang.StringUtils; 46import org.apache.log4j.Logger; 47import org.springframework.beans.factory.annotation.Autowired; 48import org.springframework.stereotype.Service; 49import org.springframework.transaction.annotation.Propagation; 50import org.springframework.transaction.annotation.Transactional; 51 52import java.util.ArrayList; 53import java.util.Date; 54import java.util.HashMap; 55import java.util.HashSet; 56import java.util.Iterator; 57import java.util.LinkedList; 58import java.util.List; 59import java.util.Map; 60import java.util.Set; 61 62/** 63 * A service implementation of the IdeaService 64 * 65 * @author Charanjeet singh 66 */ 67@Service 68public class IdeaServiceImpl implements IdeaService { 69 private static Logger logger = Logger.getLogger(IdeaServiceImpl.class); 70 private static boolean isDebug = logger.isDebugEnabled(); 71 /* Default number of recent ideas to be fetched */ 72 private static final int DEFAULT_NO_OF_RECENT_IDEAS = 3; 73 /* Default number of popular ideas to be fetched */ 74 private static final int DEFAULT_NO_OF_POPULAR_IDEAS = 3; 75 @Autowired 76 private IdeaDao ideaDao; 77 @Autowired 78 private EntityIndexService entityIndexService; 79 80 @Autowired 81 private AuditManager auditManager; 82 @Autowired 83 private TagService tagService; 84 @Autowired 85 private TagWeightUpdationManager weightUpdationManager; 86 @Autowired 87 private UserService userService; 88 @Autowired 89 private ShardedCounterService shardedCounterService; 90 @Autowired 91 private AdminRequestDao adminRequestDao; 92 @Autowired 93 private ProjectService projectService; 94 @Autowired 95 private IndexQueueUpdater indexQueueUpdater; 96 97 public IndexQueueUpdater getIndexQueueUpdater() { 98 return indexQueueUpdater; 99 } 100 101 public void setIndexQueueUpdater(IndexQueueUpdater indexQueueUpdater) { 102 this.indexQueueUpdater = indexQueueUpdater; 103 } 104 105 public IdeaServiceImpl() { 106 } 107 108 @Override 109 public Idea saveIdea(Idea idea, User user) { 110 user = userService.getUserById(user.getId()); 111 if (user != null) { 112 113 if (idea != null && !StringUtils.isBlank(idea.getTitle()) && 114 !StringUtils.isBlank(user.getUserKey())) { 115 if (isDebug) { 116 logger.debug("Idea title=" + idea.getTitle() + " ,user key=" 117 + user.getUserKey()); 118 } 119 Idea savedIdea = saveIdeaLocal(idea, user); 120 return savedIdea; 121 } 122 } 123 return null; 124 } 125 126 @Override 127 public void deleteIdea(String key, User user) { 128 Idea idea = new Idea(); 129 idea = ideaDao.findEntityByPrimaryKey(idea.getClass(), key); 130 if (idea != null && 131 user != null && !StringUtils.isBlank(user.getUserKey())) { 132 // Soft delete the idea. 133 idea.setStatus(Idea.STATUS_DELETED); 134 ideaDao.saveIdea(idea); 135 } 136 } 137 138 /** 139 * Saves an idea. 140 * 141 * @param idea Idea to be saved. 142 * @return Returns the saved idea object. 143 */ 144 private Idea saveIdeaLocal(Idea idea, User user) { 145 if (!StringUtils.isBlank(idea.getStatus()) 146 && idea.getStatus().equals(Idea.STATUS_PUBLISHED)) { 147 throw new SystemException(IdeaExchangeErrorCodes.INVALID_PUBLISH, 148 IdeaExchangeConstants.Messages.INVALID_PUBLISH); 149 } 150 /* Handle tags. */ 151 String tagString = idea.getTags(); 152 if (!StringUtils.isBlank(tagString)) { 153 logger.debug("Submitted tags=" + tagString); 154 idea.setTags(formatTagString(tagString)); 155 } 156 /* Update the status and save in data store */ 157 idea.setCreatorKey(user.getUserKey()); 158 idea.setStatus(Idea.STATUS_SAVED); 159 idea.setLastUpdated(new Date(System.currentTimeMillis())); 160 idea = getIdeaDao().saveIdea(idea); 161 if (idea != null && !StringUtils.isBlank(idea.getKey())) { 162 /* Add saved idea key into users ideaKeys set. */ 163 addIdeaKeyToUser(idea, user); 164 logger.info("Idea with title='" + idea.getTitle() + "', saved successfully"); 165 } 166 return idea; 167 } 168 169 @Override 170 @Transactional(readOnly = false, propagation = Propagation.REQUIRED) 171 public Idea publishIdea(Idea idea, User user) { 172 if (user != null) { 173 /* 174 * boolean specifying whether the idea to be published was earlier 175 * marked as objectionable.If true no points would be added to the 176 * user 177 */ 178 boolean wasObjectionable = false; 179 if (!StringUtils.isBlank(idea.getKey())) { 180 /* If the idea is already published,throw exception */ 181 if (Idea.STATUS_PUBLISHED.equals(idea.getStatus())) { 182 throw new SystemException(IdeaExchangeErrorCodes.INVALID_PUBLISH, 183 IdeaExchangeConstants.Messages.INVALID_PUBLISH); 184 } 185 /* 186 * If the idea was earlier objectionable,set the boolean to 187 * true. 188 */ 189 if (Idea.STATUS_OBJECTIONABLE.equalsIgnoreCase(idea.getStatus())) { 190 wasObjectionable = true; 191 } 192 } 193 if (!StringUtils.isBlank(idea.getTitle()) && 194 !StringUtils.isBlank(user.getUserKey())) { 195 if (isDebug) { 196 logger.debug("User key=" + user.getUserKey() + " ,idea title=" 197 + idea.getTitle()); 198 } 199 String tagString = idea.getTags(); 200 if (!StringUtils.isBlank(tagString)) { 201 if (isDebug) { 202 logger.debug("Submitted tags=" + tagString); 203 } 204 idea.setTags(formatTagString(tagString)); 205 } 206 idea.setCreatorKey(user.getUserKey()); 207 idea.setStatus(Idea.STATUS_PUBLISHED); 208 idea.setLastUpdated(new Date(System.currentTimeMillis())); 209 idea.setPublishDate(new Date(System.currentTimeMillis())); 210 /* Persist idea object. */ 211 idea = publishIdeaLocal(idea); 212 if (idea != null && !StringUtils.isBlank(idea.getKey())) { 213 return performAfterPublish(idea, user, wasObjectionable); 214 } 215 } 216 } 217 return null; 218 } 219 220 @SuppressWarnings("unchecked") 221 @Override 222 public LinkedList<Idea> getRecentIdeas() { 223 /* Check the cache for the data */ 224 LinkedList<Idea> listOfRecentIdeas = (LinkedList<Idea>) CacheHelper.getObject( 225 CacheConstants.IDEA_NAMESPACE, 226 CacheConstants.RECENT_IDEAS); 227 if (listOfRecentIdeas != null && listOfRecentIdeas.size() > ServiceConstants.ZERO) { 228 logger.info("Recent ideas successfully fetched from cache"); 229 return listOfRecentIdeas; 230 } 231 /* If not found in cache then retrieve from data store. */ 232 RetrievalInfo retrievalInfo = new RetrievalInfo(); 233 retrievalInfo.setNoOfRecords(DEFAULT_NO_OF_RECENT_IDEAS); 234 retrievalInfo.setOrderBy(ServiceConstants.DEFAULT_IDEA_ORDERING_FIELD); 235 retrievalInfo.setOrderType(ServiceConstants.ORDERING_TYPE_FOR_RECENT_IDEAS); 236 /* Fetch the ideas and create a linked list from the fetched data */ 237 listOfRecentIdeas = createLinkedListFromTheFetchedData(getIdeas(retrievalInfo)); 238 /* If the list contains data, add it to the cache */ 239 if (listOfRecentIdeas.size() > ServiceConstants.ZERO) { 240 CacheHelper.putObject(CacheConstants.IDEA_NAMESPACE, CacheConstants.RECENT_IDEAS, 241 listOfRecentIdeas, CacheConstants.RECENT_IDEAS_EXPIRATION_DELAY); 242 logger.info("Recent ideas successfully added to the cache"); 243 } 244 return listOfRecentIdeas; 245 } 246 247 /** 248 * It performs all other activity, which are needed after publishing the 249 * idea. 250 * 251 * @param idea The published {@link Idea} object. 252 * @param user The {@link User} who has published the idea. 253 * @param wasObjectionale whether the idea was earlier an objectionable one 254 * @return Idea object. 255 */ 256 private Idea performAfterPublish(Idea idea, User user, boolean wasObjectionale) { 257 logger.info("Idea with title=" + idea.getTitle() + ", saved successfully"); 258 /* If the idea is a new one add points to the user */ 259 if (!wasObjectionale) { 260 /* Add saved idea key into users ideaKeys set. */ 261 user = addIdeaKeyToUser(idea, user); 262 addPointsToUserOnIdeaPublish(user.getUserKey(), idea); 263 } 264 /* Place object into cache. */ 265 CacheHelper.putObject(CacheConstants.IDEA_NAMESPACE, idea.getKey(), idea); 266 /* Place object into cache for recent ideas. */ 267 addIdeaToListInCache(idea, CacheConstants.RECENT_IDEAS, 268 DEFAULT_NO_OF_RECENT_IDEAS, CacheConstants.RECENT_IDEAS_EXPIRATION_DELAY); 269 String tagStr = idea.getTags(); 270 /* Increment Tags weights asynchronously. */ 271 if (tagStr != null && !tagStr.equals("")) 272 getWeightUpdationManager().incrementWeight(tagStr); 273 /* Audit the published activity. */ 274 getAuditManager().audit(user.getUserKey(), idea.getKey(), idea.getClass().getName(), 275 ServiceConstants.AUDIT_ACTION_TYPE_PUBLISH_IDEA); 276 /* Check idea for objectionable. */ 277 ObjectionableManager.checkObjectionable(idea.getKey()); 278 return idea; 279 } 280 281 @SuppressWarnings("unchecked") 282 public void addIdeaToListInCache(Idea originalIdea, String keyOfTheList, 283 int noOfIdeas, int expiryDelay) { 284 LinkedList<Idea> listOfIdeas = (LinkedList<Idea>) CacheHelper.getObject( 285 CacheConstants.IDEA_NAMESPACE, 286 keyOfTheList); 287 if (listOfIdeas != null) { 288 if (listOfIdeas.size() >= noOfIdeas) { 289 /* Remove the last element which is also the oldest */ 290 listOfIdeas.pollLast(); 291 } 292 } else { 293 listOfIdeas = new LinkedList<Idea>(); 294 } 295 /* Create a new idea object to contain the required data only */ 296 Idea ideaWithTheRequiredDataOnly = new Idea(); 297 ideaWithTheRequiredDataOnly.setTitle(StringUtils.abbreviate(originalIdea.getTitle(), 298 ServiceConstants.FIFTY)); 299 /* Limit the description to hundred characters */ 300 ideaWithTheRequiredDataOnly.setDescription(StringUtils.abbreviate(originalIdea 301 .getDescription(), ServiceConstants.HUNDRED)); 302 ideaWithTheRequiredDataOnly.setKey(originalIdea.getKey()); 303 /* Add the idea to the head of the list */ 304 listOfIdeas.addFirst(ideaWithTheRequiredDataOnly); 305 /* Put the updated list back to the cache */ 306 CacheHelper.putObject(CacheConstants.IDEA_NAMESPACE, 307 keyOfTheList, listOfIdeas, expiryDelay); 308 } 309 310 /** 311 * Update sharded counters for the users reputation point calculation. 312 * 313 * @param user 314 * @param idea 315 * @return 316 */ 317 318 private void addPointsToUserOnIdeaPublish(String userKey, Idea idea) { 319 int points = 0; 320 if (!StringUtils.isBlank(idea.getTitle())) { 321 points = points + IdeaExchangeConstants.REPUTATION_POINTS_TITLE; 322 } 323 if (!StringUtils.isBlank(idea.getDescription())) { 324 points = points + IdeaExchangeConstants.REPUTATION_POINTS_DESCRIPTION; 325 } 326 if (!StringUtils.isBlank(idea.getMonetization())) { 327 points = points + IdeaExchangeConstants.REPUTATION_POINTS_MONETIZATION; 328 } 329 if (!StringUtils.isBlank(idea.getCompetition())) { 330 points = points + IdeaExchangeConstants.REPUTATION_POINTS_COMPETITION; 331 } 332 if (!StringUtils.isBlank(idea.getTargetAudience())) { 333 points = points + IdeaExchangeConstants.REPUTATION_POINTS_TARGET_AUDIENCE; 334 } 335 updateShardedCounter(userKey, points); 336 } 337 338 /** 339 * Update counter. 340 * 341 * @param user 342 * @param points 343 */ 344 @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) 345 private void updateShardedCounter(String userKey, int points) { 346 shardedCounterService.updateTotalPoints(userKey, points); 347 } 348 349 /** 350 * Adds the {@link Idea } key to user's idea key set on save and publish 351 * idea. 352 * 353 * @param idea The saved/published {@link Idea} object. 354 * @param user The {@link User} who has saved/published the idea. 355 * @return User object. 356 */ 357 358 private User addIdeaKeyToUser(Idea idea, User user) { 359 if (idea.getKey() != null) { 360 user.getIdeaKeys().add(idea.getKey()); 361 userService.saveUser(user); 362 363 } 364 365 return user; 366 } 367 368 @Transactional(readOnly = false, propagation = Propagation.REQUIRED) 369 public Idea publishIdeaLocal(Idea idea) { 370 // Persist idea object. 371 idea = getIdeaDao().saveIdea(idea); 372 if (idea != null) { 373 /* 374 * Index the entity.Create an EntityIndex object for the entity 375 * to be indexed and then queue the job to task queue 376 */ 377 EntityIndex entityIndex = entityIndexService.createEntityIndex(idea.getKey()); 378 getIndexQueueUpdater().indexEntity(entityIndex.getKey()); 379 380 } 381 return idea; 382 } 383 384 /** 385 * Formats the tag string submitted by application user for display on view. 386 * 387 * @param tagString String having tags submitted by application user. 388 * @return formated comma separate tags string. 389 */ 390 protected final String formatTagString(String tagString) { 391 String[] tags = tagString.trim().split("[\\s,]"); 392 StringBuilder sb = new StringBuilder(); 393 for (int i = 0; i < tags.length; i++) { 394 String tmpString = tags[i].trim().toLowerCase(); 395 if (!tmpString.equals("")) 396 sb.append(tmpString + ","); 397 if (i == tags.length - 1) 398 sb.deleteCharAt(sb.length() - 1); 399 } 400 return sb.toString(); 401 } 402 403 @Override 404 public Idea getIdeaDetails(Idea idea) { 405 if (idea != null && !StringUtils.isBlank(idea.getKey())) { 406 if (isDebug) { 407 logger.debug("Retrieving idea details for the idea with key=" + idea.getKey()); 408 } 409 return ideaDao.getIdea(idea); 410 } 411 return null; 412 } 413 414 @Override 415 public List<Idea> getIdeas(RetrievalInfo retrievalInfo) { 416 /* 417 * Retrieve ideas based on the retrieval information. If retrievalInfo 418 * object is null then use default parameter information. 419 */ 420 retrievalInfo = prepareRetrievalInfoForQuery(retrievalInfo); 421 /* Prepare the Set of status */ 422 Set<String> statusOfIdeas = new HashSet<String>(); 423 statusOfIdeas.add(Idea.STATUS_PUBLISHED); 424 statusOfIdeas.add(Idea.STATUS_DUPLICATE); 425 426 return ideaDao.getIdeas(retrievalInfo, statusOfIdeas); 427 } 428 429 @Override 430 public boolean addSummary(String key, String summary, User user) { 431 Idea idea = new Idea(); 432 idea = ideaDao.findEntityByPrimaryKey(idea.getClass(), key); 433 if (idea == null || user == null 434 || StringUtils.isBlank(idea.getKey()) 435 || StringUtils.isBlank(user.getUserKey()) 436 || StringUtils.isBlank(idea.getStatus()) 437 || !(idea.getStatus().equals(Idea.STATUS_PUBLISHED)) 438 || StringUtils.isBlank(idea.getCreatorKey()) 439 || !(idea.getCreatorKey().equals(user.getUserKey()))) { 440 441 throw new SystemException(IdeaExchangeErrorCodes.INVALID_IDEA_SUMMARY, 442 IdeaExchangeConstants.Messages.INVALID_IDEA_SUMMARY); 443 } 444 // Allow user to add Idea summary only once. 445 if (StringUtils.isBlank(idea.getIdeaSummary())) { 446 idea.setIdeaSummary(summary); 447 getIdeaDao().saveIdea(idea); 448 return true; 449 } 450 return false; 451 } 452 453 /* Returns the ideas saved or published by user */ 454 @Override 455 public List<Idea> getIdeasForUser(User user, RetrievalInfo retrievalInfo) { 456 if (user == null || StringUtils.isBlank(user.getUserKey())) { 457 return null; 458 } 459 if (isDebug) { 460 logger.debug("Retrieving ideas for the user with key=" + user.getUserKey()); 461 } 462 /* 463 * Retrieve user's ideas based on the retrieval information. In case of 464 * listing user's ideas, ordering will be done on the field 465 * 'lastUpdated'. 466 */ 467 if (retrievalInfo == null) { 468 retrievalInfo = new RetrievalInfo(); 469 } 470 retrievalInfo.setOrderBy(DaoConstants.IDEA_ORDERING_FIELD_LAST_UPDATE_DATE); 471 // Prepare retrieval parameters to fetch users idea. 472 retrievalInfo = prepareRetrievalInfoForQuery(retrievalInfo); 473 /* Prepare the Set of status */ 474 Set<String> statusOfIdeas = new HashSet<String>(); 475 statusOfIdeas.add(Idea.STATUS_SAVED); 476 statusOfIdeas.add(Idea.STATUS_PUBLISHED); 477 statusOfIdeas.add(Idea.STATUS_OBJECTIONABLE); 478 statusOfIdeas.add(Idea.STATUS_DUPLICATE); 479 480 return ideaDao.getUserIdeas(user, statusOfIdeas, retrievalInfo); 481 } 482 483 @Override 484 public boolean updateStatus(Idea idea) { 485 if (idea == null || StringUtils.isBlank(idea.getKey())) { 486 return false; 487 } 488 if (isDebug) { 489 logger.debug("updating status of idea for the key=" + idea.getKey()); 490 } 491 return ideaDao.updateStatus(idea); 492 } 493 494 @Override 495 public boolean updateIdeaVotes(Idea idea) { 496 boolean flag = false; 497 if (idea != null && !StringUtils.isBlank(idea.getKey())) { 498 499 if (isDebug) { 500 logger.debug("updating status of idea for the key=" + idea.getKey()); 501 } 502 503 flag = ideaDao.updateIdeaPoints(idea); 504 } 505 return flag; 506 } 507 508 @Override 509 public List<Idea> getIdeasByTagName(String tagName, RetrievalInfo retrievalInfo) { 510 /* 511 * If the tagname param is not null and is not empty then fetch the Tag 512 * object through tag service 513 */ 514 if (tagName != null && tagName.length() > ServiceConstants.ZERO) { 515 Tag tag = tagService.getTagByName(tagName); 516 /* If tag is not null then get the key of the tag */ 517 if (tag != null) { 518 String tagKey = tag.getKey(); 519 /* 520 * If the tag key contains value then fetch the 521 * list of ideas associated with the tag key 522 */ 523 if (tagKey.length() > ServiceConstants.ZERO) { 524 retrievalInfo = prepareRetrievalInfoForQuery(retrievalInfo); 525 Set<String> statusOfIdeas = new HashSet<String>(); 526 statusOfIdeas.add(Idea.STATUS_PUBLISHED); 527 statusOfIdeas.add(Idea.STATUS_DUPLICATE); 528 List<Idea> ideaList = ideaDao.getIdeasByTagKey(tagKey, statusOfIdeas, 529 retrievalInfo); 530 return ideaList; 531 } 532 } 533 } 534 return null; 535 } 536 537 @SuppressWarnings("unchecked") 538 @Override 539 public LinkedList<Idea> getPopularIdeas() { 540 /* First check the cache for the data */ 541 LinkedList<Idea> popularIdeas = (LinkedList<Idea>) CacheHelper.getObject( 542 CacheConstants.IDEA_NAMESPACE, 543 CacheConstants.POPULAR_IDEAS); 544 if (popularIdeas != null && popularIdeas.size() > ServiceConstants.ZERO) { 545 logger.info("Popular ideas successfully fetched from cache"); 546 return popularIdeas; 547 } 548 /* If not in cache ,fetch from data store */ 549 RetrievalInfo retrievalInfo = new RetrievalInfo(); 550 /* Set the RetrievalInfo object to contain query parameters */ 551 retrievalInfo.setNoOfRecords(DEFAULT_NO_OF_POPULAR_IDEAS); 552 retrievalInfo.setOrderBy(ServiceConstants.IDEA_ORDERING_FIELD_TOTAL_POSITIVE_VOTES); 553 retrievalInfo.setOrderType(ServiceConstants.ORDERING_DESCENDING); 554 /* Create the set of status conditions to be matched in the query */ 555 Set<String> statusOfIdeas = new HashSet<String>(); 556 statusOfIdeas.add(Idea.STATUS_PUBLISHED); 557 /* 558 * Fetch the ideas from the datastore and create a linked list from the 559 * fetched ideas 560 */ 561 popularIdeas = createLinkedListFromTheFetchedData(ideaDao.getIdeas(retrievalInfo, 562 statusOfIdeas)); 563 if (popularIdeas.size() > ServiceConstants.ZERO) { 564 /* Put popular ideas into cache */ 565 CacheHelper.putObject(CacheConstants.IDEA_NAMESPACE, CacheConstants.POPULAR_IDEAS, 566 popularIdeas, CacheConstants.POPULAR_IDEAS_EXPIRATION_DELAY); 567 logger.info("Popular ideas successfully added to the cache"); 568 } 569 return popularIdeas; 570 } 571 572 /** 573 * Prepares the {@link RetrievalInfo} object with values to be used as query 574 * parameters. 575 * Checks the received RetrievalInfo object attributes for valid 576 * data.Updates the attributes if they contain garbage values.If the 577 * received {@link RetrievalInfo} object is null,sets it to a new instance 578 * with its attributes set to default values. 579 * 580 * @param retrievalInfo the {@link RetrievalInfo} object containing the 581 * values to be used as query parameters 582 * @return the {@link RetrievalInfo} object containing the query parameters 583 */ 584 585 private RetrievalInfo prepareRetrievalInfoForQuery(RetrievalInfo retrievalInfo) { 586 if (retrievalInfo == null) { 587 retrievalInfo = new RetrievalInfo(); 588 retrievalInfo.setStartIndex(ServiceConstants.ZERO); 589 retrievalInfo.setNoOfRecords(ServiceConstants.IDEAS_LIST_DEFAULT_SIZE); 590 retrievalInfo.setOrderType(ServiceConstants.DEFAULT_IDEA_ORDERING_TYPE); 591 retrievalInfo.setOrderBy(ServiceConstants.DEFAULT_IDEA_ORDERING_FIELD); 592 } else { 593 // Handle garbage values if any. 594 String orderBY = retrievalInfo.getOrderBy(); 595 String orderType = retrievalInfo.getOrderType(); 596 if (retrievalInfo.getStartIndex() < ServiceConstants.ZERO) 597 retrievalInfo.setStartIndex(ServiceConstants.ZERO); 598 if (retrievalInfo.getNoOfRecords() <= ServiceConstants.ZERO) 599 retrievalInfo.setNoOfRecords(ServiceConstants.IDEAS_LIST_DEFAULT_SIZE); 600 if (orderType == null || !((orderType.equals(DaoConstants.ORDERING_ASCENDING) 601 || orderType.equals(DaoConstants.ORDERING_DESCENDING)))) 602 retrievalInfo.setOrderType(ServiceConstants.DEFAULT_IDEA_ORDERING_TYPE); 603 if (orderBY == null 604 || !((orderBY.equals(DaoConstants.IDEA_ORDERING_FIELD_LAST_UPDATE_DATE) 605 || orderBY.equals(DaoConstants.IDEA_ORDERING_FIELD_PUBLISH_DATE) 606 || orderBY.equals(DaoConstants.IDEA_ORDERING_FIELD_VOTE)))) { 607 retrievalInfo.setOrderBy(ServiceConstants.DEFAULT_IDEA_ORDERING_FIELD); 608 } 609 } 610 return retrievalInfo; 611 } 612 613 /** 614 * Create a linked list from the list of ideas received.Removes the data not 615 * required on the homepage.This method is intended to create 616 * list for Recent ideas and Popular ideas method 617 * 618 * @param ideas list of ideas 619 * @return a {@link LinkedList} object containing the ideas 620 */ 621 private LinkedList<Idea> createLinkedListFromTheFetchedData(List<Idea> ideas) { 622 LinkedList<Idea> linkedList = new LinkedList<Idea>(); 623 Iterator<Idea> iterator = ideas.iterator(); 624 Idea originalIdea = null; 625 Idea ideaWithTheRequiredDataOnly = null; 626 while (iterator.hasNext()) { 627 originalIdea = iterator.next(); 628 if (originalIdea.getStatus().equals(Idea.STATUS_OBJECTIONABLE)) 629 continue; 630 ideaWithTheRequiredDataOnly = new Idea(); 631 ideaWithTheRequiredDataOnly.setTitle(StringUtils.abbreviate(originalIdea.getTitle() 632 , ServiceConstants.FIFTY)); 633 /* Limit the description to hundred characters */ 634 ideaWithTheRequiredDataOnly.setDescription(StringUtils.abbreviate(originalIdea 635 .getDescription(), ServiceConstants.HUNDRED)); 636 ideaWithTheRequiredDataOnly.setKey(originalIdea.getKey()); 637 /* Add the idea to the linked list */ 638 linkedList.add(ideaWithTheRequiredDataOnly); 639 } 640 return linkedList; 641 } 642 643 @Override 644 public String flagObjectionableIdea(String ideaKey, User user) { 645 String status = IdeaExchangeConstants.FAIL; 646 /* Get title of the idea */ 647 Idea idea = this.getIdeaByKey(ideaKey); 648 if (idea != null 649 && isFlagTypeAllreadyExist(idea.getFlagType(), Idea.FLAG_TYPE_OBJECTIONABLE)) { 650 status = IdeaExchangeConstants.IDEA_ALLREADY_FLAGED; 651 return status; 652 } 653 /* 654 * Create an admin request to handle the objectionabe flag request for 655 * idea 656 */ 657 AdminRequest adminRequest = new AdminRequest(); 658 adminRequest.setEntityKey(ideaKey); 659 adminRequest.setEntityType(Idea.class.getSimpleName()); 660 adminRequest.setRequesterkey(user.getUserKey()); 661 adminRequest.setRequestType(AdminRequest.REQUEST_OBJECTIONABLE); 662 adminRequest.setCreatedOn(new Date()); 663 adminRequest.setStatus(AdminRequest.STATUS_PENDING); 664 665 if (!StringUtils.isBlank(user.getEmailId())) { 666 adminRequest.setRequesterEmail(user.getEmailId()); 667 } 668 669 /* Get Idea to get title and update FlagType of the entity */ 670 if (idea != null && !StringUtils.isBlank(idea.getKey())) { 671 adminRequest.setEntityTitle(idea.getTitle()); 672 673 idea.getFlagType().add(Idea.FLAG_TYPE_OBJECTIONABLE); 674 ideaDao.saveIdea(idea); 675 } else { 676 throw new SystemException(IdeaExchangeErrorCodes.IDEA_NULL_EXCEPTION, 677 "There is no idea that belongs to the given key in data store"); 678 } 679 if (adminRequestDao.saveRequest(adminRequest)) { 680 status = IdeaExchangeConstants.SUCCESS; 681 } 682 return status; 683 } 684 685 @Override 686 public String flagDuplicateIdea(String ideaKey, String originalIdeakey, User user) { 687 String status = IdeaExchangeConstants.FAIL; 688 /* Get title of the idea */ 689 Idea idea = this.getIdeaByKey(ideaKey); 690 if (idea != null && isFlagTypeAllreadyExist(idea.getFlagType(), Idea.FLAG_TYPE_DUPLICATE)) { 691 status = IdeaExchangeConstants.IDEA_ALLREADY_MARKED_DUPLICATE; 692 return status; 693 } 694 /* 695 * Create an admin request to handle the duplicate flag request for 696 * idea. 697 */ 698 AdminRequest adminRequest = new AdminRequest(); 699 adminRequest.setEntityKey(ideaKey); 700 adminRequest.setEntityType(Idea.class.getSimpleName()); 701 adminRequest.setRequesterkey(user.getUserKey()); 702 if (!StringUtils.isBlank(user.getEmailId())) { 703 adminRequest.setRequesterEmail(user.getEmailId()); 704 } 705 706 adminRequest.setRequestType(AdminRequest.REQUEST_DUPLICATE); 707 adminRequest.setCreatedOn(new Date()); 708 709 /* Creating string for other information set of AdminRequest */ 710 StringBuilder otherInfoString = new StringBuilder(); 711 otherInfoString.append(AdminRequest.INFO_ORIGINAL_IDEA_KEY); 712 otherInfoString.append(AdminRequest.INFO_SEPARATOR); 713 otherInfoString.append(originalIdeakey); 714 715 Set<String> otherInfo = new HashSet<String>(); 716 otherInfo.add(otherInfoString.toString()); 717 adminRequest.setOtherInfo(otherInfo); 718 adminRequest.setStatus(AdminRequest.STATUS_PENDING); 719 /* Mark Idea as duplicate and save into data store. */ 720 if (idea != null && !StringUtils.isBlank(idea.getKey())) { 721 adminRequest.setEntityTitle(idea.getTitle()); 722 723 idea.getFlagType().add(Idea.FLAG_TYPE_DUPLICATE); 724 idea.setOriginalIdeaKey(originalIdeakey); 725 ideaDao.saveIdea(idea); 726 } else { 727 728 throw new SystemException(IdeaExchangeErrorCodes.IDEA_NULL_EXCEPTION, 729 "There is no idea that belongs to the given key in data store"); 730 731 } 732 /* Save admin request */ 733 if (adminRequestDao.saveRequest(adminRequest)) { 734 status = IdeaExchangeConstants.SUCCESS; 735 } 736 return status; 737 } 738 739 /** 740 * check for flag type. 741 * 742 * @param flagTypes Type of flags associated with idea for Example 743 * Objectionable,Duplicate. 744 * @param flagTypeToCheck Type of flags associated with the idea. 745 * @return True if flag already exist in set of flagTypes. 746 */ 747 private boolean isFlagTypeAllreadyExist(Set<String> flagTypes, String flagTypeToCheck) { 748 for (String flagType : flagTypes) { 749 if (flagType != null && flagType.equalsIgnoreCase(flagTypeToCheck)) { 750 return true; 751 } 752 753 } 754 return false; 755 } 756 757 @Override 758 public Idea updateIdea(Idea idea) { 759 return ideaDao.saveIdea(idea); 760 761 } 762 763 @SuppressWarnings("unchecked") 764 @Override 765 public LinkedList<Idea> getRecentlyPickedIdeas() { 766 /* First check the cache for the data */ 767 LinkedList<Idea> recentlyPickedIdeas = (LinkedList<Idea>) CacheHelper.getObject( 768 CacheConstants.IDEA_NAMESPACE, 769 CacheConstants.RECENTLY_PICKED_IDEAS); 770 if (recentlyPickedIdeas != null && recentlyPickedIdeas.size() > ServiceConstants.ZERO) { 771 logger.info("Recently picked ideas successfully fetched from cache"); 772 return recentlyPickedIdeas; 773 } 774 /* 775 * Get the recently created projects.Iterate through the list and fetch 776 * key of idea related to the project 777 */ 778 List<Project> recentProjects = projectService.getRecentProjects(); 779 List<Idea> ideas = new ArrayList<Idea>(); 780 Iterator<Project> iterator = recentProjects.iterator(); 781 Set<String> setOfIdeaKeys = new HashSet<String>(); 782 while (iterator.hasNext()) { 783 String ideaKey = iterator.next().getIdeaKey(); 784 if (!setOfIdeaKeys.contains(ideaKey)) { 785 setOfIdeaKeys.add(ideaKey); 786 ideas.add(getIdeaByKey(ideaKey)); 787 } 788 } 789 recentlyPickedIdeas = createLinkedListFromTheFetchedData(ideas); 790 if (recentlyPickedIdeas.size() > ServiceConstants.ZERO) { 791 /* Put the recently picked ideas into the cache */ 792 CacheHelper.putObject(CacheConstants.IDEA_NAMESPACE, 793 CacheConstants.RECENTLY_PICKED_IDEAS, 794 recentlyPickedIdeas, 795 CacheConstants.RECENTLY_PICKED_IDEAS_EXPIRATION_DELAY); 796 logger.info("Recently picked ideas successfully added to the cache"); 797 } 798 return recentlyPickedIdeas; 799 } 800 801 @SuppressWarnings("unchecked") 802 @Override 803 public void removeIdeaFromAllListsInCache(String ideaKey) { 804 /* 805 * Create a map containing all list names as keys and the corressponding 806 * expiration delays as values 807 */ 808 Map<String, Integer> map = new HashMap<String, Integer>(); 809 /* Recent ideas list */ 810 map.put(CacheConstants.RECENT_IDEAS, CacheConstants.RECENT_IDEAS_EXPIRATION_DELAY); 811 /* Recently picked ideas list */ 812 map.put(CacheConstants.RECENTLY_PICKED_IDEAS, 813 CacheConstants.RECENTLY_PICKED_IDEAS_EXPIRATION_DELAY); 814 /* Popular ideas list */ 815 map.put(CacheConstants.POPULAR_IDEAS, CacheConstants.POPULAR_IDEAS_EXPIRATION_DELAY); 816 Iterator<String> iterator = map.keySet().iterator(); 817 LinkedList<Idea> listOfIdeas = null; 818 String keyOfTheList = null; 819 while (iterator.hasNext()) { 820 keyOfTheList = iterator.next(); 821 /* Fetch the list */ 822 listOfIdeas = (LinkedList<Idea>) CacheHelper.getObject( 823 CacheConstants.IDEA_NAMESPACE, 824 keyOfTheList); 825 /* If the list is not null check and remove the idea */ 826 if (listOfIdeas != null) { 827 removeIdeaFromList(listOfIdeas, ideaKey, keyOfTheList, map.get(keyOfTheList)); 828 } 829 } 830 831 /* First check in Recent ideas list and remove if available */ 832 833 } 834 835 /** 836 * Remove idea from the list 837 * 838 * @param ideas the list of the ideas 839 * @param ideaKey the key of the idea to be removed 840 * @param keyOfTheList the key of the ideas list as used in the cache 841 * @param expiryDelay the expiry delay for the list in cache 842 */ 843 private void removeIdeaFromList(LinkedList<Idea> ideas, String ideaKey, String keyOfTheList, 844 int expiryDelay) { 845 Iterator<Idea> iterator = ideas.iterator(); 846 Idea idea = null; 847 Idea ideaToBeRemoved = null; 848 while (iterator.hasNext()) { 849 idea = iterator.next(); 850 if (ideaKey.equalsIgnoreCase(idea.getKey())) { 851 ideaToBeRemoved = idea; 852 break; 853 } 854 } 855 if (ideaToBeRemoved != null) { 856 ideas.remove(ideaToBeRemoved); 857 /* Put the updated list back to the cache */ 858 CacheHelper.putObject(CacheConstants.IDEA_NAMESPACE, 859 keyOfTheList, ideas, expiryDelay); 860 } 861 862 } 863 864 /** 865 * Returns the IdeaDao type implementation 866 * 867 * @return Returns the TagService 868 */ 869 public IdeaDao getIdeaDao() { 870 return ideaDao; 871 } 872 873 /** 874 * Sets the IdeaDao type implementation. 875 * 876 * @param val The IdeaDao object 877 */ 878 public void setIdeaDao(IdeaDao val) { 879 this.ideaDao = val; 880 } 881 882 /** 883 * Sets the AuditManager. 884 * 885 * @param auditManager the auditManager to set 886 */ 887 public void setAuditManager(AuditManager auditManager) { 888 this.auditManager = auditManager; 889 } 890 891 /** 892 * @return the auditManager 893 */ 894 public AuditManager getAuditManager() { 895 return auditManager; 896 } 897 898 @Override 899 public Idea getIdeaByKey(String key) { 900 return ideaDao.findEntityByPrimaryKey(Idea.class, key); 901 902 } 903 904 public TagService getTagService() { 905 return tagService; 906 } 907 908 public void setTagService(TagService tagService) { 909 this.tagService = tagService; 910 } 911 912 /** 913 * @param weightUpdationManager the weightUpdationManager to set 914 */ 915 public void setWeightUpdationManager(TagWeightUpdationManager weightUpdationManager) { 916 this.weightUpdationManager = weightUpdationManager; 917 } 918 919 /** 920 * @return the weightUpdationManager 921 */ 922 public TagWeightUpdationManager getWeightUpdationManager() { 923 return weightUpdationManager; 924 } 925 926 /** 927 * @param userService the userService to set 928 */ 929 public void setUserService(UserService userService) { 930 this.userService = userService; 931 } 932 933 /** 934 * @return the userService 935 */ 936 public UserService getUserService() { 937 return userService; 938 } 939 940 public EntityIndexService getEntityIndexService() { 941 return entityIndexService; 942 } 943 944 public void setEntityIndexService(EntityIndexService entityIndexService) { 945 this.entityIndexService = entityIndexService; 946 } 947 948 /** 949 * @param shardedCounterService the shardedCounterService to set 950 */ 951 public void setShardedCounterService(ShardedCounterService shardedCounterService) { 952 this.shardedCounterService = shardedCounterService; 953 } 954 955 /** 956 * @return the shardedCounterService 957 */ 958 public ShardedCounterService getShardedCounterService() { 959 return shardedCounterService; 960 } 961 962 /** 963 * @return the adminRequestDao 964 */ 965 public AdminRequestDao getAdminRequestDao() { 966 return adminRequestDao; 967 } 968 969 /** 970 * @param adminRequestDao the adminRequestDao to set 971 */ 972 public void setAdminRequestDao(AdminRequestDao adminRequestDao) { 973 this.adminRequestDao = adminRequestDao; 974 } 975 976 @Override 977 public List<Idea> getIdeasByCategory(String categoryKey, RetrievalInfo retrievalInfo) { 978 if (categoryKey != null && categoryKey.length() > ServiceConstants.ZERO) { 979 retrievalInfo = prepareRetrievalInfoForQuery(retrievalInfo); 980 List<Idea> ideaList = ideaDao.getIdeasByCategoryKey(categoryKey, Idea.STATUS_PUBLISHED, 981 retrievalInfo); 982 return ideaList; 983 } 984 return null; 985 } 986} 987