/*
* (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.marshallers.json;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE;
import static org.nuxeo.ecm.core.io.marshallers.json.enrichers.AbstractJsonEnricher.ENTITY_ENRICHER_NAME;
import static org.nuxeo.ecm.core.io.registry.MarshallingConstants.ENTITY_FIELD_NAME;
import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.reflect.TypeUtils;
import org.codehaus.jackson.JsonGenerator;
import org.nuxeo.ecm.core.io.marshallers.json.enrichers.Enriched;
import org.nuxeo.ecm.core.io.registry.MarshallerRegistry;
import org.nuxeo.ecm.core.io.registry.Writer;
import org.nuxeo.ecm.core.io.registry.context.MaxDepthReachedException;
import org.nuxeo.ecm.core.io.registry.context.RenderingContext;
import org.nuxeo.ecm.core.io.registry.context.WrappedContext;
/**
* Base class to write Nuxeo Json entity. This class write the json object, the json "entity-type" property and enable
* all activated enrichers registered in the {@link MarshallerRegistry} and compatible with the marshalled Java type.
*
* @param <EntityType> The managed Java type.
* @since 7.2
*/
public abstract class ExtensibleEntityJsonWriter<EntityType> extends AbstractJsonWriter<EntityType> {
/**
* The "entity-type" Json property value.
*/
private final String entityType;
/**
* The {@link Enriched} generic type parametrized with the given EntityType.
*/
private final Type genericType;
/**
* @param entityType The "entity-type" Json property value.
* @param entityClass The entity type.
*/
public ExtensibleEntityJsonWriter(String entityType, Class<EntityType> entityClass) {
super();
this.entityType = entityType;
genericType = TypeUtils.parameterize(Enriched.class, entityClass);
}
@Override
public void write(EntityType entity, JsonGenerator jg) throws IOException {
jg.writeStartObject();
List<Object> entityList = new ArrayList<>();
entityList.add(this.entityType);
ctx.addParameterListValues(RenderingContext.RESPONSE_HEADER_ENTITY_TYPE_KEY, entityList);
jg.writeStringField(ENTITY_FIELD_NAME, entityType);
writeEntityBody(entity, jg);
try {
WrappedContext wrappedCtx = ctx.wrap().controlDepth();
Set<String> enrichers = ctx.getEnrichers(entityType);
if (enrichers.size() > 0) {
boolean hasEnrichers = false;
Enriched<EntityType> enriched = null;
for (String enricherName : enrichers) {
try (Closeable resource = wrappedCtx.with(ENTITY_ENRICHER_NAME, enricherName).open()) {
@SuppressWarnings("rawtypes")
Collection<Writer<Enriched>> writers = registry.getAllWriters(ctx, Enriched.class,
this.genericType, APPLICATION_JSON_TYPE);
for (@SuppressWarnings("rawtypes")
Writer<Enriched> writer : writers) {
if (!hasEnrichers) {
hasEnrichers = true;
jg.writeObjectFieldStart("contextParameters");
enriched = new Enriched<EntityType>(entity);
}
OutputStreamWithJsonWriter out = new OutputStreamWithJsonWriter(jg);
writer.write(enriched, Enriched.class, this.genericType, APPLICATION_JSON_TYPE, out);
}
}
}
if (hasEnrichers) {
jg.writeEndObject();
}
}
} catch (MaxDepthReachedException e) {
// do nothing, do not call enrichers
}
extend(entity, jg);
jg.writeEndObject();
}
/**
* Implement this method to write the entity body.
*
* @param entity The Java entity.
* @param jg A {@link JsonGenerator} ready to write your entity as Json.
* @since 7.2
*/
protected abstract void writeEntityBody(EntityType entity, JsonGenerator jg) throws IOException;
/**
* Override this method to add additional property in the entity. This method is useful to override a marshaller
* implementing this class.
*
* @param entity The Java entity.
* @param jg A {@link JsonGenerator} ready to write your entity as Json.
* @since 7.2
*/
protected void extend(EntityType entity, JsonGenerator jg) throws IOException {
}
}