001/* 002 * Copyright 2014 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.runtime.parameter; 017 018import java.io.InputStream; 019import java.time.ZonedDateTime; 020import java.time.chrono.IsoChronology; 021import java.time.format.DateTimeFormatter; 022import java.time.format.ResolverStyle; 023import java.util.ArrayList; 024import java.util.Collection; 025import java.util.Date; 026import java.util.HashMap; 027import java.util.List; 028import java.util.Map; 029 030import org.apache.cocoon.ProcessingException; 031import org.apache.cocoon.xml.AttributesImpl; 032import org.apache.cocoon.xml.XMLUtils; 033import org.slf4j.Logger; 034import org.slf4j.LoggerFactory; 035import org.xml.sax.ContentHandler; 036import org.xml.sax.SAXException; 037 038import org.ametys.core.util.DateUtils; 039import org.ametys.runtime.i18n.I18nizableText; 040import org.ametys.runtime.model.DefinitionContext; 041import org.ametys.runtime.model.ElementDefinition; 042import org.ametys.runtime.model.type.ElementType; 043 044 045/** 046 * This class handles all needed to use typed parameters 047 * @deprecated All of this helper methods are now in the new Parameter API classes 048 */ 049@Deprecated 050public final class ParameterHelper 051{ 052 /** 053 * Enumeration of supported types 054 * @deprecated Use {@link ElementType} 055 */ 056 @Deprecated 057 public static enum ParameterType 058 { 059 /** boolean values */ 060 BOOLEAN, 061 /** string values */ 062 STRING, 063 /** password values */ 064 PASSWORD, 065 /** long values */ 066 LONG, 067 /** double values */ 068 DOUBLE, 069 /** date values */ 070 DATE, 071 /** binary values */ 072 BINARY, 073 /** datasource values */ 074 DATASOURCE 075 } 076 077 /** 078 * The ISO date-time formatter that formats or parses a date-time with an offset, such as '2011-12-03T10:15:30.000+01:00'. 079 */ 080 private static DateTimeFormatter __ISO_OFFSET_DATE_TIME = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX").withResolverStyle(ResolverStyle.STRICT).withChronology(IsoChronology.INSTANCE); 081 082 // Logger for traces 083 private static Logger _logger = LoggerFactory.getLogger(ParameterHelper.class); 084 085 private ParameterHelper () 086 { 087 // empty 088 } 089 090 /** 091 * Get the ISO date-time formatter that formats or parses a date-time with an offset, such as '2011-12-03T10:15:30.000+01:00'. 092 * This formatter is similar to {@link DateTimeFormatter#ISO_OFFSET_DATE_TIME} but force 3-digits milliseconds. 093 * @return ISO date-time formatter 094 */ 095 public static DateTimeFormatter getISODateTimeFormatter() 096 { 097 return __ISO_OFFSET_DATE_TIME; 098 } 099 100 /** 101 * Return the readable name of a type 102 * 103 * @param type Type to convert 104 * @return Returns the name of the type 105 * @throws IllegalArgumentException If the type is unknwon 106 */ 107 public static String typeToString(ParameterType type) 108 { 109 return type.name().toLowerCase(); 110 } 111 112 /** 113 * Convert a string containing a type to its value 114 * 115 * @param type Name of the type 116 * @return Type 117 * @throws IllegalArgumentException if the type is unknown 118 */ 119 public static ParameterType stringToType(String type) 120 { 121 try 122 { 123 return ParameterType.valueOf(type.toUpperCase()); 124 } 125 catch (IllegalArgumentException e) 126 { 127 throw new IllegalArgumentException("The type '" + type + "' is unknown for config parameters"); 128 } 129 } 130 131 /** 132 * Cast a untyped value (string) to an object of the type 133 * 134 * @param value Value to cast 135 * @param type Type to cast value in 136 * @return An object of the type 'type' with value 'value', or null if type 137 * is unknown or value cannot be cast 138 */ 139 public static Object castValue(String value, ParameterType type) 140 { 141 142 if (value == null) 143 { 144 return null; 145 } 146 147 try 148 { 149 if (type == ParameterType.BOOLEAN) 150 { 151 return new Boolean(value); 152 } 153 else if (type == ParameterType.STRING) 154 { 155 return value; 156 } 157 else if (type == ParameterType.PASSWORD) 158 { 159 return value; 160 } 161 else if (type == ParameterType.DATASOURCE) 162 { 163 return value; 164 } 165 else if (type == ParameterType.LONG) 166 { 167 return new Long(value); 168 } 169 else if (type == ParameterType.DOUBLE) 170 { 171 return new Double(value); 172 } 173 else if (type == ParameterType.DATE) 174 { 175 return DateUtils.parse(value); 176 } 177 else if (type == ParameterType.BINARY) 178 { 179 return null; 180 } 181 } 182 catch (Exception nfe) 183 { 184 if (value.length() != 0) 185 { 186 _logger.error("Cannot cast value '" + value + "' into type '" + typeToString(type) + "'. Null object will be used.", nfe); 187 } 188 else if (_logger.isDebugEnabled()) 189 { 190 _logger.debug("Failed to cast empty string to type '" + typeToString(type) + "'. Null object will be used.", nfe); 191 } 192 } 193 return null; 194 } 195 196 197 /** 198 * Converts known types to string 199 * 200 * @param value Typed value 201 * @return String readable by the config bean 202 * @throws IllegalArgumentException if the object is a InputStream 203 */ 204 public static String valueToString(Object value) 205 { 206 if (value == null) 207 { 208 return null; 209 } 210 211 if (value instanceof Date) 212 { 213 ZonedDateTime zdt = DateUtils.asZonedDateTime((Date) value, null); 214 return zdt.format(getISODateTimeFormatter()); 215 } 216 217 if (value instanceof InputStream) 218 { 219 throw new IllegalArgumentException("The object to convert is an input stream"); 220 } 221 222 return value.toString(); 223 } 224 225 /** 226 * SAX a parameter 227 * @param handler The content handler where to SAX 228 * @param parameter The parameter to SAX 229 * @param value The parameter value. Can be null. 230 * @throws SAXException If an error occurred while SAXing 231 * @throws ProcessingException If an error occurred 232 */ 233 public static void toSAXParameter (ContentHandler handler, Parameter parameter, Object value) throws SAXException, ProcessingException 234 { 235 AttributesImpl parameterAttr = new AttributesImpl(); 236 parameterAttr.addAttribute("", "plugin", "plugin", "CDATA", parameter.getPluginName()); 237 XMLUtils.startElement(handler, parameter.getId(), parameterAttr); 238 239 toSAXParameterInternal(handler, parameter, value); 240 241 XMLUtils.endElement(handler, parameter.getId()); 242 } 243 244 /** 245 * SAX a parameter except the root tag 246 * @param handler The content handler where to SAX 247 * @param parameter The parameter to SAX 248 * @param value The parameter value. Can be null. 249 * @throws SAXException If an error occurred while SAXing 250 * @throws ProcessingException If an error occurred 251 */ 252 public static void toSAXParameterInternal(ContentHandler handler, Parameter parameter, Object value) throws SAXException, ProcessingException 253 { 254 parameter.getLabel().toSAX(handler, "label"); 255 parameter.getDescription().toSAX(handler, "description"); 256 257 XMLUtils.createElement(handler, "type", ParameterHelper.typeToString((ParameterType) parameter.getType())); 258 259 Object defaultValue = parameter.getDefaultValue(); 260 261 if (defaultValue != null) 262 { 263 XMLUtils.createElement(handler, "default-value", ParameterHelper.valueToString(defaultValue)); 264 } 265 266 if (value != null) 267 { 268 XMLUtils.createElement(handler, "value", ParameterHelper.valueToString(value)); 269 } 270 271 if (parameter.getWidget() != null) 272 { 273 XMLUtils.createElement(handler, "widget", parameter.getWidget()); 274 } 275 276 Map<String, I18nizableText> widgetParameters = parameter.getWidgetParameters(); 277 if (widgetParameters.size() > 0) 278 { 279 XMLUtils.startElement(handler, "widget-params"); 280 for (String paramName : widgetParameters.keySet()) 281 { 282 XMLUtils.startElement(handler, paramName); 283 widgetParameters.get(paramName).toSAX(handler); 284 XMLUtils.endElement(handler, paramName); 285 } 286 XMLUtils.endElement(handler, "widget-params"); 287 } 288 289 Enumerator enumerator = parameter.getEnumerator(); 290 if (enumerator != null) 291 { 292 toSAXEnumerator(handler, enumerator); 293 } 294 295 Validator validator = parameter.getValidator(); 296 toSAXValidator(handler, validator); 297 } 298 299 /** 300 * SAX parameter enumerator 301 * @param handler The content handler where to SAX 302 * @param enumerator The enumerator to SAX 303 * @throws SAXException If an error occurred to SAX 304 * @throws ProcessingException If an error occurred 305 */ 306 public static void toSAXEnumerator (ContentHandler handler, Enumerator enumerator) throws SAXException, ProcessingException 307 { 308 XMLUtils.startElement(handler, "enumeration"); 309 310 try 311 { 312 for (Map.Entry<Object, I18nizableText> entry : enumerator.getEntries().entrySet()) 313 { 314 String valueAsString = ParameterHelper.valueToString(entry.getKey()); 315 I18nizableText label = entry.getValue(); 316 317 // Generate option 318 AttributesImpl attrs = new AttributesImpl(); 319 attrs.addCDATAAttribute("value", valueAsString); 320 321 XMLUtils.startElement(handler, "option", attrs); 322 323 if (label != null) 324 { 325 label.toSAX(handler); 326 } 327 else 328 { 329 XMLUtils.data(handler, valueAsString); 330 } 331 332 XMLUtils.endElement(handler, "option"); 333 } 334 } 335 catch (Exception e) 336 { 337 throw new ProcessingException("Unable to enumerate entries with enumerator: " + enumerator, e); 338 } 339 340 XMLUtils.endElement(handler, "enumeration"); 341 } 342 343 /** 344 * SAX parameter validator 345 * @param handler The content handler where to SAX 346 * @param validator The validator to SAX 347 * @throws SAXException If an error occurred while SAXing 348 */ 349 public static void toSAXValidator (ContentHandler handler, Validator validator) throws SAXException 350 { 351 if (validator != null) 352 { 353 XMLUtils.startElement(handler, "validation"); 354 355 Map<String, Object> configuration = validator.getConfiguration(); 356 357 for (Map.Entry<String, Object> entry : configuration.entrySet()) 358 { 359 _saxConfigurationObject(handler, entry.getKey(), entry.getValue()); 360 } 361 362 XMLUtils.endElement(handler, "validation"); 363 } 364 } 365 366 @SuppressWarnings("unchecked") 367 private static void _saxConfigurationObject(ContentHandler handler, String name, Object value) throws SAXException 368 { 369 if (value instanceof I18nizableText) 370 { 371 ((I18nizableText) value).toSAX(handler, name); 372 } 373 else if (value instanceof Collection) 374 { 375 for (Object item : (Collection) value) 376 { 377 if (item != null) 378 { 379 _saxConfigurationObject(handler, name, item); 380 } 381 } 382 } 383 else if (value instanceof Map) 384 { 385 XMLUtils.startElement(handler, name); 386 for (Map.Entry<String, Object> subEntry : ((Map<String, Object>) value).entrySet()) 387 { 388 _saxConfigurationObject(handler, subEntry.getKey(), subEntry.getValue()); 389 } 390 XMLUtils.endElement(handler, name); 391 } 392 else if (value instanceof Object[]) 393 { 394 for (Object item : (Object[]) value) 395 { 396 if (item != null) 397 { 398 _saxConfigurationObject(handler, name, item); 399 } 400 } 401 } 402 else 403 { 404 XMLUtils.createElement(handler, name, String.valueOf(value)); 405 } 406 } 407 408 /** 409 * Convert the parameter in a JSON map 410 * @param parameter The parameter to convert 411 * @return The Parameter as a map 412 * @throws ProcessingException If an error occurred when converting the parameter 413 */ 414 public static Map<String, Object> toJSON(Parameter parameter) throws ProcessingException 415 { 416 ElementDefinition definition = new ElementDefinition(); 417 definition.setName(parameter.getId()); 418 definition.setLabel(parameter.getLabel()); 419 definition.setDescription(parameter.getDescription()); 420 definition.setPluginName(parameter.getPluginName()); 421 definition.setValidator(parameter.getValidator()); 422 definition.setWidget(parameter.getWidget()); 423 definition.setWidgetParameters(parameter.getWidgetParameters()); 424 425 Map<String, Object> result = definition.toJSON(DefinitionContext.newInstance()); 426 427 // Put type from ParameterHelper.ParameterType to not convert from the old to the new API 428 result.put("type", parameter.getType().name().replaceAll("_", "-")); 429 if (parameter.getDefaultValue() != null) 430 { 431 result.put("default-value", parameter.getDefaultValue()); 432 } 433 434 // Manage enumerator from ParameterHelper because enumerator class is not the same from Parameter to ElementDefintion 435 if (parameter.getEnumerator() != null) 436 { 437 Enumerator enumerator = parameter.getEnumerator(); 438 List<Map<String, Object>> enumeration = new ArrayList<>(); 439 440 try 441 { 442 Map<Object, I18nizableText> entries = enumerator.getEntries(); 443 for (Object entryKey : entries.keySet()) 444 { 445 Map<String, Object> option = new HashMap<>(); 446 option.put("value", ParameterHelper.valueToString(entryKey)); 447 option.put("label", entries.get(entryKey)); 448 enumeration.add(option); 449 } 450 } 451 catch (Exception e) 452 { 453 throw new ProcessingException("Unable to enumerate entries with enumerator: " + enumerator, e); 454 } 455 456 result.put("enumeration", enumeration); 457 result.put("enumerationConfig", enumerator.getConfiguration()); 458 } 459 460 return result; 461 } 462}