com.crosstreelabs.cognitio.service.mongo.MongoReferenceService.java Source code

Java tutorial

Introduction

Here is the source code for com.crosstreelabs.cognitio.service.mongo.MongoReferenceService.java

Source

/*
 * Copyright 2015 Crosstree Labs.
 *
 * 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.
 */
package com.crosstreelabs.cognitio.service.mongo;

import com.crosstreelabs.cognitio.api.resource.CatalogueEntry;
import com.crosstreelabs.cognitio.api.resource.Reference;
import com.crosstreelabs.cognitio.api.service.ReferenceService;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
import com.mongodb.WriteConcern;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Queue;
import org.apache.commons.collections4.queue.CircularFifoQueue;
import org.joda.time.DateTime;

public class MongoReferenceService implements ReferenceService {
    private final MongoClient client;
    private final DB db;
    private final DBCollection references;
    private final Queue<CacheEntry> referenceCache = new CircularFifoQueue<>(100);

    public MongoReferenceService(final MongoClient client) {
        this.client = client;
        db = client.getDB("cognitio");
        if (!db.collectionExists("references")) {
            references = db.createCollection("references", null);
            //            references.createIndex(new BasicDBObject("location", 1), new BasicDBObject("unique", true));
        } else {
            references = db.getCollection("references");
        }
    }

    @Override
    public Collection<Reference> findReferencesTo(final CatalogueEntry entry) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public Collection<Reference> findReferencesFrom(final CatalogueEntry entry) {
        Collection<Reference> result = new HashSet<>();
        DBCursor cursor = references.find(new BasicDBObject("linker", entry.id));
        for (DBObject obj : cursor) {
            Reference ref = fromMongoObject(obj);
            result.add(ref);
        }
        return result;
    }

    @Override
    public Collection<String> findReferencedUrlsFrom(final CatalogueEntry entry) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public Reference find(final String from, final String to) {
        // Check cache first
        for (CacheEntry entry : referenceCache) {
            if (entry.getReference().linker.equals(from) && entry.getReference().linkee.equals(to)) {
                return entry.getReference();
            }
        }
        DBObject obj = references.findOne(new BasicDBObject("linker", from).append("linkee", to));
        if (obj == null) {
            return null;
        }
        Reference result = fromMongoObject(obj);
        referenceCache.add(new CacheEntry(result));
        return result;
    }

    @Override
    public void save(final Reference reference) {
        Reference existing = find(reference.linker, reference.linkee);
        if (existing != null) {
            return;
        }

        DBObject obj = toMongoObject(reference);
        references.insert(obj, WriteConcern.JOURNALED);
        reference.id = obj.get("_id").toString();
        referenceCache.add(new CacheEntry(reference));
    }

    @Override
    public void saveAll(final Reference... references) {
        saveAll(Arrays.asList(references));
    }

    @Override
    public void saveAll(final Collection<Reference> references) {
        if (references.isEmpty()) {
            return;
        }
        List<DBObject> objs = new ArrayList<>();
        for (Reference ref : references) {
            objs.add(toMongoObject(ref));
        }
        this.references.insert(objs);
    }

    //~ Conversion methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    protected DBObject toMongoObject(final Reference reference) {
        DBObject result = new BasicDBObject();
        result.put("linker", reference.linker);
        result.put("linkee", reference.linkee);
        if (reference.discovered == null) {
            reference.discovered = new DateTime();
        }
        result.put("discovered", reference.discovered.toDate());
        if (reference.defunct != null) {
            result.put("defunct", reference.defunct.toDate());
        }
        return result;
    }

    protected Reference fromMongoObject(final DBObject obj) {
        Reference result = new Reference();
        result.id = obj.get("_id").toString();
        result.linker = obj.get("linker").toString();
        result.linkee = obj.get("linkee").toString();
        if (obj.get("discovered") != null) {
            result.discovered = new DateTime((Date) obj.get("discovered"));
        }
        if (obj.get("defunct") != null) {
            result.defunct = new DateTime((Date) obj.get("defunct"));
        }
        return result;
    }

    private static final class CacheEntry {
        private final Reference reference;
        private Map<String, Object> originalData;

        public CacheEntry(final Reference reference) {
            this.reference = reference;
            update();
        }

        public Reference getReference() {
            return reference;
        }

        public boolean isDirty() {
            return !(Objects.equals(reference.id, originalData.get("id"))
                    && Objects.equals(reference.linker, originalData.get("linker"))
                    && Objects.equals(reference.linkee, originalData.get("linkee"))
                    && Objects.equals(reference.discovered, originalData.get("discovered"))
                    && Objects.equals(reference.defunct, originalData.get("defunct")));
        }

        public void update() {
            Map<String, Object> data = new HashMap<>();
            data.put("id", reference.id);
            data.put("linker", reference.linker);
            data.put("linkee", reference.linkee);
            data.put("discovered", reference.discovered);
            data.put("defunct", reference.defunct);
            this.originalData = Collections.unmodifiableMap(data);
        }
    }

}