package org.bson;
import org.bson.types.BSONTimestamp;
import org.bson.types.BasicBSONList;
import org.bson.types.Binary;
import org.bson.types.Code;
import org.bson.types.CodeWScope;
import org.bson.types.Decimal128;
import org.bson.types.MaxKey;
import org.bson.types.MinKey;
import org.bson.types.ObjectId;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;
@SuppressWarnings("deprecation")
public class BasicBSONCallback implements BSONCallback {
private Object root;
private final LinkedList<BSONObject> stack;
private final LinkedList<String> nameStack;
public BasicBSONCallback() {
stack = new LinkedList<BSONObject>();
nameStack = new LinkedList<String>();
reset();
}
@Override
public Object get() {
return root;
}
public BSONObject create() {
return new BasicBSONObject();
}
protected BSONObject createList() {
return new BasicBSONList();
}
@Override
public BSONCallback createBSONCallback() {
return new BasicBSONCallback();
}
public BSONObject create(final boolean array, final List<String> path) {
return array ? createList() : create();
}
@Override
public void objectStart() {
if (stack.size() > 0) {
throw new IllegalStateException("Illegal object beginning in current context.");
}
root = create(false, null);
stack.add((BSONObject) root);
}
@Override
public void objectStart(final String name) {
nameStack.addLast(name);
BSONObject o = create(false, nameStack);
stack.getLast().put(name, o);
stack.addLast(o);
}
@Override
public Object objectDone() {
BSONObject o = stack.removeLast();
if (nameStack.size() > 0) {
nameStack.removeLast();
} else if (stack.size() > 0) {
throw new IllegalStateException("Illegal object end in current context.");
}
return !BSON.hasDecodeHooks() ? o : (BSONObject) BSON.applyDecodingHooks(o);
}
@Override
public void arrayStart() {
root = create(true, null);
stack.add((BSONObject) root);
}
@Override
public void arrayStart(final String name) {
nameStack.addLast(name);
BSONObject o = create(true, nameStack);
stack.getLast().put(name, o);
stack.addLast(o);
}
@Override
public Object arrayDone() {
return objectDone();
}
@Override
public void gotNull(final String name) {
cur().put(name, null);
}
@Override
public void gotUndefined(final String name) {
}
@Override
public void gotMinKey(final String name) {
cur().put(name, new MinKey());
}
@Override
public void gotMaxKey(final String name) {
cur().put(name, new MaxKey());
}
@Override
public void gotBoolean(final String name, final boolean value) {
_put(name, value);
}
@Override
public void gotDouble(final String name, final double value) {
_put(name, value);
}
@Override
public void gotInt(final String name, final int value) {
_put(name, value);
}
@Override
public void gotLong(final String name, final long value) {
_put(name, value);
}
@Override
public void gotDecimal128(final String name, final Decimal128 value) {
_put(name, value);
}
@Override
public void gotDate(final String name, final long millis) {
_put(name, new Date(millis));
}
@Override
public void gotRegex(final String name, final String pattern, final String flags) {
_put(name, Pattern.compile(pattern, BSON.regexFlags(flags)));
}
@Override
public void gotString(final String name, final String value) {
_put(name, value);
}
@Override
public void gotSymbol(final String name, final String value) {
_put(name, value);
}
@Override
public void gotTimestamp(final String name, final int time, final int increment) {
_put(name, new BSONTimestamp(time, increment));
}
@Override
public void gotObjectId(final String name, final ObjectId id) {
_put(name, id);
}
@Override
public void gotDBRef(final String name, final String namespace, final ObjectId id) {
_put(name, new BasicBSONObject("$ns", namespace).append("$id", id));
}
@Deprecated
@Override
public void gotBinaryArray(final String name, final byte[] data) {
gotBinary(name, BSON.B_GENERAL, data);
}
@Override
public void gotBinary(final String name, final byte type, final byte[] data) {
if (type == BSON.B_GENERAL || type == BSON.B_BINARY) {
_put(name, data);
} else {
_put(name, new Binary(type, data));
}
}
@Override
public void gotUUID(final String name, final long part1, final long part2) {
_put(name, new UUID(part1, part2));
}
@Override
public void gotCode(final String name, final String code) {
_put(name, new Code(code));
}
@Override
public void gotCodeWScope(final String name, final String code, final Object scope) {
_put(name, new CodeWScope(code, (BSONObject) scope));
}
protected void _put(final String name, final Object value) {
cur().put(name, !BSON.hasDecodeHooks() ? value : BSON.applyDecodingHooks(value));
}
protected BSONObject cur() {
return stack.getLast();
}
protected String curName() {
return nameStack.peekLast();
}
protected void setRoot(final Object root) {
this.root = root;
}
protected boolean isStackEmpty() {
return stack.size() < 1;
}
@Override
public void reset() {
root = null;
stack.clear();
nameStack.clear();
}
}