/*
* 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.metadata;
import io.undertow.server.HttpServerExchange;
import java.util.List;
import org.bson.BsonArray;
import org.bson.BsonDocument;
import org.bson.BsonValue;
import org.restheart.metadata.transformers.RepresentationTransformer;
import org.restheart.metadata.NamedSingletonsFactory;
import org.restheart.handlers.PipedHttpHandler;
import org.restheart.handlers.RequestContext;
import org.restheart.metadata.transformers.Transformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* handler that applies the transformers defined in the collection properties to
* the request
*
* @author Andrea Di Cesare {@literal <andrea@softinstigate.com>}
*/
public class RequestTransformerMetadataHandler
extends AbstractTransformerMetadataHandler {
static final Logger LOGGER
= LoggerFactory.getLogger(RequestTransformerMetadataHandler.class);
/**
* Creates a new instance of RequestTransformerMetadataHandler
*
* @param next
*/
public RequestTransformerMetadataHandler(PipedHttpHandler next) {
super(next);
}
@Override
boolean canCollRepresentationTransformersAppy(RequestContext context) {
return (!context.isInError()
&& (context.getType() == RequestContext.TYPE.DOCUMENT
|| context.getType() == RequestContext.TYPE.BULK_DOCUMENTS
|| context.getType() == RequestContext.TYPE.COLLECTION
|| context.getType() == RequestContext.TYPE.AGGREGATION
|| context.getType() == RequestContext.TYPE.FILE
|| context.getType() == RequestContext.TYPE.FILES_BUCKET
|| context.getType() == RequestContext.TYPE.INDEX
|| context.getType() == RequestContext.TYPE.COLLECTION_INDEXES
|| context.getType() == RequestContext.TYPE.SCHEMA_STORE
|| context.getType() == RequestContext.TYPE.SCHEMA)
&& context.getCollectionProps() != null
&& context.getCollectionProps()
.containsKey(RepresentationTransformer.RTS_ELEMENT_NAME));
}
@Override
boolean canDBRepresentationTransformersAppy(RequestContext context) {
return (!context.isInError()
&& (context.getType() == RequestContext.TYPE.DB
|| context.getType() == RequestContext.TYPE.COLLECTION
|| context.getType() == RequestContext.TYPE.FILES_BUCKET
|| context.getType() == RequestContext.TYPE.COLLECTION_INDEXES
|| context.getType() == RequestContext.TYPE.SCHEMA_STORE)
&& context.getDbProps() != null
&& context.getDbProps()
.containsKey(RepresentationTransformer.RTS_ELEMENT_NAME));
}
@Override
void enforceDbRepresentationTransformLogic(
HttpServerExchange exchange,
RequestContext context)
throws InvalidMetadataException {
List<RepresentationTransformer> dbRts
= RepresentationTransformer.getFromJson(context.getDbProps());
RequestContext.TYPE requestType = context.getType(); // DB, COLLECTION or FILES_BUCKET
for (RepresentationTransformer rt : dbRts) {
Transformer t;
BsonDocument confArgs;
try {
NamedSingletonsFactory nsf = NamedSingletonsFactory.getInstance();
t = (Transformer) nsf
.get("transformers", rt.getName());
confArgs
= nsf.getArgs("transformers", rt.getName());
} catch (IllegalArgumentException ex) {
context.addWarning("error applying transformer: "
+ ex.getMessage());
return;
}
if (t == null) {
throw new IllegalArgumentException("cannot find singleton "
+ rt.getName()
+ " in singleton group transformers");
}
if (rt.getPhase() == RepresentationTransformer.PHASE.REQUEST) {
if (rt.getScope() == RepresentationTransformer.SCOPE.THIS
&& requestType == RequestContext.TYPE.DB) {
t.transform(
exchange,
context,
context.getContent(),
rt.getArgs(),
confArgs);
} else {
t.transform(
exchange,
context,
context.getContent(),
rt.getArgs(),
confArgs);
}
}
}
}
@Override
void enforceCollRepresentationTransformLogic(
HttpServerExchange exchange,
RequestContext context)
throws InvalidMetadataException {
List<RepresentationTransformer> collRts = RepresentationTransformer
.getFromJson(context.getCollectionProps());
for (RepresentationTransformer rt : collRts) {
if (rt.getPhase() == RepresentationTransformer.PHASE.REQUEST) {
NamedSingletonsFactory nsf = NamedSingletonsFactory.getInstance();
Transformer t = (Transformer) nsf
.get("transformers", rt.getName());
BsonDocument confArgs
= nsf.getArgs("transformers", rt.getName());
if (t == null) {
throw new IllegalArgumentException("cannot find singleton "
+ rt.getName()
+ " in singleton group transformers");
}
BsonValue content = context.getContent();
// content can be an array for bulk POST
if (content == null) {
t.transform(
exchange,
context,
new BsonDocument(),
rt.getArgs(),
confArgs);
} else if (content.isDocument()) {
t.transform(
exchange,
context,
content.asDocument(),
rt.getArgs(),
confArgs);
} else if (content.isArray()) {
BsonArray arrayContent = content.asArray();
arrayContent.stream().forEach(obj -> {
if (obj.isDocument()) {
t.transform(
exchange,
context,
obj.asDocument(),
rt.getArgs(),
confArgs);
} else {
LOGGER.warn("an element of content array "
+ "is not an object");
}
});
}
}
}
}
}