001/* 002 * Copyright 2010 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.cms.clientsideelement; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022 023import org.apache.avalon.framework.activity.Disposable; 024import org.apache.avalon.framework.component.ComponentException; 025import org.apache.avalon.framework.configuration.Configuration; 026import org.apache.avalon.framework.configuration.ConfigurationException; 027import org.apache.avalon.framework.context.Context; 028import org.apache.avalon.framework.context.ContextException; 029import org.apache.avalon.framework.context.Contextualizable; 030import org.apache.avalon.framework.service.ServiceException; 031import org.apache.avalon.framework.service.ServiceManager; 032 033import org.ametys.core.ui.StaticClientSideElement; 034import org.ametys.runtime.i18n.I18nizableText; 035import org.ametys.runtime.parameter.Enumerator; 036import org.ametys.runtime.parameter.StaticEnumerator; 037import org.ametys.runtime.plugin.component.ThreadSafeComponentManager; 038 039/** 040 * Search tool HMI item 041 */ 042public class SearchClientSideElement extends StaticClientSideElement implements Contextualizable, Disposable 043{ 044 /** Manager component for enumerators */ 045 protected ThreadSafeComponentManager<Enumerator> _enumeratorManager; 046 /** The service manager */ 047 protected ServiceManager _manager; 048 /** The context. */ 049 protected Context _context; 050 051 private int _criteriaIndex; 052 private int _columnIndex; 053 private int _nbColumns; 054 private int _propertyIndex; 055 056 private final Map<String, String> _enumeratorsToLookup = new HashMap<>(); 057 058 @Override 059 public void service(ServiceManager smanager) throws ServiceException 060 { 061 super.service(smanager); 062 _manager = smanager; 063 } 064 065 @Override 066 public void contextualize(Context context) throws ContextException 067 { 068 _context = context; 069 } 070 071 @Override 072 public void configure(Configuration configuration) throws ConfigurationException 073 { 074 _enumeratorManager = new ThreadSafeComponentManager<>(); 075 _enumeratorManager.setLogger(getLogger()); 076 _enumeratorManager.contextualize(_context); 077 _enumeratorManager.service(_manager); 078 079 super.configure(configuration); 080 081 _configureSearchCriteria(configuration.getChild("search-criteria")); 082 _configureColumns(configuration.getChild("columns")); 083 _configureProperties(configuration.getChild("property-mapping")); 084 _configurePageSize(configuration); 085 _configureSearchUrl(configuration); 086 _configureExportUrl(configuration); 087 088 try 089 { 090 _enumeratorManager.initialize(); 091 } 092 catch (Exception e) 093 { 094 throw new ConfigurationException("Unable to lookup parameter local components", configuration, e); 095 } 096 } 097 098 @Override 099 public List<Script> getScripts(boolean ignoreRights, Map<String, Object> contextParameters) 100 { 101 List<Script> scripts = super.getScripts(ignoreRights, contextParameters); 102 103 Map<String, Object> parameters = new HashMap<>(); 104 List<ScriptFile> cssFiles = new ArrayList<>(); 105 List<ScriptFile> scriptFiles = new ArrayList<>(); 106 for (Script script : scripts) 107 { 108 cssFiles.addAll(script.getCSSFiles()); 109 scriptFiles.addAll(script.getScriptFiles()); 110 parameters.putAll(script.getParameters()); 111 } 112 Script script = new Script(this.getId(), _script.getScriptClassname(), scriptFiles, cssFiles, parameters); 113 114 try 115 { 116 for (String prefix : _enumeratorsToLookup.keySet()) 117 { 118 String className = _enumeratorsToLookup.get(prefix); 119 try 120 { 121 Enumerator enumerator = _enumeratorManager.lookup(className); 122 123 setEnumeratorValues(script, enumerator, prefix); 124 } 125 catch (ComponentException e) 126 { 127 getLogger().error("Unable to instantiate enumerator for class: " + className, e); 128 } 129 } 130 } 131 catch (Exception e) 132 { 133 getLogger().error("Unable to lookup parameter local components", e); 134 } 135 136 List<Script> result = new ArrayList<>(); 137 result.add(script); 138 return result; 139 } 140 141 /** 142 * Configure the search criteria 143 * @param configuration The configuration 144 * @throws ConfigurationException if the configuration is not valid. 145 */ 146 protected void _configureSearchCriteria (Configuration configuration) throws ConfigurationException 147 { 148 for (Configuration criteriaConfiguration : configuration.getChildren("criteria")) 149 { 150 _configureCriteria (criteriaConfiguration, "criteria-" + _criteriaIndex); 151 _criteriaIndex++; 152 } 153 this._script.getParameters().put("criteria-size", _criteriaIndex); 154 this._script.getParameters().put("nb-columns", _nbColumns); 155 } 156 157 /** 158 * Configures the criteria parameters 159 * @param configuration the item configuration 160 * @param prefix the criteria prefix 161 * @throws ConfigurationException if the configuration is not valid. 162 */ 163 protected void _configureCriteria (Configuration configuration, String prefix) throws ConfigurationException 164 { 165 Map<String, Object> initialParameters = _script.getParameters(); 166 String name = configuration.getAttribute("name"); 167 String type = configuration.getAttribute("type", "string"); 168 int column = configuration.getAttributeAsInteger("column", 1); 169 I18nizableText label = _configureLabel(configuration); 170 String testOperator = configuration.getChild("test-operator", true).getValue("wd"); 171 String defaultValue = configuration.getChild("default-value", true).getValue(""); 172 boolean metadata = configuration.getAttributeAsBoolean("metadata", true); 173 boolean multiple = configuration.getAttributeAsBoolean("multiple", false); 174 boolean mandatory = configuration.getAttributeAsBoolean("mandatory", false); 175 boolean hidden = configuration.getAttributeAsBoolean("hidden", false); 176 Enumerator staticEnum = _configureEnumerator(configuration, prefix + "-enumerator"); 177 String widget = _configureWidget (configuration); 178 Map<String, Object> widgetParams = _configureWidgetParams(configuration); 179 String width = configuration.getChild("width", true).getValue(null); 180 181 initialParameters.put(prefix + "-name", name); 182 initialParameters.put(prefix + "-type", type); 183 initialParameters.put(prefix + "-column", column); 184 initialParameters.put(prefix + "-label", label); 185 initialParameters.put(prefix + "-test-operator", testOperator); 186 initialParameters.put(prefix + "-default-value", defaultValue); 187 initialParameters.put(prefix + "-metadata", metadata); 188 initialParameters.put(prefix + "-hidden", hidden); 189 initialParameters.put(prefix + "-multiple", multiple); 190 initialParameters.put(prefix + "-mandatory", mandatory); 191 192 if (width != null) 193 { 194 initialParameters.put(prefix + "-width", width); 195 } 196 197 if (widget != null) 198 { 199 initialParameters.put(prefix + "-widget", widget); 200 } 201 202 initialParameters.put(prefix + "-widget-param-size", widgetParams.size()); 203 204 if (widgetParams.size() > 0) 205 { 206 int i = 0; 207 for (String paramName : widgetParams.keySet()) 208 { 209 initialParameters.put(prefix + "-widget-param-" + i, paramName); 210 initialParameters.put(prefix + "-widget-param-" + i + "-value", widgetParams.get(paramName)); 211 i++; 212 } 213 } 214 215 if (staticEnum != null) 216 { 217 setEnumeratorValues(_script, staticEnum, prefix + "-enumerator"); 218 } 219 220 if (column > _nbColumns) 221 { 222 _nbColumns = column; 223 } 224 } 225 226 /** 227 * Set the enumerator values in script parameters 228 * @param script The script into which set the parameters 229 * @param enumerator The enumerator 230 * @param prefix The parameters prefix 231 */ 232 protected void setEnumeratorValues (Script script, Enumerator enumerator, String prefix) 233 { 234 try 235 { 236 script.getParameters().put(prefix, true); 237 Map<Object, I18nizableText> entries = enumerator.getEntries(); 238 int index = 0; 239 for (Object value : entries.keySet()) 240 { 241 script.getParameters().put(prefix + "-" + index + "-value", value); 242 if (entries.get(value) != null) 243 { 244 script.getParameters().put(prefix + "-" + index + "-label", entries.get(value)); 245 } 246 else 247 { 248 script.getParameters().put(prefix + "-" + "-label", value); 249 } 250 index++; 251 } 252 253 script.getParameters().put(prefix + "-size", index); 254 } 255 catch (Exception e) 256 { 257 getLogger().error("Unable to set values for enumerator " + enumerator.getClass().getName(), e); 258 } 259 } 260 /** 261 * Configure the columns 262 * @param configuration The configuration 263 * @throws ConfigurationException if the configuration is not valid. 264 */ 265 protected void _configureColumns (Configuration configuration) throws ConfigurationException 266 { 267 for (Configuration colConfiguration : configuration.getChildren("column")) 268 { 269 _configureColumn (colConfiguration, "column-" + _columnIndex); 270 _columnIndex++; 271 } 272 273 Configuration groupBy = configuration.getChild("group-by", false); 274 if (groupBy != null) 275 { 276 this._script.getParameters().put("group-by", groupBy.getValue()); 277 } 278 279 Configuration sortBy = configuration.getChild("sort-by", false); 280 if (sortBy != null) 281 { 282 this._script.getParameters().put("sort-by", sortBy.getValue()); 283 } 284 285 this._script.getParameters().put("column-size", _columnIndex); 286 } 287 288 /** 289 * Configures the criteria parameters 290 * @param configuration the item configuration 291 * @param prefix the criteria prefix 292 * @throws ConfigurationException if the configuration is not valid. 293 */ 294 protected void _configureColumn (Configuration configuration, String prefix) throws ConfigurationException 295 { 296 Map<String, Object> initialParameters = _script.getParameters(); 297 String id = configuration.getAttribute("id"); 298 I18nizableText label = _configureLabel(configuration); 299 String width = configuration.getChild("width", true).getValue(""); 300 301 initialParameters.put(prefix + "-id", id); 302 initialParameters.put(prefix + "-width", width); 303 initialParameters.put(prefix + "-label", label); 304 305 String renderFn = configuration.getChild("renderer", true).getValue(null); 306 if (renderFn != null) 307 { 308 initialParameters.put(prefix + "-renderer", renderFn); 309 } 310 311 boolean sortable = configuration.getAttributeAsBoolean("sortable", true); 312 boolean hideable = configuration.getAttributeAsBoolean("hideable", true); 313 boolean hidden = configuration.getAttributeAsBoolean("hidden", false); 314 315 initialParameters.put(prefix + "-sortable", sortable); 316 initialParameters.put(prefix + "-hideable", hideable); 317 initialParameters.put(prefix + "-hidden", hidden); 318 } 319 320 /** 321 * Configure the columns 322 * @param configuration The configuration 323 * @throws ConfigurationException if the configuration is not valid. 324 */ 325 protected void _configureProperties (Configuration configuration) throws ConfigurationException 326 { 327 for (Configuration propConfiguration : configuration.getChildren("property")) 328 { 329 _configureProperty (propConfiguration, "property-" + _propertyIndex); 330 _propertyIndex++; 331 } 332 this._script.getParameters().put("property-size", _propertyIndex); 333 } 334 335 /** 336 * Configures the criteria parameters 337 * @param configuration the item configuration 338 * @param prefix the criteria prefix 339 * @throws ConfigurationException if the configuration is not valid. 340 */ 341 protected void _configureProperty (Configuration configuration, String prefix) throws ConfigurationException 342 { 343 String id = configuration.getAttribute("id"); 344 String path = configuration.getAttribute("path"); 345 String type = configuration.getAttribute("type", "string"); 346 347 this._script.getParameters().put(prefix + "-id", id); 348 this._script.getParameters().put(prefix + "-path", path); 349 this._script.getParameters().put(prefix + "-type", type); 350 } 351 352 /** 353 * Configures the label. 354 * @param configuration the configuration to use. 355 * @return the i18n text. 356 * @throws ConfigurationException if the configuration is not valid. 357 */ 358 protected I18nizableText _configureLabel (Configuration configuration) throws ConfigurationException 359 { 360 Configuration labelConfig = configuration.getChild("label"); 361 boolean i18nSupported = labelConfig.getAttributeAsBoolean("i18n", false); 362 363 if (i18nSupported) 364 { 365 String catalogue = labelConfig.getAttribute("catalogue", null); 366 if (catalogue == null) 367 { 368 catalogue = "plugin." + _pluginName; 369 } 370 371 return new I18nizableText(catalogue, labelConfig.getValue()); 372 } 373 else 374 { 375 return new I18nizableText(labelConfig.getValue("")); 376 } 377 } 378 379 /** 380 * Configures the enumerator 381 * @param configuration The configuration to use 382 * @param prefix The prefix 383 * @return The static enumerator or null. 384 * @throws ConfigurationException If the configuraiton has an issue 385 */ 386 @SuppressWarnings("unchecked") 387 protected Enumerator _configureEnumerator (Configuration configuration, String prefix) throws ConfigurationException 388 { 389 Configuration enumeratorConfig = configuration.getChild("enumeration", false); 390 if (enumeratorConfig != null) 391 { 392 Configuration customEnumerator = enumeratorConfig.getChild("custom-enumerator", false); 393 if (customEnumerator != null) 394 { 395 String criterionName = configuration.getAttribute("name"); 396 String enumeratorClassName = customEnumerator.getAttribute("class"); 397 String role = criterionName + "$" + enumeratorClassName; 398 399 try 400 { 401 Class enumeratorClass = Class.forName(enumeratorClassName); 402 _enumeratorManager.addComponent(_pluginName, null, role, enumeratorClass, configuration); 403 } 404 catch (Exception e) 405 { 406 throw new ConfigurationException("Unable to instantiate enumerator for class: " + enumeratorClassName, e); 407 } 408 409 _enumeratorsToLookup.put(prefix, role); 410 } 411 else 412 { 413 StaticEnumerator staticEnumerator = new StaticEnumerator(); 414 for (Configuration entryConfig : enumeratorConfig.getChildren("entry")) 415 { 416 String value = entryConfig.getChild("value").getValue(""); 417 I18nizableText label = null; 418 419 if (entryConfig.getChild("label", false) != null) 420 { 421 label = _configureLabel(entryConfig); 422 } 423 staticEnumerator.add(label, value); 424 } 425 return staticEnumerator; 426 } 427 } 428 429 return null; 430 } 431 432 /** 433 * Configures the widget 434 * @param configuration The configuration to use 435 * @return The widget id 436 * @throws ConfigurationException if the configuration is not valid. 437 */ 438 protected String _configureWidget (Configuration configuration) throws ConfigurationException 439 { 440 Configuration widgetConfig = configuration.getChild("widget", false); 441 if (widgetConfig != null) 442 { 443 return widgetConfig.getValue("*"); 444 } 445 446 return null; 447 } 448 449 /** 450 * Configures the widget 451 * @param configuration The configuration to use 452 * @return The widget id 453 * @throws ConfigurationException if the configuration is not valid. 454 */ 455 protected Map<String, Object> _configureWidgetParams (Configuration configuration) throws ConfigurationException 456 { 457 Map<String, Object> widgetParams = new HashMap<>(); 458 459 Configuration widgetConfig = configuration.getChild("widget-params", false); 460 if (widgetConfig != null) 461 { 462 Configuration[] params = widgetConfig.getChildren("param"); 463 for (Configuration paramConfig : params) 464 { 465 boolean i18nSupported = paramConfig.getAttributeAsBoolean("i18n", false); 466 if (i18nSupported) 467 { 468 String catalogue = paramConfig.getAttribute("catalogue", null); 469 if (catalogue == null) 470 { 471 catalogue = "plugin." + _pluginName; 472 } 473 474 widgetParams.put(paramConfig.getAttribute("name"), new I18nizableText(catalogue, paramConfig.getValue())); 475 } 476 else 477 { 478 widgetParams.put(paramConfig.getAttribute("name"), paramConfig.getValue("")); 479 } 480 } 481 } 482 483 return widgetParams; 484 } 485 486 /** 487 * Configures the result page size. 488 * @param configuration the configuration to use. 489 * @throws ConfigurationException if the configuration is not valid. 490 */ 491 protected void _configurePageSize (Configuration configuration) throws ConfigurationException 492 { 493 Configuration pageSizeConfig = configuration.getChild("nb-result-per-page", false); 494 if (pageSizeConfig != null) 495 { 496 this._script.getParameters().put("page-size", pageSizeConfig.getValue()); 497 } 498 } 499 500 /** 501 * Configure the URL used for search 502 * @param configuration The configuration to use. 503 * @throws ConfigurationException if the configuration is not valid. 504 */ 505 protected void _configureSearchUrl (Configuration configuration) throws ConfigurationException 506 { 507 Configuration urlConfig = configuration.getChild("search-url", false); 508 if (urlConfig != null) 509 { 510 String pluginName = urlConfig.getAttribute("plugin", _pluginName); 511 this._script.getParameters().put("search-url", "/plugins/" + pluginName + "/" + urlConfig.getValue()); 512 } 513 } 514 515 /** 516 * Configure the URL used for XSL export 517 * @param configuration The configuration to use. 518 * @throws ConfigurationException if the configuration is not valid. 519 */ 520 protected void _configureExportUrl (Configuration configuration) throws ConfigurationException 521 { 522 Configuration urlConfig = configuration.getChild("export-url", false); 523 if (urlConfig != null) 524 { 525 String pluginName = urlConfig.getAttribute("plugin", _pluginName); 526 this._script.getParameters().put("export-url", "/plugins/" + pluginName + "/" + urlConfig.getValue()); 527 } 528 } 529 530 @Override 531 public void dispose() 532 { 533 _enumeratorManager.dispose(); 534 _enumeratorManager = null; 535 } 536}