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.LocalDateTime; 020import java.time.ZonedDateTime; 021import java.time.chrono.IsoChronology; 022import java.time.format.DateTimeFormatter; 023import java.time.format.ResolverStyle; 024import java.util.ArrayList; 025import java.util.Collection; 026import java.util.Date; 027import java.util.HashMap; 028import java.util.List; 029import java.util.Map; 030 031import org.apache.cocoon.ProcessingException; 032import org.apache.cocoon.xml.AttributesImpl; 033import org.apache.cocoon.xml.XMLUtils; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036import org.xml.sax.ContentHandler; 037import org.xml.sax.SAXException; 038 039import org.ametys.core.util.DateUtils; 040import org.ametys.runtime.i18n.I18nizableText; 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 LocalDateTime ldt = LocalDateTime.parse(value, DateTimeFormatter.ISO_DATE_TIME); 176 return DateUtils.asDate(ldt); 177 } 178 else if (type == ParameterType.BINARY) 179 { 180 return null; 181 } 182 } 183 catch (Exception nfe) 184 { 185 if (value.length() != 0) 186 { 187 _logger.error("Cannot cast value '" + value + "' into type '" + typeToString(type) + "'. Null object will be used.", nfe); 188 } 189 else if (_logger.isDebugEnabled()) 190 { 191 _logger.debug("Failed to cast empty string to type '" + typeToString(type) + "'. Null object will be used.", nfe); 192 } 193 } 194 return null; 195 } 196 197 198 /** 199 * Converts known types to string 200 * 201 * @param value Typed value 202 * @return String readable by the config bean 203 * @throws IllegalArgumentException if the object is a InputStream 204 */ 205 public static String valueToString(Object value) 206 { 207 if (value == null) 208 { 209 return null; 210 } 211 212 if (value instanceof Date) 213 { 214 ZonedDateTime zdt = DateUtils.asZonedDateTime((Date) value, null); 215 return zdt.format(getISODateTimeFormatter()); 216 } 217 218 if (value instanceof InputStream) 219 { 220 throw new IllegalArgumentException("The object to convert is an input stream"); 221 } 222 223 return value.toString(); 224 } 225 226 /** 227 * SAX a parameter 228 * @param handler The content handler where to SAX 229 * @param parameter The parameter to SAX 230 * @param value The parameter value. Can be null. 231 * @throws SAXException If an error occurred while SAXing 232 * @throws ProcessingException If an error occurred 233 */ 234 public static void toSAXParameter (ContentHandler handler, Parameter parameter, Object value) throws SAXException, ProcessingException 235 { 236 AttributesImpl parameterAttr = new AttributesImpl(); 237 parameterAttr.addAttribute("", "plugin", "plugin", "CDATA", parameter.getPluginName()); 238 XMLUtils.startElement(handler, parameter.getId(), parameterAttr); 239 240 toSAXParameterInternal(handler, parameter, value); 241 242 XMLUtils.endElement(handler, parameter.getId()); 243 } 244 245 /** 246 * SAX a parameter except the root tag 247 * @param handler The content handler where to SAX 248 * @param parameter The parameter to SAX 249 * @param value The parameter value. Can be null. 250 * @throws SAXException If an error occurred while SAXing 251 * @throws ProcessingException If an error occurred 252 */ 253 public static void toSAXParameterInternal(ContentHandler handler, Parameter parameter, Object value) throws SAXException, ProcessingException 254 { 255 parameter.getLabel().toSAX(handler, "label"); 256 parameter.getDescription().toSAX(handler, "description"); 257 258 XMLUtils.createElement(handler, "type", ParameterHelper.typeToString((ParameterType) parameter.getType())); 259 260 Object defaultValue = parameter.getDefaultValue(); 261 262 if (defaultValue != null) 263 { 264 XMLUtils.createElement(handler, "default-value", ParameterHelper.valueToString(defaultValue)); 265 } 266 267 if (value != null) 268 { 269 XMLUtils.createElement(handler, "value", ParameterHelper.valueToString(value)); 270 } 271 272 if (parameter.getWidget() != null) 273 { 274 XMLUtils.createElement(handler, "widget", parameter.getWidget()); 275 } 276 277 Map<String, I18nizableText> widgetParameters = parameter.getWidgetParameters(); 278 if (widgetParameters.size() > 0) 279 { 280 XMLUtils.startElement(handler, "widget-params"); 281 for (String paramName : widgetParameters.keySet()) 282 { 283 XMLUtils.startElement(handler, paramName); 284 widgetParameters.get(paramName).toSAX(handler); 285 XMLUtils.endElement(handler, paramName); 286 } 287 XMLUtils.endElement(handler, "widget-params"); 288 } 289 290 Enumerator enumerator = parameter.getEnumerator(); 291 if (enumerator != null) 292 { 293 toSAXEnumerator(handler, enumerator); 294 } 295 296 Validator validator = parameter.getValidator(); 297 toSAXValidator(handler, validator); 298 } 299 300 /** 301 * SAX parameter enumerator 302 * @param handler The content handler where to SAX 303 * @param enumerator The enumerator to SAX 304 * @throws SAXException If an error occurred to SAX 305 * @throws ProcessingException If an error occurred 306 */ 307 public static void toSAXEnumerator (ContentHandler handler, Enumerator enumerator) throws SAXException, ProcessingException 308 { 309 XMLUtils.startElement(handler, "enumeration"); 310 311 try 312 { 313 for (Map.Entry<Object, I18nizableText> entry : enumerator.getEntries().entrySet()) 314 { 315 String valueAsString = ParameterHelper.valueToString(entry.getKey()); 316 I18nizableText label = entry.getValue(); 317 318 // Generate option 319 AttributesImpl attrs = new AttributesImpl(); 320 attrs.addCDATAAttribute("value", valueAsString); 321 322 XMLUtils.startElement(handler, "option", attrs); 323 324 if (label != null) 325 { 326 label.toSAX(handler); 327 } 328 else 329 { 330 XMLUtils.data(handler, valueAsString); 331 } 332 333 XMLUtils.endElement(handler, "option"); 334 } 335 } 336 catch (Exception e) 337 { 338 throw new ProcessingException("Unable to enumerate entries with enumerator: " + enumerator, e); 339 } 340 341 XMLUtils.endElement(handler, "enumeration"); 342 } 343 344 /** 345 * SAX parameter validator 346 * @param handler The content handler where to SAX 347 * @param validator The validator to SAX 348 * @throws SAXException If an error occurred while SAXing 349 */ 350 public static void toSAXValidator (ContentHandler handler, Validator validator) throws SAXException 351 { 352 if (validator != null) 353 { 354 XMLUtils.startElement(handler, "validation"); 355 356 Map<String, Object> configuration = validator.getConfiguration(); 357 358 for (Map.Entry<String, Object> entry : configuration.entrySet()) 359 { 360 _saxConfigurationObject(handler, entry.getKey(), entry.getValue()); 361 } 362 363 XMLUtils.endElement(handler, "validation"); 364 } 365 } 366 367 @SuppressWarnings("unchecked") 368 private static void _saxConfigurationObject(ContentHandler handler, String name, Object value) throws SAXException 369 { 370 if (value instanceof I18nizableText) 371 { 372 ((I18nizableText) value).toSAX(handler, name); 373 } 374 else if (value instanceof Collection) 375 { 376 for (Object item : (Collection) value) 377 { 378 if (item != null) 379 { 380 _saxConfigurationObject(handler, name, item); 381 } 382 } 383 } 384 else if (value instanceof Map) 385 { 386 XMLUtils.startElement(handler, name); 387 for (Map.Entry<String, Object> subEntry : ((Map<String, Object>) value).entrySet()) 388 { 389 _saxConfigurationObject(handler, subEntry.getKey(), subEntry.getValue()); 390 } 391 XMLUtils.endElement(handler, name); 392 } 393 else if (value instanceof Object[]) 394 { 395 for (Object item : (Object[]) value) 396 { 397 if (item != null) 398 { 399 _saxConfigurationObject(handler, name, item); 400 } 401 } 402 } 403 else 404 { 405 XMLUtils.createElement(handler, name, String.valueOf(value)); 406 } 407 } 408 409 /** 410 * Convert the parameter in a JSON map 411 * @param parameter The parameter to convert 412 * @return The Parameter as a map 413 * @throws ProcessingException If an error occurred when converting the parameter 414 */ 415 @SuppressWarnings("unchecked") 416 public static Map<String, Object> toJSON(Parameter parameter) throws ProcessingException 417 { 418 ElementDefinition definition = new ElementDefinition(); 419 definition.setName(parameter.getId()); 420 definition.setLabel(parameter.getLabel()); 421 definition.setDescription(parameter.getDescription()); 422 definition.setPluginName(parameter.getPluginName()); 423 definition.setValidator(parameter.getValidator()); 424 definition.setWidget(parameter.getWidget()); 425 definition.setWidgetParameters(parameter.getWidgetParameters()); 426 427 Map<String, Object> result = definition.toJSON(); 428 429 // Put type from ParameterHelper.ParameterType to not convert from the old to the new API 430 result.put("type", parameter.getType().name()); 431 if (parameter.getDefaultValue() != null) 432 { 433 result.put("default-value", parameter.getDefaultValue()); 434 } 435 436 // Manage enumerator from ParameterHelper because enumerator class is not the same from Parameter to ElementDefintion 437 if (parameter.getEnumerator() != null) 438 { 439 Enumerator enumerator = parameter.getEnumerator(); 440 List<Map<String, Object>> enumeration = new ArrayList<>(); 441 442 try 443 { 444 Map<Object, I18nizableText> entries = enumerator.getEntries(); 445 for (Object entryKey : entries.keySet()) 446 { 447 Map<String, Object> option = new HashMap<>(); 448 option.put("value", ParameterHelper.valueToString(entryKey)); 449 option.put("label", entries.get(entryKey)); 450 enumeration.add(option); 451 } 452 } 453 catch (Exception e) 454 { 455 throw new ProcessingException("Unable to enumerate entries with enumerator: " + enumerator, e); 456 } 457 458 result.put("enumeration", enumeration); 459 result.put("enumerationConfig", enumerator.getConfiguration()); 460 } 461 462 return result; 463 } 464}