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