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 * Gabriel Barata <gbarata@nuxeo.com> 018 */ 019package org.nuxeo.ecm.platform.search.core; 020 021import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE; 022import static org.nuxeo.ecm.core.io.registry.MarshallingConstants.WILDCARD_VALUE; 023import static org.nuxeo.ecm.core.io.registry.reflect.Instantiations.SINGLETON; 024import static org.nuxeo.ecm.core.io.registry.reflect.Priorities.REFERENCE; 025 026import java.io.Closeable; 027import java.io.IOException; 028import java.io.OutputStream; 029import java.util.Arrays; 030import java.util.Collection; 031import java.util.HashMap; 032import java.util.HashSet; 033import java.util.Iterator; 034import java.util.Map; 035import java.util.Set; 036 037import javax.inject.Inject; 038 039import org.nuxeo.ecm.core.api.DocumentModel; 040import org.nuxeo.ecm.core.api.model.Property; 041import org.nuxeo.ecm.core.io.marshallers.json.ExtensibleEntityJsonWriter; 042import org.nuxeo.ecm.core.io.marshallers.json.OutputStreamWithJsonWriter; 043import org.nuxeo.ecm.core.io.registry.Writer; 044import org.nuxeo.ecm.core.io.registry.reflect.Setup; 045import org.nuxeo.ecm.core.schema.SchemaManager; 046import org.nuxeo.ecm.core.schema.types.Field; 047import org.nuxeo.ecm.core.schema.types.Schema; 048 049import com.fasterxml.jackson.core.JsonGenerator; 050import org.nuxeo.runtime.api.Framework; 051 052/** 053 * @since 8.3 054 */ 055@Setup(mode = SINGLETON, priority = REFERENCE) 056public class SavedSearchWriter extends ExtensibleEntityJsonWriter<SavedSearch> { 057 058 public static final String ENTITY_TYPE = "savedSearch"; 059 060 @Inject 061 private SchemaManager schemaManager; 062 063 public SavedSearchWriter() { 064 super(ENTITY_TYPE, SavedSearch.class); 065 } 066 067 @Override 068 protected void writeEntityBody(SavedSearch search, JsonGenerator jg) throws IOException { 069 jg.writeStringField("id", search.getId()); 070 jg.writeStringField("title", search.getTitle()); 071 jg.writeStringField("queryParams", search.getQueryParams()); 072 jg.writeStringField("query", search.getQuery()); 073 jg.writeStringField("queryLanguage", search.getQueryLanguage()); 074 jg.writeStringField("pageProviderName", search.getPageProviderName()); 075 jg.writeStringField("pageSize", search.getPageSize() == null ? null : search.getPageSize().toString()); 076 jg.writeStringField("currentPageIndex", search.getCurrentPageIndex() == null ? null 077 : search.getCurrentPageIndex().toString()); 078 jg.writeStringField("maxResults", search.getMaxResults() == null ? null : search.getMaxResults().toString()); 079 jg.writeStringField("sortBy", search.getSortBy()); 080 jg.writeStringField("sortOrder", search.getSortOrder()); 081 jg.writeStringField("contentViewData", search.getContentViewData()); 082 083 Map<String, String> params = search.getNamedParams(); 084 if (params == null) { 085 params = new HashMap<>(); 086 } 087 088 jg.writeObjectFieldStart("params"); 089 Iterator<String> it = params.keySet().iterator(); 090 while (it.hasNext()) { 091 String param = it.next(); 092 jg.writeStringField(param, search.getNamedParams().get(param)); 093 } 094 095 // write own schema properties as search parameters (unprefixed) 096 SchemaManager schemaManager = Framework.getService(SchemaManager.class); 097 DocumentModel doc = search.getDocument(); 098 Set<String> ownSchemas = new HashSet<>(Arrays.asList(doc.getSchemas())); 099 doc.getFacets() 100 .stream() 101 .map(facet -> schemaManager.getFacet(facet).getSchemas()) 102 .flatMap(Collection::stream) 103 .forEach(schema -> ownSchemas.remove(schema.getName())); 104 for (String schema : ownSchemas) { 105 writeSchemaProperties(jg, doc, schema, false); 106 } 107 jg.writeEndObject(); 108 109 // write document model properties 110 Set<String> schemas = ctx.getProperties(); 111 if (schemas.size() > 0) { 112 jg.writeObjectFieldStart("properties"); 113 if (schemas.contains(WILDCARD_VALUE)) { 114 // full document 115 for (String schema : doc.getSchemas()) { 116 writeSchemaProperties(jg, doc, schema); 117 } 118 } else { 119 for (String schema : schemas) { 120 if (doc.hasSchema(schema)) { 121 writeSchemaProperties(jg, doc, schema); 122 } 123 } 124 } 125 jg.writeEndObject(); 126 } 127 } 128 129 private void writeSchemaProperties(JsonGenerator jg, DocumentModel doc, String schemaName) throws IOException { 130 writeSchemaProperties(jg, doc, schemaName, true); 131 } 132 133 private void writeSchemaProperties(JsonGenerator jg, DocumentModel doc, String schemaName, boolean usePrefix) 134 throws IOException { 135 Writer<Property> propertyWriter = registry.getWriter(ctx, Property.class, APPLICATION_JSON_TYPE); 136 // provides the current document to the property marshaller 137 try (Closeable resource = ctx.wrap().with(ENTITY_TYPE, doc).open()) { 138 Schema schema = schemaManager.getSchema(schemaName); 139 String prefix = ""; 140 if (usePrefix) { 141 prefix = schema.getNamespace().prefix; 142 if (prefix == null || prefix.length() == 0) { 143 prefix = schemaName; 144 } 145 prefix = prefix + ":"; 146 } 147 for (Field field : schema.getFields()) { 148 String prefixedName = prefix + field.getName().getLocalName(); 149 jg.writeFieldName(prefixedName); 150 Property property = doc.getProperty(prefixedName); 151 OutputStream out = new OutputStreamWithJsonWriter(jg); 152 propertyWriter.write(property, Property.class, Property.class, APPLICATION_JSON_TYPE, out); 153 } 154 } 155 } 156}