001/* 002 * (C) Copyright 2015 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-2.1.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 * Nicolas Chapurlat <nchapurlat@nuxeo.com> 016 */ 017 018package org.nuxeo.ecm.core.io.registry.context; 019 020import java.io.Closeable; 021import java.io.IOException; 022import java.util.List; 023import java.util.Locale; 024import java.util.Map; 025import java.util.Set; 026 027import org.nuxeo.ecm.core.api.CoreSession; 028import org.nuxeo.ecm.core.api.DocumentModel; 029import org.nuxeo.ecm.core.io.registry.MarshallingException; 030import org.nuxeo.ecm.core.io.registry.context.RenderingContextImpl.RenderingContextBuilder; 031 032/** 033 * A context used to deliver parameter to marshallers during a marshalling request. 034 * <p> 035 * Use {@link CtxBuilder} to create your context. 036 * </p> 037 * <p> 038 * When a {@link RenderingContext} is automatically provided from an HttpServletRequest, it contains request parameters, 039 * headers and request attribute. 040 * </p> 041 * <p> 042 * To get/set parameter values, use: 043 * <ul> 044 * <li>{@link RenderingContext#getParameter(String)}</li> 045 * <li>{@link RenderingContext#getParameters(String)}</li> 046 * <li>{@link RenderingContext#getBooleanParameter(String)}</li> 047 * <li>{@link RenderingContext#getAllParameters()}</li> 048 * <li>{@link RenderingContext#addParameterValues(String, Object...)}</li> 049 * <li>{@link RenderingContext#addParameterListValues(String, List)}</li> 050 * <li>{@link RenderingContext#setParameterValues(String, Object...)}</li> 051 * <li>{@link RenderingContext#setParameterListValues(String, List)}</li> 052 * </ul> 053 * </p> 054 * <p> 055 * To manage document properties, entity enrichers or properties fetching, use: 056 * <ul> 057 * <li>{@link RenderingContext#getProperties()}</li> 058 * <li>{@link RenderingContext#getEnrichers(String)}</li> 059 * <li>{@link RenderingContext#getFetched(String)}</li> 060 * </ul> 061 * </p> 062 * <p> 063 * To manage infinite loop when calling a marshaller from another marshaller, use: 064 * <ul> 065 * <li>{@link RenderingContext#wrap()} -> {@link WrappedContext#controlDepth()}</li> 066 * </ul> 067 * Example: 068 * 069 * <pre> 070 * // This will control infinite loop in this marshaller 071 * try (Closeable resource = ctx.wrap().controlDepth().open()) { 072 * // call another marshaller to fetch the desired property here 073 * } catch (MaxDepthReachedException mdre) { 074 * // do not call the other marshaller 075 * } 076 * </pre> 077 * 078 * </p> 079 * 080 * @since 7.2. 081 */ 082public interface RenderingContext { 083 084 public static final Locale DEFAULT_LOCALE = Locale.ENGLISH; 085 086 public static final String DEFAULT_URL = "http://fake-url.nuxeo.com/"; 087 088 /** 089 * Gets the requested {@link Locale}. 090 * 091 * @since 7.2 092 */ 093 public Locale getLocale(); 094 095 /** 096 * Gets the current base url. 097 * 098 * @since 7.2 099 */ 100 public String getBaseUrl(); 101 102 /** 103 * Gets the current {@link CoreSession} or try to create one. 104 * 105 * @param document may be null, if present, this method search for a session in the document. 106 * @return The current {@link CoreSession} if it exists. null otherwise. 107 * @throws MarshallingException if no session could be created or found. 108 * @since 7.2 109 */ 110 public SessionWrapper getSession(DocumentModel document) throws MarshallingException; 111 112 /** 113 * Provides a {@link CoreSession} to marshallers. 114 * <p> 115 * For example: a {@link CoreSession} from the request context. 116 * </p> 117 * 118 * @param session The existing {@link CoreSession} which lifecycle is managed outside the marshalling context. 119 * @since 7.2 120 */ 121 public void setExistingSession(CoreSession session); 122 123 /** 124 * Get all document properties. This will aggregate all values from parameters "properties", "X-NXproperties" and 125 * "X-NXDocumentProperties". This supports value separated by comma. 126 * 127 * @return All document properties. 128 * @since 7.2 129 */ 130 public Set<String> getProperties(); 131 132 /** 133 * Get all properties to fetch for a given entity type. This will aggregate all values from parameters 134 * "fetch.entity" and "X-NXfetch.entity". This supports value separated by comma. 135 * 136 * @param entity The type of the entity on which you want to fetch properties. 137 * @return All properties to fetch. 138 * @since 7.2 139 */ 140 public Set<String> getFetched(String entity); 141 142 /** 143 * Get all properties to translate for a given entity type. This will aggregate all values from parameters 144 * "translate.entity" and "X-NXtranslate.entity". This supports value separated by comma. 145 * 146 * @param entity The type of the entity on which you want to fetch properties. 147 * @return All properties to fetch. 148 * @since 7.2 149 */ 150 public Set<String> getTranslated(String entity); 151 152 /** 153 * Get all enrichers to activate on the given entity type. This will aggregate all values from parameters 154 * "enrichers.entity", "X-NXenrichers.entity" and "X-NXContext-Category". This supports value separated by comma. 155 * 156 * @param entity The type of the entity on which you want to activate enrichers. 157 * @return All enrichers to activate. 158 * @since 7.2 159 */ 160 public Set<String> getEnrichers(String entity); 161 162 /** 163 * see {@link WrappedContext} 164 * 165 * @return A new {@link WrappedContext} 166 * @since 7.2 167 */ 168 public WrappedContext wrap(); 169 170 /** 171 * Get the casted parameter value for a given name. If multiple are available, the first found is returned. 172 * 173 * @param name The parameter name. 174 * @return The first parameter value, null if no parameter are availble. 175 * @since 7.2 176 */ 177 public <T> T getParameter(String name); 178 179 /** 180 * see {@link #getParameter(String)} 181 * 182 * @return true is the parameter exists and if it's Boolean.TRUE or "true", false otherwise. 183 */ 184 public boolean getBooleanParameter(String name); 185 186 /** 187 * Get the casted parameter values for a given name. 188 * 189 * @param name The parameter name. 190 * @return The parameter values. 191 * @since 7.2 192 */ 193 public <T> List<T> getParameters(String name); 194 195 /** 196 * Get all parameter in this context except wrapped parameters. 197 * 198 * @return All parameter's names and their values. 199 * @since 7.2 200 */ 201 public Map<String, List<Object>> getAllParameters(); 202 203 /** 204 * @see #setParameterListValues(String, List) 205 * @since 7.2 206 */ 207 public void setParameterValues(String name, Object... values); 208 209 /** 210 * Push values in the context with a given name. Please note that this method remove any value for the given name. 211 * 212 * @param name The parameter name. 213 * @param values The parameter values. 214 * @since 7.2 215 */ 216 public void setParameterListValues(String name, List<Object> values); 217 218 /** 219 * @see #addParameterListValues(String, List) 220 * @since 7.2 221 */ 222 public void addParameterValues(String name, Object... values); 223 224 /** 225 * Add values in the context with a given name. Please note that this method keep current values for the given name. 226 * 227 * @param name The parameter name. 228 * @param values The parameter values. 229 * @since 7.2 230 */ 231 public void addParameterListValues(String name, List<Object> values); 232 233 /** 234 * {@link RenderingContext} builder. 235 * <p> 236 * RenderingContext ctx = CtxBuilder.base("http://mine.nuxeo.com/nuxeo").locale(Locale.ENGLISH).param("name", 237 * "value1", "value2").get(); 238 * </p> 239 * 240 * @since 7.2 241 */ 242 public static final class CtxBuilder { 243 private CtxBuilder() { 244 } 245 246 public static RenderingContextBuilder builder() { 247 return new RenderingContextBuilder(); 248 } 249 250 public static RenderingContextBuilder base(String url) { 251 RenderingContextBuilder builder = new RenderingContextBuilder(); 252 return builder.base(url); 253 } 254 255 public static RenderingContextBuilder locale(Locale locale) { 256 RenderingContextBuilder builder = new RenderingContextBuilder(); 257 return builder.locale(locale); 258 } 259 260 public static RenderingContextBuilder session(CoreSession session) { 261 RenderingContextBuilder builder = new RenderingContextBuilder(); 262 return builder.session(session); 263 } 264 265 public static RenderingContextBuilder param(String name, Object value) { 266 RenderingContextBuilder builder = new RenderingContextBuilder(); 267 return builder.param(name, value); 268 } 269 270 public static RenderingContextBuilder paramValues(String name, Object... values) { 271 RenderingContextBuilder builder = new RenderingContextBuilder(); 272 return builder.paramValues(name, values); 273 } 274 275 public static RenderingContextBuilder paramList(String name, List<Object> values) { 276 RenderingContextBuilder builder = new RenderingContextBuilder(); 277 return builder.paramList(name, values); 278 } 279 280 public static RenderingContextBuilder properties(String... schemaName) { 281 RenderingContextBuilder builder = new RenderingContextBuilder(); 282 return builder.properties(schemaName); 283 } 284 285 public static RenderingContextBuilder fetch(String entityType, String... propertyName) { 286 RenderingContextBuilder builder = new RenderingContextBuilder(); 287 return builder.fetch(entityType, propertyName); 288 } 289 290 public static RenderingContextBuilder fetchInDoc(String... propertyName) { 291 RenderingContextBuilder builder = new RenderingContextBuilder(); 292 return builder.fetchInDoc(propertyName); 293 } 294 295 public static RenderingContextBuilder translate(String entityType, String... propertyName) { 296 RenderingContextBuilder builder = new RenderingContextBuilder(); 297 return builder.translate(entityType, propertyName); 298 } 299 300 public static RenderingContextBuilder enrich(String entityType, String... enricherName) { 301 RenderingContextBuilder builder = new RenderingContextBuilder(); 302 return builder.enrich(entityType, enricherName); 303 } 304 305 public static RenderingContextBuilder enrichDoc(String... enricherName) { 306 RenderingContextBuilder builder = new RenderingContextBuilder(); 307 return builder.enrichDoc(enricherName); 308 } 309 310 public static RenderingContextBuilder depth(DepthValues value) { 311 RenderingContextBuilder builder = new RenderingContextBuilder(); 312 return builder.depth(value); 313 } 314 315 public static RenderingContext get() { 316 RenderingContextBuilder builder = new RenderingContextBuilder(); 317 return builder.get(); 318 } 319 } 320 321 /** 322 * Session wrapper that manage the closing of new created session and preserve request scoped or document scoped 323 * session. 324 * 325 * @since 7.2 326 */ 327 public class SessionWrapper implements Closeable { 328 329 private CoreSession session; 330 331 private boolean shouldBeClosed; 332 333 public SessionWrapper(CoreSession session, boolean shouldBeClosed) { 334 super(); 335 this.session = session; 336 this.shouldBeClosed = shouldBeClosed; 337 } 338 339 public CoreSession getSession() { 340 return session; 341 } 342 343 public boolean shouldBeClosed() { 344 return shouldBeClosed; 345 } 346 347 @Override 348 public void close() throws IOException { 349 if (shouldBeClosed) { 350 session.close(); 351 } 352 } 353 354 } 355 356}