PageRenderTime 41ms CodeModel.GetById 16ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

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