de.fhg.igd.mongomvcc.impl.DefaultConvertStrategy.java Source code

Java tutorial

Introduction

Here is the source code for de.fhg.igd.mongomvcc.impl.DefaultConvertStrategy.java

Source

// This file is part of MongoMVCC.
//
// Copyright (c) 2012 Fraunhofer IGD
//
// MongoMVCC is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// MongoMVCC 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with MongoMVCC. If not, see <http://www.gnu.org/licenses/>.

package de.fhg.igd.mongomvcc.impl;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;

import com.mongodb.BasicDBObject;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;
import com.mongodb.gridfs.GridFSInputFile;

import de.fhg.igd.mongomvcc.VCounter;
import de.fhg.igd.mongomvcc.helper.FloatArrayInputStream;

/**
 * The default convert strategy handles different types of binary data
 * which is stores in a MongoDB GridFS
 * @author Michel Kraemer
 */
public class DefaultConvertStrategy implements ConvertStrategy {
    /**
     * Binary types
     */
    private static final int BYTEARRAY = 0;
    private static final int INPUTSTREAM = 1;
    private static final int BYTEBUFFER = 2;
    private static final int FLOATARRAY = 3;
    private static final int FLOATBUFFER = 4;

    /**
     * The metadata attribute that denotes the binary type
     */
    private static final String BINARY_TYPE = "binary_type";

    /**
     * The MongoDB GridFS storing binary data
     */
    private final GridFS _gridFS;

    /**
     * A counter to generate replacement OIDs
     */
    private final VCounter _counter;

    /**
     * The files that have been created by this convert strategy
     */
    private final List<GridFSInputFile> _convertedFiles = new ArrayList<GridFSInputFile>();

    /**
     * Constructs a new convert strategy
     * @param gridFS the MongoDB GridFS storing binary data
     * @param counter a counter to generate replacement OIDs
     */
    public DefaultConvertStrategy(GridFS gridFS, VCounter counter) {
        _gridFS = gridFS;
        _counter = counter;
    }

    /**
     * @return the files that have been created by this convert strategy
     */
    public List<GridFSInputFile> getConvertedFiles() {
        return _convertedFiles;
    }

    @Override
    public long convert(Object data) {
        GridFSInputFile file;
        if (data instanceof byte[]) {
            file = _gridFS.createFile((byte[]) data);
            file.put(BINARY_TYPE, BYTEARRAY);
        } else if (data instanceof float[]) {
            file = _gridFS.createFile(new FloatArrayInputStream((float[]) data));
            file.put(BINARY_TYPE, FLOATARRAY);
        } else if (data instanceof InputStream) {
            file = _gridFS.createFile((InputStream) data);
            file.put(BINARY_TYPE, INPUTSTREAM);
        } else if (data instanceof ByteBuffer) {
            ByteBuffer bb = (ByteBuffer) data;
            byte[] buf;
            if (bb.hasArray()) {
                buf = bb.array();
            } else {
                bb.rewind();
                buf = new byte[bb.remaining()];
                bb.get(buf);
            }
            file = _gridFS.createFile(buf);
            file.put(BINARY_TYPE, BYTEBUFFER);
        } else if (data instanceof FloatBuffer) {
            FloatBuffer bb = (FloatBuffer) data;
            float[] buf;
            if (bb.hasArray()) {
                buf = bb.array();
            } else {
                bb.rewind();
                buf = new float[bb.remaining()];
                bb.get(buf);
            }
            file = _gridFS.createFile(new FloatArrayInputStream(buf));
            file.put(BINARY_TYPE, FLOATBUFFER);
        } else {
            return 0;
        }

        long oid = _counter.getNextId();
        file.put(MongoDBVLargeCollection.OID, oid);
        _convertedFiles.add(file);
        return oid;
    }

    @Override
    public Object convert(long oid) throws IOException {
        GridFSDBFile file = _gridFS.findOne(new BasicDBObject(MongoDBVLargeCollection.OID, oid));
        if (file == null) {
            return null;
        }
        int type = (Integer) file.get(BINARY_TYPE);
        Object r;
        if (type == BYTEARRAY) {
            r = toByteArray(file);
        } else if (type == INPUTSTREAM) {
            r = file.getInputStream();
        } else if (type == BYTEBUFFER) {
            r = ByteBuffer.wrap(toByteArray(file));
        } else if (type == FLOATARRAY) {
            r = toFloatArray(file);
        } else if (type == FLOATBUFFER) {
            r = FloatBuffer.wrap(toFloatArray(file));
        } else {
            //no information. simply forward the input stream
            r = file.getInputStream();
        }
        return r;
    }

    /**
     * Converts the contents of a GridFS file to a byte array
     * @param file the file
     * @return the byte array
     * @throws IOException if the file could not be read
     */
    private byte[] toByteArray(GridFSDBFile file) throws IOException {
        InputStream is = file.getInputStream();
        int len = (int) file.getLength();
        int pos = 0;
        byte[] b = new byte[len];
        while (len > 0) {
            int read = is.read(b, pos, len);
            pos += read;
            len -= read;
        }
        return b;
    }

    /**
     * Converts the contents of a GridFS file to a float array
     * @param file the file
     * @return the float array
     * @throws IOException if the file could not be read
     */
    private float[] toFloatArray(GridFSDBFile file) throws IOException {
        DataInputStream is = new DataInputStream(new BufferedInputStream(file.getInputStream()));
        int len = (int) file.getLength() / (Float.SIZE / Byte.SIZE);
        float[] b = new float[len];
        for (int i = 0; i < len; ++i) {
            b[i] = is.readFloat();
        }
        return b;
    }
}