org.nuxeo.directory.mongodb.MongoDBDirectory.java Source code

Java tutorial

Introduction

Here is the source code for org.nuxeo.directory.mongodb.MongoDBDirectory.java

Source

/*
 * (C) Copyright 2017 Nuxeo (http://nuxeo.com/) and others.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributors:
 *     Funsho David
 *
 */

package org.nuxeo.directory.mongodb;

import static org.nuxeo.ecm.directory.BaseDirectoryDescriptor.CREATE_TABLE_POLICY_ALWAYS;
import static org.nuxeo.ecm.directory.BaseDirectoryDescriptor.CREATE_TABLE_POLICY_ON_MISSING_COLUMNS;
import static org.nuxeo.directory.mongodb.MongoDBSerializationHelper.MONGODB_ID;
import static org.nuxeo.directory.mongodb.MongoDBSerializationHelper.MONGODB_SEQ;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import org.nuxeo.ecm.core.cache.CacheService;
import org.nuxeo.ecm.core.schema.SchemaManager;
import org.nuxeo.ecm.core.schema.types.Field;
import org.nuxeo.ecm.core.schema.types.Schema;
import org.nuxeo.ecm.directory.AbstractDirectory;
import org.nuxeo.ecm.directory.Directory;
import org.nuxeo.ecm.directory.DirectoryCSVLoader;
import org.nuxeo.ecm.directory.DirectoryException;
import org.nuxeo.ecm.directory.Session;
import org.nuxeo.runtime.api.Framework;

import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Filters;

/**
 * MongoDB implementation of a {@link Directory}
 * 
 * @since 9.1
 */
public class MongoDBDirectory extends AbstractDirectory {

    protected Map<String, Field> schemaFieldMap;

    protected String countersCollectionName;

    protected boolean initialized;

    public MongoDBDirectory(MongoDBDirectoryDescriptor descriptor) {
        super(descriptor);

        // register the references to other directories
        addReferences(descriptor.getInverseReferences());
        addReferences(descriptor.getMongoDBReferences());

        // cache parameterization
        String cacheEntryName = descriptor.cacheEntryName;
        String cacheEntryNameWithoutReferencesName = descriptor.cacheEntryWithoutReferencesName;

        cache.setEntryCacheName(cacheEntryName);
        cache.setEntryCacheWithoutReferencesName(cacheEntryNameWithoutReferencesName);
        cache.setNegativeCaching(descriptor.negativeCaching);

        // cache fallback
        CacheService cacheService = Framework.getService(CacheService.class);
        if (cacheService != null) {
            if (cacheEntryName == null && descriptor.getCacheMaxSize() != 0) {
                cache.setEntryCacheName("cache-" + getName());
                cacheService.registerCache("cache-" + getName(), descriptor.getCacheMaxSize(),
                        descriptor.getCacheTimeout() / 60);
            }
            if (cacheEntryNameWithoutReferencesName == null && descriptor.getCacheMaxSize() != 0) {
                cache.setEntryCacheWithoutReferencesName("cacheWithoutReference-" + getName());
                cacheService.registerCache("cacheWithoutReference-" + getName(), descriptor.getCacheMaxSize(),
                        descriptor.getCacheTimeout() / 60);
            }
        }

        countersCollectionName = getName() + ".counters";

    }

    @Override
    public MongoDBDirectoryDescriptor getDescriptor() {
        return (MongoDBDirectoryDescriptor) descriptor;
    }

    @Override
    public Session getSession() throws DirectoryException {

        SchemaManager schemaManager = Framework.getService(SchemaManager.class);
        Schema schema = schemaManager.getSchema(getSchema());
        if (schema == null) {
            throw new DirectoryException(getSchema() + " is not a registered schema");
        }
        schemaFieldMap = new LinkedHashMap<>();
        schema.getFields().forEach(f -> schemaFieldMap.put(f.getName().getLocalName(), f));

        MongoDBSession session = new MongoDBSession(this);
        addSession(session);

        // Initialize counters collection if autoincrement enabled
        if (descriptor.isAutoincrementIdField() && !session.hasCollection(countersCollectionName)) {
            Map<String, Object> seq = new HashMap<>();
            seq.put(MONGODB_ID, getName());
            seq.put(MONGODB_SEQ, 0L);
            session.getCollection(countersCollectionName).insertOne(MongoDBSerializationHelper.fieldMapToBson(seq));
        }

        if (!initialized) {
            String policy = descriptor.getCreateTablePolicy();
            MongoCollection collection = session.getCollection(getName());
            boolean dropCollection = false;
            boolean loadData = false;

            switch (policy) {
            case CREATE_TABLE_POLICY_ALWAYS:
                dropCollection = true;
                loadData = true;
                break;
            case CREATE_TABLE_POLICY_ON_MISSING_COLUMNS:
                if (session.hasCollection(getName())) {
                    long totalEntries = collection.count();
                    boolean missingColumns = schema.getFields().stream().map(f -> f.getName().getLocalName())
                            .anyMatch(fname -> collection.count(Filters.exists(fname, false)) == totalEntries);
                    if (missingColumns) {
                        dropCollection = true;
                        loadData = true;
                    }
                } else {
                    loadData = true;
                }
                break;
            default:
                if (!session.hasCollection(getName())) {
                    loadData = true;
                }
                break;
            }
            if (dropCollection) {
                collection.drop();
            }
            if (loadData) {
                loadData(schema, session);
            }
            initialized = true;
        }
        return session;
    }

    protected void loadData(Schema schema, Session session) {
        if (descriptor.getDataFileName() != null) {
            DirectoryCSVLoader.loadData(descriptor.getDataFileName(), descriptor.getDataFileCharacterSeparator(),
                    schema, session::createEntry);
        }
    }

    public Map<String, Field> getSchemaFieldMap() {
        return schemaFieldMap;
    }

    public String getCountersCollectionName() {
        return countersCollectionName;
    }
}