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.marshallers.json; 021 022import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE; 023import static org.nuxeo.ecm.core.io.marshallers.json.enrichers.AbstractJsonEnricher.ENTITY_ENRICHER_NAME; 024import static org.nuxeo.ecm.core.io.registry.MarshallingConstants.ENTITY_FIELD_NAME; 025 026import java.io.Closeable; 027import java.io.IOException; 028import java.lang.reflect.Type; 029import java.util.ArrayList; 030import java.util.Collection; 031import java.util.List; 032import java.util.Set; 033 034import org.apache.commons.lang3.reflect.TypeUtils; 035import org.codehaus.jackson.JsonGenerator; 036import org.nuxeo.ecm.core.io.marshallers.json.enrichers.Enriched; 037import org.nuxeo.ecm.core.io.registry.MarshallerRegistry; 038import org.nuxeo.ecm.core.io.registry.Writer; 039import org.nuxeo.ecm.core.io.registry.context.MaxDepthReachedException; 040import org.nuxeo.ecm.core.io.registry.context.RenderingContext; 041import org.nuxeo.ecm.core.io.registry.context.WrappedContext; 042 043/** 044 * Base class to write Nuxeo Json entity. This class write the json object, the json "entity-type" property and enable 045 * all activated enrichers registered in the {@link MarshallerRegistry} and compatible with the marshalled Java type. 046 * 047 * @param <EntityType> The managed Java type. 048 * @since 7.2 049 */ 050public abstract class ExtensibleEntityJsonWriter<EntityType> extends AbstractJsonWriter<EntityType> { 051 052 /** 053 * The "entity-type" Json property value. 054 */ 055 private final String entityType; 056 057 /** 058 * The {@link Enriched} generic type parametrized with the given EntityType. 059 */ 060 private final Type genericType; 061 062 /** 063 * @param entityType The "entity-type" Json property value. 064 * @param entityClass The entity type. 065 */ 066 public ExtensibleEntityJsonWriter(String entityType, Class<EntityType> entityClass) { 067 super(); 068 this.entityType = entityType; 069 genericType = TypeUtils.parameterize(Enriched.class, entityClass); 070 } 071 072 @Override 073 public void write(EntityType entity, JsonGenerator jg) throws IOException { 074 jg.writeStartObject(); 075 List<Object> entityList = new ArrayList<>(); 076 entityList.add(this.entityType); 077 ctx.addParameterListValues(RenderingContext.RESPONSE_HEADER_ENTITY_TYPE_KEY, entityList); 078 jg.writeStringField(ENTITY_FIELD_NAME, entityType); 079 writeEntityBody(entity, jg); 080 try { 081 WrappedContext wrappedCtx = ctx.wrap().controlDepth(); 082 Set<String> enrichers = ctx.getEnrichers(entityType); 083 if (enrichers.size() > 0) { 084 boolean hasEnrichers = false; 085 Enriched<EntityType> enriched = null; 086 for (String enricherName : enrichers) { 087 try (Closeable resource = wrappedCtx.with(ENTITY_ENRICHER_NAME, enricherName).open()) { 088 @SuppressWarnings("rawtypes") 089 Collection<Writer<Enriched>> writers = registry.getAllWriters(ctx, Enriched.class, 090 this.genericType, APPLICATION_JSON_TYPE); 091 for (@SuppressWarnings("rawtypes") 092 Writer<Enriched> writer : writers) { 093 if (!hasEnrichers) { 094 hasEnrichers = true; 095 jg.writeObjectFieldStart("contextParameters"); 096 enriched = new Enriched<EntityType>(entity); 097 } 098 OutputStreamWithJsonWriter out = new OutputStreamWithJsonWriter(jg); 099 writer.write(enriched, Enriched.class, this.genericType, APPLICATION_JSON_TYPE, out); 100 } 101 } 102 } 103 if (hasEnrichers) { 104 jg.writeEndObject(); 105 } 106 } 107 } catch (MaxDepthReachedException e) { 108 // do nothing, do not call enrichers 109 } 110 extend(entity, jg); 111 jg.writeEndObject(); 112 } 113 114 /** 115 * Implement this method to write the entity body. 116 * 117 * @param entity The Java entity. 118 * @param jg A {@link JsonGenerator} ready to write your entity as Json. 119 * @since 7.2 120 */ 121 protected abstract void writeEntityBody(EntityType entity, JsonGenerator jg) throws IOException; 122 123 /** 124 * Override this method to add additional property in the entity. This method is useful to override a marshaller 125 * implementing this class. 126 * 127 * @param entity The Java entity. 128 * @param jg A {@link JsonGenerator} ready to write your entity as Json. 129 * @since 7.2 130 */ 131 protected void extend(EntityType entity, JsonGenerator jg) throws IOException { 132 } 133 134}