001/* 002 * (C) Copyright 2010 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Anahide Tchertchian 016 */ 017package org.nuxeo.ecm.platform.forms.layout.export; 018 019import java.util.ArrayList; 020import java.util.Arrays; 021import java.util.Collections; 022import java.util.HashMap; 023import java.util.LinkedHashMap; 024import java.util.List; 025import java.util.Map; 026 027import javax.servlet.http.HttpServletRequest; 028import javax.ws.rs.GET; 029import javax.ws.rs.Path; 030import javax.ws.rs.PathParam; 031import javax.ws.rs.QueryParam; 032import javax.ws.rs.core.Context; 033import javax.ws.rs.core.Response; 034import javax.ws.rs.core.UriInfo; 035 036import org.apache.commons.lang.StringUtils; 037import org.nuxeo.ecm.platform.forms.layout.api.WidgetTypeConfiguration; 038import org.nuxeo.ecm.platform.forms.layout.api.WidgetTypeDefinition; 039import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetTypeDefinitionComparator; 040import org.nuxeo.ecm.platform.forms.layout.api.service.LayoutStore; 041import org.nuxeo.ecm.webengine.model.exceptions.WebResourceNotFoundException; 042import org.nuxeo.ecm.webengine.model.view.TemplateView; 043import org.nuxeo.runtime.api.Framework; 044 045/** 046 * Exports and presents documentation about widget type definitions 047 * 048 * @author Anahide Tchertchian 049 * @since 5.4 050 */ 051public class WidgetTypeResource { 052 053 protected final String category; 054 055 protected LayoutStore service; 056 057 protected final List<WidgetTypeDefinition> widgetTypes; 058 059 protected final Map<String, List<WidgetTypeDefinition>> widgetTypesByCat; 060 061 public WidgetTypeResource(String category) { 062 this.category = category; 063 service = Framework.getService(LayoutStore.class); 064 widgetTypes = service.getWidgetTypeDefinitions(category); 065 // sort so that order is deterministic 066 Collections.sort(widgetTypes, new WidgetTypeDefinitionComparator(true)); 067 widgetTypesByCat = getWidgetTypesByCategory(); 068 } 069 070 protected Map<String, List<WidgetTypeDefinition>> getWidgetTypesByCategory() { 071 Map<String, List<WidgetTypeDefinition>> cats = new HashMap<String, List<WidgetTypeDefinition>>(); 072 List<WidgetTypeDefinition> unknownCatWidgets = new ArrayList<WidgetTypeDefinition>(); 073 for (WidgetTypeDefinition wTypeDef : widgetTypes) { 074 List<String> categories = null; 075 WidgetTypeConfiguration conf = wTypeDef.getConfiguration(); 076 if (conf != null) { 077 categories = conf.getCategories(); 078 } 079 boolean added = false; 080 if (categories != null) { 081 for (String cat : categories) { 082 List<WidgetTypeDefinition> list = cats.get(cat); 083 if (list == null) { 084 list = new ArrayList<WidgetTypeDefinition>(); 085 } 086 list.add(wTypeDef); 087 cats.put(cat, list); 088 added = true; 089 } 090 } 091 if (!added) { 092 unknownCatWidgets.add(wTypeDef); 093 } 094 } 095 if (!unknownCatWidgets.isEmpty()) { 096 cats.put("unknown", unknownCatWidgets); 097 } 098 // sort by category key 099 List<String> sortedKeys = new ArrayList<String>(cats.keySet()); 100 Collections.sort(sortedKeys); 101 Map<String, List<WidgetTypeDefinition>> res = new LinkedHashMap<String, List<WidgetTypeDefinition>>(); 102 for (String key : sortedKeys) { 103 res.put(key, cats.get(key)); 104 } 105 return res; 106 } 107 108 /** 109 * Returns widget types definitions for given categories 110 * <p> 111 * If the category is null, the filter does not check the category. Widget types without a configuration are 112 * included if boolean 'all' is set to true. Mutliple categories are extracted from the query parameter by splitting 113 * on the space character. 114 * <p> 115 * If not null, the version parameter will exclude all widget types that did not exist before this version. 116 */ 117 @GET 118 @Path("widgetTypes") 119 public Object getWidgetTypeDefinitions(@Context HttpServletRequest request, 120 @QueryParam("categories") String categories, @QueryParam("version") String version, 121 @QueryParam("all") Boolean all) { 122 // TODO: refactor so that's cached 123 List<String> catsList = new ArrayList<String>(); 124 if (categories != null) { 125 for (String cat : categories.split(" ")) { 126 catsList.add(cat); 127 } 128 } 129 WidgetTypeDefinitions res = new WidgetTypeDefinitions(); 130 for (WidgetTypeDefinition def : widgetTypes) { 131 WidgetTypeConfiguration conf = def.getConfiguration(); 132 if (!Boolean.TRUE.equals(all) && conf == null) { 133 continue; 134 } 135 if (version != null && conf != null) { 136 String confVersion = conf.getSinceVersion(); 137 if (confVersion != null && version.compareTo(confVersion) < 0) { 138 continue; 139 } 140 } 141 if (catsList != null && !catsList.isEmpty()) { 142 boolean hasCats = false; 143 if (conf != null) { 144 // filter on category 145 List<String> confCats = conf.getCategories(); 146 if (confCats != null) { 147 hasCats = true; 148 if (confCats.containsAll(catsList)) { 149 res.add(def); 150 } 151 } 152 } 153 if (!hasCats && catsList.size() == 1 && catsList.contains("unknown")) { 154 res.add(def); 155 } 156 } else { 157 if (conf == null && !Boolean.TRUE.equals(all)) { 158 continue; 159 } 160 res.add(def); 161 } 162 } 163 return res; 164 } 165 166 /** 167 * Returns widget types definitions for given category. 168 * <p> 169 * If the category is null, the filter does not check the category. Widget types without a configuration are 170 * included if boolean 'all' is set to true. 171 * <p> 172 * If not null, the version parameter will exclude all widget types that did not exist before this version. 173 */ 174 @GET 175 @Path("widgetTypes/{category}") 176 public Object getWidgetTypeDefinitionsForCategory(@Context HttpServletRequest request, 177 @PathParam("category") String category, @QueryParam("version") String version, 178 @QueryParam("all") Boolean all) { 179 return getWidgetTypeDefinitions(request, category, version, all); 180 } 181 182 @GET 183 @Path("widgetType/{name}") 184 public Object getWidgetTypeDefinition(@Context HttpServletRequest request, @PathParam("name") String name) { 185 WidgetTypeDefinition def = service.getWidgetTypeDefinition(category, name); 186 if (def != null) { 187 return def; 188 } else { 189 return Response.status(401).build(); 190 } 191 } 192 193 public TemplateView getTemplate(@Context UriInfo uriInfo) { 194 return getTemplate("widget-types.ftl", uriInfo); 195 } 196 197 @GET 198 @Path("wiki") 199 public Object getWikiDocumentation(@Context UriInfo uriInfo) { 200 return getTemplate("widget-types-wiki.ftl", uriInfo); 201 } 202 203 protected List<String> getNuxeoVersions() { 204 if ("jsf".equals(category)) { 205 return Arrays.asList("5.6", "5.8", "6.0"); 206 } else if ("jsfAction".equals(category)) { 207 return Arrays.asList("5.8", "6.0"); 208 } 209 return Collections.emptyList(); 210 } 211 212 protected TemplateView getTemplate(String name, UriInfo uriInfo) { 213 String baseURL = uriInfo.getAbsolutePath().toString(); 214 if (!baseURL.endsWith("/")) { 215 baseURL += "/"; 216 } 217 TemplateView tv = new TemplateView(this, name); 218 tv.arg("categories", widgetTypesByCat); 219 tv.arg("nuxeoVersions", getNuxeoVersions()); 220 tv.arg("widgetTypeCategory", category); 221 tv.arg("widgetTypes", widgetTypes); 222 tv.arg("baseURL", baseURL); 223 return tv; 224 } 225 226 @GET 227 public Object doGet(@QueryParam("widgetType") String widgetTypeName, @Context UriInfo uriInfo) { 228 if (widgetTypeName == null) { 229 return getTemplate(uriInfo); 230 } else { 231 WidgetTypeDefinition wType = service.getWidgetTypeDefinition(category, widgetTypeName); 232 if (wType == null) { 233 throw new WebResourceNotFoundException("No widget type found with name: " + widgetTypeName); 234 } 235 TemplateView tpl = getTemplate(uriInfo); 236 tpl.arg("widgetType", wType); 237 return tpl; 238 } 239 } 240 241 public String getWidgetTypeLabel(WidgetTypeDefinition wTypeDef) { 242 if (wTypeDef != null) { 243 WidgetTypeConfiguration conf = wTypeDef.getConfiguration(); 244 if (conf != null) { 245 return conf.getTitle(); 246 } 247 return wTypeDef.getName(); 248 } 249 return null; 250 } 251 252 public String getWidgetTypeDescription(WidgetTypeDefinition wTypeDef) { 253 if (wTypeDef != null) { 254 WidgetTypeConfiguration conf = wTypeDef.getConfiguration(); 255 if (conf != null) { 256 return conf.getDescription(); 257 } 258 } 259 return null; 260 } 261 262 public List<String> getWidgetTypeCategories(WidgetTypeDefinition wTypeDef) { 263 if (wTypeDef != null) { 264 WidgetTypeConfiguration conf = wTypeDef.getConfiguration(); 265 if (conf != null) { 266 return conf.getCategories(); 267 } 268 } 269 return null; 270 } 271 272 public String getWidgetTypeCategoriesAsString(WidgetTypeDefinition wTypeDef) { 273 List<String> categories = getWidgetTypeCategories(wTypeDef); 274 if (categories == null) { 275 return ""; 276 } else { 277 return StringUtils.join(categories, ", "); 278 } 279 } 280 281}