001/* 002 * (C) Copyright 2016 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 * Guillaume Renard <grenard@nuxeo.com> 018 */ 019package org.nuxeo.elasticsearch.io.marshallers.json; 020 021import static org.nuxeo.ecm.core.io.registry.MarshallingConstants.FETCH_PROPERTIES; 022import static org.nuxeo.ecm.core.io.registry.MarshallingConstants.MAX_DEPTH_PARAM; 023import static org.nuxeo.ecm.core.io.registry.MarshallingConstants.TRANSLATE_PROPERTIES; 024import static org.nuxeo.ecm.core.io.registry.reflect.Instantiations.SINGLETON; 025import static org.nuxeo.ecm.core.io.registry.reflect.Priorities.REFERENCE; 026 027import java.io.Closeable; 028import java.io.IOException; 029import java.lang.reflect.Type; 030import java.util.List; 031 032import javax.inject.Inject; 033import javax.ws.rs.core.MediaType; 034 035import org.apache.commons.logging.Log; 036import org.apache.commons.logging.LogFactory; 037import org.codehaus.jackson.JsonGenerationException; 038import org.codehaus.jackson.JsonGenerator; 039import org.nuxeo.ecm.core.api.model.Property; 040import org.nuxeo.ecm.core.api.model.impl.PropertyFactory; 041import org.nuxeo.ecm.core.io.marshallers.json.ExtensibleEntityJsonWriter; 042import org.nuxeo.ecm.core.io.marshallers.json.document.DocumentModelJsonWriter; 043import org.nuxeo.ecm.core.io.registry.reflect.Setup; 044import org.nuxeo.ecm.core.schema.SchemaManager; 045import org.nuxeo.ecm.core.schema.types.Field; 046import org.nuxeo.ecm.core.schema.types.ListType; 047import org.nuxeo.ecm.core.schema.utils.DateParser; 048import org.nuxeo.ecm.directory.io.DirectoryEntryJsonWriter; 049import org.nuxeo.ecm.platform.query.api.Aggregate; 050import org.nuxeo.ecm.platform.query.api.Bucket; 051import org.nuxeo.ecm.platform.query.core.BucketRange; 052import org.nuxeo.ecm.platform.query.core.BucketRangeDate; 053import org.nuxeo.elasticsearch.aggregate.SignificantTermAggregate; 054import org.nuxeo.elasticsearch.aggregate.TermAggregate; 055 056/** 057 * @since 8.4 058 */ 059@SuppressWarnings("rawtypes") 060@Setup(mode = SINGLETON, priority = REFERENCE) 061public class AggregateJsonWriter extends ExtensibleEntityJsonWriter<Aggregate> { 062 063 private static final Log log = LogFactory.getLog(AggregateJsonWriter.class); 064 065 public static final String ENTITY_TYPE = "aggregate"; 066 067 public static final String FETCH_KEY = "key"; 068 069 @Inject 070 private SchemaManager schemaManager; 071 072 public AggregateJsonWriter() { 073 super(ENTITY_TYPE, Aggregate.class); 074 } 075 076 public AggregateJsonWriter(String entityType, Class<Aggregate> entityClass) { 077 super(entityType, entityClass); 078 } 079 080 @Override 081 public boolean accept(Class<?> clazz, Type genericType, MediaType mediatype) { 082 return true; 083 } 084 085 @SuppressWarnings("unchecked") 086 @Override 087 protected void writeEntityBody(Aggregate agg, JsonGenerator jg) throws IOException { 088 boolean fetch = ctx.getFetched(ENTITY_TYPE).contains(FETCH_KEY); 089 jg.writeObjectField("id", agg.getId()); 090 jg.writeObjectField("field", agg.getField()); 091 jg.writeObjectField("properties", agg.getProperties()); 092 jg.writeObjectField("ranges", agg.getRanges()); 093 jg.writeObjectField("selection", agg.getSelection()); 094 jg.writeObjectField("type", agg.getType()); 095 if (!fetch || !(agg instanceof TermAggregate || agg instanceof SignificantTermAggregate)) { 096 jg.writeObjectField("buckets", agg.getBuckets()); 097 jg.writeObjectField("extendedBuckets", agg.getExtendedBuckets()); 098 } else { 099 String fieldName = agg.getField(); 100 Field field = schemaManager.getField(fieldName); 101 if (field != null) { 102 try (Closeable resource = ctx.wrap() 103 .with(FETCH_PROPERTIES + "." + DocumentModelJsonWriter.ENTITY_TYPE, 104 "properties") 105 .with(FETCH_PROPERTIES + "." + DirectoryEntryJsonWriter.ENTITY_TYPE, 106 "parent") 107 .with(TRANSLATE_PROPERTIES + "." + DirectoryEntryJsonWriter.ENTITY_TYPE, 108 "label") 109 .with(MAX_DEPTH_PARAM, "max") 110 .open()) { 111 112 writeBuckets("buckets", agg.getBuckets(), field, jg); 113 writeBuckets("extendedBuckets", agg.getExtendedBuckets(), field, jg); 114 } 115 } else { 116 log.warn(String.format("Could not resolve field %s for aggrgeate %s", fieldName, agg.getId())); 117 jg.writeObjectField("buckets", agg.getBuckets()); 118 jg.writeObjectField("extendedBuckets", agg.getExtendedBuckets()); 119 } 120 } 121 } 122 123 protected void writeBuckets(String fieldName, List<Bucket> buckets, Field field, JsonGenerator jg) 124 throws IOException, JsonGenerationException { 125 jg.writeArrayFieldStart(fieldName); 126 for (Bucket bucket : buckets) { 127 jg.writeStartObject(); 128 129 jg.writeObjectField("key", bucket.getKey()); 130 131 Property prop = PropertyFactory.createProperty(null, field, Property.NONE); 132 if (prop.isList()) { 133 ListType t = (ListType) prop.getType(); 134 t.getField(); 135 prop = PropertyFactory.createProperty(null, t.getField(), Property.NONE); 136 } 137 log.debug(String.format("Writing %s for field %s resolved to %s", fieldName, field.getName().toString(), 138 prop.getName())); 139 prop.setValue(bucket.getKey()); 140 141 writeEntityField("fetchedKey", prop, jg); 142 jg.writeNumberField("docCount", bucket.getDocCount()); 143 jg.writeEndObject(); 144 145 if (bucket instanceof BucketRange) { 146 BucketRange bucketRange = (BucketRange) bucket; 147 jg.writeNumberField("from", bucketRange.getFrom()); 148 jg.writeNumberField("to", bucketRange.getTo()); 149 } 150 151 if (bucket instanceof BucketRangeDate) { 152 BucketRangeDate bucketRange = (BucketRangeDate) bucket; 153 jg.writeStringField("fromAsDate", DateParser.formatW3CDateTime(bucketRange.getFromAsDate().toDate())); 154 jg.writeStringField("toAsDate", DateParser.formatW3CDateTime(bucketRange.getToAsDate().toDate())); 155 } 156 } 157 jg.writeEndArray(); 158 } 159 160}