001/* 002 * Copyright 2022 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.plugins.forms.processing; 017 018import java.io.File; 019import java.time.LocalDate; 020import java.time.ZoneId; 021import java.time.ZoneOffset; 022import java.time.ZonedDateTime; 023import java.time.chrono.IsoChronology; 024import java.time.format.DateTimeFormatter; 025import java.util.ArrayList; 026import java.util.List; 027import java.util.Map; 028 029import org.apache.avalon.framework.service.ServiceException; 030import org.apache.avalon.framework.service.ServiceManager; 031import org.apache.cocoon.generation.ServiceableGenerator; 032import org.apache.cocoon.xml.AttributesImpl; 033import org.apache.cocoon.xml.XMLUtils; 034import org.apache.commons.lang.StringUtils; 035import org.xml.sax.SAXException; 036 037import org.ametys.core.util.DateUtils; 038import org.ametys.plugins.forms.Field; 039import org.ametys.plugins.forms.data.FieldValue; 040import org.ametys.plugins.forms.jcr.FormPropertiesManager; 041 042/** 043 * Abstract generator to sax form entry values 044 * 045 */ 046public abstract class AbstractFormFieldGenerator extends ServiceableGenerator 047{ 048 /** The form properties manager */ 049 protected FormPropertiesManager _formPropManager; 050 051 @Override 052 public void service(ServiceManager smanager) throws ServiceException 053 { 054 super.service(smanager); 055 _formPropManager = (FormPropertiesManager) smanager.lookup(FormPropertiesManager.ROLE); 056 } 057 058 /** 059 * Sax a field value 060 * @param fdValue the field value 061 * @throws SAXException if an error occurred while saxing 062 */ 063 protected void saxFieldValue(FieldValue fdValue) throws SAXException 064 { 065 saxFieldValue("field", fdValue); 066 } 067 068 /** 069 * Sax a field value 070 * @param tagName the root tag name 071 * @param fdValue the field value 072 * @throws SAXException if an error occurred while saxing 073 */ 074 protected void saxFieldValue(String tagName, FieldValue fdValue) throws SAXException 075 { 076 Field field = fdValue.getField(); 077 Object rawValue = fdValue.getValue(); 078 079 String value = _getReadableValue(field, rawValue); 080 081 if (value != null) 082 { 083 AttributesImpl atts = new AttributesImpl(); 084 atts.addCDATAAttribute("label", field.getLabel()); 085 atts.addCDATAAttribute("name", field.getName()); 086 atts.addCDATAAttribute("columnName", fdValue.getColumnName()); 087 atts.addCDATAAttribute("type", field.getType().name()); 088 089 Map<String, String> properties = field.getProperties(); 090 if (properties.containsKey("regexptype")) 091 { 092 atts.addCDATAAttribute("regexptype", properties.get("regexptype")); 093 } 094 095 XMLUtils.createElement(contentHandler, tagName, atts, value); 096 } 097 } 098 099 /** 100 * Get the readable value as String 101 * @param field the field 102 * @param rawValue the raw value. Cannot be null. 103 * @return the value as String 104 */ 105 protected String _getReadableValue(Field field, Object rawValue) 106 { 107 if (rawValue == null) 108 { 109 return null; 110 } 111 112 switch (field.getType()) 113 { 114 case SELECT: 115 boolean multiple = "true".equals(field.getProperties().get("multiple")); 116 if (multiple) 117 { 118 String[] rawValues = ((String) rawValue).split("\n"); 119 List<String> readableValues = new ArrayList<>(); 120 for (String v : rawValues) 121 { 122 readableValues.add(_formPropManager.getDisplayValue(field, v)); 123 } 124 return StringUtils.join(readableValues, ", "); 125 } 126 else 127 { 128 return _formPropManager.getDisplayValue(field, (String) rawValue); 129 } 130 case RADIO: 131 return _formPropManager.getDisplayValue(field, (String) rawValue); 132 case TEXT: 133 String typedValue = StringUtils.trim((String) rawValue); 134 String regexptype = field.getProperties().get("regexptype"); 135 if ("datetime".equals(regexptype) && StringUtils.isNotEmpty(typedValue)) 136 { 137 ZonedDateTime date = _getZonedDateTime(typedValue); 138 if (date == null) 139 { 140 LocalDate localDate = _getLocalDate(typedValue); 141 return localDate != null ? DateUtils.zonedDateTimeToString(localDate.atStartOfDay(ZoneOffset.UTC)) : null; 142 } 143 return DateUtils.zonedDateTimeToString(date); 144 } 145 else if ("date".equals(regexptype) && StringUtils.isNotEmpty(typedValue)) 146 { 147 LocalDate localDate = _getLocalDate(typedValue); 148 if (localDate == null) 149 { 150 ZonedDateTime date = _getZonedDateTime(typedValue); 151 return date != null ? DateUtils.localDateToString(date.toLocalDate()) : null; 152 } 153 return DateUtils.localDateToString(localDate); 154 } 155 else 156 { 157 // Trim value since some rendering (including default rendering) add many leading spaces 158 return typedValue; 159 } 160 case FILE: 161 if (rawValue instanceof File) 162 { 163 File file = (File) rawValue; 164 return file.getName(); 165 } 166 else 167 { 168 return String.valueOf(rawValue); 169 } 170 case PASSWORD: 171 case CAPTCHA: 172 // ignore value 173 return null; 174 default: 175 return String.valueOf(rawValue); 176 } 177 } 178 179 /** 180 * Get the zoned date time from string value 181 * @param value the string value 182 * @return the zoned date time. Null if string value can't be parsed 183 */ 184 protected ZonedDateTime _getZonedDateTime(String value) 185 { 186 try 187 { 188 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm") 189 .withZone(ZoneId.systemDefault()) 190 .withChronology(IsoChronology.INSTANCE); 191 192 return ZonedDateTime.parse(value, formatter); 193 } 194 catch (Exception e) 195 { 196 return null; 197 } 198 } 199 200 /** 201 * Get the local date from string value 202 * @param value the string value 203 * @return the local date time. Null if string value can't be parsed 204 */ 205 protected LocalDate _getLocalDate(String value) 206 { 207 try 208 { 209 return DateUtils.parseLocalDate(value); 210 } 211 catch (Exception e) 212 { 213 return null; 214 } 215 } 216}