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