All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.redhat.lightblue.crud.mongo.BasicDocSaver Maven / Gradle / Ivy

The newest version!
/*
 Copyright 2013 Red Hat, Inc. and/or its affiliates.

 This file is part of lightblue.

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU 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 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see .
 */
package com.redhat.lightblue.crud.mongo;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
import com.mongodb.WriteResult;
import com.redhat.lightblue.crud.CRUDOperation;
import com.redhat.lightblue.crud.CRUDOperationContext;
import com.redhat.lightblue.crud.CrudConstants;
import com.redhat.lightblue.crud.DocCtx;
import com.redhat.lightblue.eval.FieldAccessRoleEvaluator;
import com.redhat.lightblue.interceptor.InterceptPoint;
import com.redhat.lightblue.metadata.EntityMetadata;
import com.redhat.lightblue.metadata.Field;
import com.redhat.lightblue.mongo.hystrix.FindOneCommand;
import com.redhat.lightblue.mongo.hystrix.InsertCommand;
import com.redhat.lightblue.mongo.hystrix.UpdateCommand;
import com.redhat.lightblue.util.Error;
import com.redhat.lightblue.util.JsonDoc;
import com.redhat.lightblue.util.Path;

/**
 * Basic doc saver with no transaction support
 */
public class BasicDocSaver implements DocSaver {

    private static final Logger LOGGER = LoggerFactory.getLogger(BasicDocSaver.class);

    private final FieldAccessRoleEvaluator roleEval;
    private final Translator translator;

    /**
     * Creates a doc saver with the given translator and role evaluator
     */
    public BasicDocSaver(Translator translator,
            FieldAccessRoleEvaluator roleEval) {
        this.translator = translator;
        this.roleEval = roleEval;
    }

    @Override
    public void saveDoc(CRUDOperationContext ctx,
            Op op,
            boolean upsert,
            DBCollection collection,
            EntityMetadata md,
            DBObject dbObject,
            DocCtx inputDoc) {

        WriteResult result = null;
        String error = null;

        DBObject oldDBObject=null;
        
        Object id=dbObject.get(MongoCRUDController.ID_STR);
        if(id==null) {
            LOGGER.debug("Null _id, looking up the doc using identity fields");
            Field[] identityFields=md.getEntitySchema().getIdentityFields();
            Object[] identityFieldValues=fill(dbObject,identityFields);
            if(!isNull(identityFieldValues)) {                            
                DBObject lookupq=getLookupQ(identityFields,identityFieldValues);
                LOGGER.debug("Lookup query: {}",lookupq);                            
                oldDBObject=new FindOneCommand(collection,lookupq).executeAndUnwrap();
                LOGGER.debug("Retrieved:{}",oldDBObject);
                if(oldDBObject!=null)
                    id=oldDBObject.get(MongoCRUDController.ID_STR);
                LOGGER.debug("Retrieved id:{}",id);
            }
        }
        
        if (op == DocSaver.Op.insert
            || (id==null && upsert)) {
            // Inserting
            result = insertDoc(ctx, collection, md, dbObject, inputDoc);
        } else if (op == DocSaver.Op.save && id!=null) {
            // Updating
            LOGGER.debug("Updating doc {}" + id);
            BasicDBObject q = new BasicDBObject(MongoCRUDController.ID_STR, Translator.createIdFrom(id));
            if(oldDBObject==null) {
                oldDBObject = new FindOneCommand(collection, q).executeAndUnwrap();
            }
            if (oldDBObject != null) {
                if (md.getAccess().getUpdate().hasAccess(ctx.getCallerRoles())) {
                    JsonDoc oldDoc = translator.toJson(oldDBObject);
                    inputDoc.setOriginalDocument(oldDoc);
                    List paths = roleEval.getInaccessibleFields_Update(inputDoc, oldDoc);
                    if (paths == null || paths.isEmpty()) {
                        ctx.getFactory().getInterceptors().callInterceptors(InterceptPoint.PRE_CRUD_UPDATE_DOC, ctx, inputDoc);
                        translator.addInvisibleFields(oldDBObject, dbObject, md);
                        result = new UpdateCommand(collection, q, dbObject, upsert, false).executeAndUnwrap();
                        inputDoc.setCRUDOperationPerformed(CRUDOperation.UPDATE);
                        ctx.getFactory().getInterceptors().callInterceptors(InterceptPoint.POST_CRUD_UPDATE_DOC, ctx, inputDoc);
                    } else {
                        inputDoc.addError(Error.get("update",
                                CrudConstants.ERR_NO_FIELD_UPDATE_ACCESS, paths.toString()));
                    }
                } else {
                    inputDoc.addError(Error.get("update",
                            CrudConstants.ERR_NO_ACCESS, "update:" + md.getName()));
                }
            } else {
                // Cannot update, doc does not exist, insert
                result = insertDoc(ctx, collection, md, dbObject, inputDoc);
            }
        } else {
            // Error, invalid request
            LOGGER.warn("Invalid request, cannot update or insert");
            inputDoc.addError(Error.get(op.toString(), MongoCrudConstants.ERR_SAVE_ERROR, "Invalid request"));
        }

        LOGGER.debug("Write result {}", result);
        if (result != null) {
            if (error == null) {
                error = result.getError();
            }
            if (error != null) {
                inputDoc.addError(Error.get(op.toString(), MongoCrudConstants.ERR_SAVE_ERROR, error));
            }
        }
    }

    private DBObject getLookupQ(Field[] fields,Object[] values) {
        BasicDBObject dbObject=new BasicDBObject();
        for(int i=0;i paths = roleEval.getInaccessibleFields_Insert(inputDoc);
            LOGGER.debug("Inaccessible fields:{}", paths);
            if (paths == null || paths.isEmpty()) {
                try {
                    ctx.getFactory().getInterceptors().callInterceptors(InterceptPoint.PRE_CRUD_INSERT_DOC, ctx, inputDoc);
                    WriteResult r = new InsertCommand(collection, dbObject).executeAndUnwrap();
                    inputDoc.setCRUDOperationPerformed(CRUDOperation.INSERT);
                    ctx.getFactory().getInterceptors().callInterceptors(InterceptPoint.POST_CRUD_INSERT_DOC, ctx, inputDoc);
                    return r;
                } catch (MongoException.DuplicateKey dke) {
                    LOGGER.error("saveOrInsert failed: {}", dke);
                    inputDoc.addError(Error.get("insert", MongoCrudConstants.ERR_DUPLICATE, dke));
                }
            } else {
                for(Path path : paths){
                    inputDoc.addError(Error.get("insert", CrudConstants.ERR_NO_FIELD_INSERT_ACCESS, path.toString()));
                }
            }
        }
        return null;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy