com.redhat.lightblue.crud.mongo.BasicDocSaver.java Source code

Java tutorial

Introduction

Here is the source code for com.redhat.lightblue.crud.mongo.BasicDocSaver.java

Source

/*
 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 <http://www.gnu.org/licenses/>.
 */
package com.redhat.lightblue.crud.mongo;

import java.util.List;

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

import org.bson.types.ObjectId;

import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
import com.mongodb.WriteConcern;
import com.mongodb.WriteResult;
import com.mongodb.BasicDBObject;

import com.redhat.lightblue.crud.CRUDOperationContext;
import com.redhat.lightblue.crud.DocCtx;
import com.redhat.lightblue.crud.Operation;
import com.redhat.lightblue.crud.CrudConstants;
import com.redhat.lightblue.eval.FieldAccessRoleEvaluator;
import com.redhat.lightblue.metadata.EntityMetadata;
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;

        Object id = dbObject.get(MongoCRUDController.ID_STR);
        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, new ObjectId(id.toString()));
            DBObject oldDBObject = new FindOneCommand(null, collection, q).execute();
            if (oldDBObject != null) {
                if (md.getAccess().getUpdate().hasAccess(ctx.getCallerRoles())) {
                    JsonDoc oldDoc = translator.toJson(oldDBObject);
                    inputDoc.setOriginalDocument(oldDoc);
                    List<Path> paths = roleEval.getInaccessibleFields_Update(inputDoc, oldDoc);
                    if (paths == null || paths.isEmpty()) {
                        translator.addInvisibleFields(oldDBObject, dbObject, md);
                        result = new UpdateCommand(null, collection, q, dbObject, upsert, upsert, WriteConcern.SAFE)
                                .execute();
                        inputDoc.setOperationPerformed(Operation.UPDATE);
                    } 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 WriteResult insertDoc(CRUDOperationContext ctx, DBCollection collection, EntityMetadata md,
            DBObject dbObject, DocCtx inputDoc) {
        LOGGER.debug("Inserting doc");
        if (!md.getAccess().getInsert().hasAccess(ctx.getCallerRoles())) {
            inputDoc.addError(Error.get("insert", MongoCrudConstants.ERR_NO_ACCESS, "insert:" + md.getName()));
        } else {
            List<Path> paths = roleEval.getInaccessibleFields_Insert(inputDoc);
            LOGGER.debug("Inaccessible fields:{}", paths);
            if (paths == null || paths.isEmpty()) {
                try {
                    WriteResult r = new InsertCommand(null, collection, dbObject, WriteConcern.SAFE).execute();
                    inputDoc.setOperationPerformed(Operation.INSERT);
                    return r;
                } catch (MongoException.DuplicateKey dke) {
                    LOGGER.error("saveOrInsert failed: {}", dke);
                    inputDoc.addError(Error.get("insert", MongoCrudConstants.ERR_DUPLICATE, dke.toString()));
                }
            } else {
                inputDoc.addError(Error.get("insert", CrudConstants.ERR_NO_FIELD_INSERT_ACCESS, paths.toString()));
            }
        }
        return null;
    }
}