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 static org.jboss.seam.ScopeType.EVENT; 022import static org.jboss.seam.ScopeType.SESSION; 023 024import java.io.Serializable; 025import java.util.ArrayList; 026import java.util.Arrays; 027import java.util.HashMap; 028import java.util.List; 029import java.util.Locale; 030import java.util.Map; 031 032import org.jboss.seam.annotations.Factory; 033import org.jboss.seam.annotations.In; 034import org.jboss.seam.annotations.Name; 035import org.jboss.seam.annotations.Scope; 036import org.jboss.seam.faces.FacesMessages; 037import org.jboss.seam.international.LocaleSelector; 038import org.jboss.seam.international.StatusMessage; 039import org.nuxeo.ecm.core.api.DocumentModel; 040import org.nuxeo.ecm.core.api.NuxeoException; 041import org.nuxeo.ecm.core.api.validation.ConstraintViolation; 042import org.nuxeo.ecm.core.api.validation.DocumentValidationReport; 043import org.nuxeo.ecm.core.api.validation.DocumentValidationService; 044import org.nuxeo.ecm.platform.forms.layout.api.LayoutDefinition; 045import org.nuxeo.ecm.platform.forms.layout.api.LayoutRowDefinition; 046import org.nuxeo.ecm.platform.forms.layout.api.WidgetDefinition; 047import org.nuxeo.ecm.platform.forms.layout.api.WidgetReference; 048import org.nuxeo.ecm.platform.forms.layout.api.WidgetTypeDefinition; 049import org.nuxeo.ecm.platform.forms.layout.api.service.LayoutStore; 050import org.nuxeo.ecm.platform.forms.layout.demo.service.DemoWidgetType; 051import org.nuxeo.ecm.platform.forms.layout.demo.service.LayoutDemoManager; 052import org.nuxeo.ecm.platform.forms.layout.service.WebLayoutManager; 053import org.nuxeo.ecm.platform.url.api.DocumentView; 054import org.nuxeo.runtime.api.Framework; 055 056/** 057 * Seam component providing a document model for layout demo and testing, and handling reset of this document model when 058 * the page changes. 059 * 060 * @author Anahide Tchertchian 061 */ 062@Name("layoutDemoActions") 063@Scope(SESSION) 064public class LayoutDemoActions implements Serializable { 065 066 private static final long serialVersionUID = 1L; 067 068 @In(create = true) 069 protected LayoutDemoManager layoutDemoManager; 070 071 @In(create = true) 072 protected WebLayoutManager webLayoutManager; 073 074 @In(create = true) 075 protected DocumentModel layoutBareDemoDocument; 076 077 @In(create = true) 078 protected DocumentModel layoutValidationDocument; 079 080 @In(create = true) 081 protected LayoutDemoContext layoutDemoContext; 082 083 protected DocumentModel layoutDemoDocument; 084 085 protected DemoWidgetType currentWidgetType; 086 087 protected String currentTabId; 088 089 protected String currentSubTabId; 090 091 protected PreviewLayoutDefinition viewPreviewLayoutDef; 092 093 protected PreviewLayoutDefinition editPreviewLayoutDef; 094 095 /** 096 * @since 7.2 097 */ 098 @In(create = true) 099 protected transient LocaleSelector localeSelector; 100 101 /** 102 * @since 7.2 103 */ 104 @In(create = true) 105 protected FacesMessages facesMessages; 106 107 /** 108 * @since 7.2 109 */ 110 @In(create = true) 111 protected Map<String, String> messages; 112 113 @Factory(value = "layoutDemoDocument", scope = EVENT) 114 public DocumentModel getDemoDocument() { 115 if (layoutDemoDocument == null) { 116 try { 117 layoutDemoDocument = layoutBareDemoDocument.clone(); 118 } catch (CloneNotSupportedException e) { 119 throw new NuxeoException(e); 120 } 121 } 122 return layoutDemoDocument; 123 } 124 125 public String initContextFromRestRequest(DocumentView docView) { 126 127 DemoWidgetType widgetType = null; 128 boolean isPreviewFrame = false; 129 if (docView != null) { 130 String viewId = docView.getViewId(); 131 if (viewId != null) { 132 // try to deduce current widget type 133 widgetType = layoutDemoManager.getWidgetTypeByViewId(viewId); 134 } 135 } 136 137 if (!isPreviewFrame) { 138 // avoid resetting contextual info when generating preview frame 139 setCurrentWidgetType(widgetType); 140 } 141 142 return null; 143 } 144 145 public void setCurrentWidgetType(DemoWidgetType newWidgetType) { 146 if (currentWidgetType != null && !currentWidgetType.equals(newWidgetType)) { 147 // reset demo doc too 148 layoutDemoDocument = null; 149 viewPreviewLayoutDef = null; 150 editPreviewLayoutDef = null; 151 currentTabId = null; 152 currentSubTabId = null; 153 } 154 currentWidgetType = newWidgetType; 155 } 156 157 @Factory(value = "currentWidgetType", scope = EVENT) 158 public DemoWidgetType getCurrentWidgetType() { 159 return currentWidgetType; 160 } 161 162 @Factory(value = "currentWidgetTypeDef", scope = EVENT) 163 public WidgetTypeDefinition getCurrentWidgetTypeDefinition() { 164 if (currentWidgetType != null) { 165 String type = currentWidgetType.getName(); 166 LayoutStore lm = Framework.getLocalService(LayoutStore.class); 167 return lm.getWidgetTypeDefinition(currentWidgetType.getWidgetTypeCategory(), type); 168 } 169 return null; 170 } 171 172 @Factory(value = "layoutDemoCurrentTabId", scope = EVENT) 173 public String getCurrentTabId() { 174 return currentTabId; 175 } 176 177 public void setCurrentTabId(String currentTabId) { 178 this.currentTabId = currentTabId; 179 } 180 181 @Factory(value = "layoutDemoCurrentSubTabId", scope = EVENT) 182 public String getCurrentSubTabId() { 183 return currentSubTabId; 184 } 185 186 public void setCurrentSubTabId(String currentSubTabId) { 187 this.currentSubTabId = currentSubTabId; 188 } 189 190 protected PreviewLayoutDefinition createPreviewLayoutDefinition(DemoWidgetType widgetType) { 191 String type = widgetType.getName(); 192 193 Map<String, Serializable> props = new HashMap<>(); 194 if (widgetType.getDefaultProperties() != null) { 195 props.putAll(widgetType.getDefaultProperties()); 196 } 197 if (type != null && type.contains("Aggregate")) { 198 // fill up aggregates mapping as default properties 199 if (type.contains("Aggregate")) { 200 props.put("selectOptions", "#{layoutDemoAggregates['dir_terms'].buckets}"); 201 } else { 202 props.put("selectOptions", "#{layoutDemoAggregates['string_terms'].buckets}"); 203 } 204 props.put("directoryName", "layout_demo_crew"); 205 } 206 PreviewLayoutDefinition def = new PreviewLayoutDefinition(widgetType.getName(), widgetType.getFields(), props); 207 208 if (def != null) { 209 // add some special conf for preview needs, hardcoded right now 210 if ("list".equals(type)) { 211 LayoutDefinition ldef = webLayoutManager.getLayoutDefinition("complexListWidgetLayout"); 212 def.setSubWidgets(retrieveSubWidgets(ldef)); 213 } else if ("complex".equals(type)) { 214 LayoutDefinition ldef = webLayoutManager.getLayoutDefinition("complexWidgetLayout"); 215 def.setSubWidgets(retrieveSubWidgets(ldef)); 216 } else if ("container".equals(type)) { 217 LayoutDefinition ldef = webLayoutManager.getLayoutDefinition("containerWidgetLayout"); 218 def.setSubWidgets(retrieveSubWidgets(ldef)); 219 def.setHandlingLabels(Boolean.TRUE); 220 } else if ("actions".equals(type) || "toggleableLayoutWithForms".equals(type)) { 221 def.setHandlingLabels(Boolean.TRUE); 222 } 223 } 224 225 // set a custom label and help label 226 def.setLabel("My widget label"); 227 def.setHelpLabel("My widget help label"); 228 return def; 229 } 230 231 protected List<WidgetDefinition> retrieveSubWidgets(LayoutDefinition layoutDef) { 232 List<WidgetDefinition> res = new ArrayList<WidgetDefinition>(); 233 LayoutRowDefinition[] rows = layoutDef.getRows(); 234 if (rows != null && rows.length > 0) { 235 WidgetReference[] refs = rows[0].getWidgetReferences(); 236 if (refs != null && refs.length > 0) { 237 String wName = refs[0].getName(); 238 WidgetDefinition wDef = layoutDef.getWidgetDefinition(wName); 239 if (wDef != null) { 240 WidgetDefinition[] subs = wDef.getSubWidgetDefinitions(); 241 if (subs != null) { 242 res.addAll(Arrays.asList(subs)); 243 } 244 } 245 } 246 } 247 return res; 248 } 249 250 @Factory(value = "viewPreviewLayoutDef", scope = EVENT) 251 public PreviewLayoutDefinition getViewPreviewLayoutDefinition() { 252 if (viewPreviewLayoutDef == null && currentWidgetType != null) { 253 viewPreviewLayoutDef = createPreviewLayoutDefinition(currentWidgetType); 254 } 255 return viewPreviewLayoutDef; 256 } 257 258 @Factory(value = "editPreviewLayoutDef", scope = EVENT) 259 public PreviewLayoutDefinition getEditPreviewLayoutDefinition() { 260 if (editPreviewLayoutDef == null && currentWidgetType != null) { 261 editPreviewLayoutDef = createPreviewLayoutDefinition(currentWidgetType); 262 } 263 return editPreviewLayoutDef; 264 } 265 266 /** 267 * @since 7.2 268 */ 269 public void validateDocument() { 270 DocumentValidationService s = Framework.getService(DocumentValidationService.class); 271 DocumentValidationReport report = s.validate(layoutValidationDocument); 272 if (report.hasError()) { 273 Locale locale = localeSelector.getLocale(); 274 for (ConstraintViolation v : report.asList()) { 275 String msg = v.getMessage(locale); 276 facesMessages.addToControl("errors", StatusMessage.Severity.ERROR, msg); 277 } 278 } else { 279 facesMessages.addToControl("errors", StatusMessage.Severity.INFO, "Validation done"); 280 } 281 } 282 283 /** 284 * @since 7.2 285 */ 286 public String resetValidationDocument() { 287 layoutDemoContext.resetValidationDocument(); 288 return null; 289 } 290 291}