/* * RESTHeart - the Web API for MongoDB * Copyright (C) SoftInstigate Srl * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.restheart.handlers.indexes; import io.undertow.server.HttpServerExchange; import static java.lang.Math.toIntExact; import java.util.List; import org.bson.BsonDocument; import org.bson.BsonInt32; import org.bson.BsonString; import org.bson.BsonValue; import org.restheart.Configuration; import org.restheart.hal.Link; import org.restheart.hal.Representation; import org.restheart.handlers.IllegalQueryParamenterException; import org.restheart.handlers.RequestContext; import org.restheart.utils.URLUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author Andrea Di Cesare {@literal <andrea@softinstigate.com>} */ public class IndexesRepresentationFactory { private static final Logger LOGGER = LoggerFactory.getLogger(IndexesRepresentationFactory.class); /** * * @param exchange * @param context * @param embeddedData * @param size * @throws IllegalQueryParamenterException */ static public Representation getRepresentation( HttpServerExchange exchange, RequestContext context, List<BsonDocument> embeddedData, long size) throws IllegalQueryParamenterException { String requestPath = URLUtils.removeTrailingSlashes( context.getUnmappedRequestUri()); String queryString = exchange.getQueryString() == null || exchange.getQueryString().isEmpty() ? "" : "?" + URLUtils.decodeQueryString(exchange.getQueryString()); Representation rep; if (context.isFullHalMode()) { rep = new Representation(requestPath + queryString); } else { rep = new Representation(); } if (size >= 0) { rep.addProperty("_size", new BsonInt32(toIntExact(size))); } if (embeddedData != null) { long count = embeddedData.stream() .filter((props) -> props.keySet().stream() .anyMatch((k) -> k.equals("id") || k.equals("_id"))) .count(); rep.addProperty("_returned", new BsonInt32(toIntExact(count))); if (!embeddedData.isEmpty()) { embeddedDocuments( embeddedData, requestPath, rep, context.isFullHalMode()); } } if (context.isFullHalMode()) { rep.addProperty("_type", new BsonString(context.getType().name())); if (context.isParentAccessible()) { // this can happen due to mongo-mounts mapped URL if (context.getCollectionName().endsWith( RequestContext.FS_FILES_SUFFIX)) { rep.addLink(new Link( "rh:bucket", URLUtils.getParentPath(requestPath))); } else { rep.addLink(new Link( "rh:coll", URLUtils.getParentPath(requestPath))); } } rep.addLink(new Link("rh:indexes", requestPath)); rep.addLink(new Link("rh", "curies", Configuration.RESTHEART_ONLINE_DOC_URL + "/{rel}.html", true), true); } return rep; } private static void embeddedDocuments( List<BsonDocument> embeddedData, String requestPath, Representation rep, boolean isHalFull) { embeddedData.stream().forEach((d) -> { BsonValue _id = d.get("_id"); if (_id != null && (_id.isString() || _id.isObjectId())) { Representation nrep = new Representation(); if (isHalFull) { nrep.addProperty("_type", new BsonString(RequestContext.TYPE.INDEX.name())); } nrep.addProperties(d); rep.addRepresentation("rh:index", nrep); } else { rep.addWarning("index with _id " + _id + (_id == null ? " " : " of type " + _id.getBsonType().name()) + "filtered out. Indexes can only " + "have ids of type String"); LOGGER.debug("index missing string _id field", d); } }); } private IndexesRepresentationFactory() { } }