/src/main/java/com/google/ie/business/service/impl/TagServiceImpl.java

http://thoughtsite.googlecode.com/ · Java · 500 lines · 340 code · 40 blank · 120 comment · 74 complexity · 907ae3af7da7e1a8ab2ed3ab563136e7 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. package com.google.ie.business.service.impl;
  16. import com.google.ie.business.dao.TagDao;
  17. import com.google.ie.business.domain.Idea;
  18. import com.google.ie.business.domain.Tag;
  19. import com.google.ie.business.domain.User;
  20. import com.google.ie.business.service.EntityIndexService;
  21. import com.google.ie.business.service.IdeaService;
  22. import com.google.ie.business.service.ServiceConstants;
  23. import com.google.ie.business.service.TagService;
  24. import com.google.ie.common.audit.AuditManager;
  25. import com.google.ie.common.cache.CacheConstants;
  26. import com.google.ie.common.cache.CacheHelper;
  27. import com.google.ie.common.comparator.TagTitleComparator;
  28. import com.google.ie.common.constants.IdeaExchangeConstants;
  29. import com.google.ie.common.util.SearchUtility;
  30. import com.google.ie.dto.RetrievalInfo;
  31. import org.apache.commons.lang.StringUtils;
  32. import org.apache.log4j.Logger;
  33. import org.springframework.beans.factory.annotation.Autowired;
  34. import org.springframework.stereotype.Service;
  35. import java.io.Serializable;
  36. import java.util.ArrayList;
  37. import java.util.Collection;
  38. import java.util.Collections;
  39. import java.util.Date;
  40. import java.util.HashSet;
  41. import java.util.Iterator;
  42. import java.util.LinkedHashSet;
  43. import java.util.List;
  44. import java.util.Set;
  45. /**
  46. * A service implementation of the TagService
  47. *
  48. * @author Sachneet
  49. *
  50. */
  51. @Service
  52. public class TagServiceImpl implements TagService {
  53. private static Logger log = Logger.getLogger(TagServiceImpl.class);
  54. @Autowired
  55. private AuditManager auditManager;
  56. @Autowired
  57. private TagDao tagDao;
  58. @Autowired
  59. private IdeaService ideaService;
  60. @Autowired
  61. private EntityIndexService entityIndexService;
  62. public TagServiceImpl() {
  63. }
  64. @Override
  65. public List<Tag> getTagsByKeys(Collection<String> keys) {
  66. if (keys == null || keys.size() == 0)
  67. return null;
  68. return getTagDao().getTagsByKeys(keys);
  69. }
  70. @Override
  71. public List<Tag> saveTags(String tagString) {
  72. /* If not valid tag string, return null. */
  73. if (StringUtils.isEmpty(tagString)) {
  74. return null;
  75. }
  76. List<Tag> tagsToSave = new ArrayList<Tag>();
  77. List<Tag> existingTag = new ArrayList<Tag>();
  78. // Parse tags.
  79. List<Tag> tags = parseTags(tagString);
  80. // Prepare a list of tags to be saved.
  81. for (Tag tag : tags) {
  82. Tag tagObj = checkForDuplicate(tag);
  83. if (StringUtils.isBlank(tagObj.getKey()))
  84. tagsToSave.add(tagObj);
  85. else
  86. existingTag.add(tagObj);
  87. }
  88. if (tagsToSave.size() > 0) {
  89. List<Tag> tagList = saveTags(tagsToSave);
  90. if (tagList != null && tagList.size() > 0)
  91. tagList.addAll(existingTag);
  92. return tagList;
  93. }
  94. return existingTag;
  95. }
  96. @Override
  97. public boolean retagIdea(ArrayList<Tag> newTag, Idea idea, User user) {
  98. return true;
  99. }
  100. @Override
  101. public List<Tag> getTagsForAutoSuggestion(String startString, RetrievalInfo retrievalInfo) {
  102. if (startString != null && startString.length() > ServiceConstants.ZERO) {
  103. /*
  104. * Configure the RetrievalInfo object to be used to set the query
  105. * parameters
  106. */
  107. retrievalInfo = getRetrievalInfoSetToQueryParameters(retrievalInfo,
  108. ServiceConstants.DEFAULT_NO_OF_RECORDS_FOR_TAG);
  109. List<Tag> tagList = tagDao.getTagsWithSpecificStartString(startString, retrievalInfo);
  110. return tagList;
  111. }
  112. return null;
  113. }
  114. @Override
  115. public List<Tag> getTagsWithSpecificStartString(String startString, RetrievalInfo retrievalInfo) {
  116. if (startString != null && startString.length() > ServiceConstants.ZERO) {
  117. /*
  118. * Configure the RetrievalInfo object to be used to set the query
  119. * parameters
  120. */
  121. retrievalInfo = getRetrievalInfoSetToQueryParameters(retrievalInfo,
  122. ServiceConstants.DEFAULT_NO_OF_RECORDS_FOR_TAG_LIST);
  123. List<Tag> tagList = tagDao.getTagsWithSpecificStartString(startString, retrievalInfo);
  124. /* Remove the tags with zero weight */
  125. if (tagList.size() > ServiceConstants.ZERO) {
  126. removeTagWithZeroWeight(tagList);
  127. }
  128. return tagList;
  129. }
  130. return null;
  131. }
  132. @Override
  133. public List<Tag> removeTagWithZeroWeight(List<Tag> tagList) {
  134. Collection<Tag> tagsToBeRemoved = new ArrayList<Tag>();
  135. Iterator<Tag> iterator = tagList.iterator();
  136. Tag tag;
  137. /* Iterate the list and remove the tags with zero weight */
  138. while (iterator.hasNext()) {
  139. tag = iterator.next();
  140. if (tag.getWeightage() <= ServiceConstants.ZERO) {
  141. tagsToBeRemoved.add(tag);
  142. }
  143. }
  144. if (tagsToBeRemoved.size() > ServiceConstants.ZERO) {
  145. log.debug("Removing " + tagsToBeRemoved.size()
  146. + " tags from the fetched list because they have ZERO weight");
  147. tagList.removeAll(tagsToBeRemoved);
  148. }
  149. return tagList;
  150. }
  151. @Override
  152. public List<Tag> getTagsForTagCloud(RetrievalInfo retrievalInfo) {
  153. /* First check the cache for the tag cloud data */
  154. List<Tag> tagList = getTagCloudDataFromCache();
  155. if (tagList != null && tagList.size() > ServiceConstants.ZERO) {
  156. return tagList;
  157. }
  158. /*
  159. * If not available in cache get the data from datastore.
  160. * Configure the RetrievalInfo object to be used to set the query
  161. * parameters.
  162. */
  163. retrievalInfo = getRetrievalInfoSetToQueryParameters(retrievalInfo,
  164. ServiceConstants.DEFAULT_NO_OF_RECORDS_FOR_TAG);
  165. tagList = tagDao.getTagsForTagCloud(retrievalInfo);
  166. /*
  167. * If the taglist is not null and contains data ,add the list to the
  168. * cache
  169. */
  170. if (tagList != null && tagList.size() > ServiceConstants.ZERO) {
  171. CacheHelper.putObject(CacheConstants.TAG_NAMESPACE,
  172. CacheConstants.TAG_CLOUD,
  173. (Serializable) tagList, CacheConstants.TAG_CLOUD_DATA_EXPIRATION_DELAY);
  174. }
  175. return tagList;
  176. }
  177. @Override
  178. public Tag getTagByName(String tagName) {
  179. if (tagName != null && tagName.length() > ServiceConstants.ZERO) {
  180. Tag tag = tagDao.getTagByTitle(tagName);
  181. return tag;
  182. }
  183. return null;
  184. }
  185. @Override
  186. public List<Tag> getMyTagCloud(User user) {
  187. /*
  188. * Second argument is null so that idea service instantiates a new
  189. * RetrievalInfo object with default parameters
  190. */
  191. List<Idea> userIdeas = ideaService.getIdeasForUser(user, null);
  192. if (userIdeas != null && userIdeas.size() > ServiceConstants.ZERO) {
  193. Set<String> completeSetOfTagKeys = getSetOfTagKeys(userIdeas);
  194. List<Tag> myTags = getTagsByKeys(completeSetOfTagKeys);
  195. if (myTags != null && myTags.size() > ServiceConstants.ZERO) {
  196. myTags = removeTagWithZeroWeight(myTags);
  197. /* Sort the list alphabetically */
  198. Collections.sort(myTags, TagTitleComparator.TAG_TITLE_COMPARATOR);
  199. }
  200. return myTags;
  201. }
  202. return null;
  203. }
  204. @Override
  205. public List<Tag> incrementWeights(String tagsString) {
  206. log.debug("Tag string =" + tagsString);
  207. List<Tag> tagList = getTagsFromTagString(tagsString);
  208. List<Tag> tags = new ArrayList<Tag>();
  209. if (tagList != null && tagList.size() > 0) {
  210. for (Tag tag : tagList) {
  211. Tag tagObj = tagDao.getTagByTitle(tag.getTitle());
  212. tagObj.setWeightage(tagObj.getWeightage()
  213. + IdeaExchangeConstants.TAG_WEIGHT_INCREMENT_SIZE);
  214. tagObj.setUpdatedOn(new Date());
  215. tagObj = saveTagLocal(tagObj);
  216. if (tagObj != null) {
  217. tags.add(tagObj);
  218. }
  219. }
  220. }
  221. if (tags.size() > 0) {
  222. log
  223. .info("Weights of the following tags: " + tagsString
  224. + " successfully decremented");
  225. return tags;
  226. }
  227. return null;
  228. }
  229. @Override
  230. public List<Tag> decrementWeights(String tagsString) {
  231. log.debug("Tag string =" + tagsString + " for decrementing weights");
  232. List<Tag> tagList = getTagsFromTagString(tagsString);
  233. List<Tag> tags = new ArrayList<Tag>();
  234. if (tagList != null && tagList.size() > ServiceConstants.ZERO) {
  235. for (Tag tag : tagList) {
  236. Tag tagObj = tagDao.getTagByTitle(tag.getTitle());
  237. tagObj.setWeightage(tagObj.getWeightage()
  238. - IdeaExchangeConstants.TAG_WEIGHT_INCREMENT_SIZE);
  239. tagObj.setUpdatedOn(new Date());
  240. tagObj = saveTagLocal(tagObj);
  241. if (tagObj != null) {
  242. tags.add(tagObj);
  243. }
  244. }
  245. }
  246. if (tags.size() > ServiceConstants.ZERO) {
  247. log
  248. .info("Weights of the following tags: " + tagsString
  249. + " successfully decremented");
  250. return tags;
  251. }
  252. return null;
  253. }
  254. @Override
  255. public Tag saveTag(Tag tag) {
  256. return saveTagLocal(tag);
  257. }
  258. private Tag saveTagLocal(Tag tag) {
  259. Tag savedTag = tagDao.saveTag(tag);
  260. // Synchronous indexing of data.
  261. SearchUtility.indexEntity(savedTag);
  262. return savedTag;
  263. }
  264. private List<Tag> saveTags(List<Tag> tagsToSave) {
  265. List<Tag> tagsToReturn = new ArrayList<Tag>();
  266. /* Iterate and save tag objects. */
  267. for (Tag tag : tagsToSave) {
  268. tag.setCreatedOn(new Date());
  269. Tag savedTag = saveTag(tag);
  270. if (!StringUtils.isBlank(savedTag.getKey()))
  271. tagsToReturn.add(savedTag);
  272. }
  273. return tagsToReturn;
  274. }
  275. /**
  276. * Prepares the {@link RetrievalInfo} object with values to be used as query
  277. * parameters.
  278. * Checks the received RetrievalInfo object attributes for valid
  279. * data.Updates the attributes if they contain garbage values.If the
  280. * received {@link RetrievalInfo} object is null,sets it to a new instance
  281. * with its attributes set to default values.
  282. *
  283. * @param retrievalInfo the {@link RetrievalInfo} object containing the
  284. * values to be used as query parameters
  285. * @param defaultNoOfRecords the number of records to be fetched in case the
  286. * number is not explicitly specified by the request parameter
  287. * @return the {@link RetrievalInfo} object containing the query parameters
  288. */
  289. private RetrievalInfo getRetrievalInfoSetToQueryParameters(RetrievalInfo retrievalInfo,
  290. long defaultNoOfRecords) {
  291. if (null == retrievalInfo) {
  292. retrievalInfo = new RetrievalInfo();
  293. retrievalInfo.setNoOfRecords(defaultNoOfRecords);
  294. retrievalInfo.setOrderBy(ServiceConstants.DEFAULT_ORDER_BY_FIELD_FOR_TAG);
  295. retrievalInfo.setOrderBy(ServiceConstants.DEFAULT_ORDER_TYPE_FOR_TAG);
  296. } else {
  297. if (retrievalInfo.getStartIndex() < ServiceConstants.ZERO) {
  298. retrievalInfo.setStartIndex(ServiceConstants.DEFAULT_START_INDEX_FOR_TAG);
  299. }
  300. if (retrievalInfo.getNoOfRecords() <= ServiceConstants.ZERO) {
  301. retrievalInfo.setNoOfRecords(defaultNoOfRecords);
  302. }
  303. if (null == retrievalInfo.getOrderType()
  304. || retrievalInfo.getOrderType().length() <= ServiceConstants.ZERO) {
  305. retrievalInfo.setOrderType(ServiceConstants.DEFAULT_ORDER_TYPE_FOR_TAG);
  306. }
  307. if (null == retrievalInfo.getOrderBy()
  308. || retrievalInfo.getOrderBy().length() <= ServiceConstants.ZERO) {
  309. retrievalInfo.setOrderBy(ServiceConstants.DEFAULT_ORDER_BY_FIELD_FOR_TAG);
  310. }
  311. }
  312. return retrievalInfo;
  313. }
  314. /**
  315. * Checks the cache for the tags data
  316. *
  317. * @return list of {@link Tag } objects
  318. */
  319. @SuppressWarnings("unchecked")
  320. private List<Tag> getTagCloudDataFromCache() {
  321. /* Check the cache for the tag cloud data */
  322. if (CacheHelper.containsObject(CacheConstants.TAG_NAMESPACE,
  323. CacheConstants.TAG_CLOUD)) {
  324. List<Tag> tagList = (List<Tag>) CacheHelper
  325. .getObject(CacheConstants.TAG_NAMESPACE, CacheConstants.TAG_CLOUD);
  326. return tagList;
  327. }
  328. return null;
  329. }
  330. /**
  331. * Imposes duplicate check on Tag object passed as a parameter. If duplicate
  332. * of parameter Tag found then it returns the already stored Tag object,
  333. * else it returns the Tag object passed to it.
  334. *
  335. * @param tag Tag object to be checked for duplicate.
  336. *
  337. * @return The already stored duplicate Tag object if found, else it
  338. * returns the Tag object passed to it.
  339. */
  340. private Tag checkForDuplicate(Tag tag) {
  341. Tag savedTag = null;
  342. // check if tag already exist with same title.
  343. savedTag = getTagDao().getTagByTitle(tag.getTitle());
  344. if (savedTag != null) {
  345. return savedTag;
  346. }
  347. return tag;
  348. }
  349. /**
  350. * Converts the comma separated string of tags to list of tag objects.
  351. *
  352. * @param tags Comma separated tags string.
  353. * @return List of Tag objects.
  354. */
  355. private List<Tag> getTagsFromTagString(String tags) {
  356. /* Split the string */
  357. String[] tagArray = tags.trim().split(",");
  358. List<Tag> tagList = new ArrayList<Tag>();
  359. /* Set of the tag titles. */
  360. Set<String> setOfTagTitle = new LinkedHashSet<String>();
  361. /* Add the data to the set */
  362. for (String tagTitle : tagArray) {
  363. if (!StringUtils.isEmpty(tagTitle)) {
  364. setOfTagTitle.add(tagTitle);
  365. }
  366. }
  367. Iterator<String> tagTitleIterator = setOfTagTitle.iterator();
  368. /* Iterate the set and create tag objects */
  369. while (tagTitleIterator.hasNext()) {
  370. Tag tagObj = new Tag();
  371. tagObj.setTitle(tagTitleIterator.next());
  372. /* Add the tags to the list */
  373. tagList.add(tagObj);
  374. }
  375. if (tagList.size() > ServiceConstants.ZERO)
  376. return tagList;
  377. return null;
  378. }
  379. /**
  380. * Parses string to get tags and removes the white spaces and changes into
  381. * lower case string.
  382. *
  383. * @param tagString String object having the comma separated tags string.
  384. * @return list of Tag objects.
  385. */
  386. protected final List<Tag> parseTags(String tagString) {
  387. Tag tmpTag = null;
  388. List<Tag> tagList = new ArrayList<Tag>();
  389. String[] arrayOfTagTitle = tagString.trim().split("[\\s,]");
  390. /* Set of tag titles. */
  391. Set<String> setOfTagTitle = new LinkedHashSet<String>();
  392. for (String tagTitle : arrayOfTagTitle) {
  393. if (!StringUtils.isEmpty(tagTitle)) {
  394. /* change to lower case */
  395. tagTitle = tagTitle.toLowerCase();
  396. setOfTagTitle.add(tagTitle);
  397. }
  398. }
  399. Iterator<String> titleIterator = setOfTagTitle.iterator();
  400. /* Iterate and create tag objects */
  401. while (titleIterator.hasNext()) {
  402. tmpTag = new Tag();
  403. tmpTag.setTitle(titleIterator.next());
  404. tagList.add(tmpTag);
  405. }
  406. return tagList;
  407. }
  408. /**
  409. * Create a combined set of tag keys from a list of ideas
  410. *
  411. * @param ideas the list of ideas
  412. * @return a {@link Set} of tag keys
  413. */
  414. private Set<String> getSetOfTagKeys(List<Idea> ideas) {
  415. Set<String> setOfTagKeys = new HashSet<String>();
  416. Iterator<Idea> iteratorOfIdeas = ideas.iterator();
  417. Set<String> individualSets;
  418. while (iteratorOfIdeas.hasNext()) {
  419. individualSets = iteratorOfIdeas.next().getTagKeys();
  420. setOfTagKeys.addAll(individualSets);
  421. }
  422. return setOfTagKeys;
  423. }
  424. /**
  425. * @param tagDao the tagDao to set
  426. */
  427. public void setTagDao(TagDao tagDao) {
  428. this.tagDao = tagDao;
  429. }
  430. /**
  431. * @return the tagDao
  432. */
  433. public TagDao getTagDao() {
  434. return tagDao;
  435. }
  436. /**
  437. * @param auditManager the auditManager to set
  438. */
  439. public void setAuditManager(AuditManager auditManager) {
  440. this.auditManager = auditManager;
  441. }
  442. /**
  443. * @return the auditManager
  444. */
  445. public AuditManager getAuditManager() {
  446. return auditManager;
  447. }
  448. public IdeaService getIdeaService() {
  449. return ideaService;
  450. }
  451. public void setIdeaService(IdeaService ideaService) {
  452. this.ideaService = ideaService;
  453. }
  454. public EntityIndexService getEntityIndexService() {
  455. return entityIndexService;
  456. }
  457. public void setEntityIndexService(EntityIndexService entityIndexService) {
  458. this.entityIndexService = entityIndexService;
  459. }
  460. }