/* * (C) Copyright 2016 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: * Guillaume Renard <grenard@nuxeo.com> */ package org.nuxeo.elasticsearch.io.marshallers.json; import static org.nuxeo.ecm.core.io.registry.MarshallingConstants.FETCH_PROPERTIES; import static org.nuxeo.ecm.core.io.registry.MarshallingConstants.MAX_DEPTH_PARAM; import static org.nuxeo.ecm.core.io.registry.MarshallingConstants.TRANSLATE_PROPERTIES; import static org.nuxeo.ecm.core.io.registry.reflect.Instantiations.SINGLETON; import static org.nuxeo.ecm.core.io.registry.reflect.Priorities.REFERENCE; import java.io.Closeable; import java.io.IOException; import java.lang.reflect.Type; import java.util.List; import javax.inject.Inject; import javax.ws.rs.core.MediaType; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codehaus.jackson.JsonGenerationException; import org.codehaus.jackson.JsonGenerator; import org.nuxeo.ecm.core.api.model.Property; import org.nuxeo.ecm.core.api.model.impl.PropertyFactory; import org.nuxeo.ecm.core.io.marshallers.json.ExtensibleEntityJsonWriter; import org.nuxeo.ecm.core.io.marshallers.json.document.DocumentModelJsonWriter; import org.nuxeo.ecm.core.io.registry.reflect.Setup; import org.nuxeo.ecm.core.schema.SchemaManager; import org.nuxeo.ecm.core.schema.types.Field; import org.nuxeo.ecm.core.schema.types.ListType; import org.nuxeo.ecm.core.schema.utils.DateParser; import org.nuxeo.ecm.directory.io.DirectoryEntryJsonWriter; import org.nuxeo.ecm.platform.query.api.Aggregate; import org.nuxeo.ecm.platform.query.api.Bucket; import org.nuxeo.ecm.platform.query.core.BucketRange; import org.nuxeo.ecm.platform.query.core.BucketRangeDate; import org.nuxeo.elasticsearch.aggregate.SignificantTermAggregate; import org.nuxeo.elasticsearch.aggregate.TermAggregate; /** * @since 8.4 */ @SuppressWarnings("rawtypes") @Setup(mode = SINGLETON, priority = REFERENCE) public class AggregateJsonWriter extends ExtensibleEntityJsonWriter<Aggregate> { private static final Log log = LogFactory.getLog(AggregateJsonWriter.class); public static final String ENTITY_TYPE = "aggregate"; public static final String FETCH_KEY = "key"; @Inject private SchemaManager schemaManager; public AggregateJsonWriter() { super(ENTITY_TYPE, Aggregate.class); } public AggregateJsonWriter(String entityType, Class<Aggregate> entityClass) { super(entityType, entityClass); } @Override public boolean accept(Class<?> clazz, Type genericType, MediaType mediatype) { return true; } @SuppressWarnings("unchecked") @Override protected void writeEntityBody(Aggregate agg, JsonGenerator jg) throws IOException { boolean fetch = ctx.getFetched(ENTITY_TYPE).contains(FETCH_KEY); jg.writeObjectField("id", agg.getId()); jg.writeObjectField("field", agg.getField()); jg.writeObjectField("properties", agg.getProperties()); jg.writeObjectField("ranges", agg.getRanges()); jg.writeObjectField("selection", agg.getSelection()); jg.writeObjectField("type", agg.getType()); if (!fetch || !(agg instanceof TermAggregate || agg instanceof SignificantTermAggregate)) { jg.writeObjectField("buckets", agg.getBuckets()); jg.writeObjectField("extendedBuckets", agg.getExtendedBuckets()); } else { String fieldName = agg.getField(); Field field = schemaManager.getField(fieldName); if (field != null) { try (Closeable resource = ctx.wrap() .with(FETCH_PROPERTIES + "." + DocumentModelJsonWriter.ENTITY_TYPE, "properties") .with(FETCH_PROPERTIES + "." + DirectoryEntryJsonWriter.ENTITY_TYPE, "parent") .with(TRANSLATE_PROPERTIES + "." + DirectoryEntryJsonWriter.ENTITY_TYPE, "label") .with(MAX_DEPTH_PARAM, "max") .open()) { writeBuckets("buckets", agg.getBuckets(), field, jg); writeBuckets("extendedBuckets", agg.getExtendedBuckets(), field, jg); } } else { log.warn(String.format("Could not resolve field %s for aggrgeate %s", fieldName, agg.getId())); jg.writeObjectField("buckets", agg.getBuckets()); jg.writeObjectField("extendedBuckets", agg.getExtendedBuckets()); } } } protected void writeBuckets(String fieldName, List<Bucket> buckets, Field field, JsonGenerator jg) throws IOException, JsonGenerationException { jg.writeArrayFieldStart(fieldName); for (Bucket bucket : buckets) { jg.writeStartObject(); jg.writeObjectField("key", bucket.getKey()); Property prop = PropertyFactory.createProperty(null, field, Property.NONE); if (prop.isList()) { ListType t = (ListType) prop.getType(); t.getField(); prop = PropertyFactory.createProperty(null, t.getField(), Property.NONE); } log.debug(String.format("Writing %s for field %s resolved to %s", fieldName, field.getName().toString(), prop.getName())); prop.setValue(bucket.getKey()); writeEntityField("fetchedKey", prop, jg); jg.writeNumberField("docCount", bucket.getDocCount()); jg.writeEndObject(); if (bucket instanceof BucketRange) { BucketRange bucketRange = (BucketRange) bucket; jg.writeNumberField("from", bucketRange.getFrom()); jg.writeNumberField("to", bucketRange.getTo()); } if (bucket instanceof BucketRangeDate) { BucketRangeDate bucketRange = (BucketRangeDate) bucket; jg.writeStringField("fromAsDate", DateParser.formatW3CDateTime(bucketRange.getFromAsDate().toDate())); jg.writeStringField("toAsDate", DateParser.formatW3CDateTime(bucketRange.getToAsDate().toDate())); } } jg.writeEndArray(); } }