com.zjy.mongo.io.BSONWritable.java Source code

Java tutorial

Introduction

Here is the source code for com.zjy.mongo.io.BSONWritable.java

Source

/*
 * Copyright 2010-2013 10gen Inc.
 *
 * 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.zjy.mongo.io;

import com.mongodb.BasicDBObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.io.AbstractMapWritable;
import org.apache.hadoop.io.ArrayWritable;
import org.apache.hadoop.io.BooleanWritable;
import org.apache.hadoop.io.ByteWritable;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.DataInputBuffer;
import org.apache.hadoop.io.DataOutputBuffer;
import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.FloatWritable;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
import org.bson.BSONCallback;
import org.bson.BSONDecoder;
import org.bson.BSONEncoder;
import org.bson.BSONObject;
import org.bson.BasicBSONCallback;
import org.bson.BasicBSONDecoder;
import org.bson.BasicBSONEncoder;
import org.bson.BasicBSONObject;
import org.bson.io.BasicOutputBuffer;
import org.bson.io.Bits;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Map;

@SuppressWarnings("deprecation")
public class BSONWritable implements WritableComparable {

    private static final byte[] HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
            'E', 'F' };

    private static final Log LOG = LogFactory.getLog(BSONWritable.class);

    static {
        WritableComparator.define(BSONWritable.class, new BSONWritableComparator());
    }

    private BSONObject doc;

    public BSONWritable() {
        doc = new BasicBSONObject();
    }

    public BSONWritable(final BSONObject doc) {
        this();
        setDoc(doc);
    }

    public void setDoc(final BSONObject doc) {
        this.doc = doc;
    }

    public BSONObject getDoc() {
        return doc;
    }

    /**
     * {@inheritDoc}
     *
     * @see Writable#write(DataOutput)
     */
    public void write(final DataOutput out) throws IOException {
        BSONEncoder enc = new BasicBSONEncoder();
        BasicOutputBuffer buf = new BasicOutputBuffer();
        enc.set(buf);
        enc.putObject(doc);
        enc.done();
        buf.pipe(new DataOutputOutputStreamAdapter(out));
    }

    /**
     * {@inheritDoc}
     *
     * @see Writable#readFields(DataInput)
     */
    public void readFields(final DataInput in) throws IOException {
        BSONDecoder dec = new BasicBSONDecoder();
        BSONCallback cb = new BasicBSONCallback();
        // Read the BSON length from the start of the record
        byte[] l = new byte[4];
        try {
            in.readFully(l);
            int dataLen = Bits.readInt(l);
            if (LOG.isDebugEnabled()) {
                LOG.debug("*** Expected DataLen: " + dataLen);
            }
            byte[] data = new byte[dataLen + 4];
            System.arraycopy(l, 0, data, 0, 4);
            in.readFully(data, 4, dataLen - 4);
            dec.decode(data, cb);
            doc = (BSONObject) cb.get();
            if (LOG.isTraceEnabled()) {
                LOG.trace("Decoded a BSON Object: " + doc);
            }
        } catch (Exception e) {
            /* If we can't read another length it's not an error, just return quietly. */
            // TODO - Figure out how to gracefully mark this as an empty
            LOG.info("No Length Header available." + e);
            doc = new BasicDBObject();
        }

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return "<BSONWritable:" + doc + ">";
    }

    /**
     * Used by child copy constructors.
     * @param other the Writable to copy.
     */
    protected synchronized void copy(final Writable other) {
        if (other != null) {
            try {
                DataOutputBuffer out = new DataOutputBuffer();
                other.write(out);
                DataInputBuffer in = new DataInputBuffer();
                in.reset(out.getData(), out.getLength());
                readFields(in);

            } catch (IOException e) {
                throw new IllegalArgumentException("map cannot be copied: " + e.getMessage());
            }

        } else {
            throw new IllegalArgumentException("source map cannot be null");
        }
    }

    public int compareTo(final Object o) {
        return new BSONWritableComparator().compare(this, o);
    }

    protected static void dumpBytes(final BasicOutputBuffer buf) {// Temp debug output
        dumpBytes(buf.toByteArray());
    }

    protected static void dumpBytes(final byte[] buffer) {
        StringBuilder sb = new StringBuilder(2 + 3 * buffer.length);

        for (byte b : buffer) {
            sb.append("0x").append((char) HEX_CHAR[(b & 0x00F0) >> 4]).append((char) HEX_CHAR[b & 0x000F])
                    .append(" ");
        }

        LOG.info("Byte Dump: " + sb);
    }

    /**
     * Unwrap a (usually Writable) Object, getting back a value suitable for
     * putting into a BSONObject. If the given object is not Writable, then
     * simply return the Object back.
     *
     * @param x the Object to turn into BSON.
     * @return the BSON representation of the Object.
     */
    @SuppressWarnings("unchecked")
    public static Object toBSON(final Object x) {
        if (x == null) {
            return null;
        }
        if (x instanceof Text) {
            return x.toString();
        }
        if (x instanceof BSONWritable) {
            return ((BSONWritable) x).getDoc();
        }
        if (x instanceof Writable) {
            if (x instanceof AbstractMapWritable) {
                if (!(x instanceof Map)) {
                    throw new IllegalArgumentException(String.format(
                            "Cannot turn %s into BSON, since it does " + "not implement java.util.Map.",
                            x.getClass().getName()));
                }
                Map<Writable, Writable> map = (Map<Writable, Writable>) x;
                BasicBSONObject bson = new BasicBSONObject();
                for (Map.Entry<Writable, Writable> entry : map.entrySet()) {
                    bson.put(entry.getKey().toString(), toBSON(entry.getValue()));
                }
                return bson;
            }
            if (x instanceof ArrayWritable) {
                Writable[] o = ((ArrayWritable) x).get();
                Object[] a = new Object[o.length];
                for (int i = 0; i < o.length; i++) {
                    a[i] = toBSON(o[i]);
                }
                return a;
            }
            if (x instanceof NullWritable) {
                return null;
            }
            if (x instanceof BooleanWritable) {
                return ((BooleanWritable) x).get();
            }
            if (x instanceof BytesWritable) {
                return ((BytesWritable) x).getBytes();
            }
            if (x instanceof ByteWritable) {
                return ((ByteWritable) x).get();
            }
            if (x instanceof DoubleWritable) {
                return ((DoubleWritable) x).get();
            }
            if (x instanceof FloatWritable) {
                return ((FloatWritable) x).get();
            }
            if (x instanceof LongWritable) {
                return ((LongWritable) x).get();
            }
            if (x instanceof IntWritable) {
                return ((IntWritable) x).get();
            }

            // TODO - Support counters

        }
        return x;
    }

    @Override
    public boolean equals(final Object obj) {
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        final BSONWritable other = (BSONWritable) obj;
        return !(doc != other.doc && (doc == null || !doc.equals(other.doc)));
    }

    @Override
    public int hashCode() {
        return doc != null ? doc.hashCode() : 0;
    }

}