org.eclipselabs.mongoemf.streams.MongoInputStream.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipselabs.mongoemf.streams.MongoInputStream.java

Source

/*******************************************************************************
 * Copyright (c) 2011 Bryan Hunt & Ed Merks.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Bryan Hunt & Ed Merks - initial API and implementation
 *******************************************************************************/

package org.eclipselabs.mongoemf.streams;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipselabs.emodeling.EReferenceCollection;
import org.eclipselabs.emodeling.EmodelingFactory;
import org.eclipselabs.mongoemf.ConverterService;
import org.eclipselabs.mongoemf.EObjectBuilder;
import org.eclipselabs.mongoemf.EObjectBuilderFactory;
import org.eclipselabs.mongoemf.Keywords;
import org.eclipselabs.mongoemf.MongoUtils;
import org.eclipselabs.mongoemf.Options;
import org.eclipselabs.mongoemf.QueryEngine;
import org.eclipselabs.mongoemf.model.ModelFactory;
import org.eclipselabs.mongoemf.model.MongoCursor;
import org.eclipselabs.mongoemf.model.MongoQuery;

import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;

/**
 * @author bhunt
 * 
 */
public class MongoInputStream extends InputStream implements URIConverter.Loadable {
    public MongoInputStream(ConverterService converterService, EObjectBuilderFactory builderFactory,
            QueryEngine queryEngine, DBCollection collection, URI uri, Map<?, ?> options,
            Map<Object, Object> response) throws IOException {
        if (converterService == null)
            throw new NullPointerException("The converter service must not be null");

        if (collection == null)
            throw new NullPointerException("The database collection must not be null");

        this.converterService = converterService;
        this.builderFactory = builderFactory;
        this.queryEngine = queryEngine;
        this.collection = collection;
        this.uri = uri;
        this.options = options;
        this.response = response;
    }

    @Override
    public void loadResource(Resource resource) throws IOException {
        // We need to set up the XMLResource.URIHandler so that proxy URIs are handled properly.

        XMLResource.URIHandler uriHandler = (XMLResource.URIHandler) options.get(XMLResource.OPTION_URI_HANDLER);

        if (uriHandler == null)
            uriHandler = new org.eclipse.emf.ecore.xmi.impl.URIHandlerImpl();

        if (resource.getURI().hasQuery())
            uriHandler.setBaseURI(resource.getURI().trimSegments(1).appendSegment("-1"));
        else
            uriHandler.setBaseURI(resource.getURI());

        boolean includeAttributesForProxyReferences = Boolean.TRUE
                .equals(options.get(Options.OPTION_PROXY_ATTRIBUTES));
        EObjectBuilder builder = builderFactory.createObjectBuilder(converterService, uriHandler,
                includeAttributesForProxyReferences, eClassCache);

        // If the URI contains a query string, use it to locate a collection of objects from
        // MongoDB, otherwise simply get the object from MongoDB using the id.

        EList<EObject> contents = resource.getContents();

        if (uri.query() != null) {
            if (queryEngine == null)
                throw new IOException("The query engine was not found");

            MongoQuery mongoQuery = queryEngine.buildDBObjectQuery(uri);
            DBCursor resultCursor = null;

            if (mongoQuery.getProjection() == null)
                resultCursor = collection.find(mongoQuery.getFilter());
            else
                resultCursor = collection.find(mongoQuery.getFilter(), mongoQuery.getProjection());

            if (mongoQuery.getSkip() != null)
                resultCursor.skip(mongoQuery.getSkip());

            if (mongoQuery.getSort() != null)
                resultCursor = resultCursor.sort(mongoQuery.getSort());

            if (mongoQuery.getLimit() != null)
                resultCursor = resultCursor.limit(mongoQuery.getLimit());

            boolean createCursor = Boolean.TRUE.equals(options.get(Options.OPTION_QUERY_CURSOR));

            if (createCursor) {
                MongoCursor cursor = ModelFactory.eINSTANCE.createMongoCursor();
                cursor.setDbCollection(collection);
                cursor.setDbCursor(resultCursor);
                cursor.setObjectBuilder(builder);
                contents.add(cursor);
            } else {
                EReferenceCollection eCollection = EmodelingFactory.eINSTANCE.createEReferenceCollection();
                InternalEList<EObject> values = (InternalEList<EObject>) eCollection.getValues();

                for (DBObject dbObject : resultCursor)
                    values.addUnique(builder.buildEObject(collection, dbObject, resource, true));

                contents.add(eCollection);
            }
        } else {
            DBObject dbObject = collection.findOne(new BasicDBObject(Keywords.ID_KEY, MongoUtils.getID(uri)));

            if (dbObject != null) {
                EObject eObject = builder.buildEObject(collection, dbObject, resource, false);

                if (eObject != null)
                    contents.add(eObject);

                response.put(URIConverter.RESPONSE_TIME_STAMP_PROPERTY, dbObject.get(Keywords.TIME_STAMP_KEY));
            }
        }
    }

    @Override
    public int read() throws IOException {
        // InputStream requires that we implement this function. It will never be called
        // since this implementation implements URIConverter.Loadable. The loadResource()
        // function will be called instead.

        return -1;
    }

    private URI uri;
    private Map<?, ?> options;
    private Map<Object, Object> response;
    private ConverterService converterService;
    private QueryEngine queryEngine;
    private DBCollection collection;
    private Map<String, EClass> eClassCache = new HashMap<String, EClass>();
    private EObjectBuilderFactory builderFactory;
}