001/* 002 * (C) Copyright 2010 Nuxeo SA (http://nuxeo.com/) and others. 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 * 016 * Contributors: 017 * Anahide Tchertchian 018 */ 019package org.nuxeo.ecm.platform.forms.layout.demo.jsf; 020 021import java.io.Serializable; 022import java.util.ArrayList; 023import java.util.HashMap; 024import java.util.List; 025import java.util.Map; 026 027import javax.faces.application.FacesMessage; 028import javax.faces.component.UIComponent; 029import javax.faces.context.FacesContext; 030import javax.faces.validator.ValidatorException; 031 032import org.apache.commons.lang3.StringUtils; 033import org.nuxeo.ecm.platform.forms.layout.api.FieldDefinition; 034import org.nuxeo.ecm.platform.forms.layout.api.WidgetDefinition; 035import org.nuxeo.ecm.platform.forms.layout.api.impl.FieldDefinitionImpl; 036 037/** 038 * Collects information to generate a layout definition from user information. 039 * 040 * @author Anahide Tchertchian 041 * @since 5.4 042 */ 043public class PreviewLayoutDefinition implements Serializable { 044 045 private static final long serialVersionUID = 1L; 046 047 protected final String widgetType; 048 049 protected final List<String> fields; 050 051 protected String label; 052 053 protected String helpLabel; 054 055 protected Boolean translated; 056 057 protected Boolean handlingLabels; 058 059 protected Map<String, Serializable> defaultProperties; 060 061 protected Map<String, Serializable> properties; 062 063 protected List<Map<String, Serializable>> customProperties; 064 065 protected List<WidgetDefinition> subWidgets; 066 067 public PreviewLayoutDefinition(String widgetType, List<String> fields, Map<String, Serializable> defaultProperties) { 068 super(); 069 this.widgetType = widgetType; 070 this.fields = fields; 071 this.defaultProperties = defaultProperties; 072 } 073 074 public String getWidgetType() { 075 return widgetType; 076 } 077 078 public List<String> getFields() { 079 return fields; 080 } 081 082 public List<FieldDefinition> getFieldDefinitions() { 083 if (fields != null) { 084 List<FieldDefinition> res = new ArrayList<FieldDefinition>(); 085 for (String field : fields) { 086 res.add(new FieldDefinitionImpl(null, field)); 087 } 088 return res; 089 } 090 return null; 091 } 092 093 public String getLabel() { 094 return label; 095 } 096 097 public void setLabel(String label) { 098 this.label = label; 099 } 100 101 public String getHelpLabel() { 102 return helpLabel; 103 } 104 105 public void setHelpLabel(String helpLabel) { 106 this.helpLabel = helpLabel; 107 } 108 109 public Boolean getTranslated() { 110 return translated; 111 } 112 113 public void setTranslated(Boolean translated) { 114 this.translated = translated; 115 } 116 117 public Boolean getHandlingLabels() { 118 return handlingLabels; 119 } 120 121 public void setHandlingLabels(Boolean handlingLabels) { 122 this.handlingLabels = handlingLabels; 123 } 124 125 public List<WidgetDefinition> getSubWidgets() { 126 return subWidgets; 127 } 128 129 public void setSubWidgets(List<WidgetDefinition> subWidgets) { 130 this.subWidgets = subWidgets; 131 } 132 133 public Map<String, Serializable> getProperties() { 134 if (properties == null) { 135 properties = new HashMap<String, Serializable>(); 136 // fill with default properties 137 if (defaultProperties != null) { 138 properties.putAll(defaultProperties); 139 } 140 } 141 return properties; 142 } 143 144 public void setProperties(Map<String, Serializable> properties) { 145 this.properties = properties; 146 } 147 148 public List<Map<String, Serializable>> getCustomProperties() { 149 if (customProperties == null) { 150 customProperties = new ArrayList<Map<String, Serializable>>(); 151 } 152 return customProperties; 153 } 154 155 public void setCustomProperties(List<Map<String, Serializable>> customProperties) { 156 this.customProperties = customProperties; 157 } 158 159 public Map<String, Serializable> getWidgetProperties() { 160 Map<String, Serializable> widgetProps = new HashMap<String, Serializable>(); 161 Map<String, Serializable> props = getProperties(); 162 if (props != null) { 163 widgetProps.putAll(props); 164 } 165 List<Map<String, Serializable>> customProps = getCustomProperties(); 166 if (customProps != null) { 167 widgetProps.putAll(convertCustomProperties(customProps, true)); 168 } 169 return cleanUpProperties(widgetProps); 170 } 171 172 /** 173 * Removes empty properties as the JSF component may not accept empty values for some properties like "converter" or 174 * "validator". 175 */ 176 protected Map<String, Serializable> cleanUpProperties(Map<String, Serializable> props) { 177 Map<String, Serializable> res = new HashMap<String, Serializable>(); 178 if (props != null) { 179 for (Map.Entry<String, Serializable> prop : props.entrySet()) { 180 Serializable value = prop.getValue(); 181 if (value == null || (value instanceof String && StringUtils.isEmpty((String) value))) { 182 continue; 183 } 184 res.put(prop.getKey(), value); 185 } 186 } 187 return res; 188 } 189 190 public Map<String, Serializable> getNewCustomProperty() { 191 Map<String, Serializable> prop = new HashMap<String, Serializable>(); 192 prop.put("key", null); 193 prop.put("value", null); 194 return prop; 195 } 196 197 protected Map<String, Serializable> convertCustomProperties(List<Map<String, Serializable>> listProps, 198 boolean ignoreErrors) throws ValidatorException { 199 Map<String, Serializable> values = new HashMap<String, Serializable>(); 200 if (listProps != null) { 201 for (Map<String, Serializable> entry : listProps) { 202 String key = (String) entry.get("key"); 203 Serializable value = entry.get("value"); 204 if (key == null || key.trim().length() == 0) { 205 if (ignoreErrors) { 206 continue; 207 } 208 FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Invalid empty key", null); 209 throw new ValidatorException(message); 210 } 211 if (values.containsKey(key)) { 212 if (ignoreErrors) { 213 continue; 214 } 215 FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, String.format( 216 "Duplicate key '%s'", key), null); 217 throw new ValidatorException(message); 218 } 219 values.put(key, value); 220 } 221 } 222 return values; 223 } 224 225 @SuppressWarnings({ "unchecked", "rawtypes" }) 226 public void validateCustomProperties(FacesContext context, UIComponent component, Object value) { 227 if (value != null && !(value instanceof List)) { 228 FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Invalid value: " + value, null); 229 // also add global message 230 context.addMessage(null, message); 231 throw new ValidatorException(message); 232 } 233 List<Map<String, Serializable>> listValue = (List) value; 234 // will throw an error 235 convertCustomProperties(listValue, false); 236 } 237 238}