package org.exoplatform.forum.service.search; import java.net.URLDecoder; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.apache.commons.lang.StringEscapeUtils; import org.exoplatform.commons.api.search.SearchServiceConnector; import org.exoplatform.commons.api.search.data.SearchContext; import org.exoplatform.commons.api.search.data.SearchResult; import org.exoplatform.container.ExoContainer; import org.exoplatform.container.ExoContainerContext; import org.exoplatform.container.xml.InitParams; import org.exoplatform.forum.common.CommonUtils; import org.exoplatform.forum.service.DataStorage; import org.exoplatform.forum.service.Forum; import org.exoplatform.forum.service.ForumSearchResult; import org.exoplatform.forum.service.Topic; import org.exoplatform.forum.service.Utils; import org.exoplatform.portal.config.UserPortalConfigService; import org.exoplatform.portal.mop.SiteKey; import org.exoplatform.portal.mop.SiteType; import org.exoplatform.portal.mop.navigation.NavigationContext; import org.exoplatform.portal.mop.navigation.NavigationService; import org.exoplatform.portal.mop.navigation.NodeContext; import org.exoplatform.portal.mop.navigation.NodeModel; import org.exoplatform.portal.mop.navigation.Scope; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.services.security.ConversationState; /** * @author <a href="mailto:alain.defrance@exoplatform.com">Alain Defrance</a> */ public class DiscussionSearchConnector extends SearchServiceConnector { private static final Log LOG = ExoLogger.getLogger(DiscussionSearchConnector.class); private DataStorage storage; //"/forum/skin/DefaultSkin/webui/skinIcons/48x48/defaultTopic.png"; private String FIX_ICON = "/eXoSkin/skin/images/themes/default/Icons/AppIcons/uiIconAppDefault.png"; public static final String SPACES_GROUP = "spaces"; public static final String CATEGORY = "category"; private static final String FORUM_PAGE_NAGVIGATION = "forum"; private static final String FORUM_PORTLET_NAME = "ForumPortlet"; private static final String FORMAT_DATE = "EEEEE, MMMMMMMM d, yyyy K:mm a"; public DiscussionSearchConnector(InitParams initParams, DataStorage storage) { super(initParams); this.storage = storage; } @Override public Collection<SearchResult> search(SearchContext context, String query, Collection<String> sites, int offset, int limit, String sort, String order) { List<SearchResult> results = new ArrayList<SearchResult>(); if (CommonUtils.isEmpty(query)) { return results; } ExoContainerContext eXoContext = (ExoContainerContext)ExoContainerContext.getCurrentContainer() .getComponentInstanceOfType(ExoContainerContext.class); String portalName = eXoContext.getPortalContainerName(); String currentUser = getCurrentUserName(); try { List<ForumSearchResult> searchResults = storage.getUnifiedSearch(query, currentUser, offset, limit, sort, order); for (ForumSearchResult searchResult : searchResults) { PostId id = new PostId(searchResult.getPath()); Forum forum = storage.getForum(id.getCategoryId(), id.getForumId()); Topic topic = storage.getTopicByPath(id.getTopicPath(), false); StringBuilder sb = new StringBuilder(); sb.append(forum.getForumName()); sb.append(" - " + topic.getPostCount() + " replies"); //sb.append(" - " + topic.getVoteRating()); SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_DATE); sb.append(" - " + sdf.format(searchResult.getCreatedDate())); String uri = buildLink(context, portalName, id.getCategoryId(), id.getForumId(), id.getTopicId(), topic.getLink()); String postUri = (searchResult.getType().equals(Utils.POST) ? CommonUtils.SLASH + searchResult.getId() : CommonUtils.EMPTY_STR); UnifiedSearchResult result = new UnifiedSearchResult( uri + postUri, searchResult.getName(), StringEscapeUtils.unescapeHtml(searchResult.getExcerpt()), sb.toString(), FIX_ICON, searchResult.getCreatedDate().getTime(), searchResult.getRelevancy(), topic.getVoteRating()); results.add(result); } } catch (Exception e) { LOG.error("Failed in searching.", e); } return results; } /** * Forum build link * @param portalName * @param categoryId * @param forumId * @param topicId * @param defaultLink * @param router * @return */ private String buildLink(SearchContext context, String portalName, String categoryId, String forumId, String topicId, String defaultLink) { try { String forumURI = null; // if (categoryId.indexOf(SPACES_GROUP) > 0) { forumURI = makeURIForSpaceContext(context, portalName, forumId); forumURI = URLDecoder.decode(forumURI, "UTF-8"); } else { forumURI = makeURIForPortalContext(context, portalName); } if (!CommonUtils.isEmpty(forumURI)) { return String.format("%s/%s/%s", forumURI, Utils.TOPIC, topicId); } else { return defaultLink; } } catch (Exception ex) { return CommonUtils.EMPTY_STR; } } /** * builds URI under Portal site context * @param context * @param portalName * @param siteName * @return * @throws Exception */ private String makeURIForPortalContext(SearchContext context, String portalName) throws Exception { // String path = ""; String siteType = ""; String siteName = ""; List<String> allSites = getAllPortalSites(); // for(String siteName_ : allSites) { SiteKey siteKey = SiteKey.portal(siteName_); siteType = SiteType.PORTAL.getName(); path = getSiteName(siteKey); if(!CommonUtils.isEmpty(path)) { siteName = siteKey.getName(); break; } } // if (Utils.isEmpty(path)) { return CommonUtils.EMPTY_STR; } String forumURI = context.handler(portalName) .lang("") .siteName(siteName) .siteType(siteType) .path(path) .renderLink(); return String.format("/%s%s", portalName, forumURI); } /** * builds URI for Forum what is inside Space context * * @param context * @param portalName * @param forumId * @param siteName * @return * @throws Exception */ private String makeURIForSpaceContext(SearchContext context, String portalName, String forumId) throws Exception { // String path = ""; String siteType = ""; String prefixId = Utils.FORUM_SPACE_ID_PREFIX; String groupId = forumId.replaceFirst(prefixId, ""); String spaceGroupId = String.format("/%s/%s", SPACES_GROUP, groupId);// /spaces/space1 SiteKey siteKey = SiteKey.group(spaceGroupId); // String siteName = spaceGroupId.replaceAll(CommonUtils.SLASH, CommonUtils.COLON); // siteType = SiteType.GROUP.getName(); // String forumNavName = getSiteName(siteKey); // if (Utils.isEmpty(forumNavName)) { return CommonUtils.EMPTY_STR; } path = groupId + CommonUtils.SLASH + forumNavName; String forumURI = context.handler(portalName) .lang("") .siteName(siteName) .siteType(siteType) .path(path) .renderLink(); return String.format("/%s%s", portalName, forumURI); } /** * @return */ private List<String> getAllPortalSites() { UserPortalConfigService dataStorage = (UserPortalConfigService) ExoContainerContext.getCurrentContainer() .getComponentInstanceOfType(UserPortalConfigService.class); try { return dataStorage.getAllPortalNames(); } catch (Exception e) { return new ArrayList<String>(); } } /** * * @param siteKey * @return */ private String getSiteName(SiteKey siteKey) { try { ExoContainer container = ExoContainerContext.getCurrentContainer(); NavigationService navService = (NavigationService) container.getComponentInstance(NavigationService.class); NavigationContext nav = navService.loadNavigation(siteKey); NodeContext<NodeContext<?>> parentNodeCtx = navService.loadNode(NodeModel.SELF_MODEL, nav, Scope.ALL, null); Collection<NodeContext<?>> children = parentNodeCtx.getNodes(); if (siteKey.getType() == SiteType.GROUP) { children = parentNodeCtx.get(0).getNodes(); } Iterator<NodeContext<?>> it = children.iterator(); NodeContext<?> child = null; while (it.hasNext()) { child = it.next(); if (FORUM_PAGE_NAGVIGATION.equals(child.getName()) || child.getName().indexOf(FORUM_PORTLET_NAME) >= 0) { return child.getName(); } } return CommonUtils.EMPTY_STR; } catch (Exception e) { return CommonUtils.EMPTY_STR; } } /** * * @return */ private String getCurrentUserName() { return ConversationState.getCurrent().getIdentity().getUserId(); } }