View Javadoc
1   /*
2    * Copyright (C) 2003-2009 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.wcm.webui.selector.content;
18  
19  import java.text.DateFormat;
20  import java.text.ParseException;
21  import java.text.SimpleDateFormat;
22  import java.util.ArrayList;
23  import java.util.Calendar;
24  import java.util.List;
25  import java.util.ResourceBundle;
26  
27  import javax.jcr.RepositoryException;
28  import javax.jcr.query.InvalidQueryException;
29  
30  import org.exoplatform.portal.webui.util.Util;
31  import org.exoplatform.services.cms.templates.TemplateService;
32  import org.exoplatform.services.wcm.core.WCMConfigurationService;
33  import org.exoplatform.services.wcm.search.QueryCriteria;
34  import org.exoplatform.services.wcm.search.QueryCriteria.DATE_RANGE_SELECTED;
35  import org.exoplatform.services.wcm.search.QueryCriteria.DatetimeRange;
36  import org.exoplatform.services.wcm.search.ResultNode;
37  import org.exoplatform.services.wcm.search.SiteSearchService;
38  import org.exoplatform.services.wcm.search.base.AbstractPageList;
39  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
40  import org.exoplatform.wcm.webui.selector.content.UIContentSelector;
41  import org.exoplatform.web.application.ApplicationMessage;
42  import org.exoplatform.webui.application.WebuiRequestContext;
43  import org.exoplatform.webui.config.annotation.ComponentConfig;
44  import org.exoplatform.webui.config.annotation.EventConfig;
45  import org.exoplatform.webui.core.UIApplication;
46  import org.exoplatform.webui.core.UIContainer;
47  import org.exoplatform.webui.core.lifecycle.UIFormLifecycle;
48  import org.exoplatform.webui.core.model.SelectItemOption;
49  import org.exoplatform.webui.event.Event;
50  import org.exoplatform.webui.event.EventListener;
51  import org.exoplatform.webui.form.UIForm;
52  import org.exoplatform.webui.form.UIFormDateTimeInput;
53  import org.exoplatform.webui.form.UIFormSelectBox;
54  import org.exoplatform.webui.form.UIFormStringInput;
55  
56  /**
57   * Created by The eXo Platform SAS
58   * Author : DANG TAN DUNG
59   *          dzungdev@gmail.com
60   * Jan 5, 2009
61   */
62  
63  @ComponentConfig(
64      lifecycle = UIFormLifecycle.class,
65      template = "classpath:groovy/wcm/webui/selector/content/UIContentSearchForm.gtmpl",
66      events = {
67        @EventConfig(listeners = UIContentSearchForm.SearchWebContentActionListener.class),
68        @EventConfig(listeners = UIContentSearchForm.AddMetadataTypeActionListener.class),
69        @EventConfig(listeners = UIContentSearchForm.AddNodeTypeActionListener.class)
70      }
71  )
72  
73  public class UIContentSearchForm extends UIForm {
74  
75    public static final String LOCATION = "location";
76    public static final String SEARCH_BY_NAME = "name";
77    public static final String SEARCH_BY_CONTENT = "content";
78    public static final String RADIO_NAME = "WcmRadio";
79    final static public String TIME_OPTION = "timeOpt";
80    final static public String PROPERTY = "property";
81    final static public String CONTAIN = "contain";
82    final static public String START_TIME = "startTime";
83    final static public String END_TIME = "endTime";
84    final static public String DOC_TYPE = "docType";
85    final static public String CATEGORY = "category";
86    final static public String CREATED_DATE = "CREATED";
87    final static public String MODIFIED_DATE = "MODIFIED";
88    final static public String EXACTLY_PROPERTY = "exactlyPro";
89    final static public String CONTAIN_PROPERTY = "containPro";
90    final static public String NOT_CONTAIN_PROPERTY = "notContainPro";
91    final static public String DATE_PROPERTY = "datePro";
92    final static public String NODETYPE_PROPERTY = "nodetypePro";
93    final static public String CHECKED_RADIO_ID = "checkedRadioId";
94  
95    private String checkedRadioId;
96  
97    public UIContentSearchForm() throws Exception {
98    }
99  
100   public void init() throws Exception {
101     List<SelectItemOption<String>> portalNameOptions = new ArrayList<SelectItemOption<String>>();
102     List<String> portalNames = getPortalNames();
103     for(String portalName: portalNames) {
104       portalNameOptions.add(new SelectItemOption<String>(portalName, portalName));
105     }
106     UIFormSelectBox portalNameSelectBox = new UIFormSelectBox(LOCATION, LOCATION, portalNameOptions);
107     portalNameSelectBox.setDefaultValue(portalNames.get(0));
108     addChild(portalNameSelectBox);
109 
110     addUIFormInput(new UIFormStringInput(SEARCH_BY_NAME,SEARCH_BY_NAME,null));
111     addUIFormInput(new UIFormStringInput(SEARCH_BY_CONTENT, SEARCH_BY_CONTENT, null));
112 
113     addUIFormInput(new UIFormStringInput(PROPERTY, PROPERTY, null).setDisabled(true));
114     addUIFormInput(new UIFormStringInput(CONTAIN, CONTAIN, null));
115 
116     List<SelectItemOption<String>> dateOptions = new ArrayList<SelectItemOption<String>>();
117     dateOptions.add(new SelectItemOption<String>(CREATED_DATE,CREATED_DATE));
118     dateOptions.add(new SelectItemOption<String>(MODIFIED_DATE,MODIFIED_DATE));
119     addUIFormInput(new UIFormSelectBox(TIME_OPTION,TIME_OPTION, dateOptions));
120     UIFormDateTimeInput startTime = new UIFormDateTimeInput(START_TIME, START_TIME, null, true);
121     addUIFormInput(startTime);
122     UIFormDateTimeInput endTime = new UIFormDateTimeInput(END_TIME, END_TIME, null, true);
123     addUIFormInput(endTime);
124     addUIFormInput(new UIFormStringInput(DOC_TYPE, DOC_TYPE, null).setDisabled(true));
125 
126     setActions(new String[] {"SearchWebContent"} );
127   }
128   
129   private List<String> getPortalNames() throws Exception {
130     List<String> portalNames = new ArrayList<String>();
131     String currentPortalName = Util.getPortalRequestContext().getPortalOwner();
132     WCMConfigurationService configService = getApplicationComponent(WCMConfigurationService.class);
133     String sharedPortalName = configService.getSharedPortalName();
134     portalNames.add(currentPortalName);
135     portalNames.add(sharedPortalName);
136     return portalNames;
137   }
138 
139   public static class AddMetadataTypeActionListener extends EventListener<UIContentSearchForm> {
140     public void execute(Event<UIContentSearchForm> event) throws Exception {
141       UIContentSearchForm contentSearchForm = event.getSource();
142       UIContentSelector contentSelector = contentSearchForm.getParent();
143       contentSearchForm.setCheckedRadioId(event.getRequestContext().getRequestParameter(CHECKED_RADIO_ID));
144       UIContainer uiContainer = 
145           contentSearchForm.getAncestorOfType(UIContentSelector.class).getAncestorOfType(UIContainer.class);
146       contentSelector.initMetadataPopup(uiContainer);
147       event.getRequestContext().addUIComponentToUpdateByAjax(uiContainer);
148     }
149   }
150 
151   public static class AddNodeTypeActionListener extends EventListener<UIContentSearchForm> {
152     public void execute(Event<UIContentSearchForm> event) throws Exception {
153       UIContentSearchForm contentSearchForm = event.getSource();
154       UIContentSelector contentSelector = contentSearchForm.getParent();
155       contentSearchForm.setCheckedRadioId(event.getRequestContext().getRequestParameter(CHECKED_RADIO_ID));
156       UIContainer uiContainer = 
157           contentSearchForm.getAncestorOfType(UIContentSelector.class).getAncestorOfType(UIContainer.class);
158       contentSelector.initNodeTypePopup(uiContainer);
159       event.getRequestContext().addUIComponentToUpdateByAjax(uiContainer);
160     }
161   }
162 
163   private QueryCriteria getInitialQueryCriteria(String siteName) throws Exception {
164     QueryCriteria qCriteria = new QueryCriteria();
165     TemplateService templateService = WCMCoreUtils.getService(TemplateService.class);
166     String[] allContentType = templateService.getDocumentTemplates().toArray(new String[0]);
167     qCriteria.setContentTypes(allContentType);  //only get the content nodes which have the document template.
168     qCriteria.setSearchWebpage(false);
169     qCriteria.setSiteName(siteName);
170     qCriteria.setLiveMode(false);
171     return qCriteria;
172   }
173 
174   private boolean haveEmptyField(UIApplication uiApp, Event<UIContentSearchForm> event, String field, String messageKey) throws Exception {
175       if(field == null || "".equals(field) || (field.toString().trim().length() <= 0)) {
176         uiApp.addMessage(new ApplicationMessage(
177             messageKey, null, ApplicationMessage.WARNING));
178         WebuiRequestContext requestContext = WebuiRequestContext.getCurrentInstance();
179         requestContext.addUIComponentToUpdateByAjax(this);
180         return true;
181     }
182     return false;
183   }
184 
185   private AbstractPageList<ResultNode> searchContentByName(String keyword,
186       QueryCriteria qCriteria, int pageSize) throws Exception {
187     qCriteria.setFulltextSearch(false);
188     qCriteria.setKeyword(keyword);
189 
190     WebuiRequestContext requestContext = WebuiRequestContext.getCurrentInstance();
191     SiteSearchService siteSearch = getApplicationComponent(SiteSearchService.class);
192     return siteSearch.searchSiteContents(WCMCoreUtils.getUserSessionProvider(), qCriteria, requestContext.getLocale(), pageSize, true);
193   }
194 
195   private AbstractPageList<ResultNode> searchContentByFulltext(String keyword,
196       QueryCriteria qCriteria, int pageSize) throws Exception {
197     qCriteria.setFulltextSearch(true);
198     qCriteria.setFulltextSearchProperty(new String[] {QueryCriteria.ALL_PROPERTY_SCOPE});
199     qCriteria.setKeyword(keyword);
200 
201     WebuiRequestContext requestContext = WebuiRequestContext.getCurrentInstance();
202     SiteSearchService siteSearch = getApplicationComponent(SiteSearchService.class);
203     return siteSearch.searchSiteContents(WCMCoreUtils.getUserSessionProvider(), qCriteria, requestContext.getLocale(), pageSize, true);
204   }
205 
206   private AbstractPageList<ResultNode> searchContentByProperty(String property,
207       String keyword, QueryCriteria qCriteria, int pageSize) throws Exception {
208     qCriteria.setFulltextSearch(true);
209     qCriteria.setFulltextSearchProperty(new String[] {property});
210     qCriteria.setKeyword(keyword);
211 
212     WebuiRequestContext requestContext = WebuiRequestContext.getCurrentInstance();
213     SiteSearchService siteSearchService = getApplicationComponent(SiteSearchService.class);
214     return siteSearchService.searchSiteContents(WCMCoreUtils.getUserSessionProvider(), qCriteria, requestContext.getLocale(), pageSize, true);
215   }
216 
217   private AbstractPageList<ResultNode> searchContentByDate(DATE_RANGE_SELECTED dateRangeSelected,
218       Calendar fromDate, Calendar endDate, QueryCriteria qCriteria, int pageSize) throws Exception {
219     qCriteria.setDateRangeSelected(dateRangeSelected);
220     DatetimeRange dateTimeRange = new QueryCriteria.DatetimeRange(fromDate, endDate);
221     if(DATE_RANGE_SELECTED.CREATED.equals(dateRangeSelected)) {
222       qCriteria.setCreatedDateRange(dateTimeRange);
223     } else if(DATE_RANGE_SELECTED.MODIFIDED.equals(dateRangeSelected)) {
224       qCriteria.setLastModifiedDateRange(dateTimeRange);
225     }
226     qCriteria.setFulltextSearch(true);
227     qCriteria.setFulltextSearchProperty(null);
228 
229     WebuiRequestContext requestContext = WebuiRequestContext.getCurrentInstance();
230     SiteSearchService siteSearch = getApplicationComponent(SiteSearchService.class);
231     return siteSearch.searchSiteContents(WCMCoreUtils.getUserSessionProvider(), qCriteria, requestContext.getLocale(), pageSize, true);
232   }
233 
234   private AbstractPageList<ResultNode> searchContentByType(String documentType,
235       QueryCriteria qCriteria, int pageSize) throws Exception {
236     qCriteria.setFulltextSearch(true);
237     qCriteria.setFulltextSearchProperty(null);
238     qCriteria.setContentTypes(documentType.split(","));
239 
240     WebuiRequestContext requestContext = WebuiRequestContext.getCurrentInstance();
241     SiteSearchService siteSearch = getApplicationComponent(SiteSearchService.class);
242     return siteSearch.searchSiteContents(WCMCoreUtils.getUserSessionProvider(), qCriteria, requestContext.getLocale(), pageSize, true);
243   }
244 
245   static public class SearchWebContentActionListener extends EventListener<UIContentSearchForm> {
246 
247     public void execute(Event<UIContentSearchForm> event) throws Exception {
248       WebuiRequestContext requestContext = WebuiRequestContext.getCurrentInstance();
249       UIContentSearchForm uiWCSearch = event.getSource();
250       
251       int pageSize = 5;
252       String radioValue = event.getRequestContext().getRequestParameter(RADIO_NAME);
253       uiWCSearch.setCheckedRadioId(event.getRequestContext().getRequestParameter(CHECKED_RADIO_ID));
254       String siteName = uiWCSearch.getUIStringInput(UIContentSearchForm.LOCATION).getValue();
255       UIContentSelector uiWCTabSelector = uiWCSearch.getParent();
256       UIApplication uiApp = uiWCSearch.getAncestorOfType(UIApplication.class);
257       QueryCriteria qCriteria = uiWCSearch.getInitialQueryCriteria(siteName);
258       AbstractPageList<ResultNode> pagResult = null;
259 
260       ResourceBundle resourceBundle = WebuiRequestContext.getCurrentInstance().getApplicationResourceBundle();
261       try {
262 
263         if (UIContentSearchForm.SEARCH_BY_NAME.equals(radioValue)) {
264           String keyword = uiWCSearch.getUIStringInput(radioValue).getValue();
265           if (uiWCSearch.haveEmptyField(uiApp, event, keyword,"UIContentSearchForm.msg.empty-name"))
266             return;
267           pagResult = uiWCSearch.searchContentByName(keyword.trim(), qCriteria, pageSize);
268         } else if (UIContentSearchForm.SEARCH_BY_CONTENT.equals(radioValue)) {
269           String keyword = uiWCSearch.getUIStringInput(radioValue).getValue();
270           if (uiWCSearch.haveEmptyField(uiApp, event, keyword,"UIContentSearchForm.msg.empty-content"))
271             return;
272           pagResult = uiWCSearch.searchContentByFulltext(keyword, qCriteria, pageSize);
273         } else if (UIContentSearchForm.PROPERTY.equals(radioValue)) {
274           String property = uiWCSearch.getUIStringInput(UIContentSearchForm.PROPERTY).getValue();
275           if (uiWCSearch.haveEmptyField(uiApp, event, property,"UIContentSearchForm.msg.empty-property"))
276             return;
277           String keyword = uiWCSearch.getUIStringInput(UIContentSearchForm.CONTAIN).getValue();
278           if (uiWCSearch.haveEmptyField(uiApp, event, keyword,"UIContentSearchForm.msg.empty-property-keyword"))
279             return;
280           pagResult = uiWCSearch.searchContentByProperty(property,
281                                                             keyword,
282                                                             qCriteria,
283                                                             pageSize);
284         } else if (UIContentSearchForm.TIME_OPTION.equals(radioValue)) {
285           UIFormDateTimeInput startDateInput = uiWCSearch.getUIFormDateTimeInput(UIContentSearchForm.START_TIME);
286           UIFormDateTimeInput endDateInput = uiWCSearch.getUIFormDateTimeInput(UIContentSearchForm.END_TIME);
287 
288           //startDateInput cannot be empty
289           String strStartDate = startDateInput.getValue();
290           if (uiWCSearch.haveEmptyField(uiApp, event, strStartDate,"UIContentSearchForm.msg.empty-startDate"))
291             return;
292           
293           //startDateInput must have a valid format
294           try {
295             DateFormat dateFormat = new SimpleDateFormat(startDateInput.getDatePattern_().trim());
296             dateFormat.setLenient(false);
297             dateFormat.parse(startDateInput.getValue());
298           } catch (ParseException e) {
299             uiApp.addMessage(new ApplicationMessage("UIContentSearchForm.msg.invalid-format",
300                                                     new Object[] 
301                                                                { resourceBundle.getString("UIContentSearchForm.title.FromDate") },
302                                                     ApplicationMessage.WARNING));
303             requestContext.addUIComponentToUpdateByAjax(uiWCSearch);
304             return;
305           }
306           
307           Calendar startDate = startDateInput.getCalendar();
308           Calendar endDate = null;
309           
310           if (endDateInput.getValue() == null || endDateInput.getValue().length() == 0) {
311             //set endDate value when endDateInput is empty
312             if (startDate.getTimeInMillis() > Calendar.getInstance().getTimeInMillis()) {
313               endDate = startDate;
314             } else {
315               endDate = Calendar.getInstance();
316             }
317           } else {
318             //endDateInput should have a valid format
319             try {
320               DateFormat dateFormat = new SimpleDateFormat(endDateInput.getDatePattern_().trim());
321               dateFormat.setLenient(false);
322               dateFormat.parse(endDateInput.getValue());
323             } catch (ParseException e) {
324               uiApp.addMessage(new ApplicationMessage("UIContentSearchForm.msg.invalid-format",
325                                                       new Object[] 
326                                                                  { resourceBundle.getString("UIContentSearchForm.title.ToDate") },
327                                                       ApplicationMessage.WARNING));
328               requestContext.addUIComponentToUpdateByAjax(uiWCSearch);
329               return;
330             }
331             
332             endDate = endDateInput.getCalendar();
333           }
334           
335           //startDate cannot be after endDate
336           if (startDate.getTimeInMillis() > endDate.getTimeInMillis()) {
337             uiApp.addMessage(new ApplicationMessage("UIContentSearchForm.msg.invalid-date",
338                                                     null,
339                                                     ApplicationMessage.WARNING));
340             requestContext.addUIComponentToUpdateByAjax(uiWCSearch);
341             return;
342           }
343           // startDate cannot be later than today
344           if (startDate.getTimeInMillis() > Calendar.getInstance().getTimeInMillis()) {
345             uiApp.addMessage(new ApplicationMessage("UIContentSearchForm.msg.invalid-startDate",
346                                                     null,
347                                                     ApplicationMessage.WARNING));
348             requestContext.addUIComponentToUpdateByAjax(uiWCSearch);
349             return;
350           }
351           try {
352             String dateRangeSelected = uiWCSearch.getUIStringInput(UIContentSearchForm.TIME_OPTION).getValue();
353             if (UIContentSearchForm.CREATED_DATE.equals(dateRangeSelected)) {
354               pagResult = uiWCSearch.searchContentByDate(DATE_RANGE_SELECTED.CREATED,
355                                                             startDate,
356                                                             endDate,
357                                                             qCriteria,
358                                                             pageSize);
359             } else {
360               pagResult = uiWCSearch.searchContentByDate(DATE_RANGE_SELECTED.MODIFIDED,
361                                                             startDate,
362                                                             endDate,
363                                                             qCriteria,
364                                                             pageSize);
365             }
366           } catch (IllegalArgumentException iaEx) {
367             uiApp.addMessage(new ApplicationMessage("UIContentSearchForm.msg.time-to-late",
368                                                     null,
369                                                     ApplicationMessage.WARNING));
370             requestContext.addUIComponentToUpdateByAjax(uiWCSearch);
371             return;
372           }
373         } else if (UIContentSearchForm.DOC_TYPE.equals(radioValue)) {
374           String documentType = uiWCSearch.getUIStringInput(UIContentSearchForm.DOC_TYPE)
375                                           .getValue();
376           if (uiWCSearch.haveEmptyField(uiApp, event, documentType,"UIContentSearchForm.msg.empty-doctype"))
377             return;
378           try {
379             pagResult = uiWCSearch.searchContentByType(documentType,
380                                                                   qCriteria,
381                                                                   pageSize);
382           } catch (Exception ex) {
383             uiApp.addMessage(new ApplicationMessage("UIContentSearchForm.msg.invalid-nodeType",
384                                                     new Object[] { documentType },
385                                                     ApplicationMessage.ERROR));
386             requestContext.addUIComponentToUpdateByAjax(uiWCSearch);
387             return;
388           }
389         }
390       } catch (InvalidQueryException iqe) {
391         uiApp.addMessage(new ApplicationMessage("UIContentSearchForm.msg.invalid-keyword",
392                                                 null,
393                                                 ApplicationMessage.WARNING));
394         requestContext.addUIComponentToUpdateByAjax(uiWCSearch);
395         return;
396       } catch (RepositoryException re) {
397         uiApp.addMessage(new ApplicationMessage("UIContentSearchForm.msg.invalid-keyword",
398                                                 null,
399                                                 ApplicationMessage.WARNING));
400         requestContext.addUIComponentToUpdateByAjax(uiWCSearch);
401         return;
402       }
403       UIContentSearchResult uiWCSearchResult = uiWCTabSelector.getChild(UIContentSearchResult.class);
404       uiWCSearchResult.updateGrid(pagResult);
405       event.getRequestContext().addUIComponentToUpdateByAjax(uiWCTabSelector);
406       uiWCTabSelector.setSelectedTab(uiWCSearchResult.getId());
407     }
408   }
409 
410   public String getCheckedRadioId() {
411     return checkedRadioId;
412   }
413 
414   public void setCheckedRadioId(String checkedRadioId) {
415     this.checkedRadioId = checkedRadioId;
416   }
417 }