001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ui.apps.search; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.CmsProject; 032import org.opencms.file.CmsPropertyDefinition; 033import org.opencms.file.CmsResource; 034import org.opencms.file.CmsResourceFilter; 035import org.opencms.file.types.CmsResourceTypeXmlContainerPage; 036import org.opencms.file.types.I_CmsResourceType; 037import org.opencms.loader.CmsLoaderException; 038import org.opencms.main.CmsException; 039import org.opencms.main.CmsLog; 040import org.opencms.main.OpenCms; 041import org.opencms.search.CmsSearchIndex; 042import org.opencms.search.I_CmsSearchIndex; 043import org.opencms.ui.A_CmsUI; 044import org.opencms.ui.CmsVaadinUtils; 045import org.opencms.ui.CmsVaadinUtils.PropertyId; 046import org.opencms.ui.apps.Messages; 047import org.opencms.ui.components.fileselect.CmsPathSelectField; 048import org.opencms.util.CmsStringUtil; 049import org.opencms.util.CmsUUID; 050 051import java.util.Collections; 052import java.util.Locale; 053 054import org.apache.commons.logging.Log; 055 056import com.vaadin.ui.Button; 057import com.vaadin.ui.Button.ClickEvent; 058import com.vaadin.ui.Button.ClickListener; 059import com.vaadin.v7.data.Property.ValueChangeEvent; 060import com.vaadin.v7.data.Property.ValueChangeListener; 061import com.vaadin.v7.data.util.IndexedContainer; 062import com.vaadin.v7.shared.ui.combobox.FilteringMode; 063import com.vaadin.v7.ui.CheckBox; 064import com.vaadin.v7.ui.ComboBox; 065import com.vaadin.v7.ui.TextField; 066import com.vaadin.v7.ui.VerticalLayout; 067 068/** 069 * The source search form.<p> 070 */ 071public class CmsSourceSearchForm extends VerticalLayout { 072 073 /** The available search types. */ 074 public static enum SearchType { 075 /** XML content values only. */ 076 contentValues(false, true, false), 077 /** Full text search. */ 078 fullText(false, false, false), 079 /** Filter using a solr index, before searching for matches. */ 080 solr(true, false, false), 081 /** Filter using a solr index, before searching for matches, XML content values only. */ 082 solrContentValues(true, true, false), 083 084 /** Property search. */ 085 properties(false, false, true), 086 /** */ 087 resourcetype(false, false, false), 088 /** */ 089 renameContainer(false, false, false); 090 091 /** The content values only flag. */ 092 private boolean m_contentValuesOnly; 093 094 /** The is solr search flag. */ 095 private boolean m_solrSearch; 096 097 /** The property flag.*/ 098 private boolean m_property; 099 100 /** 101 * Constructor.<p> 102 * 103 * @param solrSearch the is solr search flag 104 * @param contentValuesOnly the content values only flag 105 * @param property the property flag 106 */ 107 private SearchType(boolean solrSearch, boolean contentValuesOnly, boolean property) { 108 109 m_solrSearch = solrSearch; 110 m_contentValuesOnly = contentValuesOnly; 111 m_property = property; 112 } 113 114 /** 115 * Returns whether this is a content values only search type.<p> 116 * 117 * @return <code>true</code> if this is a content values only search type 118 */ 119 public boolean isContentValuesOnly() { 120 121 return m_contentValuesOnly; 122 } 123 124 /** 125 * Returns whether this is a property search type.<p> 126 * 127 * @return true if this is property search 128 * */ 129 public boolean isPropertySearch() { 130 131 return m_property; 132 } 133 134 /** 135 * Returns whether this is a SOLR search type.<p> 136 * 137 * @return <code>true</code> if this is a SOLR search type 138 */ 139 public boolean isSolrSearch() { 140 141 return m_solrSearch; 142 } 143 } 144 145 /**Regex expression for finding all. */ 146 public static final String REGEX_ALL = ".*"; 147 148 /** The log object for this class. */ 149 static final Log LOG = CmsLog.getLog(CmsSourceSearchForm.class); 150 151 /** The serial version id. */ 152 private static final long serialVersionUID = 1023130318064811880L; 153 154 /** The source search app instance. */ 155 private CmsSourceSearchApp m_app; 156 157 /** The search locale select. */ 158 private ComboBox m_locale; 159 160 /** The replace check box. */ 161 private CheckBox m_replace; 162 163 /** The replace pattern field. */ 164 private TextField m_replacePattern; 165 166 /** The resource type select. */ 167 private ComboBox m_resourceType; 168 169 /** The search button. */ 170 private Button m_search; 171 172 /** Vaadin component.*/ 173 private TextField m_oldName; 174 175 /** Vaadin component.*/ 176 private TextField m_newName; 177 178 /** Check box to ignore subsites. */ 179 private CheckBox m_ignoreSubSites; 180 181 /** The site select. */ 182 private ComboBox m_siteSelect; 183 184 /** The search index select. */ 185 private ComboBox m_searchIndex; 186 187 /** The search pattern field. */ 188 private TextField m_searchPattern; 189 190 /** The search root path select. */ 191 private CmsPathSelectField m_searchRoot; 192 193 /** The search root path select. */ 194 private CmsPathSelectField m_replaceResource; 195 196 /** The search root path select. */ 197 private CmsPathSelectField m_resourceSearch; 198 199 /** The search type select. */ 200 private ComboBox m_searchType; 201 202 /** The property select.*/ 203 private ComboBox m_property; 204 205 /** The SOLR query field. */ 206 private TextField m_solrQuery; 207 208 /** The replace project. */ 209 private ComboBox m_workProject; 210 211 /** The XPath field. */ 212 private TextField m_xPath; 213 214 /** 215 * Constructor.<p> 216 * 217 * @param app the source search app instance 218 */ 219 public CmsSourceSearchForm(CmsSourceSearchApp app) { 220 221 m_app = app; 222 CmsVaadinUtils.readAndLocalizeDesign(this, CmsVaadinUtils.getWpMessagesForCurrentLocale(), null); 223 initFields(); 224 m_replace.addValueChangeListener(new ValueChangeListener() { 225 226 private static final long serialVersionUID = 1L; 227 228 public void valueChange(ValueChangeEvent event) { 229 230 updateReplace(); 231 } 232 }); 233 m_searchType.addValueChangeListener(new ValueChangeListener() { 234 235 private static final long serialVersionUID = 1L; 236 237 public void valueChange(ValueChangeEvent event) { 238 239 changedSearchType(); 240 } 241 }); 242 m_search.addClickListener(new ClickListener() { 243 244 private static final long serialVersionUID = 1L; 245 246 public void buttonClick(ClickEvent event) { 247 248 search(); 249 } 250 }); 251 updateReplace(); 252 changedSearchType(); 253 } 254 255 /** 256 * Initializes the form with the given settings.<p> 257 * 258 * @param settings the settings 259 */ 260 public void initFormValues(CmsSearchReplaceSettings settings) { 261 262 m_siteSelect.setValue(settings.getSiteRoot()); 263 m_ignoreSubSites.setValue(new Boolean(settings.ignoreSubSites())); 264 m_searchType.setValue(settings.getType()); 265 if (!settings.getPaths().isEmpty()) { 266 m_searchRoot.setValue(settings.getPaths().get(0)); 267 } 268 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(settings.getTypes())) { 269 try { 270 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(settings.getTypes()); 271 m_resourceType.setValue(type); 272 } catch (CmsLoaderException e) { 273 // nothing to do, skip setting the type 274 } 275 } 276 m_searchPattern.setValue(settings.getSearchpattern()); 277 m_ignoreSubSites.setValue(new Boolean(settings.ignoreSubSites())); 278 if (settings.getType().isContentValuesOnly()) { 279 if (settings.getLocale() != null) { 280 m_locale.setValue(settings.getLocale()); 281 } 282 m_xPath.setValue(settings.getXpath()); 283 } 284 if (settings.getType().isSolrSearch()) { 285 m_solrQuery.setValue(settings.getQuery()); 286 m_searchIndex.setValue(settings.getSource()); 287 } 288 289 if (settings.getType().isPropertySearch()) { 290 m_property.select(settings.getProperty()); 291 } 292 if (settings.getType().equals(SearchType.resourcetype)) { 293 try { 294 CmsObject cms = OpenCms.initCmsObject(A_CmsUI.getCmsObject()); 295 cms.getRequestContext().setSiteRoot(""); 296 m_resourceSearch.setValue( 297 cms.readResource( 298 new CmsUUID( 299 settings.getSearchpattern().substring( 300 settings.getSearchpattern().indexOf("<uuid>") + 6, 301 settings.getSearchpattern().indexOf("</uuid>")))).getRootPath()); 302 } catch (CmsException e) { 303 LOG.error("Unable to read resource", e); 304 } 305 306 } 307 } 308 309 /** 310 * Updates the search root.<p> 311 * 312 * @throws CmsException if CmsObject init fails 313 */ 314 protected void updateSearchRoot() throws CmsException { 315 316 CmsObject newCms = OpenCms.initCmsObject(A_CmsUI.getCmsObject()); 317 newCms.getRequestContext().setSiteRoot((String)m_siteSelect.getValue()); 318 m_searchRoot.setCmsObject(newCms); 319 m_searchRoot.setValue("/"); 320 321 } 322 323 /** 324 * Handles search type changes.<p> 325 */ 326 void changedSearchType() { 327 328 SearchType type = (SearchType)m_searchType.getValue(); 329 330 m_property.setVisible(type.isPropertySearch()); 331 m_searchPattern.setVisible( 332 (!type.equals(SearchType.resourcetype)) & (!type.equals(SearchType.renameContainer))); 333 m_resourceSearch.setVisible(type.equals(SearchType.resourcetype) | type.equals(SearchType.renameContainer)); 334 if ((!type.equals(SearchType.resourcetype)) & (!type.equals(SearchType.renameContainer))) { 335 m_ignoreSubSites.setValue(Boolean.FALSE); 336 m_ignoreSubSites.setVisible(false); 337 } else { 338 m_ignoreSubSites.setVisible(true); 339 } 340 341 m_searchIndex.setVisible(type.isSolrSearch()); 342 m_solrQuery.setVisible(type.isSolrSearch()); 343 updateReplace(); 344 m_xPath.setVisible(type.isContentValuesOnly()); 345 m_locale.setVisible(type.isContentValuesOnly()); 346 347 m_resourceType.setVisible( 348 !type.isPropertySearch() 349 & !type.equals(SearchType.resourcetype) 350 & !type.equals(SearchType.renameContainer)); 351 352 IndexedContainer types = (IndexedContainer)m_resourceType.getContainerDataSource(); 353 types.removeAllContainerFilters(); 354 types.addContainerFilter( 355 type.isContentValuesOnly() ? CmsVaadinUtils.FILTER_XML_CONTENTS : CmsVaadinUtils.FILTER_NO_FOLDERS); 356 } 357 358 /** 359 * Calls the search for the given parameters.<p> 360 */ 361 void search() { 362 363 CmsSearchReplaceSettings settings = new CmsSearchReplaceSettings(); 364 settings.setSiteRoot((String)m_siteSelect.getValue()); 365 settings.setType((SearchType)m_searchType.getValue()); 366 settings.setPaths(Collections.singletonList(m_searchRoot.getValue())); 367 settings.setIgnoreSubSites(m_ignoreSubSites.getValue().booleanValue()); 368 I_CmsResourceType type = (I_CmsResourceType)m_resourceType.getValue(); 369 if (type != null) { 370 settings.setTypes(type.getTypeName()); 371 } 372 if (SearchType.resourcetype.equals(m_searchType.getValue()) 373 | SearchType.renameContainer.equals(m_searchType.getValue())) { 374 settings.setTypes( 375 CmsResourceTypeXmlContainerPage.getStaticTypeName() 376 + "," 377 + CmsResourceTypeXmlContainerPage.MODEL_GROUP_TYPE_NAME); 378 } 379 380 if (SearchType.renameContainer.equals(m_searchType.getValue())) { 381 try { 382 CmsObject cms = OpenCms.initCmsObject(A_CmsUI.getCmsObject()); 383 cms.getRequestContext().setSiteRoot(""); 384 CmsResource element = cms.readResource(m_resourceSearch.getValue()); 385 settings.setElementResource(element); 386 } catch (CmsException e) { 387 LOG.error("Can not read resource", e); 388 } 389 } 390 391 if (m_replace.getValue().booleanValue()) { 392 try { 393 CmsProject workProject = A_CmsUI.getCmsObject().readProject((CmsUUID)m_workProject.getValue()); 394 settings.setProject(workProject.getName()); 395 } catch (CmsException e) { 396 // ignore 397 } 398 if (SearchType.resourcetype.equals(m_searchType.getValue())) { 399 try { 400 CmsObject cms = OpenCms.initCmsObject(A_CmsUI.getCmsObject()); 401 cms.getRequestContext().setSiteRoot(""); 402 CmsResource resource = cms.readResource(m_replaceResource.getValue()); 403 settings.setReplacepattern(CmsSearchReplaceSettings.replaceElementInPagePattern(resource)); 404 } catch (CmsException e) { 405 LOG.error("Unable to read resource.", e); 406 } 407 } else if (SearchType.renameContainer.equals(m_searchType.getValue())) { 408 settings.setReplacepattern(m_oldName.getValue() + ";" + m_newName.getValue()); 409 } else { 410 411 settings.setReplacepattern(m_replacePattern.getValue()); 412 } 413 414 } 415 416 if (SearchType.resourcetype.equals(m_searchType.getValue()) 417 | SearchType.renameContainer.equals(m_searchType.getValue())) { 418 try { 419 CmsObject cms = OpenCms.initCmsObject(A_CmsUI.getCmsObject()); 420 cms.getRequestContext().setSiteRoot(""); 421 CmsResource resource = cms.readResource(m_resourceSearch.getValue()); 422 settings.setSearchpattern(CmsSearchReplaceSettings.searchElementInPagePattern(resource)); 423 } catch (CmsException e) { 424 LOG.error("Unable to read resource.", e); 425 } 426 } else { 427 428 settings.setSearchpattern(m_searchPattern.getValue()); 429 } 430 if (settings.getType().isContentValuesOnly()) { 431 if (m_locale.getValue() != null) { 432 settings.setLocale(m_locale.getValue().toString()); 433 } 434 settings.setXpath(m_xPath.getValue()); 435 } 436 if (settings.getType().isSolrSearch()) { 437 settings.setQuery(m_solrQuery.getValue()); 438 settings.setSource((String)m_searchIndex.getValue()); 439 } 440 441 if (settings.getType().isPropertySearch()) { 442 settings.setProperty((CmsPropertyDefinition)m_property.getValue()); 443 settings.setForceReplace(m_replace.getValue().booleanValue()); 444 } 445 446 m_app.search(settings, true); 447 } 448 449 /** 450 * Toggles the replace option.<p> 451 */ 452 void updateReplace() { 453 454 boolean replace = m_replace.getValue().booleanValue(); 455 456 m_replaceResource.setVisible(replace ? SearchType.resourcetype.equals(m_searchType.getValue()) : replace); 457 m_replacePattern.setVisible( 458 replace 459 ? !SearchType.resourcetype.equals(m_searchType.getValue()) 460 & !SearchType.renameContainer.equals(m_searchType.getValue()) 461 : replace); 462 463 m_newName.setVisible(replace ? SearchType.renameContainer.equals(m_searchType.getValue()) : replace); 464 m_oldName.setVisible(replace ? SearchType.renameContainer.equals(m_searchType.getValue()) : replace); 465 466 m_workProject.setVisible(replace); 467 468 m_search.setCaption( 469 replace 470 ? CmsVaadinUtils.getMessageText(Messages.GUI_SOURCESEARCH_REPLACE_0) 471 : CmsVaadinUtils.getMessageText(Messages.GUI_SOURCESEARCH_SEARCH_0)); 472 473 } 474 475 /** 476 * Initializes the form fields.<p> 477 */ 478 private void initFields() { 479 480 CmsObject cms = A_CmsUI.getCmsObject(); 481 boolean online = cms.getRequestContext().getCurrentProject().isOnlineProject(); 482 483 if (m_searchPattern.getValue().isEmpty()) { 484 m_searchPattern.setValue(REGEX_ALL); 485 } 486 m_resourceSearch.setUseRootPaths(true); 487 m_replaceResource.setUseRootPaths(true); 488 m_resourceSearch.requireFile(); 489 m_replaceResource.requireFile(); 490 CmsObject rootCms; 491 try { 492 rootCms = OpenCms.initCmsObject(cms); 493 494 rootCms.getRequestContext().setSiteRoot(""); 495 m_resourceSearch.setCmsObject(rootCms); 496 m_resourceSearch.setDefaultPath(cms.getRequestContext().getSiteRoot()); 497 m_replaceResource.setCmsObject(rootCms); 498 m_replaceResource.setDefaultPath(cms.getRequestContext().getSiteRoot()); 499 500 } catch (CmsException e1) { 501 // 502 } 503 m_siteSelect.setContainerDataSource( 504 CmsVaadinUtils.getAvailableSitesContainer(cms, CmsVaadinUtils.PROPERTY_LABEL)); 505 m_siteSelect.setItemCaptionPropertyId(CmsVaadinUtils.PROPERTY_LABEL); 506 m_siteSelect.setTextInputAllowed(true); 507 m_siteSelect.setNullSelectionAllowed(false); 508 m_siteSelect.setFilteringMode(FilteringMode.CONTAINS); 509 m_siteSelect.setValue(cms.getRequestContext().getSiteRoot()); 510 try { 511 for (CmsPropertyDefinition prop : A_CmsUI.getCmsObject().readAllPropertyDefinitions()) { 512 m_property.addItem(prop); 513 m_property.setItemCaption(prop, prop.getName()); 514 } 515 } catch (CmsException e) { 516 // 517 } 518 m_siteSelect.addValueChangeListener(new ValueChangeListener() { 519 520 private static final long serialVersionUID = -1079794209679015125L; 521 522 public void valueChange(ValueChangeEvent event) { 523 524 try { 525 updateSearchRoot(); 526 } catch (CmsException e) { 527 LOG.error("Unable to initialize CmsObject", e); 528 } 529 } 530 531 }); 532 m_property.setNullSelectionAllowed(false); 533 m_property.select(m_property.getItemIds().iterator().next()); 534 m_property.setFilteringMode(FilteringMode.CONTAINS); 535 m_searchType.setFilteringMode(FilteringMode.OFF); 536 m_searchType.setNullSelectionAllowed(false); 537 m_searchType.addItem(SearchType.fullText); 538 m_searchType.setItemCaption( 539 SearchType.fullText, 540 CmsVaadinUtils.getMessageText(Messages.GUI_SOURCESEARCH_SERACH_TYPE_FULLTEXT_0)); 541 m_searchType.addItem(SearchType.contentValues); 542 m_searchType.setItemCaption( 543 SearchType.contentValues, 544 CmsVaadinUtils.getMessageText(Messages.GUI_SOURCESEARCH_SERACH_TYPE_XMLCONTENT_0)); 545 m_searchType.addItem(SearchType.properties); 546 m_searchType.setItemCaption( 547 SearchType.properties, 548 CmsVaadinUtils.getMessageText(Messages.GUI_SOURCESEARCH_PROPERTY_SEARCH_0)); 549 m_searchType.addItem(SearchType.resourcetype); 550 m_searchType.setItemCaption( 551 SearchType.resourcetype, 552 CmsVaadinUtils.getMessageText(Messages.GUI_SOURCESEARCH_RESOURCE_SEARCH_0)); 553 m_searchType.addItem(SearchType.renameContainer); 554 m_searchType.setItemCaption( 555 SearchType.renameContainer, 556 CmsVaadinUtils.getMessageText(Messages.GUI_SOURCESEARCH_RENAME_CONTAINER_SEARCH_0)); 557 if (OpenCms.getSearchManager().getSolrServerConfiguration().isEnabled()) { 558 559 m_searchIndex.setFilteringMode(FilteringMode.OFF); 560 m_searchIndex.setNullSelectionAllowed(false); 561 String selectIndex = null; 562 for (CmsSearchIndex index : OpenCms.getSearchManager().getAllSolrIndexes()) { 563 boolean offlineMode = I_CmsSearchIndex.REBUILD_MODE_OFFLINE.equals(index.getRebuildMode()); 564 // in case the current project is offline, show offline indexes, otherwise show online indexes 565 if ((!online && offlineMode) || (online && !offlineMode)) { 566 m_searchIndex.addItem(index.getName()); 567 if (selectIndex == null) { 568 selectIndex = index.getName(); 569 } 570 } 571 } 572 if (selectIndex != null) { 573 m_searchIndex.setValue(selectIndex); 574 575 // only add the solr search types if there is an index available 576 m_searchType.addItem(SearchType.solr); 577 m_searchType.setItemCaption( 578 SearchType.solr, 579 CmsVaadinUtils.getMessageText(Messages.GUI_SOURCESEARCH_SERACH_TYPE_SOLR_0)); 580 m_searchType.addItem(SearchType.solrContentValues); 581 m_searchType.setItemCaption( 582 SearchType.solrContentValues, 583 CmsVaadinUtils.getMessageText(Messages.GUI_SOURCESEARCH_SERACH_TYPE_SOLR_CONTENT_VALUES_0)); 584 585 } 586 } 587 m_searchType.setValue(SearchType.fullText); 588 589 m_searchRoot.setValue("/"); 590 m_searchRoot.disableSiteSwitch(); 591 m_searchRoot.setResourceFilter(CmsResourceFilter.DEFAULT_FOLDERS); 592 m_searchRoot.requireFolder(); 593 m_locale.setFilteringMode(FilteringMode.OFF); 594 for (Locale locale : OpenCms.getLocaleManager().getAvailableLocales()) { 595 m_locale.addItem(locale); 596 } 597 598 m_resourceType.setNullSelectionAllowed(true); 599 IndexedContainer resTypes = CmsVaadinUtils.getResourceTypesContainer(); 600 resTypes.addContainerFilter(CmsVaadinUtils.FILTER_NO_FOLDERS); 601 602 m_resourceType.setContainerDataSource(resTypes); 603 m_resourceType.setItemCaptionPropertyId(PropertyId.caption); 604 m_resourceType.setItemIconPropertyId(PropertyId.icon); 605 m_resourceType.setFilteringMode(FilteringMode.CONTAINS); 606 607 m_workProject.setNullSelectionAllowed(false); 608 IndexedContainer projects = CmsVaadinUtils.getProjectsContainer(A_CmsUI.getCmsObject(), "caption"); 609 projects.removeItem(CmsProject.ONLINE_PROJECT_ID); 610 m_workProject.setContainerDataSource(projects); 611 m_workProject.setItemCaptionPropertyId("caption"); 612 613 if (online) { 614 m_replace.setEnabled(false); 615 } else { 616 m_workProject.setValue(cms.getRequestContext().getCurrentProject().getUuid()); 617 } 618 } 619}