///////////////////////////////////////////////////////////////////////////// // // Project ProjectForge Community Edition // www.projectforge.org // // Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de) // // ProjectForge is dual-licensed. // // This community edition is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as published // by the Free Software Foundation; version 3 of the License. // // This community edition is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General // Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, see http://www.gnu.org/licenses/. // ///////////////////////////////////////////////////////////////////////////// package org.projectforge.web.core; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.apache.wicket.Component; import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder; import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable; import org.apache.wicket.extensions.markup.html.repeater.data.table.DefaultDataTable; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.link.Link; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.request.mapper.parameter.PageParameters; import org.apache.wicket.spring.injection.annot.SpringBean; import org.projectforge.common.BeanHelper; import org.projectforge.core.BaseSearchFilter; import org.projectforge.core.ExtendedBaseDO; import org.projectforge.core.NumberFormatter; import org.projectforge.core.SearchDao; import org.projectforge.core.SearchResultData; import org.projectforge.database.StatisticsCache; import org.projectforge.task.TaskDependentFilter; import org.projectforge.web.registry.WebRegistryEntry; import org.projectforge.web.wicket.AbstractListForm; import org.projectforge.web.wicket.AbstractListPage; import org.projectforge.web.wicket.IListPageColumnsCreator; import org.projectforge.web.wicket.MySortableDataProvider; import org.projectforge.web.wicket.WicketUtils; public class SearchAreaPanel extends Panel { private static final long serialVersionUID = -4258095807245346743L; private static final int MAXIMUM_ENTRIES_WITHOUT_FILTER_SETTINGS = 10000; @SpringBean(name = "searchDao") private SearchDao searchDao; @SpringBean(name = "statisticsCache") private StatisticsCache statisticsCache; /** * @param page Needed, because in constructor this panel is not yet added to a page. * @param id * @param filter * @param registryEntry the area to show. */ @SuppressWarnings("serial") public SearchAreaPanel(final WebPage page, final String id, final SearchPageFilter filter, final WebRegistryEntry webRegistryEntry) { super(id); final long millis = System.currentTimeMillis(); final Class< ? extends IListPageColumnsCreator< ? >> listPageColumnsCreatorClass = webRegistryEntry.getListPageColumnsCreatorClass(); final IListPageColumnsCreator< ? > listPageColumnsCreator = listPageColumnsCreatorClass == null ? null : (IListPageColumnsCreator< ? >) BeanHelper.newInstance(listPageColumnsCreatorClass, PageParameters.class, new PageParameters()); if (listPageColumnsCreator == null) { setVisible(false); return; } if (listPageColumnsCreator instanceof AbstractListPage) { ((AbstractListPage< ? , ? , ? >) listPageColumnsCreator).setCalledBySearchPage(true); } final Integer number = statisticsCache.getNumberOfEntities(webRegistryEntry.getDOClass()); final Class< ? extends BaseSearchFilter> registeredFilterClass = webRegistryEntry.getSearchFilterClass(); final boolean isTaskDependentFilter = registeredFilterClass != null && TaskDependentFilter.class.isAssignableFrom(registeredFilterClass); if (number > MAXIMUM_ENTRIES_WITHOUT_FILTER_SETTINGS && (filter.getSearchString() == null || filter.getSearchString().length() < 3) && (isTaskDependentFilter == false || filter.getTask() == null) && filter.getStartTimeOfModification() == null && filter.getStopTimeOfModification() == null) { // Don't search to large tables if to less filter settings are given. setVisible(false); return; } filter.updateUseModificationFilterFlag(); final BaseSearchFilter baseSearchFilter; if (isTaskDependentFilter == true) { baseSearchFilter = (BaseSearchFilter) BeanHelper.newInstance(registeredFilterClass, new Class< ? >[] { BaseSearchFilter.class}, filter); ((TaskDependentFilter) baseSearchFilter).setTaskId(filter.getTaskId()); baseSearchFilter.copyBaseSearchFieldsFrom(filter); } else { baseSearchFilter = filter; } final List<SearchResultData> searchResult = searchDao.getEntries(baseSearchFilter, webRegistryEntry.getDOClass(), webRegistryEntry.getDao()); boolean hasError = false; if (searchResult == null) { // An error occured! hasError = true; } else if (searchResult.size() == 0) { // No hits. setVisible(false); return; } boolean hasMore = false; if (hasError == true) { add(WicketUtils.getInvisibleComponent("dataTable")); } else { final List<ExtendedBaseDO<Integer>> list = new ArrayList<ExtendedBaseDO<Integer>>(); for (final SearchResultData data : searchResult) { if (data.getDataObject() != null) { list.add(data.getDataObject()); } else { // Empty entry means: more entries found. hasMore = true; break; } } final List< ? > columns = listPageColumnsCreator.createColumns(page, false); @SuppressWarnings({ "rawtypes", "unchecked"}) final DataTable< ? , String> dataTable = new DefaultDataTable("dataTable", columns, new MySortableDataProvider("NOSORT", SortOrder.DESCENDING) { @Override public List< ? > getList() { return list; } @Override protected IModel< ? > getModel(final Object object) { return new Model((Serializable) object); } }, filter.getMaxRows()); add(dataTable); } final Label hasMoreEntries; if (hasError == true) { hasMoreEntries = new Label("hasMoreEntries", page.getString("search.error") + " | "); } else { hasMoreEntries = new Label("hasMoreEntries", page.getString("moreEntriesAvailable") + " | "); hasMoreEntries.setVisible(false); } add(hasMoreEntries); Component showMoreEntrieslink = null; if (hasMore == true) { final int maxRows = filter.getMaxRows(); if (maxRows < SearchForm.MAX_PAGE_SIZE) { showMoreEntrieslink = new Link<Void>("showMoreEntrieslink") { /** * @see org.apache.wicket.markup.html.link.Link#onClick() */ @Override public void onClick() { for (final int number : AbstractListForm.PAGE_SIZES) { if (number > maxRows) { filter.setMaxRows(number); break; } } filter.setArea(webRegistryEntry.getId()); } }; add(showMoreEntrieslink); } else { hasMoreEntries.setVisible(true); } } if (showMoreEntrieslink == null) { add(new Label("showMoreEntrieslink", "[invisible]").setVisible(false)); } if (listPageColumnsCreator instanceof AbstractListPage< ? , ? , ? >) { add(new Link<Void>("listPageLink") { /** * @see org.apache.wicket.markup.html.link.Link#onClick() */ @Override public void onClick() { final AbstractListPage< ? , ? , ? > listPage = (AbstractListPage< ? , ? , ? >) listPageColumnsCreator; listPage.copySearchFieldsFrom(filter); setResponsePage(listPage); } }); } else { add(new Label("listPageLink", "[invisible]").setVisible(false)); } final long duration = System.currentTimeMillis() - millis; add(new Label("areaTitle", page.getString(webRegistryEntry.getI18nTitleHeading()))); add(new Label("timeOfSearch", NumberFormatter.format(duration))); } }