/* * Copyright (C) 2003-2008 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. */ package org.exoplatform.wcm.webui.search; import java.text.DateFormat; import java.text.Normalizer; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.HashSet; import java.util.List; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.Set; import javax.jcr.Node; import javax.jcr.Session; import javax.jcr.Value; import javax.portlet.PortletPreferences; import javax.portlet.PortletRequest; import org.exoplatform.commons.utils.ISO8601; import org.apache.commons.lang.StringUtils; import org.exoplatform.commons.utils.ObjectPageList; import org.exoplatform.commons.utils.PageList; import org.exoplatform.portal.application.PortalRequestContext; import org.exoplatform.portal.mop.SiteType; import org.exoplatform.portal.webui.container.UIContainer; import org.exoplatform.portal.webui.util.Util; import org.exoplatform.resolver.ResourceResolver; import org.exoplatform.services.cms.templates.TemplateService; import org.exoplatform.services.wcm.core.NodetypeConstant; import org.exoplatform.services.wcm.portal.LivePortalManagerService; import org.exoplatform.services.wcm.publication.WCMComposer; import org.exoplatform.services.wcm.search.QueryCriteria; import org.exoplatform.services.wcm.search.ResultNode; import org.exoplatform.services.wcm.search.SiteSearchService; import org.exoplatform.services.wcm.search.base.AbstractPageList; import org.exoplatform.services.wcm.utils.WCMCoreUtils; import org.exoplatform.wcm.webui.Utils; import org.exoplatform.wcm.webui.paginator.UICustomizeablePaginator; import org.exoplatform.web.application.ApplicationMessage; import org.exoplatform.web.url.navigation.NavigationResource; import org.exoplatform.web.url.navigation.NodeURL; import org.exoplatform.webui.application.WebuiRequestContext; import org.exoplatform.webui.application.portlet.PortletRequestContext; import org.exoplatform.webui.config.annotation.ComponentConfig; import org.exoplatform.webui.config.annotation.ComponentConfigs; import org.exoplatform.webui.config.annotation.EventConfig; import org.exoplatform.webui.core.UIApplication; import org.exoplatform.webui.core.lifecycle.Lifecycle; import org.exoplatform.webui.form.UIFormHiddenInput; import org.exoplatform.webui.form.UIFormRadioBoxInput; /* * Created by The eXo Platform SAS Author : Anh Do Ngoc anh.do@exoplatform.com * Oct 31, 2008 */ @SuppressWarnings("deprecation") @ComponentConfigs( { @ComponentConfig(lifecycle = Lifecycle.class), @ComponentConfig(type = UICustomizeablePaginator.class, events = @EventConfig(listeners = UICustomizeablePaginator.ShowPageActionListener.class)) }) public class UISearchResult extends UIContainer { /** The template path. */ private String templatePath; /** The resource resolver. */ private ResourceResolver resourceResolver; /** The ui paginator. */ private UICustomizeablePaginator uiPaginator; /** The keyword. */ private String keyword; /** The result type. */ private String resultType; /** The suggestion. */ private String suggestion; /** The suggestion. */ private String suggestionURL; /** The PageMode */ private String pageMode; /** The date formatter. */ private SimpleDateFormat dateFormatter = new SimpleDateFormat(ISO8601.SIMPLE_DATETIME_FORMAT); /** The search time. */ private float searchTime; /** The search result in "More" mode */ private List<ResultNode> moreListResult; /** The page that already queried (used only in "More" mode */ private Set<Integer> morePageSet; /** The Constant PARAMETER_REGX. */ public final static String PARAMETER_REGX = "(portal=.*)&(keyword=.*)"; /** The Constant RESULT_NOT_FOUND. */ public final static String RESULT_NOT_FOUND = "UISearchResult.msg.result-not-found"; /** * Inits the. * * @param templatePath the template path * @param resourceResolver the resource resolver * @throws Exception the exception */ public void init(String templatePath, ResourceResolver resourceResolver) throws Exception { PortletRequestContext portletRequestContext = (PortletRequestContext) WebuiRequestContext.getCurrentInstance(); PortletPreferences portletPreferences = portletRequestContext.getRequest().getPreferences(); String paginatorTemplatePath = portletPreferences.getValue(UIWCMSearchPortlet.SEARCH_PAGINATOR_TEMPLATE_PATH, null); this.pageMode = portletPreferences.getValue(UIWCMSearchPortlet.PAGE_MODE, SiteSearchService.PAGE_MODE_NONE); this.templatePath = templatePath; this.resourceResolver = resourceResolver; uiPaginator = addChild(UICustomizeablePaginator.class, null, null); uiPaginator.setTemplatePath(paginatorTemplatePath); uiPaginator.setResourceResolver(resourceResolver); uiPaginator.setPageMode(pageMode); clearResult(); } /* * (non-Javadoc) * @see * org.exoplatform.webui.core.UIComponent#processRender(org.exoplatform.webui * .application.WebuiRequestContext) */ public void processRender(WebuiRequestContext context) throws Exception { PortletRequestContext porletRequestContext = (PortletRequestContext) context; PortletPreferences portletPreferences = porletRequestContext.getRequest().getPreferences(); if (resultType == null || resultType.trim().length() == 0) { resultType = "Document"; } PortalRequestContext portalRequestContext = Util.getPortalRequestContext(); String portal = portalRequestContext.getRequestParameter("portal"); String keyword = portalRequestContext.getRequestParameter("keyword"); if ((portal != null) && (keyword != null) && (keyword.length() > 0)) { UISearchPageLayout uiSearchPageContainer = getAncestorOfType(UISearchPageLayout.class); UISearchForm searchForm = uiSearchPageContainer.getChild(UISearchForm.class); // searchForm.getUIFormSelectBox(UISearchForm.PORTALS_SELECTOR).setSelectedValues(new // String[] {portal}); searchForm.getUIStringInput(UISearchForm.KEYWORD_INPUT).setValue(keyword); if (searchForm.getUIFormSelectBox(UISearchForm.PORTALS_SELECTOR).getValue() != null) { portal = searchForm.getUIFormSelectBox(UISearchForm.PORTALS_SELECTOR).getValue(); } if (searchForm.getUIStringInput(UISearchForm.KEYWORD_INPUT).getValue() != null) { keyword = searchForm.getUIStringInput(UISearchForm.KEYWORD_INPUT).getValue(); } setKeyword(keyword); keyword = Normalizer.normalize(keyword, Normalizer.Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+", ""); SiteSearchService siteSearchService = getApplicationComponent(SiteSearchService.class); QueryCriteria queryCriteria = new QueryCriteria(); UIFormRadioBoxInput searchOption = searchForm.getUIFormRadioBoxInput(UISearchForm.SEARCH_OPTION); boolean isSearchDocument = (searchOption.getValue().equals(UISearchForm.DOCUMENT_CHECKING)); boolean isWebPage = (searchOption.getValue().equals(UISearchForm.PAGE_CHECKING)); List<String> documentNodeTypes = new ArrayList<String>(); if (isSearchDocument) { TemplateService templateService = WCMCoreUtils.getService(TemplateService.class); documentNodeTypes = templateService.getAllDocumentNodeTypes(); portal = Util.getPortalRequestContext().getPortalOwner(); resultType = "Document"; } else { documentNodeTypes.add("gtn:language"); documentNodeTypes.add("exo:pageMetadata"); queryCriteria.setFulltextSearchProperty(new String[] {"exo:metaKeywords", "exo:metaDescription", "gtn:name"}); resultType = "Page"; } String pageMode = portletPreferences.getValue(UIWCMSearchPortlet.PAGE_MODE, SiteSearchService.PAGE_MODE_NONE); queryCriteria.setContentTypes(documentNodeTypes.toArray(new String[documentNodeTypes.size()])); queryCriteria.setSiteName(portal); queryCriteria.setKeyword( org.exoplatform.services.cms.impl.Utils.escapeIllegalCharacterInQuery(keyword).toLowerCase()); queryCriteria.setSearchWebpage(isWebPage); queryCriteria.setSearchDocument(isSearchDocument); queryCriteria.setSearchWebContent(isSearchDocument); queryCriteria.setPageMode(pageMode); queryCriteria.setLiveMode(WCMComposer.MODE_LIVE.equals(Utils.getCurrentMode())); queryCriteria.setSortBy(this.getSortField()); queryCriteria.setOrderBy(this.getOrderType()); int itemsPerPage = Integer.parseInt(portletPreferences.getValue(UIWCMSearchPortlet.ITEMS_PER_PAGE, null)); try { AbstractPageList<ResultNode> pageList = null; if (isWebPage) { pageList = siteSearchService.searchPageContents(WCMCoreUtils.getSystemSessionProvider(), queryCriteria, itemsPerPage, false); } else { pageList = siteSearchService.searchSiteContents(WCMCoreUtils.getUserSessionProvider(), queryCriteria, itemsPerPage, false); } setSearchTime(pageList.getQueryTime() / 1000); setSuggestion(pageList.getSpellSuggestion()); if (pageList.getAvailable() <= 0) { String suggestion = pageList.getSpellSuggestion(); setSuggestionURL(suggestion); searchForm.setSubmitAction(suggestion); } setPageList(pageList); } catch (Exception e) { UIApplication uiApp = getAncestorOfType(UIApplication.class); uiApp.addMessage(new ApplicationMessage(UISearchForm.MESSAGE_NOT_SUPPORT_KEYWORD, null, ApplicationMessage.WARNING)); } } super.processRender(context); } /** * Sets the page list. * * @param dataPageList the new page list */ @SuppressWarnings("unchecked") public void setPageList(PageList dataPageList) { uiPaginator.setPageList(dataPageList); moreListResult = new ArrayList<ResultNode>(); morePageSet = new HashSet<Integer>(); } /** * Gets the total item. * * @return the total item */ public int getTotalItem() { return uiPaginator.getPageList().getAvailable(); } /** * Gets the items per page. * * @return the items per page */ public int getItemsPerPage() { return uiPaginator.getPageList().getPageSize(); } /** * Gets the current page. * * @return the current page */ public int getCurrentPage() { return uiPaginator.getCurrentPage(); } /** * Gets the page mode * @return the page mode */ public String getPageMode() { return pageMode; } /* * (non-Javadoc) * @see org.exoplatform.portal.webui.portal.UIPortalComponent#getTemplate() */ public String getTemplate() { return templatePath; } /* * (non-Javadoc) * @see * org.exoplatform.webui.core.UIComponent#getTemplateResourceResolver(org. * exoplatform.webui.application.WebuiRequestContext, java.lang.String) */ public ResourceResolver getTemplateResourceResolver(WebuiRequestContext context, String template) { return resourceResolver; } /** * Gets the current page data. * * @return the current page data * @throws Exception the exception */ @SuppressWarnings("unchecked") public List getCurrentPageData() throws Exception { return uiPaginator.getCurrentPageData(); } /** * Gets the title. * * @param node the node * @return the title * @throws Exception the exception */ public String getTitle(Node node) throws Exception { if (UIWCMSearchPortlet.SEARCH_CONTENT_MODE.equals(this.getResultType())) { return org.exoplatform.ecm.webui.utils.Utils.getTitle(node); } else { Session session = node.getSession(); Node mopLink = (Node) session.getItem(node.getPath() + "/mop:link"); if (mopLink != null && mopLink.hasProperty("mop:page")) { String mopPageLink = mopLink.getProperty("mop:page").getValue().getString(); Node mopPage = (Node) session.getItem(mopPageLink); if (mopPage != null && mopPage.hasProperty("gtn:name")) { return mopPage.getProperty("gtn:name").getValue().getString(); } else { return node.getName().replaceFirst("mop:", ""); } } else { return node.getName().replaceFirst("mop:", ""); } } } /** * Gets the uRL. * * @param node the node * @return the uRL * @throws Exception the exception */ public List<String> getURLs(Node node) throws Exception { List<String> urls = new ArrayList<String>(); if (!node.hasProperty("publication:navigationNodeURIs")) { urls.add(getURL(node)); } else { for (Value value : node.getProperty("publication:navigationNodeURIs").getValues()) { urls.add(value.getString()); } } return urls; } /** * Gets the published node uri. * * @param navNodeURI the nav node uri * @return the published node uri */ public String getPublishedNodeURI(String navNodeURI) { PortalRequestContext portalRequestContext = Util.getPortalRequestContext(); PortletRequest portletRequest = getPortletRequest(); StringBuffer baseURI = new StringBuffer(); baseURI.append(portletRequest.getScheme()).append("://").append(portletRequest.getServerName()); if (portletRequest.getServerPort() != 80) { baseURI.append(":").append(String.format("%s", portletRequest.getServerPort())); } if (navNodeURI.startsWith(baseURI.toString())) return navNodeURI; NodeURL nodeURL = portalRequestContext.createURL(NodeURL.TYPE); NavigationResource resource = new NavigationResource(portalRequestContext.getSiteType(), portalRequestContext.getSiteName(), navNodeURI); nodeURL.setResource(resource); return baseURI + nodeURL.toString(); } /** * Gets the uRL. * * @param node the node * @return the uRL * @throws Exception the exception */ public String getURL(Node node) throws Exception { PortletRequest portletRequest = getPortletRequest(); PortletPreferences portletPreferences = portletRequest.getPreferences(); String repository = WCMCoreUtils.getRepository().getConfiguration().getName(); String workspace = portletPreferences.getValue(UIWCMSearchPortlet.WORKSPACE, null); String basePath = portletPreferences.getValue(UIWCMSearchPortlet.BASE_PATH, null); String detailParameterName = portletPreferences.getValue(UIWCMSearchPortlet.DETAIL_PARAMETER_NAME, null); StringBuffer path = new StringBuffer(); path.append("/").append(repository).append("/").append(workspace); NodeURL nodeURL = Util.getPortalRequestContext().createURL(NodeURL.TYPE); NavigationResource resource = new NavigationResource(SiteType.PORTAL, Util.getPortalRequestContext() .getPortalOwner(), basePath); nodeURL.setResource(resource); if (node.isNodeType("nt:frozenNode")) { String uuid = node.getProperty("jcr:frozenUuid").getString(); Node originalNode = node.getSession().getNodeByUUID(uuid); path.append(originalNode.getPath()); nodeURL.setQueryParameterValue("version", node.getParent().getName()); } else { path.append(node.getPath()); } nodeURL.setQueryParameterValue(detailParameterName, path.toString()); nodeURL.setSchemeUse(true); return nodeURL.toString(); } private PortletRequest getPortletRequest() { PortletRequestContext portletRequestContext = WebuiRequestContext.getCurrentInstance(); return portletRequestContext.getRequest(); } /** * Gets the created date. * * @param node the node * @return the created date * @throws Exception the exception */ public String getCreatedDate(Node node) throws Exception { if (node.hasProperty("exo:dateCreated")) { Calendar calendar = node.getProperty("exo:dateCreated").getValue().getDate(); return dateFormatter.format(calendar.getTime()); } return null; } /** * Gets the mofified date of search result node. * * @param node the node * @return the mofified date * @throws Exception the exception */ private String getModifiedDate(Node node) throws Exception { Calendar calendar = node.hasProperty(NodetypeConstant.EXO_LAST_MODIFIED_DATE) ? node.getProperty(NodetypeConstant.EXO_LAST_MODIFIED_DATE).getDate() : node.getProperty(NodetypeConstant.EXO_DATE_CREATED).getDate(); DateFormat simpleDateFormat = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.FULL, SimpleDateFormat.SHORT); return simpleDateFormat.format(calendar.getTime()); } /** * Checks if is show paginator. * * @return true, if is show paginator * @throws Exception the exception */ public boolean isShowPaginator() throws Exception { PortletPreferences portletPreferences = ((PortletRequestContext) WebuiRequestContext.getCurrentInstance()).getRequest() .getPreferences(); String itemsPerPage = portletPreferences.getValue(UIWCMSearchPortlet.ITEMS_PER_PAGE, null); int totalItems = uiPaginator.getTotalItems(); if (totalItems > Integer.parseInt(itemsPerPage)) { return true; } return false; } /** * Gets the search time. * * @return the search time */ public float getSearchTime() { return searchTime; } /** * Sets the search time. * * @param searchTime the new search time */ public void setSearchTime(float searchTime) { this.searchTime = searchTime; } /** * Gets the suggestion. * * @return the suggestion */ public String getSuggestion() { return suggestion; } /** * Sets the suggestion. * * @param suggestion the suggestion */ public void setSuggestion(String suggestion) { this.suggestion = suggestion; } /** * Gets the suggestion URL. * * @return the suggestion URL */ public String getSuggestionURL() { return suggestionURL; } /** * Sets the suggestion URL. * * @param suggestionURL the suggestion url */ public void setSuggestionURL(String suggestionURL) { this.suggestionURL = suggestionURL; } /** * Gets the keyword. * * @return the keyword */ public String getKeyword() { return this.keyword; } /** * Sets the keyword. * * @param keyword the new keyword */ public void setKeyword(String keyword) { this.keyword = keyword; } /** * Gets the result type. * * @return the result type */ public String getResultType() { return this.resultType; } /** * Sets the result type. * * @param resultType the new result type */ public void setResultType(String resultType) { this.resultType = resultType; } /** * Gets the number of page. * * @return the number of page */ public int getNumberOfPage() { return uiPaginator.getPageList().getAvailablePage(); } /** * Clears the displayed result list */ @SuppressWarnings("unchecked") public void clearResult() { moreListResult = new ArrayList<ResultNode>(); morePageSet = new HashSet<Integer>(); PortletPreferences portletPreferences = ((PortletRequestContext) WebuiRequestContext.getCurrentInstance()).getRequest() .getPreferences(); String itemsPerPage = portletPreferences.getValue(UIWCMSearchPortlet.ITEMS_PER_PAGE, null); setPageList(new ObjectPageList(new ArrayList<ResultNode>(), Integer.parseInt(itemsPerPage))); } /** * Gets the real node list to display * * @return the real node list */ public List<ResultNode> getRealCurrentPageData() throws Exception { int currentPage = getCurrentPage(); if (SiteSearchService.PAGE_MODE_MORE.equals(pageMode)) { if (!morePageSet.contains(currentPage)) { morePageSet.add(currentPage); moreListResult.addAll(getCurrentPageData()); } } return SiteSearchService.PAGE_MODE_MORE.equals(pageMode) ? moreListResult : getCurrentPageData(); } /** * Get string used to describe search result node. * * @param resultNode ResultNode * @return result node description * @throws Exception */ private String getDetail(ResultNode resultNode) throws Exception { Node realNode = org.exoplatform.wcm.webui.Utils.getRealNode(resultNode.getNode()); String resultType = this.getResultType(); if (UIWCMSearchPortlet.SEARCH_CONTENT_MODE.equals(resultType)) { return WCMCoreUtils.getService(LivePortalManagerService.class).getLivePortalByChild(realNode).getName() .concat(org.exoplatform.services.cms.impl.Utils.fileSize(realNode)) .concat(" - ") .concat(getModifiedDate(realNode)); } else { return StringUtils.substringBefore(StringUtils.substringAfter(realNode.getPath(), SiteSearchService.PATH_PORTAL_SITES.concat("/mop:")),"/") .concat(" - ") .concat(resultNode.getUserNavigationURI()); } } /** * Get resource bundle from given key. * * @param key Key * @return */ private String getLabel(String key) { try { ResourceBundle rs = WebuiRequestContext.getCurrentInstance().getApplicationResourceBundle(); return rs.getString(key); } catch (MissingResourceException e) { return key; } } /** * Get Order Type ("asc" or "desc") from user criteria. * * @return order type * @throws Exception */ private String getOrderType() throws Exception { UISearchForm uiSearchForm = this.getParent().findFirstComponentOfType(UISearchForm.class); String orderType = ((UIFormHiddenInput)uiSearchForm.getUIInput(UISearchForm.ORDER_TYPE_HIDDEN_INPUT)).getValue(); return StringUtils.isEmpty(orderType) ? "asc" : orderType; } /** * Get Sort Field from user criteria. * * @return sort field used to sort result */ private String getSortField() { UISearchForm uiSearchForm = this.getParent().findFirstComponentOfType(UISearchForm.class); String sortField = ((UIFormHiddenInput)uiSearchForm.getUIInput(UISearchForm.SORT_FIELD_HIDDEN_INPUT)).getValue(); return StringUtils.isEmpty(sortField) ? "relevancy" : sortField; } }