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.util.ArrayList;
20  import java.util.Calendar;
21  import java.util.List;
22  import java.util.MissingResourceException;
23  import java.util.ResourceBundle;
24  
25  import javax.jcr.Node;
26  import javax.jcr.RepositoryException;
27  import javax.jcr.query.Query;
28  import javax.jcr.query.QueryManager;
29  import javax.jcr.query.QueryResult;
30  
31  import org.apache.commons.lang.StringUtils;
32  import org.exoplatform.commons.utils.XPathUtils;
33  import org.exoplatform.ecm.jcr.model.Preference;
34  import org.exoplatform.ecm.webui.component.explorer.UIJCRExplorer;
35  import org.exoplatform.ecm.webui.form.UIFormInputSetWithAction;
36  import org.exoplatform.services.log.ExoLogger;
37  import org.exoplatform.services.log.Log;
38  import org.exoplatform.services.security.IdentityConstants;
39  import org.exoplatform.web.application.ApplicationMessage;
40  import org.exoplatform.web.application.RequestContext;
41  import org.exoplatform.webui.config.annotation.ComponentConfig;
42  import org.exoplatform.webui.config.annotation.EventConfig;
43  import org.exoplatform.webui.core.UIApplication;
44  import org.exoplatform.webui.core.UIPopupContainer;
45  import org.exoplatform.webui.core.UIPopupWindow;
46  import org.exoplatform.webui.core.lifecycle.UIFormLifecycle;
47  import org.exoplatform.webui.core.model.SelectItemOption;
48  import org.exoplatform.webui.event.Event;
49  import org.exoplatform.webui.event.Event.Phase;
50  import org.exoplatform.webui.event.EventListener;
51  import org.exoplatform.webui.form.UIForm;
52  import org.exoplatform.webui.form.UIFormInputInfo;
53  import org.exoplatform.webui.form.UIFormSelectBox;
54  import org.exoplatform.webui.form.UIFormStringInput;
55  import org.exoplatform.services.cms.impl.Utils;
56  /**
57   * Created by The eXo Platform SARL
58   * Author : Dang Van Minh
59   *          minh.dang@exoplatform.com
60   * Dec 26, 2006
61   * 4:29:08 PM
62   */
63  @ComponentConfig(
64      lifecycle = UIFormLifecycle.class,
65      template =  "app:/groovy/webui/component/explorer/search/UISimpleSearch.gtmpl",
66      events = {
67        @EventConfig(listeners = UISimpleSearch.CancelActionListener.class, phase=Phase.DECODE),
68        @EventConfig(listeners = UISimpleSearch.SearchActionListener.class),
69        @EventConfig(listeners = UISimpleSearch.SaveActionListener.class),
70        @EventConfig(listeners = UISimpleSearch.MoreConstraintsActionListener.class, phase=Phase.DECODE),
71        @EventConfig(listeners = UISimpleSearch.RemoveConstraintActionListener.class, phase=Phase.DECODE),
72        @EventConfig(listeners = UISimpleSearch.AddActionListener.class),
73        @EventConfig(listeners = UISimpleSearch.CompareExactlyActionListener.class),
74        @EventConfig(listeners = UISimpleSearch.AddMetadataTypeActionListener.class),
75        @EventConfig(listeners = UISimpleSearch.AddNodeTypeActionListener.class),
76        @EventConfig(listeners = UISimpleSearch.AddCategoryActionListener.class)
77      }
78  )
79  public class UISimpleSearch extends UIForm {
80  
81    public static final String CONSTRAINTS_FORM = "ConstraintsForm";
82    public static final String INPUT_SEARCH = "input";
83    public static final String CONSTRAINTS = "constraints";
84    public static final String NODE_PATH = "nodePath";
85    public static final String FIRST_OPERATOR = "firstOperator";
86    public static final String OR = "or";
87    public static final String AND = "and";
88  
89    private static final Log LOG  = ExoLogger.getLogger(UISimpleSearch.class.getName());
90    private List<String> constraints_ = new ArrayList<String>();
91    private List<String> virtualConstraints_ = new ArrayList<String>();
92    private List<String> categoryPathList = new ArrayList<String>();
93  
94    public List<String> getCategoryPathList() { return categoryPathList; }
95    public void setCategoryPathList(List<String> categoryPathListItem) {
96      categoryPathList = categoryPathListItem;
97    }
98  
99    private static final String ROOT_XPATH_QUERY = "//*";
100 
101   private static final String XPATH_QUERY      = "/jcr:root$0//*";
102 
103   private static final String ROOT_SQL_QUERY   = "SELECT * FROM nt:base WHERE jcr:path LIKE '/%' ";
104   
105   private static final String NT_RESOURCE_EXCLUDE = "AND ( not jcr:primaryType like 'nt:resource') ";
106 
107   private static final String LINK_REQUIREMENT = "AND ( (jcr:primaryType like 'exo:symlink' or " +
108                                                         "jcr:primaryType like 'exo:taxonomyLink') ";
109 
110   private static final String SQL_QUERY        = "SELECT * FROM nt:base WHERE jcr:path LIKE '$0/%' ";
111 
112   private String              _OR  = "Or";
113 
114   private String              _AND = "And";
115 
116   public UISimpleSearch() throws Exception {
117     addUIFormInput(new UIFormInputInfo(NODE_PATH, NODE_PATH, null));
118     addUIFormInput(new UIFormStringInput(INPUT_SEARCH, INPUT_SEARCH, null));
119     List<SelectItemOption<String>> operators = new ArrayList<SelectItemOption<String>>();
120     RequestContext context = RequestContext.getCurrentInstance();
121     try {
122     ResourceBundle res = context.getApplicationResourceBundle();
123       _AND = res.getString("UIConstraintForm.label.and");
124       _OR = res.getString("UIConstraintForm.label.or");
125     }catch (MissingResourceException e) {
126       // There is no resource found, just use the default resource-bundle in English as first value of _OR & _AND
127       if (LOG.isWarnEnabled()) {
128         LOG.warn("Can not get resource bundle for UISimpleSearch label: " + e.getMessage());
129       }
130     }
131     operators.add(new SelectItemOption<String>(_AND, AND));
132     operators.add(new SelectItemOption<String>(_OR, OR));
133     addUIFormInput(new UIFormSelectBox(FIRST_OPERATOR, FIRST_OPERATOR, operators));
134     UIFormInputSetWithAction uiInputAct = new UIFormInputSetWithAction("moreConstraints");
135     uiInputAct.addUIFormInput(new UIFormInputInfo(CONSTRAINTS, CONSTRAINTS, null));
136     addUIComponentInput(uiInputAct);
137     UIConstraintsForm uiConstraintsForm = new UIConstraintsForm(CONSTRAINTS_FORM);
138     uiConstraintsForm.setRendered(false);
139     addChild(uiConstraintsForm);
140 
141     setActions(new String[] {"MoreConstraints", "Search", "Save", "Cancel"});
142   }
143 
144   public List<String> getConstraints() { return constraints_; }
145 
146   public void updateAdvanceConstraint(String constraint, String operator, String virtualDateQuery) {
147     if (constraint.length() > 0) {
148       if (constraints_.size() == 0) {
149         constraints_.add("(" + constraint + " )");
150         if (virtualDateQuery != null)
151           virtualConstraints_.add("(" + virtualDateQuery + " )");
152         else
153           virtualConstraints_.add("(" + constraint + " )");
154       } else {
155         constraints_.add(" " + operator.toLowerCase() + " (" + constraint + " ) ");
156         if (virtualDateQuery != null)
157           virtualConstraints_.add(" " + operator.toLowerCase() + " (" + virtualDateQuery + " ) ");
158         else
159           virtualConstraints_.add(" " + operator.toLowerCase() + " (" + constraint + " ) ");
160       }
161     }
162     UIFormInputSetWithAction inputInfor = getChildById("moreConstraints");
163     inputInfor.setIsDeleteOnly(true);
164     inputInfor.setListInfoField(CONSTRAINTS, virtualConstraints_);
165     String[] actionInfor = {"RemoveConstraint"};
166     inputInfor.setActionInfo(CONSTRAINTS, actionInfor);
167   }
168 
169   private String getQueryStatement() throws Exception {
170     Node currentNode = getAncestorOfType(UIJCRExplorer.class).getCurrentNode();
171     StringBuilder statement = new StringBuilder(1024);
172     String text = getUIStringInput(INPUT_SEARCH).getValue();
173     String escapedText = text == null ? null : Utils.escapeIllegalCharacterInQuery(text);
174     if(text != null && constraints_.size() == 0) {
175       if ("/".equals(currentNode.getPath())) {
176         statement.append(ROOT_XPATH_QUERY);
177       } else {
178         statement.append(StringUtils.replace(XPATH_QUERY, "$0", currentNode.getPath()));
179       }
180       statement.append("[(jcr:contains(.,'").append(escapedText).append("'))]");
181     } else if(constraints_.size() > 0) {
182       if(text == null) {
183         if ("/".equals(currentNode.getPath())) {
184           statement.append(ROOT_XPATH_QUERY).append("[(");
185         } else {
186           statement.append(StringUtils.replace(XPATH_QUERY, "$0", currentNode.getPath())).append("[(");
187         }
188       } else {
189         String operator = getUIFormSelectBox(FIRST_OPERATOR).getValue();
190         if ("/".equals(currentNode.getPath())) {
191           statement.append(ROOT_XPATH_QUERY);
192         } else {
193           statement.append(StringUtils.replace(XPATH_QUERY, "$0", currentNode.getPath()));
194         }
195         statement.append("[(jcr:contains(.,'")
196                  .append(escapedText.replaceAll("'", "''"))
197                  .append("')) ")
198                  .append(operator)
199                  .append(" (");
200       }
201       for(String constraint : constraints_) {
202         if (!constraint.contains("exo:category"))
203           statement.append(constraint);
204       }
205       statement.append(")]");
206     }
207     return statement.toString();
208   }
209 
210   private String getSQLStatement() throws Exception {
211     Node currentNode = getAncestorOfType(UIJCRExplorer.class).getCurrentNode();
212     StringBuilder statement = new StringBuilder(1024);
213     String text = getUIStringInput(INPUT_SEARCH).getValue();
214     String escapedText = text == null ? null : Utils.escapeIllegalCharacterInQuery(text);
215     if(text != null && constraints_.size() == 0) {//no constraint
216       if ("/".equals(currentNode.getPath())) {
217         statement.append(ROOT_SQL_QUERY);
218       } else {
219         statement.append(StringUtils.replace(SQL_QUERY, "$0", currentNode.getPath()));
220       }
221       statement.append(NT_RESOURCE_EXCLUDE);
222       statement.append(LINK_REQUIREMENT).append(" OR ( CONTAINS(*,'").
223                 append(escapedText).append("') ) )");
224     } else if(constraints_.size() > 0) {//constraint != null
225       //get constraint statement
226       StringBuilder tmpStatement = new StringBuilder();
227       String operator = getUIFormSelectBox(FIRST_OPERATOR).getValue();
228       for(String constraint : constraints_) {
229         if (!constraint.contains("exo:category")) {
230           tmpStatement.append(constraint);
231         }
232       }
233       String str = tmpStatement.toString().trim();
234       if (str.toLowerCase().startsWith("or")) str = str.substring("or".length());
235       if (str.toLowerCase().startsWith("and")) str = str.substring("and".length());
236       String constraintsStatement = str.length() == 0 ? str : operator + " ( " + str + " ) ";
237       //get statement
238       if(text == null) {
239         if ("/".equals(currentNode.getPath())) {
240           statement.append(ROOT_SQL_QUERY);
241         } else {
242           statement.append(StringUtils.replace(SQL_QUERY, "$0", currentNode.getPath()));
243         }
244         statement.append(NT_RESOURCE_EXCLUDE);
245         if (constraintsStatement.length() > 0)
246           statement.append(constraintsStatement);
247       } else {
248         if ("/".equals(currentNode.getPath())) {
249           statement.append(ROOT_SQL_QUERY);
250         } else {
251           statement.append(StringUtils.replace(SQL_QUERY, "$0", currentNode.getPath()));
252         }
253         statement.append(NT_RESOURCE_EXCLUDE);
254         statement.append(LINK_REQUIREMENT).append("OR ( CONTAINS(*,'").
255                   append(escapedText.replaceAll("'", "''")).append("') ");
256         if (constraintsStatement.length() > 0)
257           statement.append(constraintsStatement);
258         statement.append(" ) )");
259       }
260     }
261     return statement.toString();
262   }
263 
264   static  public class SaveActionListener extends EventListener<UISimpleSearch> {
265     public void execute(Event<UISimpleSearch> event) throws Exception {
266       UISimpleSearch uiSimpleSearch = event.getSource();
267       UIApplication uiApp = uiSimpleSearch.getAncestorOfType(UIApplication.class);
268       String text = uiSimpleSearch.getUIStringInput(INPUT_SEARCH).getValue();
269       if((text == null) && uiSimpleSearch.constraints_.size() == 0) {
270         uiApp.addMessage(new ApplicationMessage("UISimpleSearch.msg.value-save-null", null, ApplicationMessage.WARNING));
271         event.getRequestContext().addUIComponentToUpdateByAjax(uiSimpleSearch);
272         return;
273       }
274       UISearchContainer uiSearchContainer = uiSimpleSearch.getParent();
275       uiSearchContainer.initSaveQueryPopup(uiSimpleSearch.getQueryStatement(), true, Query.XPATH);
276       event.getRequestContext().addUIComponentToUpdateByAjax(uiSearchContainer);
277     }
278   }
279 
280   static  public class CancelActionListener extends EventListener<UISimpleSearch> {
281     public void execute(Event<UISimpleSearch> event) throws Exception {
282       event.getSource().getAncestorOfType(UIJCRExplorer.class).cancelAction();
283     }
284   }
285 
286   static  public class RemoveConstraintActionListener extends EventListener<UISimpleSearch> {
287     public void execute(Event<UISimpleSearch> event) throws Exception {
288       UISimpleSearch uiSimpleSearch = event.getSource();
289       int intIndex = Integer.parseInt(event.getRequestContext().getRequestParameter(OBJECTID));
290       uiSimpleSearch.constraints_.remove(intIndex);
291       uiSimpleSearch.virtualConstraints_.remove(intIndex);
292       if (uiSimpleSearch.categoryPathList.size() > intIndex) uiSimpleSearch.categoryPathList.remove(intIndex);
293       if(uiSimpleSearch.constraints_.size() > 0 && intIndex == 0) {
294         String newFirstConstraint = null;
295         String newFirstVirtualConstraint = null;
296         if(uiSimpleSearch.constraints_.get(0).trim().startsWith(OR)) {
297           newFirstConstraint = uiSimpleSearch.constraints_.get(0).substring(3, uiSimpleSearch.constraints_.get(0).length());
298           newFirstVirtualConstraint = uiSimpleSearch.virtualConstraints_.get(0)
299                                                                         .substring(3,
300                                                                                    uiSimpleSearch.virtualConstraints_.get(0)
301                                                                                                                      .length());
302           uiSimpleSearch.constraints_.set(0, newFirstConstraint);
303           uiSimpleSearch.virtualConstraints_.set(0, newFirstVirtualConstraint);
304         } else if(uiSimpleSearch.constraints_.get(0).trim().startsWith(AND)) {
305           newFirstConstraint = uiSimpleSearch.constraints_.get(0).substring(4, uiSimpleSearch.constraints_.get(0).length());
306           newFirstVirtualConstraint = uiSimpleSearch.virtualConstraints_.get(0)
307                                                                         .substring(4,
308                                                                                    uiSimpleSearch.virtualConstraints_.get(0)
309                                                                                                                      .length());
310           uiSimpleSearch.constraints_.set(0, newFirstConstraint);
311           uiSimpleSearch.virtualConstraints_.set(0, newFirstVirtualConstraint);
312         }
313       }
314       event.getRequestContext().addUIComponentToUpdateByAjax(uiSimpleSearch.getParent());
315     }
316   }
317 
318   static public class SearchActionListener extends EventListener<UISimpleSearch> {
319     public void execute(Event<UISimpleSearch> event) throws Exception {
320       UISimpleSearch uiSimpleSearch = event.getSource();
321       String text = uiSimpleSearch.getUIStringInput(INPUT_SEARCH).getValue();
322       UIJCRExplorer uiExplorer = uiSimpleSearch.getAncestorOfType(UIJCRExplorer.class);
323       Node currentNode = uiExplorer.getCurrentNode();
324       UIECMSearch uiECMSearch = uiSimpleSearch.getAncestorOfType(UIECMSearch.class);
325       UISearchResult uiSearchResult = uiECMSearch.getChild(UISearchResult.class);
326       UIApplication uiApp = uiSimpleSearch.getAncestorOfType(UIApplication.class);
327       if(text == null && uiSimpleSearch.constraints_.size() == 0) {
328         uiApp.addMessage(new ApplicationMessage("UISimpleSearch.msg.value-null", null, ApplicationMessage.WARNING));
329         event.getRequestContext().addUIComponentToUpdateByAjax(uiSimpleSearch);
330         return;
331       }
332       uiSearchResult.setCategoryPathList(uiSimpleSearch.getCategoryPathList());
333 
334       Preference pref = uiExplorer.getPreference();
335       String queryType = pref.getQueryType();
336       String statement;
337       //List<String> searchCategoryPathList = uiSimpleSearch.getCategoryPathList();
338       if (queryType.equals(Preference.XPATH_QUERY)) {
339         statement = uiSimpleSearch.getQueryStatement() + " order by @exo:dateCreated descending";
340       } else {
341         statement = uiSimpleSearch.getSQLStatement() + " order by exo:dateCreated DESC";
342       }
343       long startTime = System.currentTimeMillis();
344       try {
345         uiSearchResult.setQuery(statement, currentNode.getSession().getWorkspace().getName(),
346                                 queryType.equals(Preference.XPATH_QUERY) ? Query.XPATH : Query.SQL,
347                                 IdentityConstants.SYSTEM.equals(currentNode.getSession().getUserID()), text);
348         uiSearchResult.updateGrid();
349       } catch (RepositoryException reEx) {
350         uiApp.addMessage(new ApplicationMessage("UISimpleSearch.msg.inputSearch-invalid", null, ApplicationMessage.WARNING));
351         event.getRequestContext().addUIComponentToUpdateByAjax(uiSimpleSearch);
352         return;
353       } catch(Exception e) {
354         if (LOG.isErrorEnabled()) {
355           LOG.error("Unexpected error", e);
356         }
357         uiApp.addMessage(new ApplicationMessage("UISimpleSearch.msg.query-invalid", null,
358                                                 ApplicationMessage.WARNING));
359         event.getRequestContext().addUIComponentToUpdateByAjax(uiSimpleSearch);
360         return;
361       }
362       long time = System.currentTimeMillis() - startTime;
363       uiSearchResult.setSearchTime(time);
364       uiECMSearch.setSelectedTab(uiSearchResult.getId());
365       uiSimpleSearch.getUIFormInputInfo(UISimpleSearch.NODE_PATH).setValue(currentNode.getPath());
366       event.getRequestContext().addUIComponentToUpdateByAjax(uiECMSearch);
367     }
368   }
369 
370   static  public class MoreConstraintsActionListener extends EventListener<UISimpleSearch> {
371     public void execute(Event<UISimpleSearch> event) throws Exception {
372       UISimpleSearch uiSimpleSearch = event.getSource();
373       UIConstraintsForm uiConstraintsForm = uiSimpleSearch.getChild(UIConstraintsForm.class);
374       if(uiConstraintsForm.isRendered()) uiConstraintsForm.setRendered(false);
375       else uiConstraintsForm.setRendered(true);
376       event.getRequestContext().addUIComponentToUpdateByAjax(uiSimpleSearch);
377     }
378   }
379 
380   static public class AddActionListener extends EventListener<UISimpleSearch> {
381     public void execute(Event<UISimpleSearch> event) throws Exception {
382       UIConstraintsForm uiForm = event.getSource().getChild(UIConstraintsForm.class);
383       boolean isExactly = uiForm.getUICheckBoxInput(UIConstraintsForm.EXACTLY_PROPERTY).isChecked() ;
384       boolean isContain = uiForm.getUICheckBoxInput(UIConstraintsForm.CONTAIN_PROPERTY).isChecked() ;
385       boolean isNotContain = uiForm.getUICheckBoxInput(UIConstraintsForm.NOT_CONTAIN_PROPERTY).isChecked() ;
386       boolean isDateTime = uiForm.getUICheckBoxInput(UIConstraintsForm.DATE_PROPERTY).isChecked() ;
387       boolean isNodeType = uiForm.getUICheckBoxInput(UIConstraintsForm.NODETYPE_PROPERTY).isChecked() ;
388       boolean isCategory = uiForm.getUICheckBoxInput(UIConstraintsForm.CATEGORY_PROPERTY).isChecked() ;
389       UIApplication uiApp = uiForm.getAncestorOfType(UIApplication.class) ;
390       if (!isExactly && !isContain && !isNotContain && !isDateTime && !isNodeType && !isCategory) {
391         uiApp.addMessage(new ApplicationMessage("UIConstraintsForm.msg.must-choose-one",
392                                                 null,
393                                                 ApplicationMessage.WARNING));
394         event.getRequestContext().addUIComponentToUpdateByAjax(uiForm);
395         return;
396       }
397       if (isExactly) {
398         String property = uiForm.getUIStringInput(UIConstraintsForm.PROPERTY1).getValue();
399         if (property == null || property.length() < 1) {
400           uiApp.addMessage(new ApplicationMessage("UIConstraintsForm.msg.properties-required",
401                                                   null,
402                                                   ApplicationMessage.WARNING));
403           event.getRequestContext().addUIComponentToUpdateByAjax(uiForm);
404           return;
405         }
406         String value = uiForm.getUIStringInput(UIConstraintsForm.CONTAIN_EXACTLY).getValue() ;
407         if (value == null || value.trim().length() < 0) {
408           uiApp.addMessage(new ApplicationMessage("UIConstraintsForm.msg.exactly-require",
409                                                   null,
410                                                   ApplicationMessage.WARNING));
411           event.getRequestContext().addUIComponentToUpdateByAjax(uiForm);
412           return;
413         }
414         uiForm.addConstraint(0) ;
415       }
416       if(isContain) {
417         String property = uiForm.getUIStringInput(UIConstraintsForm.PROPERTY2).getValue() ;
418         if(property == null || property.length() < 1) {
419           uiApp.addMessage(new ApplicationMessage("UIConstraintsForm.msg.properties-required", null,
420                                                   ApplicationMessage.WARNING)) ;
421           event.getRequestContext().addUIComponentToUpdateByAjax(uiForm);
422           return ;
423         }
424         String value = uiForm.getUIStringInput(UIConstraintsForm.CONTAIN).getValue() ;
425         if(value == null || value.trim().length() < 0) {
426           uiApp.addMessage(new ApplicationMessage("UIConstraintsForm.msg.value-required", null,
427                                                   ApplicationMessage.WARNING)) ;
428           event.getRequestContext().addUIComponentToUpdateByAjax(uiForm);
429           return ;
430         }
431         uiForm.addConstraint(1) ;
432       }
433       if(isNotContain) {
434         String property = uiForm.getUIStringInput(UIConstraintsForm.PROPERTY3).getValue() ;
435         if(property == null || property.length() < 1) {
436           uiApp.addMessage(new ApplicationMessage("UIConstraintsForm.msg.properties-required", null,
437                                                   ApplicationMessage.WARNING)) ;
438           event.getRequestContext().addUIComponentToUpdateByAjax(uiForm);
439           return ;
440         }
441         String value = uiForm.getUIStringInput(UIConstraintsForm.NOT_CONTAIN).getValue() ;
442         if(value == null || value.trim().length() < 0) {
443           uiApp.addMessage(new ApplicationMessage("UIConstraintsForm.msg.value-required", null,
444                                                   ApplicationMessage.WARNING)) ;
445           event.getRequestContext().addUIComponentToUpdateByAjax(uiForm);
446           return ;
447         }
448         uiForm.addConstraint(2) ;
449       }
450       if(isDateTime) {
451         String fromDate = uiForm.getUIFormDateTimeInput(UIConstraintsForm.START_TIME).getValue() ;
452         String toDate = uiForm.getUIFormDateTimeInput(UIConstraintsForm.END_TIME).getValue() ;
453         if(fromDate == null || fromDate.trim().length() == 0) {
454           uiApp.addMessage(new ApplicationMessage("UIConstraintsForm.msg.fromDate-required", null,
455                                                   ApplicationMessage.WARNING)) ;
456           event.getRequestContext().addUIComponentToUpdateByAjax(uiForm);
457           return ;
458         }
459         Calendar bfDate = uiForm.getUIFormDateTimeInput(UIConstraintsForm.START_TIME).getCalendar() ;
460         if(toDate != null && toDate.trim().length() >0) {
461           Calendar afDate = uiForm.getUIFormDateTimeInput(UIConstraintsForm.END_TIME).getCalendar();
462           if(bfDate.compareTo(afDate) == 1) {
463             uiApp.addMessage(new ApplicationMessage("UIConstraintsForm.msg.date-invalid", null,
464                                                     ApplicationMessage.WARNING)) ;
465             event.getRequestContext().addUIComponentToUpdateByAjax(uiForm);
466             return ;
467           }
468         }
469         uiForm.addConstraint(3);
470       }
471       if(isNodeType) {
472         String property = uiForm.getUIStringInput(UIConstraintsForm.DOC_TYPE).getValue() ;
473         if(property == null || property.length() < 1) {
474           uiApp.addMessage(new ApplicationMessage("UIConstraintsForm.msg.properties-required", null,
475               ApplicationMessage.WARNING)) ;
476           event.getRequestContext().addUIComponentToUpdateByAjax(uiForm);
477           return ;
478         }
479         uiForm.addConstraint(4) ;
480       }
481       if (isCategory) {
482         String category = uiForm.getUIStringInput(UIConstraintsForm.CATEGORY_TYPE).getValue();
483         if (category == null || category.length() < 1) {
484           uiApp.addMessage(new ApplicationMessage("UIConstraintsForm.msg.properties-required",
485               null, ApplicationMessage.WARNING));
486           event.getRequestContext().addUIComponentToUpdateByAjax(uiForm);
487           return;
488         }
489         uiForm.addConstraint(5);
490       }
491 
492       uiForm.resetConstraintForm() ;
493       event.getRequestContext().addUIComponentToUpdateByAjax(uiForm.getParent()) ;
494     }
495   }
496 
497   static public class AddMetadataTypeActionListener extends EventListener<UISimpleSearch> {
498     public void execute(Event<UISimpleSearch> event) throws Exception {
499       UISearchContainer uiContainer = event.getSource().getAncestorOfType(UISearchContainer.class);
500       String type = event.getRequestContext().getRequestParameter(OBJECTID) ;
501       String popupId = UIConstraintsForm.PROPERTY1;
502       if(type.equals("1")) popupId = UIConstraintsForm.PROPERTY2 ;
503       else if(type.equals("2")) popupId = UIConstraintsForm.PROPERTY3 ;
504       uiContainer.initMetadataPopup(popupId) ;
505       event.getRequestContext().addUIComponentToUpdateByAjax(uiContainer) ;
506     }
507   }
508 
509   static public class AddNodeTypeActionListener extends EventListener<UISimpleSearch> {
510     public void execute(Event<UISimpleSearch> event) throws Exception {
511       UISearchContainer uiContainer = event.getSource().getAncestorOfType(UISearchContainer.class);
512       uiContainer.initNodeTypePopup() ;
513       event.getRequestContext().addUIComponentToUpdateByAjax(uiContainer) ;
514     }
515   }
516 
517   static public class CompareExactlyActionListener extends EventListener<UISimpleSearch> {
518     public void execute(Event<UISimpleSearch> event) throws Exception {
519       UIConstraintsForm uiConstraintForm = event.getSource().getChild(UIConstraintsForm.class);
520       String property = uiConstraintForm.getUIStringInput(UIConstraintsForm.PROPERTY1).getValue() ;
521       UIJCRExplorer uiExplorer = uiConstraintForm.getAncestorOfType(UIJCRExplorer.class);
522       UIApplication uiApp = uiConstraintForm.getAncestorOfType(UIApplication.class) ;
523       if(property == null || property.trim().length() == 0) {
524         uiApp.addMessage(new ApplicationMessage("UIConstraintsForm.msg.properties-null", null,
525                                                  ApplicationMessage.WARNING)) ;
526         event.getRequestContext().addUIComponentToUpdateByAjax(uiConstraintForm);
527         return ;
528       }
529       String currentPath = uiExplorer.getCurrentNode().getPath() ;
530       StringBuffer statement = new StringBuffer("select * from nt:base where ");
531       if (!currentPath.equals("/")) {
532         statement.append("jcr:path like '").append(currentPath).append("/%' AND ");
533       }
534       property = XPathUtils.escapeIllegalXPathName(property);
535       statement.append(property).append(" is not null");
536       QueryManager queryManager = uiExplorer.getTargetSession().getWorkspace().getQueryManager() ;
537       Query query = queryManager.createQuery(statement.toString(), Query.SQL) ;
538       QueryResult result = query.execute() ;
539       if(result == null || result.getNodes().getSize() == 0) {
540         uiApp.addMessage(new ApplicationMessage("UICompareExactlyForm.msg.not-result-found", null)) ;
541         event.getRequestContext().addUIComponentToUpdateByAjax(uiConstraintForm);
542         return ;
543       }
544       UISearchContainer uiContainer = uiConstraintForm.getAncestorOfType(UISearchContainer.class);
545       UICompareExactlyForm uiCompareExactlyForm =
546         uiContainer.createUIComponent(UICompareExactlyForm.class, null, null) ;
547       UIPopupContainer uiPopup = uiContainer.getChild(UIPopupContainer.class);
548       uiPopup.getChild(UIPopupWindow.class).setId("ExactlyFormPopup") ;
549       uiPopup.getChild(UIPopupWindow.class).setShowMask(true);
550       uiCompareExactlyForm.init(property, result) ;
551       uiPopup.activate(uiCompareExactlyForm, 600, 500) ;
552       event.getRequestContext().addUIComponentToUpdateByAjax(uiPopup) ;
553     }
554   }
555 
556   static public class AddCategoryActionListener extends EventListener<UISimpleSearch> {
557     public void execute(Event<UISimpleSearch> event) throws Exception {
558       UISearchContainer uiSearchContainer = event.getSource().getAncestorOfType(UISearchContainer.class);
559       uiSearchContainer.initCategoryPopup();
560       event.getRequestContext().addUIComponentToUpdateByAjax(uiSearchContainer) ;
561     }
562   }
563 }