View Javadoc
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  
19  import java.text.DateFormat;
20  import java.text.SimpleDateFormat;
21  import java.util.ArrayList;
22  import java.util.Comparator;
23  import java.util.Date;
24  import java.util.GregorianCalendar;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Locale;
28  import java.util.Set;
29  
30  import javax.jcr.*;
31  import javax.jcr.query.Query;
32  import javax.jcr.query.QueryManager;
33  import javax.jcr.query.QueryResult;
34  import javax.jcr.query.Row;
35  
36  import org.apache.commons.lang.StringUtils;
37  
38  import org.exoplatform.commons.api.search.data.SearchResult;
39  import org.exoplatform.ecm.jcr.model.Preference;
40  import org.exoplatform.ecm.webui.component.explorer.UIDocumentContainer;
41  import org.exoplatform.ecm.webui.component.explorer.UIDocumentWorkspace;
42  import org.exoplatform.ecm.webui.component.explorer.UIDrivesArea;
43  import org.exoplatform.ecm.webui.component.explorer.UIJCRExplorer;
44  import org.exoplatform.ecm.webui.component.explorer.UIWorkingArea;
45  import org.exoplatform.ecm.webui.component.explorer.sidebar.UISideBar;
46  import org.exoplatform.ecm.webui.utils.JCRExceptionManager;
47  import org.exoplatform.ecm.webui.utils.Utils;
48  import org.exoplatform.portal.webui.util.Util;
49  import org.exoplatform.portal.webui.workspace.UIPortalApplication;
50  import org.exoplatform.services.cms.BasePath;
51  import org.exoplatform.services.cms.folksonomy.NewFolksonomyService;
52  import org.exoplatform.services.cms.link.LinkManager;
53  import org.exoplatform.services.cms.link.LinkUtils;
54  import org.exoplatform.services.cms.link.NodeFinder;
55  import org.exoplatform.services.cms.taxonomy.TaxonomyService;
56  import org.exoplatform.services.cms.templates.TemplateService;
57  import org.exoplatform.services.jcr.RepositoryService;
58  import org.exoplatform.services.jcr.core.ManageableRepository;
59  import org.exoplatform.services.jcr.ext.hierarchy.NodeHierarchyCreator;
60  import org.exoplatform.services.jcr.impl.core.JCRPath;
61  import org.exoplatform.services.jcr.impl.core.SessionImpl;
62  import org.exoplatform.services.log.ExoLogger;
63  import org.exoplatform.services.log.Log;
64  import org.exoplatform.services.wcm.core.NodetypeConstant;
65  import org.exoplatform.services.wcm.search.QueryCriteria;
66  import org.exoplatform.services.wcm.search.base.AbstractPageList;
67  import org.exoplatform.services.wcm.search.base.NodeSearchFilter;
68  import org.exoplatform.services.wcm.search.base.PageListFactory;
69  import org.exoplatform.services.wcm.search.base.QueryData;
70  import org.exoplatform.services.wcm.search.base.SearchDataCreator;
71  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
72  import org.exoplatform.wcm.webui.paginator.UILazyPageIterator;
73  import org.exoplatform.web.application.ApplicationMessage;
74  import org.exoplatform.webui.application.WebuiRequestContext;
75  import org.exoplatform.webui.config.annotation.ComponentConfig;
76  import org.exoplatform.webui.config.annotation.EventConfig;
77  import org.exoplatform.webui.core.UIApplication;
78  import org.exoplatform.webui.core.UIContainer;
79  import org.exoplatform.webui.core.UIPageIterator;
80  import org.exoplatform.webui.event.Event;
81  import org.exoplatform.webui.event.EventListener;
82  
83  /**
84   * Created by The eXo Platform SARL
85   * Author : Tran The Trong
86   *          trongtt@gmail.com
87   * Oct 2, 2006
88   * 16:37:15
89   *
90   * Edited by : Dang Van Minh
91   *             minh.dang@exoplatform.com
92   * Jan 5, 2007
93   */
94  @ComponentConfig(
95      template = "app:/groovy/webui/component/explorer/search/UISearchResult.gtmpl",
96      events = {
97          @EventConfig(listeners = UISearchResult.ViewActionListener.class),
98          @EventConfig(listeners = UISearchResult.OpenFolderActionListener.class),
99          @EventConfig(listeners = UISearchResult.SortASCActionListener.class),
100         @EventConfig(listeners = UISearchResult.SortDESCActionListener.class)
101     }
102 )
103 public class UISearchResult extends UIContainer {
104 
105   /**
106    * Logger.
107    */
108   private static final Log LOG  = ExoLogger.getLogger(UISearchResult.class.getName());
109 
110   private QueryData queryData_;
111   private long searchTime_ = 0;
112   private UIPageIterator uiPageIterator_;
113   private String iconType = "";
114   private String iconScore = "";
115   static private int PAGE_SIZE = 10;
116   private List<String> categoryPathList = new ArrayList<String>();
117   private String constraintsCondition;
118   private String workspaceName = null;
119   private String currentPath = null;
120   private String keyword ="";
121   private AbstractPageList<RowData> pageList;
122 
123   public List<String> getCategoryPathList() { return categoryPathList; }
124   public void setCategoryPathList(List<String> categoryPathListItem) {
125     categoryPathList = categoryPathListItem;
126   }
127 
128   public String getConstraintsCondition() { return constraintsCondition; }
129   public void setConstraintsCondition(String constraintsConditionItem) {
130     constraintsCondition = constraintsConditionItem;
131   }
132 
133   public UISearchResult() throws Exception {
134     uiPageIterator_ = addChild(UILazyPageIterator.class, null, "UISearchResultPageIterator");
135   }
136 
137   public void setQuery(String queryStatement, String workspaceName, String language, boolean isSystemSession, String keyword) {
138     queryData_ = new QueryData(queryStatement, workspaceName, language, isSystemSession);
139     this.keyword = keyword;
140   }
141 
142   public long getSearchTime() { return searchTime_; }
143   public void setSearchTime(long time) { this.searchTime_ = time; }
144 
145   public String getIconType() {
146     return iconType;
147   }
148 
149   public String getIconScore() {
150     return iconScore;
151   }
152 
153   public void setIconScore(String iconScore) {
154     this.iconScore = iconScore;
155   }
156 
157   public void setIconType(String iconType) {
158     this.iconType = iconType;
159   }
160 
161   public List getCurrentList() throws Exception {
162     return uiPageIterator_.getCurrentPageData();
163   }
164 
165   public DateFormat getSimpleDateFormat() {
166     Locale locale = Util.getUIPortal().getAncestorOfType(UIPortalApplication.class).getLocale();
167     return SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.SHORT, locale);
168   }
169 
170   public Session getSession() throws Exception {
171     return getAncestorOfType(UIJCRExplorer.class).getTargetSession();
172   }
173 
174   public Date getDateCreated(Node node) throws Exception{
175     if (node.hasProperty("exo:dateCreated")) {
176       return node.getProperty("exo:dateCreated").getDate().getTime();
177     }
178     return new GregorianCalendar().getTime();
179   }
180 
181   public Node getNodeByPath(String path) throws Exception {
182     try {
183       JCRPath nodePath = ((SessionImpl)getSession()).getLocationFactory().parseJCRPath(path);
184       return (Node)getSession().getItem(nodePath.getAsString(false));
185     } catch (Exception e) {
186       return null;
187     }
188   }
189 
190   public UIPageIterator getUIPageIterator() { return uiPageIterator_; }
191 
192   public void updateGrid() throws Exception {
193     TemplateService templateService = WCMCoreUtils.getService(TemplateService.class);
194     List<String> documentList = templateService.getDocumentTemplates();
195     UIJCRExplorer uiExplorer = getAncestorOfType(UIJCRExplorer.class);
196     UISideBar uiSideBar = uiExplorer.findFirstComponentOfType(UISideBar.class);
197 
198     Set<String> tagPathsUsedInSearch = null;
199     if (uiSideBar != null && uiSideBar.isRendered()
200         && StringUtils.equals(uiSideBar.getSelectedComp(), UISideBar.UI_TAG_EXPLORER)) {
201       tagPathsUsedInSearch = uiExplorer.getTagPaths();
202     }
203 
204     QueryCriteria queryCriteria = new QueryCriteria();
205     queryCriteria.setKeyword(keyword);
206     queryCriteria.setSearchPath(uiExplorer.getCurrentPath());
207     queryCriteria.setSearchWebpage(false);
208 
209     WebuiRequestContext requestContext = WebuiRequestContext.getCurrentInstance();
210     pageList = PageListFactory.createPageList(queryData_.getQueryStatement(),
211                                               requestContext.getLocale(),
212                                               queryData_.getWorkSpace(),
213                                               queryData_.getLanguage_(),
214                                               queryData_.isSystemSession(),
215                                               new NodeFilter(categoryPathList, tagPathsUsedInSearch, keyword, documentList),
216                                               new RowDataCreator(),
217                                               PAGE_SIZE,
218                                               0,
219                                               queryCriteria);
220     uiPageIterator_.setPageList(pageList);
221   }
222 
223   private static class SearchComparator implements Comparator<RowData> {
224 
225     public static final String SORT_TYPE = "NODE_TYPE";
226     public static final String SORT_SCORE = "JCR_SCORE";
227     public static final String ASC = "ASC";
228     public static final String DESC = "DECS";
229 
230     private String sortType;
231     private String orderType;
232 
233     public void setSortType(String value) { sortType = value; }
234     public void setOrderType(String value) { orderType = value; }
235 
236     public int compare(RowData row1, RowData row2) {
237       try {
238         if (SORT_TYPE.equals(sortType.trim())) {
239           String s1 = row1.getJcrPrimaryType();
240           String s2 = row2.getJcrPrimaryType();
241           if (DESC.equals(orderType.trim())) { return s2.compareTo(s1); }
242           return s1.compareTo(s2);
243         } else if (SORT_SCORE.equals(sortType.trim())) {
244           Long l1 = row1.getJcrScore();
245           Long l2 = row2.getJcrScore();
246           if (DESC.equals(orderType.trim())) { return l2.compareTo(l1); }
247           return l1.compareTo(l2);
248         }
249       } catch (Exception e) {
250         if (LOG.isErrorEnabled()) {
251           LOG.error("Cannot compare rows", e);
252         }
253       }
254       return 0;
255     }
256   }
257 
258   public String StriptHTML(String s) {
259     String[] targets = {"<div>", "</div>", "<span>", "</span>"};
260     for (String target : targets) {
261       s = s.replace(target, "");
262     }
263     return s;
264   }
265 
266   static  public class ViewActionListener extends EventListener<UISearchResult> {
267     public void execute(Event<UISearchResult> event) throws Exception {
268       UISearchResult uiSearchResult = event.getSource();
269       UIJCRExplorer uiExplorer = uiSearchResult.getAncestorOfType(UIJCRExplorer.class);
270       String path = event.getRequestContext().getRequestParameter(OBJECTID);
271       UIApplication uiApp = uiSearchResult.getAncestorOfType(UIApplication.class);
272       String workspaceName = event.getRequestContext().getRequestParameter("workspaceName");
273       Item item = null;
274       try {
275         Session session = uiExplorer.getSessionByWorkspace(workspaceName);
276         // Check if the path exists
277         NodeFinder nodeFinder = uiSearchResult.getApplicationComponent(NodeFinder.class);
278         item = nodeFinder.getItem(session, path);
279       } catch(PathNotFoundException pa) {
280         uiApp.addMessage(new ApplicationMessage("UITreeExplorer.msg.path-not-found", null,
281             ApplicationMessage.WARNING)) ;
282 
283         return ;
284       } catch(ItemNotFoundException inf) {
285           uiApp.addMessage(new ApplicationMessage("UITreeExplorer.msg.path-not-found", null,
286               ApplicationMessage.WARNING)) ;
287 
288           return ;
289       } catch(AccessDeniedException ace) {
290           uiApp.addMessage(new ApplicationMessage("UIDocumentInfo.msg.access-denied", null,
291                   ApplicationMessage.WARNING)) ;
292 
293         return ;
294       } catch(RepositoryException e) {
295         if (LOG.isErrorEnabled()) {
296           LOG.error("Repository cannot be found");
297         }
298         uiApp.addMessage(new ApplicationMessage("UITreeExplorer.msg.repository-error", null,
299             ApplicationMessage.WARNING)) ;
300 
301         return ;
302       } catch (Exception e) {
303         JCRExceptionManager.process(uiApp, e);
304         return;
305       }
306       if (isInTrash(item))
307         return;
308 
309       UIWorkingArea uiWorkingArea = uiExplorer.getChild(UIWorkingArea.class);
310       UIDocumentWorkspace uiDocumentWorkspace = uiWorkingArea.getChild(UIDocumentWorkspace.class);
311       if(!uiDocumentWorkspace.isRendered()) {
312         uiWorkingArea.getChild(UIDrivesArea.class).setRendered(false);
313         uiWorkingArea.getChild(UIDocumentWorkspace.class).setRendered(true);
314       }
315 
316       uiExplorer.setSelectNode(workspaceName, path) ;
317 
318       uiDocumentWorkspace.getChild(UIDocumentContainer.class).setRendered(true);
319       uiSearchResult.setRendered(false);
320       uiExplorer.refreshExplorer((Node)item, true);
321     }
322 
323     private boolean isInTrash(Item item) throws RepositoryException {
324       return (item instanceof Node) && Utils.isInTrash((Node) item);
325     }
326   }
327 
328   static public class OpenFolderActionListener extends EventListener<UISearchResult> {
329     public void execute(Event<UISearchResult> event) throws Exception {
330       UISearchResult uiSearchResult = event.getSource();
331       UIJCRExplorer uiExplorer = uiSearchResult.getAncestorOfType(UIJCRExplorer.class);
332       String path = event.getRequestContext().getRequestParameter(OBJECTID);
333       String folderPath = LinkUtils.getParentPath(path);
334       Node node = null;
335       try {
336         node = uiExplorer.getNodeByPath(folderPath, uiExplorer.getTargetSession());
337       } catch(AccessDeniedException ace) {
338         UIApplication uiApp = uiSearchResult.getAncestorOfType(UIApplication.class);
339         uiApp.addMessage(new ApplicationMessage("UISearchResult.msg.access-denied", null,
340             ApplicationMessage.WARNING));
341 
342         return;
343       } catch(PathNotFoundException ace) {
344         UIApplication uiApp = uiSearchResult.getAncestorOfType(UIApplication.class);
345         uiApp.addMessage(new ApplicationMessage("UISearchResult.msg.access-denied", null,
346             ApplicationMessage.WARNING));
347 
348         return;
349       } catch(Exception e) {
350         if (LOG.isErrorEnabled()) {
351           LOG.error("Cannot access the node at " + folderPath, e);
352         }
353       }
354 
355       uiExplorer.setSelectNode(node.getSession().getWorkspace().getName(), folderPath);
356       uiExplorer.refreshExplorer(node, true);
357     }
358   }
359 
360   static public class SortASCActionListener extends EventListener<UISearchResult> {
361     public void execute(Event<UISearchResult> event) throws Exception {
362       UISearchResult uiSearchResult = event.getSource();
363       String objectId = event.getRequestContext().getRequestParameter(OBJECTID);
364       SearchComparator comparator = new SearchComparator();
365       if (objectId.equals("type")) {
366         uiSearchResult.pageList.setSortByField(Utils.JCR_PRIMARYTYPE);
367         comparator.setSortType(SearchComparator.SORT_TYPE);
368         uiSearchResult.setIconType(Preference.BLUE_DOWN_ARROW);
369         uiSearchResult.setIconScore("");
370       } else if (objectId.equals("score")) {
371         uiSearchResult.pageList.setSortByField(Utils.JCR_SCORE);
372         comparator.setSortType(SearchComparator.SORT_SCORE);
373         uiSearchResult.setIconScore(Preference.BLUE_DOWN_ARROW);
374         uiSearchResult.setIconType("");
375       }
376       comparator.setOrderType(SearchComparator.ASC);
377       uiSearchResult.pageList.setComparator(comparator);
378       uiSearchResult.pageList.setOrder("ASC");
379       uiSearchResult.pageList.sortData();
380       event.getRequestContext().addUIComponentToUpdateByAjax(uiSearchResult.getParent());
381     }
382   }
383 
384   static public class SortDESCActionListener extends EventListener<UISearchResult> {
385     public void execute(Event<UISearchResult> event) throws Exception {
386       UISearchResult uiSearchResult = event.getSource() ;
387       String objectId = event.getRequestContext().getRequestParameter(OBJECTID);
388       SearchComparator comparator = new SearchComparator();
389       if (objectId.equals("type")) {
390         uiSearchResult.pageList.setSortByField(Utils.JCR_PRIMARYTYPE);
391         comparator.setSortType(SearchComparator.SORT_TYPE);
392         uiSearchResult.setIconType(Preference.BLUE_UP_ARROW);
393         uiSearchResult.setIconScore("");
394       } else if (objectId.equals("score")) {
395         uiSearchResult.pageList.setSortByField(Utils.JCR_SCORE);
396         comparator.setSortType(SearchComparator.SORT_SCORE);
397         uiSearchResult.setIconScore(Preference.BLUE_UP_ARROW);
398         uiSearchResult.setIconType("");
399       }
400       comparator.setOrderType(SearchComparator.DESC);
401       uiSearchResult.pageList.setComparator(comparator);
402       uiSearchResult.pageList.setOrder("DESC");
403       uiSearchResult.pageList.sortData();
404       event.getRequestContext().addUIComponentToUpdateByAjax(uiSearchResult.getParent());
405     }
406   }
407 
408   public static class NodeFilter implements NodeSearchFilter {
409 
410     private List<String> categoryPathList;
411     private Set<String> tagPaths;
412     private TaxonomyService taxonomyService;
413     private NodeHierarchyCreator nodeHierarchyCreator;
414     private RepositoryService repositoryService;
415     private NewFolksonomyService folksonomyService;
416     private String rootTreePath;
417     private LinkManager linkManager = null;
418     private String keyword ="";
419     private List<String> documentTypes;
420 
421     final static private String  CHECK_LINK_MATCH_QUERY1 = "select * from nt:base "
422                                                              + "where jcr:path = '$0' and ( contains(*, '$1') "
423                                                              + "or lower(exo:name) like '%$2%' "
424                                                              + "or lower(exo:title) like '%$2%')";
425 
426     final static private String  CHECK_LINK_MATCH_QUERY2 = "select * from nt:base where jcr:path like '$0/%' "
427                                                              + "and ( contains(*, '$1') or lower(exo:name) like '%$2%' "
428                                                              + "or lower(exo:title) like '%$2%')";
429     public NodeFilter(List<String> categories, Set<String> tagPaths, String keyword, List<String> documentTypes) {
430       taxonomyService = WCMCoreUtils.getService(TaxonomyService.class);
431       nodeHierarchyCreator = WCMCoreUtils.getService(NodeHierarchyCreator.class);
432       linkManager = WCMCoreUtils.getService(LinkManager.class);
433       repositoryService = WCMCoreUtils.getService(RepositoryService.class);
434       folksonomyService = WCMCoreUtils.getService(NewFolksonomyService.class);
435       rootTreePath = nodeHierarchyCreator.getJcrPath(BasePath.TAXONOMIES_TREE_STORAGE_PATH);
436       categoryPathList = categories;
437       this.tagPaths = tagPaths;
438       this.keyword = keyword;
439       this.documentTypes = documentTypes;
440     }
441 
442     public NodeFilter(List<String> categories, String keyword, List<String> documentTypes) {
443       taxonomyService = WCMCoreUtils.getService(TaxonomyService.class);
444       nodeHierarchyCreator = WCMCoreUtils.getService(NodeHierarchyCreator.class);
445       linkManager = WCMCoreUtils.getService(LinkManager.class);
446       rootTreePath = nodeHierarchyCreator.getJcrPath(BasePath.TAXONOMIES_TREE_STORAGE_PATH);
447       categoryPathList = categories;
448       this.keyword = keyword;
449       this.documentTypes = documentTypes;
450     }
451     public Node filterNodeToDisplay(Node node) {
452       try {
453         if (node == null || node.getPath().contains("/jcr:system/")) return null;
454         if (node != null) {
455           if ((tagPaths != null) && (tagPaths.size() > 0)) {
456             ManageableRepository repository = repositoryService.getCurrentRepository();
457             String workspaceName = repository.getConfiguration().getDefaultWorkspaceName();
458             if (node.isNodeType(Utils.EXO_SYMLINK)
459                 || ((Node) node.getAncestor(1)).isNodeType(NodetypeConstant.EXO_TRASH_FOLDER)) {
460               return null;
461             } else {
462               for (String tagPath : tagPaths) {
463                 List<Node> taggedDocuments = folksonomyService.getAllDocumentsByTag(tagPath,
464                                                                                     workspaceName,
465                                                                                     WCMCoreUtils.getUserSessionProvider());
466                 boolean nodeExistsInTag = false;
467                 Iterator<Node> nodesIterator = taggedDocuments.iterator();
468                 while (nodesIterator.hasNext() && !nodeExistsInTag) {
469                   Node taggedNode = nodesIterator.next();
470                   nodeExistsInTag = taggedNode.isSame(node);
471                 }
472                 if (!nodeExistsInTag) {
473                   return null;
474                 }
475               }
476             }
477           }
478           if ((categoryPathList != null) && (categoryPathList.size() > 0)){
479             for (String categoryPath : categoryPathList) {
480               int index = categoryPath.indexOf("/");
481               String taxonomyName = categoryPath;
482               String postFixTaxonomy = "";
483               if (index > 0) {
484                 taxonomyName = categoryPath.substring(0, index);
485                 postFixTaxonomy = categoryPath.substring(index + 1);
486               }
487 
488               List<String> pathCategoriesList = new ArrayList<String>();
489               String searchCategory = taxonomyService.getTaxonomyTree(taxonomyName).getPath() +
490                                       ("".equals(postFixTaxonomy) ? "" : "/" + postFixTaxonomy);
491               Node targetNode = node.isNodeType(Utils.EXO_SYMLINK) ?
492                                         linkManager.getTarget(node) : node;
493               List<Node> listCategories = taxonomyService.getCategories(targetNode, taxonomyName);
494               for (Node category : listCategories) {
495                 pathCategoriesList.add(category.getPath());
496               }
497               if (pathCategoriesList.contains(searchCategory))
498               {
499                 if (node.isNodeType(Utils.EXO_SYMLINK)) {
500                   if (checkTargetMatch(node, keyword)) return node;
501                 }else {
502                   return node;
503                 }
504               }
505             }
506             return null;
507           } else {
508             if (node.isNodeType(Utils.EXO_SYMLINK)) {
509               if (checkTargetMatch(node, keyword)) return node;
510             } else if (node.isNodeType(Utils.NT_RESOURCE)) {
511               return node.getParent();
512             } else if (node.isNodeType(Utils.EXO_COMMENTS)) {
513               return node.getParent().getParent();
514             } else {
515               return node;
516             }
517           }
518         }
519       } catch (Exception e) {
520           LOG.warn(e.getMessage());
521       }
522       return null;
523     }
524 
525     /**
526      * Check a symlink/taxonomylink if its target matches with keyword for searching ...link
527      * @param symlinkNode
528      * @param keyword
529      * @return
530      */
531     protected boolean checkTargetMatch(Node symlinkNode, String keyword) {
532       String queryStatement = CHECK_LINK_MATCH_QUERY1;
533       Session targetSession;
534       Node target=null;
535       if (keyword ==null || keyword.length()==0 ) return true;
536       if (linkManager==null) {
537         linkManager = WCMCoreUtils.getService(LinkManager.class);
538       }
539       try {
540         if (!linkManager.isLink(symlinkNode)) return true;
541         target = linkManager.getTarget(symlinkNode);
542         if (target == null) return false;
543         targetSession = target.getSession();
544         queryStatement = StringUtils.replace(queryStatement,"$0", target.getPath());
545         queryStatement = StringUtils.replace(queryStatement,"$1", keyword.replaceAll("'", "''"));
546         queryStatement = StringUtils.replace(queryStatement,"$2", keyword.replaceAll("'", "''").toLowerCase());
547         QueryManager queryManager = targetSession.getWorkspace().getQueryManager();
548         Query query = queryManager.createQuery(queryStatement, Query.SQL);
549         QueryResult queryResult = query.execute();
550         if ( queryResult.getNodes().getSize()>0 ) return true;
551         if (isFodlderDocument(target)||target.hasNode("jcr:content") ) {
552           queryStatement = CHECK_LINK_MATCH_QUERY2;
553           queryStatement = StringUtils.replace(queryStatement,"$0", target.getPath());
554           queryStatement = StringUtils.replace(queryStatement,"$1", keyword.replaceAll("'", "''"));
555           queryStatement = StringUtils.replace(queryStatement,"$2", keyword.replaceAll("'", "''").toLowerCase());
556           query = queryManager.createQuery(queryStatement, Query.SQL);
557           queryResult = query.execute();
558           return queryResult.getNodes().getSize()>0;
559         }else {
560           return false;
561         }
562       } catch (RepositoryException e) {
563         return false;
564       }
565     }
566     private boolean isFodlderDocument(Node node) throws RepositoryException{
567       if (!node.isNodeType(NodetypeConstant.NT_UNSTRUCTURED)) return false;
568       for (String documentType : documentTypes) {
569         if (node.getPrimaryNodeType().isNodeType(documentType))
570           return true;
571       }
572       return false;
573     }
574   }
575 
576   public static class RowDataCreator implements SearchDataCreator<RowData> {
577 
578     public RowData createData(Node node, Row row, SearchResult searchResult) {
579       return new RowData(row, node, searchResult);
580     }
581 
582   }
583 
584   public static class RowData {
585     private String jcrPath = "";
586     private String repExcerpt = "";
587     private long jcrScore = 0;
588     private String jcrPrimaryType = "";
589 
590     public RowData(Row row) {
591       this(row, null, null);
592     }
593     
594     public RowData(Row row, Node node, SearchResult result) {
595       try {
596         jcrPath = node != null ? node.getPath() : row.getValue("jcr:path").getString();
597       } catch (Exception e) {
598         if (LOG.isWarnEnabled()) {
599           LOG.warn(e.getMessage());
600         }
601       }
602       try {
603         if(row != null) {
604           Value rowExcerptValue = row.getValue("rep:excerpt(.)");
605           repExcerpt = rowExcerptValue != null ? rowExcerptValue.getString() : "";
606         }
607         if(StringUtils.isEmpty(repExcerpt) && result != null) {
608           repExcerpt = result.getExcerpt();
609         }
610       } catch (Exception e) {
611         if (LOG.isWarnEnabled()) {
612           LOG.warn("Cannot get excerpt of node " + jcrPath, e);
613         }
614       }
615       try {
616         if(row != null) {
617           Value rowScoreValue = row.getValue("jcr:score");
618           jcrScore = rowScoreValue != null ? rowScoreValue.getLong() : 0;
619         }
620         if(jcrScore == 0 && result != null) {
621           jcrScore = result.getRelevancy();
622         }
623       } catch (Exception e) {
624         if (LOG.isWarnEnabled()) {
625           LOG.warn("Cannot get excerpt of node " + jcrPath, e);
626         }
627       }
628       try {
629         if(row != null) {
630           Value rowPrimaryTypeValue = row.getValue("jcr:primaryType");
631           jcrPrimaryType = rowPrimaryTypeValue != null ? rowPrimaryTypeValue.getString() : "";
632         }
633         if(StringUtils.isEmpty(jcrPrimaryType) && result != null) {
634           jcrPrimaryType = node.getPrimaryNodeType().getName();
635         }
636       } catch (Exception e) {
637         if (LOG.isWarnEnabled()) {
638           LOG.warn("Cannot get excerpt of node " + jcrPath, e);
639         }
640       }
641     }
642 
643     public String getJcrPath() {
644       return jcrPath;
645     }
646 
647     public void setJcrPath(String jcrPath) {
648       this.jcrPath = jcrPath;
649     }
650 
651     public String getRepExcerpt() {
652       return repExcerpt;
653     }
654 
655     public void setRepExcerpt(String repExcerpt) {
656       this.repExcerpt = repExcerpt;
657     }
658 
659     public long getJcrScore() {
660       return jcrScore;
661     }
662 
663     public void setJcrScore(long jcrScore) {
664       this.jcrScore = jcrScore;
665     }
666 
667     public String getJcrPrimaryType() {
668       return jcrPrimaryType;
669     }
670 
671     public void setJcrPrimaryType(String value) {
672       jcrPrimaryType = value;
673     }
674 
675     public int hashCode() {
676       return (jcrPath == null ? 0 : jcrPath.hashCode());
677     }
678 
679     public boolean equals(Object o) {
680       if (o == null) return false;
681       if (! (o instanceof RowData)) return false;
682       RowData data = (RowData) o;
683       return (jcrPath == null && data.jcrPath == null || jcrPath.equals(data.jcrPath));
684     }
685   }
686 }