UISearchResult.java

  1. /*
  2.  * Copyright (C) 2003-2007 eXo Platform SAS.
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU Affero General Public License
  6.  * as published by the Free Software Foundation; either version 3
  7.  * of the License, or (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, see<http://www.gnu.org/licenses/>.
  16.  */
  17. package org.exoplatform.ecm.webui.component.explorer.search;

  18. import java.text.DateFormat;
  19. import java.text.SimpleDateFormat;
  20. import java.util.ArrayList;
  21. import java.util.Comparator;
  22. import java.util.Date;
  23. import java.util.GregorianCalendar;
  24. import java.util.Iterator;
  25. import java.util.List;
  26. import java.util.Locale;
  27. import java.util.Set;

  28. import javax.jcr.*;
  29. import javax.jcr.query.Query;
  30. import javax.jcr.query.QueryManager;
  31. import javax.jcr.query.QueryResult;
  32. import javax.jcr.query.Row;

  33. import org.apache.commons.lang.StringUtils;

  34. import org.exoplatform.commons.api.search.data.SearchResult;
  35. import org.exoplatform.ecm.jcr.model.Preference;
  36. import org.exoplatform.ecm.webui.component.explorer.UIDocumentContainer;
  37. import org.exoplatform.ecm.webui.component.explorer.UIDocumentWorkspace;
  38. import org.exoplatform.ecm.webui.component.explorer.UIDrivesArea;
  39. import org.exoplatform.ecm.webui.component.explorer.UIJCRExplorer;
  40. import org.exoplatform.ecm.webui.component.explorer.UIWorkingArea;
  41. import org.exoplatform.ecm.webui.component.explorer.sidebar.UISideBar;
  42. import org.exoplatform.ecm.webui.utils.JCRExceptionManager;
  43. import org.exoplatform.ecm.webui.utils.Utils;
  44. import org.exoplatform.portal.webui.util.Util;
  45. import org.exoplatform.portal.webui.workspace.UIPortalApplication;
  46. import org.exoplatform.services.cms.BasePath;
  47. import org.exoplatform.services.cms.folksonomy.NewFolksonomyService;
  48. import org.exoplatform.services.cms.link.LinkManager;
  49. import org.exoplatform.services.cms.link.LinkUtils;
  50. import org.exoplatform.services.cms.link.NodeFinder;
  51. import org.exoplatform.services.cms.taxonomy.TaxonomyService;
  52. import org.exoplatform.services.cms.templates.TemplateService;
  53. import org.exoplatform.services.jcr.RepositoryService;
  54. import org.exoplatform.services.jcr.core.ManageableRepository;
  55. import org.exoplatform.services.jcr.ext.hierarchy.NodeHierarchyCreator;
  56. import org.exoplatform.services.jcr.impl.core.JCRPath;
  57. import org.exoplatform.services.jcr.impl.core.SessionImpl;
  58. import org.exoplatform.services.log.ExoLogger;
  59. import org.exoplatform.services.log.Log;
  60. import org.exoplatform.services.wcm.core.NodetypeConstant;
  61. import org.exoplatform.services.wcm.search.QueryCriteria;
  62. import org.exoplatform.services.wcm.search.base.AbstractPageList;
  63. import org.exoplatform.services.wcm.search.base.NodeSearchFilter;
  64. import org.exoplatform.services.wcm.search.base.PageListFactory;
  65. import org.exoplatform.services.wcm.search.base.QueryData;
  66. import org.exoplatform.services.wcm.search.base.SearchDataCreator;
  67. import org.exoplatform.services.wcm.utils.WCMCoreUtils;
  68. import org.exoplatform.wcm.webui.paginator.UILazyPageIterator;
  69. import org.exoplatform.web.application.ApplicationMessage;
  70. import org.exoplatform.webui.application.WebuiRequestContext;
  71. import org.exoplatform.webui.config.annotation.ComponentConfig;
  72. import org.exoplatform.webui.config.annotation.EventConfig;
  73. import org.exoplatform.webui.core.UIApplication;
  74. import org.exoplatform.webui.core.UIContainer;
  75. import org.exoplatform.webui.core.UIPageIterator;
  76. import org.exoplatform.webui.event.Event;
  77. import org.exoplatform.webui.event.EventListener;

  78. /**
  79.  * Created by The eXo Platform SARL
  80.  * Author : Tran The Trong
  81.  *          trongtt@gmail.com
  82.  * Oct 2, 2006
  83.  * 16:37:15
  84.  *
  85.  * Edited by : Dang Van Minh
  86.  *             minh.dang@exoplatform.com
  87.  * Jan 5, 2007
  88.  */
  89. @ComponentConfig(
  90.     template = "app:/groovy/webui/component/explorer/search/UISearchResult.gtmpl",
  91.     events = {
  92.         @EventConfig(listeners = UISearchResult.ViewActionListener.class),
  93.         @EventConfig(listeners = UISearchResult.OpenFolderActionListener.class),
  94.         @EventConfig(listeners = UISearchResult.SortASCActionListener.class),
  95.         @EventConfig(listeners = UISearchResult.SortDESCActionListener.class)
  96.     }
  97. )
  98. public class UISearchResult extends UIContainer {

  99.   /**
  100.    * Logger.
  101.    */
  102.   private static final Log LOG  = ExoLogger.getLogger(UISearchResult.class.getName());

  103.   private QueryData queryData_;
  104.   private long searchTime_ = 0;
  105.   private UIPageIterator uiPageIterator_;
  106.   private String iconType = "";
  107.   private String iconScore = "";
  108.   static private int PAGE_SIZE = 10;
  109.   private List<String> categoryPathList = new ArrayList<String>();
  110.   private String constraintsCondition;
  111.   private String workspaceName = null;
  112.   private String currentPath = null;
  113.   private String keyword ="";
  114.   private AbstractPageList<RowData> pageList;

  115.   public List<String> getCategoryPathList() { return categoryPathList; }
  116.   public void setCategoryPathList(List<String> categoryPathListItem) {
  117.     categoryPathList = categoryPathListItem;
  118.   }

  119.   public String getConstraintsCondition() { return constraintsCondition; }
  120.   public void setConstraintsCondition(String constraintsConditionItem) {
  121.     constraintsCondition = constraintsConditionItem;
  122.   }

  123.   public UISearchResult() throws Exception {
  124.     uiPageIterator_ = addChild(UILazyPageIterator.class, null, "UISearchResultPageIterator");
  125.   }

  126.   public void setQuery(String queryStatement, String workspaceName, String language, boolean isSystemSession, String keyword) {
  127.     queryData_ = new QueryData(queryStatement, workspaceName, language, isSystemSession);
  128.     this.keyword = keyword;
  129.   }

  130.   public long getSearchTime() { return searchTime_; }
  131.   public void setSearchTime(long time) { this.searchTime_ = time; }

  132.   public String getIconType() {
  133.     return iconType;
  134.   }

  135.   public String getIconScore() {
  136.     return iconScore;
  137.   }

  138.   public void setIconScore(String iconScore) {
  139.     this.iconScore = iconScore;
  140.   }

  141.   public void setIconType(String iconType) {
  142.     this.iconType = iconType;
  143.   }

  144.   public List getCurrentList() throws Exception {
  145.     return uiPageIterator_.getCurrentPageData();
  146.   }

  147.   public DateFormat getSimpleDateFormat() {
  148.     Locale locale = Util.getUIPortal().getAncestorOfType(UIPortalApplication.class).getLocale();
  149.     return SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.SHORT, locale);
  150.   }

  151.   public Session getSession() throws Exception {
  152.     return getAncestorOfType(UIJCRExplorer.class).getTargetSession();
  153.   }

  154.   public Date getDateCreated(Node node) throws Exception{
  155.     if (node.hasProperty("exo:dateCreated")) {
  156.       return node.getProperty("exo:dateCreated").getDate().getTime();
  157.     }
  158.     return new GregorianCalendar().getTime();
  159.   }

  160.   public Node getNodeByPath(String path) throws Exception {
  161.     try {
  162.       JCRPath nodePath = ((SessionImpl)getSession()).getLocationFactory().parseJCRPath(path);
  163.       return (Node)getSession().getItem(nodePath.getAsString(false));
  164.     } catch (Exception e) {
  165.       return null;
  166.     }
  167.   }

  168.   public UIPageIterator getUIPageIterator() { return uiPageIterator_; }

  169.   public void updateGrid() throws Exception {
  170.     TemplateService templateService = WCMCoreUtils.getService(TemplateService.class);
  171.     List<String> documentList = templateService.getDocumentTemplates();
  172.     UIJCRExplorer uiExplorer = getAncestorOfType(UIJCRExplorer.class);
  173.     UISideBar uiSideBar = uiExplorer.findFirstComponentOfType(UISideBar.class);

  174.     Set<String> tagPathsUsedInSearch = null;
  175.     if (uiSideBar != null && uiSideBar.isRendered()
  176.         && StringUtils.equals(uiSideBar.getSelectedComp(), UISideBar.UI_TAG_EXPLORER)) {
  177.       tagPathsUsedInSearch = uiExplorer.getTagPaths();
  178.     }

  179.     QueryCriteria queryCriteria = new QueryCriteria();
  180.     queryCriteria.setKeyword(keyword);
  181.     queryCriteria.setSearchPath(uiExplorer.getCurrentPath());
  182.     queryCriteria.setSearchWebpage(false);

  183.     WebuiRequestContext requestContext = WebuiRequestContext.getCurrentInstance();
  184.     pageList = PageListFactory.createPageList(queryData_.getQueryStatement(),
  185.                                               requestContext.getLocale(),
  186.                                               queryData_.getWorkSpace(),
  187.                                               queryData_.getLanguage_(),
  188.                                               queryData_.isSystemSession(),
  189.                                               new NodeFilter(categoryPathList, tagPathsUsedInSearch, keyword, documentList),
  190.                                               new RowDataCreator(),
  191.                                               PAGE_SIZE,
  192.                                               0,
  193.                                               queryCriteria);
  194.     uiPageIterator_.setPageList(pageList);
  195.   }

  196.   private static class SearchComparator implements Comparator<RowData> {

  197.     public static final String SORT_TYPE = "NODE_TYPE";
  198.     public static final String SORT_SCORE = "JCR_SCORE";
  199.     public static final String ASC = "ASC";
  200.     public static final String DESC = "DECS";

  201.     private String sortType;
  202.     private String orderType;

  203.     public void setSortType(String value) { sortType = value; }
  204.     public void setOrderType(String value) { orderType = value; }

  205.     public int compare(RowData row1, RowData row2) {
  206.       try {
  207.         if (SORT_TYPE.equals(sortType.trim())) {
  208.           String s1 = row1.getJcrPrimaryType();
  209.           String s2 = row2.getJcrPrimaryType();
  210.           if (DESC.equals(orderType.trim())) { return s2.compareTo(s1); }
  211.           return s1.compareTo(s2);
  212.         } else if (SORT_SCORE.equals(sortType.trim())) {
  213.           Long l1 = row1.getJcrScore();
  214.           Long l2 = row2.getJcrScore();
  215.           if (DESC.equals(orderType.trim())) { return l2.compareTo(l1); }
  216.           return l1.compareTo(l2);
  217.         }
  218.       } catch (Exception e) {
  219.         if (LOG.isErrorEnabled()) {
  220.           LOG.error("Cannot compare rows", e);
  221.         }
  222.       }
  223.       return 0;
  224.     }
  225.   }

  226.   public String StriptHTML(String s) {
  227.     String[] targets = {"<div>", "</div>", "<span>", "</span>"};
  228.     for (String target : targets) {
  229.       s = s.replace(target, "");
  230.     }
  231.     return s;
  232.   }

  233.   static  public class ViewActionListener extends EventListener<UISearchResult> {
  234.     public void execute(Event<UISearchResult> event) throws Exception {
  235.       UISearchResult uiSearchResult = event.getSource();
  236.       UIJCRExplorer uiExplorer = uiSearchResult.getAncestorOfType(UIJCRExplorer.class);
  237.       String path = event.getRequestContext().getRequestParameter(OBJECTID);
  238.       UIApplication uiApp = uiSearchResult.getAncestorOfType(UIApplication.class);
  239.       String workspaceName = event.getRequestContext().getRequestParameter("workspaceName");
  240.       Item item = null;
  241.       try {
  242.         Session session = uiExplorer.getSessionByWorkspace(workspaceName);
  243.         // Check if the path exists
  244.         NodeFinder nodeFinder = uiSearchResult.getApplicationComponent(NodeFinder.class);
  245.         item = nodeFinder.getItem(session, path);
  246.       } catch(PathNotFoundException pa) {
  247.         uiApp.addMessage(new ApplicationMessage("UITreeExplorer.msg.path-not-found", null,
  248.             ApplicationMessage.WARNING)) ;

  249.         return ;
  250.       } catch(ItemNotFoundException inf) {
  251.           uiApp.addMessage(new ApplicationMessage("UITreeExplorer.msg.path-not-found", null,
  252.               ApplicationMessage.WARNING)) ;

  253.           return ;
  254.       } catch(AccessDeniedException ace) {
  255.           uiApp.addMessage(new ApplicationMessage("UIDocumentInfo.msg.access-denied", null,
  256.                   ApplicationMessage.WARNING)) ;

  257.         return ;
  258.       } catch(RepositoryException e) {
  259.         if (LOG.isErrorEnabled()) {
  260.           LOG.error("Repository cannot be found");
  261.         }
  262.         uiApp.addMessage(new ApplicationMessage("UITreeExplorer.msg.repository-error", null,
  263.             ApplicationMessage.WARNING)) ;

  264.         return ;
  265.       } catch (Exception e) {
  266.         JCRExceptionManager.process(uiApp, e);
  267.         return;
  268.       }
  269.       if (isInTrash(item))
  270.         return;

  271.       UIWorkingArea uiWorkingArea = uiExplorer.getChild(UIWorkingArea.class);
  272.       UIDocumentWorkspace uiDocumentWorkspace = uiWorkingArea.getChild(UIDocumentWorkspace.class);
  273.       if(!uiDocumentWorkspace.isRendered()) {
  274.         uiWorkingArea.getChild(UIDrivesArea.class).setRendered(false);
  275.         uiWorkingArea.getChild(UIDocumentWorkspace.class).setRendered(true);
  276.       }

  277.       uiExplorer.setSelectNode(workspaceName, path) ;

  278.       uiDocumentWorkspace.getChild(UIDocumentContainer.class).setRendered(true);
  279.       uiSearchResult.setRendered(false);
  280.       uiExplorer.refreshExplorer((Node)item, true);
  281.     }

  282.     private boolean isInTrash(Item item) throws RepositoryException {
  283.       return (item instanceof Node) && Utils.isInTrash((Node) item);
  284.     }
  285.   }

  286.   static public class OpenFolderActionListener extends EventListener<UISearchResult> {
  287.     public void execute(Event<UISearchResult> event) throws Exception {
  288.       UISearchResult uiSearchResult = event.getSource();
  289.       UIJCRExplorer uiExplorer = uiSearchResult.getAncestorOfType(UIJCRExplorer.class);
  290.       String path = event.getRequestContext().getRequestParameter(OBJECTID);
  291.       String folderPath = LinkUtils.getParentPath(path);
  292.       Node node = null;
  293.       try {
  294.         node = uiExplorer.getNodeByPath(folderPath, uiExplorer.getTargetSession());
  295.       } catch(AccessDeniedException ace) {
  296.         UIApplication uiApp = uiSearchResult.getAncestorOfType(UIApplication.class);
  297.         uiApp.addMessage(new ApplicationMessage("UISearchResult.msg.access-denied", null,
  298.             ApplicationMessage.WARNING));

  299.         return;
  300.       } catch(PathNotFoundException ace) {
  301.         UIApplication uiApp = uiSearchResult.getAncestorOfType(UIApplication.class);
  302.         uiApp.addMessage(new ApplicationMessage("UISearchResult.msg.access-denied", null,
  303.             ApplicationMessage.WARNING));

  304.         return;
  305.       } catch(Exception e) {
  306.         if (LOG.isErrorEnabled()) {
  307.           LOG.error("Cannot access the node at " + folderPath, e);
  308.         }
  309.       }

  310.       uiExplorer.setSelectNode(node.getSession().getWorkspace().getName(), folderPath);
  311.       uiExplorer.refreshExplorer(node, true);
  312.     }
  313.   }

  314.   static public class SortASCActionListener extends EventListener<UISearchResult> {
  315.     public void execute(Event<UISearchResult> event) throws Exception {
  316.       UISearchResult uiSearchResult = event.getSource();
  317.       String objectId = event.getRequestContext().getRequestParameter(OBJECTID);
  318.       SearchComparator comparator = new SearchComparator();
  319.       if (objectId.equals("type")) {
  320.         uiSearchResult.pageList.setSortByField(Utils.JCR_PRIMARYTYPE);
  321.         comparator.setSortType(SearchComparator.SORT_TYPE);
  322.         uiSearchResult.setIconType(Preference.BLUE_DOWN_ARROW);
  323.         uiSearchResult.setIconScore("");
  324.       } else if (objectId.equals("score")) {
  325.         uiSearchResult.pageList.setSortByField(Utils.JCR_SCORE);
  326.         comparator.setSortType(SearchComparator.SORT_SCORE);
  327.         uiSearchResult.setIconScore(Preference.BLUE_DOWN_ARROW);
  328.         uiSearchResult.setIconType("");
  329.       }
  330.       comparator.setOrderType(SearchComparator.ASC);
  331.       uiSearchResult.pageList.setComparator(comparator);
  332.       uiSearchResult.pageList.setOrder("ASC");
  333.       uiSearchResult.pageList.sortData();
  334.       event.getRequestContext().addUIComponentToUpdateByAjax(uiSearchResult.getParent());
  335.     }
  336.   }

  337.   static public class SortDESCActionListener extends EventListener<UISearchResult> {
  338.     public void execute(Event<UISearchResult> event) throws Exception {
  339.       UISearchResult uiSearchResult = event.getSource() ;
  340.       String objectId = event.getRequestContext().getRequestParameter(OBJECTID);
  341.       SearchComparator comparator = new SearchComparator();
  342.       if (objectId.equals("type")) {
  343.         uiSearchResult.pageList.setSortByField(Utils.JCR_PRIMARYTYPE);
  344.         comparator.setSortType(SearchComparator.SORT_TYPE);
  345.         uiSearchResult.setIconType(Preference.BLUE_UP_ARROW);
  346.         uiSearchResult.setIconScore("");
  347.       } else if (objectId.equals("score")) {
  348.         uiSearchResult.pageList.setSortByField(Utils.JCR_SCORE);
  349.         comparator.setSortType(SearchComparator.SORT_SCORE);
  350.         uiSearchResult.setIconScore(Preference.BLUE_UP_ARROW);
  351.         uiSearchResult.setIconType("");
  352.       }
  353.       comparator.setOrderType(SearchComparator.DESC);
  354.       uiSearchResult.pageList.setComparator(comparator);
  355.       uiSearchResult.pageList.setOrder("DESC");
  356.       uiSearchResult.pageList.sortData();
  357.       event.getRequestContext().addUIComponentToUpdateByAjax(uiSearchResult.getParent());
  358.     }
  359.   }

  360.   public static class NodeFilter implements NodeSearchFilter {

  361.     private List<String> categoryPathList;
  362.     private Set<String> tagPaths;
  363.     private TaxonomyService taxonomyService;
  364.     private NodeHierarchyCreator nodeHierarchyCreator;
  365.     private RepositoryService repositoryService;
  366.     private NewFolksonomyService folksonomyService;
  367.     private String rootTreePath;
  368.     private LinkManager linkManager = null;
  369.     private String keyword ="";
  370.     private List<String> documentTypes;

  371.     final static private String  CHECK_LINK_MATCH_QUERY1 = "select * from nt:base "
  372.                                                              + "where jcr:path = '$0' and ( contains(*, '$1') "
  373.                                                              + "or lower(exo:name) like '%$2%' "
  374.                                                              + "or lower(exo:title) like '%$2%')";

  375.     final static private String  CHECK_LINK_MATCH_QUERY2 = "select * from nt:base where jcr:path like '$0/%' "
  376.                                                              + "and ( contains(*, '$1') or lower(exo:name) like '%$2%' "
  377.                                                              + "or lower(exo:title) like '%$2%')";
  378.     public NodeFilter(List<String> categories, Set<String> tagPaths, String keyword, List<String> documentTypes) {
  379.       taxonomyService = WCMCoreUtils.getService(TaxonomyService.class);
  380.       nodeHierarchyCreator = WCMCoreUtils.getService(NodeHierarchyCreator.class);
  381.       linkManager = WCMCoreUtils.getService(LinkManager.class);
  382.       repositoryService = WCMCoreUtils.getService(RepositoryService.class);
  383.       folksonomyService = WCMCoreUtils.getService(NewFolksonomyService.class);
  384.       rootTreePath = nodeHierarchyCreator.getJcrPath(BasePath.TAXONOMIES_TREE_STORAGE_PATH);
  385.       categoryPathList = categories;
  386.       this.tagPaths = tagPaths;
  387.       this.keyword = keyword;
  388.       this.documentTypes = documentTypes;
  389.     }

  390.     public NodeFilter(List<String> categories, String keyword, List<String> documentTypes) {
  391.       taxonomyService = WCMCoreUtils.getService(TaxonomyService.class);
  392.       nodeHierarchyCreator = WCMCoreUtils.getService(NodeHierarchyCreator.class);
  393.       linkManager = WCMCoreUtils.getService(LinkManager.class);
  394.       rootTreePath = nodeHierarchyCreator.getJcrPath(BasePath.TAXONOMIES_TREE_STORAGE_PATH);
  395.       categoryPathList = categories;
  396.       this.keyword = keyword;
  397.       this.documentTypes = documentTypes;
  398.     }
  399.     public Node filterNodeToDisplay(Node node) {
  400.       try {
  401.         if (node == null || node.getPath().contains("/jcr:system/")) return null;
  402.         if (node != null) {
  403.           if ((tagPaths != null) && (tagPaths.size() > 0)) {
  404.             ManageableRepository repository = repositoryService.getCurrentRepository();
  405.             String workspaceName = repository.getConfiguration().getDefaultWorkspaceName();
  406.             if (node.isNodeType(Utils.EXO_SYMLINK)
  407.                 || ((Node) node.getAncestor(1)).isNodeType(NodetypeConstant.EXO_TRASH_FOLDER)) {
  408.               return null;
  409.             } else {
  410.               for (String tagPath : tagPaths) {
  411.                 List<Node> taggedDocuments = folksonomyService.getAllDocumentsByTag(tagPath,
  412.                                                                                     workspaceName,
  413.                                                                                     WCMCoreUtils.getUserSessionProvider());
  414.                 boolean nodeExistsInTag = false;
  415.                 Iterator<Node> nodesIterator = taggedDocuments.iterator();
  416.                 while (nodesIterator.hasNext() && !nodeExistsInTag) {
  417.                   Node taggedNode = nodesIterator.next();
  418.                   nodeExistsInTag = taggedNode.isSame(node);
  419.                 }
  420.                 if (!nodeExistsInTag) {
  421.                   return null;
  422.                 }
  423.               }
  424.             }
  425.           }
  426.           if ((categoryPathList != null) && (categoryPathList.size() > 0)){
  427.             for (String categoryPath : categoryPathList) {
  428.               int index = categoryPath.indexOf("/");
  429.               String taxonomyName = categoryPath;
  430.               String postFixTaxonomy = "";
  431.               if (index > 0) {
  432.                 taxonomyName = categoryPath.substring(0, index);
  433.                 postFixTaxonomy = categoryPath.substring(index + 1);
  434.               }

  435.               List<String> pathCategoriesList = new ArrayList<String>();
  436.               String searchCategory = taxonomyService.getTaxonomyTree(taxonomyName).getPath() +
  437.                                       ("".equals(postFixTaxonomy) ? "" : "/" + postFixTaxonomy);
  438.               Node targetNode = node.isNodeType(Utils.EXO_SYMLINK) ?
  439.                                         linkManager.getTarget(node) : node;
  440.               List<Node> listCategories = taxonomyService.getCategories(targetNode, taxonomyName);
  441.               for (Node category : listCategories) {
  442.                 pathCategoriesList.add(category.getPath());
  443.               }
  444.               if (pathCategoriesList.contains(searchCategory))
  445.               {
  446.                 if (node.isNodeType(Utils.EXO_SYMLINK)) {
  447.                   if (checkTargetMatch(node, keyword)) return node;
  448.                 }else {
  449.                   return node;
  450.                 }
  451.               }
  452.             }
  453.             return null;
  454.           } else {
  455.             if (node.isNodeType(Utils.EXO_SYMLINK)) {
  456.               if (checkTargetMatch(node, keyword)) return node;
  457.             } else if (node.isNodeType(Utils.NT_RESOURCE)) {
  458.               return node.getParent();
  459.             } else if (node.isNodeType(Utils.EXO_COMMENTS)) {
  460.               return node.getParent().getParent();
  461.             } else {
  462.               return node;
  463.             }
  464.           }
  465.         }
  466.       } catch (Exception e) {
  467.           LOG.warn(e.getMessage());
  468.       }
  469.       return null;
  470.     }

  471.     /**
  472.      * Check a symlink/taxonomylink if its target matches with keyword for searching ...link
  473.      * @param symlinkNode
  474.      * @param keyword
  475.      * @return
  476.      */
  477.     protected boolean checkTargetMatch(Node symlinkNode, String keyword) {
  478.       String queryStatement = CHECK_LINK_MATCH_QUERY1;
  479.       Session targetSession;
  480.       Node target=null;
  481.       if (keyword ==null || keyword.length()==0 ) return true;
  482.       if (linkManager==null) {
  483.         linkManager = WCMCoreUtils.getService(LinkManager.class);
  484.       }
  485.       try {
  486.         if (!linkManager.isLink(symlinkNode)) return true;
  487.         target = linkManager.getTarget(symlinkNode);
  488.         if (target == null) return false;
  489.         targetSession = target.getSession();
  490.         queryStatement = StringUtils.replace(queryStatement,"$0", target.getPath());
  491.         queryStatement = StringUtils.replace(queryStatement,"$1", keyword.replaceAll("'", "''"));
  492.         queryStatement = StringUtils.replace(queryStatement,"$2", keyword.replaceAll("'", "''").toLowerCase());
  493.         QueryManager queryManager = targetSession.getWorkspace().getQueryManager();
  494.         Query query = queryManager.createQuery(queryStatement, Query.SQL);
  495.         QueryResult queryResult = query.execute();
  496.         if ( queryResult.getNodes().getSize()>0 ) return true;
  497.         if (isFodlderDocument(target)||target.hasNode("jcr:content") ) {
  498.           queryStatement = CHECK_LINK_MATCH_QUERY2;
  499.           queryStatement = StringUtils.replace(queryStatement,"$0", target.getPath());
  500.           queryStatement = StringUtils.replace(queryStatement,"$1", keyword.replaceAll("'", "''"));
  501.           queryStatement = StringUtils.replace(queryStatement,"$2", keyword.replaceAll("'", "''").toLowerCase());
  502.           query = queryManager.createQuery(queryStatement, Query.SQL);
  503.           queryResult = query.execute();
  504.           return queryResult.getNodes().getSize()>0;
  505.         }else {
  506.           return false;
  507.         }
  508.       } catch (RepositoryException e) {
  509.         return false;
  510.       }
  511.     }
  512.     private boolean isFodlderDocument(Node node) throws RepositoryException{
  513.       if (!node.isNodeType(NodetypeConstant.NT_UNSTRUCTURED)) return false;
  514.       for (String documentType : documentTypes) {
  515.         if (node.getPrimaryNodeType().isNodeType(documentType))
  516.           return true;
  517.       }
  518.       return false;
  519.     }
  520.   }

  521.   public static class RowDataCreator implements SearchDataCreator<RowData> {

  522.     public RowData createData(Node node, Row row, SearchResult searchResult) {
  523.       return new RowData(row, node, searchResult);
  524.     }

  525.   }

  526.   public static class RowData {
  527.     private String jcrPath = "";
  528.     private String repExcerpt = "";
  529.     private long jcrScore = 0;
  530.     private String jcrPrimaryType = "";

  531.     public RowData(Row row) {
  532.       this(row, null, null);
  533.     }
  534.    
  535.     public RowData(Row row, Node node, SearchResult result) {
  536.       try {
  537.         jcrPath = node != null ? node.getPath() : row.getValue("jcr:path").getString();
  538.       } catch (Exception e) {
  539.         if (LOG.isWarnEnabled()) {
  540.           LOG.warn(e.getMessage());
  541.         }
  542.       }
  543.       try {
  544.         if(row != null) {
  545.           Value rowExcerptValue = row.getValue("rep:excerpt(.)");
  546.           repExcerpt = rowExcerptValue != null ? rowExcerptValue.getString() : "";
  547.         }
  548.         if(StringUtils.isEmpty(repExcerpt) && result != null) {
  549.           repExcerpt = result.getExcerpt();
  550.         }
  551.       } catch (Exception e) {
  552.         if (LOG.isWarnEnabled()) {
  553.           LOG.warn("Cannot get excerpt of node " + jcrPath, e);
  554.         }
  555.       }
  556.       try {
  557.         if(row != null) {
  558.           Value rowScoreValue = row.getValue("jcr:score");
  559.           jcrScore = rowScoreValue != null ? rowScoreValue.getLong() : 0;
  560.         }
  561.         if(jcrScore == 0 && result != null) {
  562.           jcrScore = result.getRelevancy();
  563.         }
  564.       } catch (Exception e) {
  565.         if (LOG.isWarnEnabled()) {
  566.           LOG.warn("Cannot get excerpt of node " + jcrPath, e);
  567.         }
  568.       }
  569.       try {
  570.         if(row != null) {
  571.           Value rowPrimaryTypeValue = row.getValue("jcr:primaryType");
  572.           jcrPrimaryType = rowPrimaryTypeValue != null ? rowPrimaryTypeValue.getString() : "";
  573.         }
  574.         if(StringUtils.isEmpty(jcrPrimaryType) && result != null) {
  575.           jcrPrimaryType = node.getPrimaryNodeType().getName();
  576.         }
  577.       } catch (Exception e) {
  578.         if (LOG.isWarnEnabled()) {
  579.           LOG.warn("Cannot get excerpt of node " + jcrPath, e);
  580.         }
  581.       }
  582.     }

  583.     public String getJcrPath() {
  584.       return jcrPath;
  585.     }

  586.     public void setJcrPath(String jcrPath) {
  587.       this.jcrPath = jcrPath;
  588.     }

  589.     public String getRepExcerpt() {
  590.       return repExcerpt;
  591.     }

  592.     public void setRepExcerpt(String repExcerpt) {
  593.       this.repExcerpt = repExcerpt;
  594.     }

  595.     public long getJcrScore() {
  596.       return jcrScore;
  597.     }

  598.     public void setJcrScore(long jcrScore) {
  599.       this.jcrScore = jcrScore;
  600.     }

  601.     public String getJcrPrimaryType() {
  602.       return jcrPrimaryType;
  603.     }

  604.     public void setJcrPrimaryType(String value) {
  605.       jcrPrimaryType = value;
  606.     }

  607.     public int hashCode() {
  608.       return (jcrPath == null ? 0 : jcrPath.hashCode());
  609.     }

  610.     public boolean equals(Object o) {
  611.       if (o == null) return false;
  612.       if (! (o instanceof RowData)) return false;
  613.       RowData data = (RowData) o;
  614.       return (jcrPath == null && data.jcrPath == null || jcrPath.equals(data.jcrPath));
  615.     }
  616.   }
  617. }