com.mongodb.hadoop.io.BSONWritable Maven / Gradle / Ivy
/*
* 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.mongodb.hadoop.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 "";
}
/**
* 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 map = (Map) x;
BasicBSONObject bson = new BasicBSONObject();
for (Map.Entry 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;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy