/* * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * Nicolas Chapurlat <nchapurlat@nuxeo.com> */ package org.nuxeo.ecm.core.io.registry.context; import java.io.Closeable; import java.io.IOException; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import org.nuxeo.ecm.core.api.CoreSession; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.io.registry.MarshallingException; import org.nuxeo.ecm.core.io.registry.context.RenderingContextImpl.RenderingContextBuilder; /** * A context used to deliver parameter to marshallers during a marshalling request. * <p> * Use {@link CtxBuilder} to create your context. * </p> * <p> * When a {@link RenderingContext} is automatically provided from an HttpServletRequest, it contains request parameters, * headers and request attribute. * </p> * <p> * To get/set parameter values, use: * <ul> * <li>{@link RenderingContext#getParameter(String)}</li> * <li>{@link RenderingContext#getParameters(String)}</li> * <li>{@link RenderingContext#getBooleanParameter(String)}</li> * <li>{@link RenderingContext#getAllParameters()}</li> * <li>{@link RenderingContext#addParameterValues(String, Object...)}</li> * <li>{@link RenderingContext#addParameterListValues(String, List)}</li> * <li>{@link RenderingContext#setParameterValues(String, Object...)}</li> * <li>{@link RenderingContext#setParameterListValues(String, List)}</li> * </ul> * </p> * <p> * To manage document properties, entity enrichers or properties fetching, use: * <ul> * <li>{@link RenderingContext#getProperties()}</li> * <li>{@link RenderingContext#getEnrichers(String)}</li> * <li>{@link RenderingContext#getFetched(String)}</li> * </ul> * </p> * <p> * To manage infinite loop when calling a marshaller from another marshaller, use: * <ul> * <li>{@link RenderingContext#wrap()} -> {@link WrappedContext#controlDepth()}</li> * </ul> * Example: * * <pre> * // This will control infinite loop in this marshaller * try (Closeable resource = ctx.wrap().controlDepth().open()) { * // call another marshaller to fetch the desired property here * } catch (MaxDepthReachedException mdre) { * // do not call the other marshaller * } * </pre> * * </p> * * @since 7.2. */ public interface RenderingContext { public static final Locale DEFAULT_LOCALE = Locale.ENGLISH; public static final String DEFAULT_URL = "http://fake-url.nuxeo.com/"; public static final String RESPONSE_HEADER_ENTITY_TYPE_KEY = "ENTITY_TYPE"; /** * Gets the requested {@link Locale}. * * @since 7.2 */ public Locale getLocale(); /** * Gets the current base url. * * @since 7.2 */ public String getBaseUrl(); /** * Gets the current {@link CoreSession} or try to create one. * * @param document may be null, if present, this method search for a session in the document. * @return The current {@link CoreSession} if it exists. null otherwise. * @throws MarshallingException if no session could be created or found. * @since 7.2 */ public SessionWrapper getSession(DocumentModel document) throws MarshallingException; /** * Provides a {@link CoreSession} to marshallers. * <p> * For example: a {@link CoreSession} from the request context. * </p> * * @param session The existing {@link CoreSession} which lifecycle is managed outside the marshalling context. * @since 7.2 */ public void setExistingSession(CoreSession session); /** * Get all document properties. This will aggregate all values from parameters "properties", "X-NXproperties" and * "X-NXDocumentProperties". This supports value separated by comma. * * @return All document properties. * @since 7.2 */ public Set<String> getProperties(); /** * Get all properties to fetch for a given entity type. This will aggregate all values from parameters * "fetch.entity" and "X-NXfetch.entity". This supports value separated by comma. * * @param entity The type of the entity on which you want to fetch properties. * @return All properties to fetch. * @since 7.2 */ public Set<String> getFetched(String entity); /** * Get all properties to translate for a given entity type. This will aggregate all values from parameters * "translate.entity" and "X-NXtranslate.entity". This supports value separated by comma. * * @param entity The type of the entity on which you want to fetch properties. * @return All properties to fetch. * @since 7.2 */ public Set<String> getTranslated(String entity); /** * Get all enrichers to activate on the given entity type. This will aggregate all values from parameters * "enrichers.entity", "X-NXenrichers.entity" and "X-NXContext-Category". This supports value separated by comma. * * @param entity The type of the entity on which you want to activate enrichers. * @return All enrichers to activate. * @since 7.2 */ public Set<String> getEnrichers(String entity); /** * see {@link WrappedContext} * * @return A new {@link WrappedContext} * @since 7.2 */ public WrappedContext wrap(); /** * Get the casted parameter value for a given name. If multiple are available, the first found is returned. * * @param name The parameter name. * @return The first parameter value, null if no parameter are availble. * @since 7.2 */ public <T> T getParameter(String name); /** * see {@link #getParameter(String)} * * @return true is the parameter exists and if it's Boolean.TRUE or "true", false otherwise. */ public boolean getBooleanParameter(String name); /** * Get the casted parameter values for a given name. * * @param name The parameter name. * @return The parameter values. * @since 7.2 */ public <T> List<T> getParameters(String name); /** * Get all parameter in this context except wrapped parameters. * * @return All parameter's names and their values. * @since 7.2 */ public Map<String, List<Object>> getAllParameters(); /** * @see #setParameterListValues(String, List) * @since 7.2 */ public void setParameterValues(String name, Object... values); /** * Push values in the context with a given name. Please note that this method remove any value for the given name. * * @param name The parameter name. * @param values The parameter values. * @since 7.2 */ public void setParameterListValues(String name, List<Object> values); /** * @see #addParameterListValues(String, List) * @since 7.2 */ public void addParameterValues(String name, Object... values); /** * Add values in the context with a given name. Please note that this method keep current values for the given name. * * @param name The parameter name. * @param values The parameter values. * @since 7.2 */ public void addParameterListValues(String name, List<Object> values); /** * {@link RenderingContext} builder. * <p> * RenderingContext ctx = CtxBuilder.base("http://mine.nuxeo.com/nuxeo").locale(Locale.ENGLISH).param("name", * "value1", "value2").get(); * </p> * * @since 7.2 */ public static final class CtxBuilder { private CtxBuilder() { } public static RenderingContextBuilder builder() { return new RenderingContextBuilder(); } public static RenderingContextBuilder base(String url) { RenderingContextBuilder builder = new RenderingContextBuilder(); return builder.base(url); } public static RenderingContextBuilder locale(Locale locale) { RenderingContextBuilder builder = new RenderingContextBuilder(); return builder.locale(locale); } public static RenderingContextBuilder session(CoreSession session) { RenderingContextBuilder builder = new RenderingContextBuilder(); return builder.session(session); } public static RenderingContextBuilder param(String name, Object value) { RenderingContextBuilder builder = new RenderingContextBuilder(); return builder.param(name, value); } public static RenderingContextBuilder paramValues(String name, Object... values) { RenderingContextBuilder builder = new RenderingContextBuilder(); return builder.paramValues(name, values); } public static RenderingContextBuilder paramList(String name, List<Object> values) { RenderingContextBuilder builder = new RenderingContextBuilder(); return builder.paramList(name, values); } public static RenderingContextBuilder properties(String... schemaName) { RenderingContextBuilder builder = new RenderingContextBuilder(); return builder.properties(schemaName); } public static RenderingContextBuilder fetch(String entityType, String... propertyName) { RenderingContextBuilder builder = new RenderingContextBuilder(); return builder.fetch(entityType, propertyName); } public static RenderingContextBuilder fetchInDoc(String... propertyName) { RenderingContextBuilder builder = new RenderingContextBuilder(); return builder.fetchInDoc(propertyName); } public static RenderingContextBuilder translate(String entityType, String... propertyName) { RenderingContextBuilder builder = new RenderingContextBuilder(); return builder.translate(entityType, propertyName); } public static RenderingContextBuilder enrich(String entityType, String... enricherName) { RenderingContextBuilder builder = new RenderingContextBuilder(); return builder.enrich(entityType, enricherName); } public static RenderingContextBuilder enrichDoc(String... enricherName) { RenderingContextBuilder builder = new RenderingContextBuilder(); return builder.enrichDoc(enricherName); } public static RenderingContextBuilder depth(DepthValues value) { RenderingContextBuilder builder = new RenderingContextBuilder(); return builder.depth(value); } public static RenderingContext get() { RenderingContextBuilder builder = new RenderingContextBuilder(); return builder.get(); } } /** * Session wrapper that manage the closing of new created session and preserve request scoped or document scoped * session. * * @since 7.2 */ public class SessionWrapper implements Closeable { private CoreSession session; private boolean shouldBeClosed; public SessionWrapper(CoreSession session, boolean shouldBeClosed) { super(); this.session = session; this.shouldBeClosed = shouldBeClosed; } public CoreSession getSession() { return session; } public boolean shouldBeClosed() { return shouldBeClosed; } @Override public void close() throws IOException { if (shouldBeClosed) { session.close(); } } } }