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