下面列出了com.mongodb.Function#org.bson.BsonNull 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private BsonValue toBsonArray(final Schema schema, final Object value) {
if (value == null) {
return BsonNull.VALUE;
}
Schema fieldSchema = schema.valueSchema();
BsonArray bsonArray = new BsonArray();
List<?> myList = (List) value;
myList.forEach(
v -> {
if (fieldSchema.type().isPrimitive()) {
if (v == null) {
bsonArray.add(BsonNull.VALUE);
} else {
bsonArray.add(getConverter(fieldSchema).toBson(v));
}
} else if (fieldSchema.type().equals(ARRAY)) {
bsonArray.add(toBsonArray(fieldSchema, v));
} else {
bsonArray.add(toBsonDoc(fieldSchema, v));
}
});
return bsonArray;
}
public BsonValue toBson(final Object data, final Schema fieldSchema) {
if (!fieldSchema.isOptional()) {
if (data == null) {
throw new DataException("Error: schema not optional but data was null");
}
LOGGER.trace("field not optional and data is '{}'", data.toString());
return toBson(data);
}
if (data != null) {
LOGGER.trace("field optional and data is '{}'", data.toString());
return toBson(data);
}
if (fieldSchema.defaultValue() != null) {
LOGGER.trace(
"field optional and no data but default value is '{}'",
fieldSchema.defaultValue().toString());
return toBson(fieldSchema.defaultValue());
}
LOGGER.trace("field optional, no data and no default value thus '{}'", BsonNull.VALUE);
return BsonNull.VALUE;
}
@Override
public BsonValue generateId(final SinkDocument doc, final SinkRecord orig) {
Optional<BsonDocument> optionalDoc = Optional.empty();
if (where.equals(ProvidedIn.KEY)) {
optionalDoc = doc.getKeyDoc();
}
if (where.equals(ProvidedIn.VALUE)) {
optionalDoc = doc.getValueDoc();
}
BsonValue id =
optionalDoc
.map(d -> d.get(ID_FIELD))
.orElseThrow(
() ->
new DataException(
"Error: provided id strategy is used but the document structure either contained"
+ " no _id field or it was null"));
if (id instanceof BsonNull) {
throw new DataException(
"Error: provided id strategy used but the document structure contained an _id of type BsonNull");
}
return id;
}
public static BsonValue getBsonValue(Object obj) {
if (obj instanceof Integer) {
return new BsonInt32((Integer) obj);
}
if (obj instanceof String) {
return new BsonString((String) obj);
}
if (obj instanceof Long) {
return new BsonInt64((Long) obj);
}
if (obj instanceof Date) {
return new BsonDateTime(((Date) obj).getTime());
}
if (obj instanceof Double || obj instanceof Float) {
return new BsonDouble((Double) obj);
}
return new BsonNull();
}
public static BsonValue getBsonValue(Object obj) {
if (obj instanceof Integer) {
return new BsonInt32((Integer) obj);
}
if (obj instanceof String) {
return new BsonString((String) obj);
}
if (obj instanceof Long) {
return new BsonInt64((Long) obj);
}
if (obj instanceof Date) {
return new BsonDateTime(((Date) obj).getTime());
}
if (obj instanceof Double || obj instanceof Float) {
return new BsonDouble((Double) obj);
}
return new BsonNull();
}
private void handleMapField(BsonDocument doc, Map m, Field field) {
logger.trace("handling complex type 'map'");
if(m==null) {
logger.trace("no field in struct -> adding null");
doc.put(field.name(), BsonNull.VALUE);
return;
}
BsonDocument bd = new BsonDocument();
for(Object entry : m.keySet()) {
String key = (String)entry;
Schema.Type valueSchemaType = field.schema().valueSchema().type();
if(valueSchemaType.isPrimitive()) {
bd.put(key, getConverter(field.schema().valueSchema()).toBson(m.get(key),field.schema()));
} else if (valueSchemaType.equals(Schema.Type.ARRAY)) {
final Field elementField = new Field(key, 0, field.schema().valueSchema());
final List list = (List)m.get(key);
logger.trace("adding array values to {} of type valueSchema={} value='{}'",
elementField.name(), elementField.schema().valueSchema(), list);
bd.put(key, handleArrayField(list, elementField));
} else {
bd.put(key, toBsonDoc(field.schema().valueSchema(), m.get(key)));
}
}
doc.put(field.name(), bd);
}
private BsonValue handleArrayField(List list, Field field) {
logger.trace("handling complex type 'array' of types '{}'",
field.schema().valueSchema().type());
if(list==null) {
logger.trace("no array -> adding null");
return BsonNull.VALUE;
}
BsonArray array = new BsonArray();
Schema.Type st = field.schema().valueSchema().type();
for(Object element : list) {
if(st.isPrimitive()) {
array.add(getConverter(field.schema().valueSchema()).toBson(element,field.schema()));
} else if(st == Schema.Type.ARRAY) {
Field elementField = new Field("first", 0, field.schema().valueSchema());
array.add(handleArrayField((List)element,elementField));
} else {
array.add(toBsonDoc(field.schema().valueSchema(), element));
}
}
return array;
}
public BsonValue toBson(Object data, Schema fieldSchema) {
if(!fieldSchema.isOptional()) {
if(data == null)
throw new DataException("error: schema not optional but data was null");
logger.trace("field not optional and data is '{}'",data.toString());
return toBson(data);
}
if(data != null) {
logger.trace("field optional and data is '{}'",data.toString());
return toBson(data);
}
if(fieldSchema.defaultValue() != null) {
logger.trace("field optional and no data but default value is '{}'",fieldSchema.defaultValue().toString());
return toBson(fieldSchema.defaultValue());
}
logger.trace("field optional, no data and no default value thus '{}'", BsonNull.VALUE);
return BsonNull.VALUE;
}
@Override
public BsonValue generateId(SinkDocument doc, SinkRecord orig) {
Optional<BsonDocument> bd = Optional.empty();
if(where.equals(ProvidedIn.KEY)) {
bd = doc.getKeyDoc();
}
if(where.equals(ProvidedIn.VALUE)) {
bd = doc.getValueDoc();
}
BsonValue _id = bd.map(d -> d.get(DBCollection.ID_FIELD_NAME))
.orElseThrow(() -> new DataException("error: provided id strategy is used "
+ "but the document structure either contained no _id field or it was null"));
if(_id instanceof BsonNull) {
throw new DataException("error: provided id strategy used "
+ "but the document structure contained an _id of type BsonNull");
}
return _id;
}
/**
* Return non-redundant timestamps of all graph element events
*
* @return HashSet<Long> timestamps
*/
public TreeSet<Long> getTimestamps() {
TreeSet<Long> timestampSet = new TreeSet<Long>();
Function<BsonDateTime, Long> mapper = new Function<BsonDateTime, Long>() {
@Override
public Long apply(BsonDateTime val) {
return val.getValue();
}
};
edgeEvents.distinct(Tokens.TIMESTAMP, BsonDateTime.class)
.filter(new BsonDocument(Tokens.TIMESTAMP, new BsonDocument(Tokens.FC.$ne.toString(), new BsonNull())))
.map(mapper).into(timestampSet);
Set<Long> vtSet = new TreeSet<Long>();
vertexEvents.distinct(Tokens.TIMESTAMP, BsonDateTime.class)
.filter(new BsonDocument(Tokens.TIMESTAMP, new BsonDocument(Tokens.FC.$ne.toString(), new BsonNull())))
.map(mapper).into(vtSet);
timestampSet.addAll(vtSet);
return timestampSet;
}
public HashSet<Long> getTimestampsHashSet() {
HashSet<Long> timestampSet = new HashSet<Long>();
Function<BsonDateTime, Long> mapper = new Function<BsonDateTime, Long>() {
@Override
public Long apply(BsonDateTime val) {
return val.getValue();
}
};
edges.distinct(Tokens.TIMESTAMP, BsonDateTime.class)
.filter(new BsonDocument(Tokens.TIMESTAMP, new BsonDocument(Tokens.FC.$ne.toString(), new BsonNull())))
.map(mapper).into(timestampSet);
return timestampSet;
}
/**
* Un-assigns a key/value property from the element. The object value of the
* removed property is returned.
*
* @param key the key of the property to remove from the element
* @return the object value associated with that key prior to removal. Should be
* instance of BsonValue
*/
@Override
public <T> T removeProperty(final String key) {
try {
BsonValue value = getProperty(key);
BsonDocument filter = new BsonDocument();
filter.put(Tokens.ID, new BsonString(this.id));
BsonDocument update = new BsonDocument();
update.put("$unset", new BsonDocument(key, new BsonNull()));
if (this instanceof ChronoVertex) {
graph.getVertexCollection().updateOne(filter, update, new UpdateOptions().upsert(true));
return (T) value;
} else {
graph.getEdgeCollection().updateOne(filter, update, new UpdateOptions().upsert(true));
return (T) value;
}
} catch (MongoWriteException e) {
throw e;
}
}
/**
* persist empty Optional of Date
*/
@Test
public void nullDate() {
final Jackson expected = ImmutableJackson.builder()
.id(ObjectId.get())
.prop1("prop11")
.prop2("prop22")
.build();
repository.insert(expected).getUnchecked();
final Jackson actual = repository.findAll()
.fetchAll().getUnchecked().get(0);
check(expected.date().asSet()).isEmpty();
check(expected).is(actual);
final BsonDocument doc = collection.find().first();
check(doc.keySet()).hasContentInAnyOrder("_id", "prop1", "prop2", "date", "uuid");
check(doc.get("date")).is(BsonNull.VALUE);
}
/**
* Check that writing nulls does not cause NPE
*/
@Test
public void writeNulls() throws IOException {
BsonDocument doc = new BsonDocument();
BsonWriter writer = new BsonWriter(new BsonDocumentWriter(doc));
writer.beginObject();
writer.name("nullString"); writer.value((String) null);
writer.name("nullBoolean"); writer.value((Boolean) null);
writer.name("nullNumber"); writer.value((Long) null);
writer.name("null"); writer.nullValue();
writer.endObject();
writer.flush();
check(doc.get("nullString")).is(BsonNull.VALUE);
check(doc.get("nullBoolean")).is(BsonNull.VALUE);
check(doc.get("nullNumber")).is(BsonNull.VALUE);
check(doc.get("null")).is(BsonNull.VALUE);
}
private static BsonValue resolveOrNull(BsonValue value, List<String> paths) {
if (paths.isEmpty()) {
return value;
}
if (!value.isDocument()) {
return BsonNull.VALUE;
}
BsonDocument document = value.asDocument();
final String first = paths.get(0);
if (!document.containsKey(first)) {
return BsonNull.VALUE;
}
return resolveOrNull(document.get(first), paths.subList(1, paths.size()));
}
@Override
public BsonValue visit(Constant constant) {
Object value = constant.value();
if (value == null) {
return BsonNull.VALUE;
}
if (value instanceof Iterable) {
return Filters.in("ignore", (Iterable<?>) value)
.toBsonDocument(BsonDocument.class, codecRegistry)
.get("ignore").asDocument()
.get("$in").asArray();
}
return Filters.eq("ignore", value)
.toBsonDocument(BsonDocument.class, codecRegistry)
.get("ignore");
}
private BsonValue toBsonDoc(final Schema schema, final Object value) {
if (value == null) {
return BsonNull.VALUE;
}
BsonDocument doc = new BsonDocument();
if (schema.type() == MAP) {
Schema fieldSchema = schema.valueSchema();
Map m = (Map) value;
for (Object entry : m.keySet()) {
String key = (String) entry;
if (fieldSchema.type().isPrimitive()) {
doc.put(key, getConverter(fieldSchema).toBson(m.get(key), fieldSchema));
} else if (fieldSchema.type().equals(ARRAY)) {
doc.put(key, toBsonArray(fieldSchema, m.get(key)));
} else {
if (m.get(key) == null) {
doc.put(key, BsonNull.VALUE);
} else {
doc.put(key, toBsonDoc(fieldSchema, m.get(key)));
}
}
}
} else {
schema.fields().forEach(f -> doc.put(f.name(), processField((Struct) value, f)));
}
return doc;
}
private BsonValue processField(final Struct struct, final Field field) {
LOGGER.trace("processing field '{}'", field.name());
if (struct.get(field.name()) == null) {
LOGGER.trace("no field in struct -> adding null");
return BsonNull.VALUE;
}
if (isSupportedLogicalType(field.schema())) {
return getConverter(field.schema()).toBson(struct.get(field), field.schema());
}
try {
switch (field.schema().type()) {
case BOOLEAN:
case FLOAT32:
case FLOAT64:
case INT8:
case INT16:
case INT32:
case INT64:
case STRING:
case BYTES:
return handlePrimitiveField(struct, field);
case STRUCT:
case MAP:
return toBsonDoc(field.schema(), struct.get(field));
case ARRAY:
return toBsonArray(field.schema(), struct.get(field));
default:
throw new DataException("unexpected / unsupported schema type " + field.schema().type());
}
} catch (Exception exc) {
throw new DataException("error while processing field " + field.name(), exc);
}
}
@TestFactory
@DisplayName("tests for boolean field conversions")
List<DynamicTest> testBooleanFieldConverter() {
SinkFieldConverter converter = new BooleanFieldConverter();
List<DynamicTest> tests = new ArrayList<>();
asList(true, false)
.forEach(
el ->
tests.add(
dynamicTest(
"conversion with " + converter.getClass().getSimpleName() + " for " + el,
() -> assertEquals(el, ((BsonBoolean) converter.toBson(el)).getValue()))));
tests.add(
dynamicTest(
"optional type conversion checks",
() -> {
Schema valueOptionalDefault = SchemaBuilder.bool().optional().defaultValue(true);
assertAll(
"",
() ->
assertThrows(
DataException.class, () -> converter.toBson(null, Schema.BOOLEAN_SCHEMA)),
() ->
assertEquals(
new BsonNull(), converter.toBson(null, Schema.OPTIONAL_BOOLEAN_SCHEMA)),
() ->
assertEquals(
valueOptionalDefault.defaultValue(),
converter.toBson(null, valueOptionalDefault).asBoolean().getValue()));
}));
return tests;
}
@TestFactory
@DisplayName("tests for int8 field conversions")
List<DynamicTest> testInt8FieldConverter() {
SinkFieldConverter converter = new Int8FieldConverter();
List<DynamicTest> tests = new ArrayList<>();
asList(Byte.MIN_VALUE, (byte) 0, Byte.MAX_VALUE)
.forEach(
el ->
tests.add(
dynamicTest(
"conversion with " + converter.getClass().getSimpleName() + " for " + el,
() ->
assertEquals(
(int) el, ((BsonInt32) converter.toBson(el)).getValue()))));
tests.add(
dynamicTest(
"optional type conversions",
() -> {
Schema valueOptionalDefault = SchemaBuilder.int8().optional().defaultValue((byte) 0);
assertAll(
"checks",
() ->
assertThrows(
DataException.class, () -> converter.toBson(null, Schema.INT8_SCHEMA)),
() ->
assertEquals(
new BsonNull(), converter.toBson(null, Schema.OPTIONAL_INT8_SCHEMA)),
() ->
assertEquals(
((Byte) valueOptionalDefault.defaultValue()).intValue(),
((BsonInt32) converter.toBson(null, valueOptionalDefault)).getValue()));
}));
return tests;
}
@TestFactory
@DisplayName("tests for int16 field conversions")
List<DynamicTest> testInt16FieldConverter() {
SinkFieldConverter converter = new Int16FieldConverter();
List<DynamicTest> tests = new ArrayList<>();
asList(Short.MIN_VALUE, (short) 0, Short.MAX_VALUE)
.forEach(
el ->
tests.add(
dynamicTest(
"conversion with " + converter.getClass().getSimpleName() + " for " + el,
() ->
assertEquals(
(short) el, ((BsonInt32) converter.toBson(el)).getValue()))));
tests.add(
dynamicTest(
"optional type conversions",
() -> {
Schema valueOptionalDefault =
SchemaBuilder.int16().optional().defaultValue((short) 0);
assertAll(
"checks",
() ->
assertThrows(
DataException.class, () -> converter.toBson(null, Schema.INT16_SCHEMA)),
() ->
assertEquals(
new BsonNull(), converter.toBson(null, Schema.OPTIONAL_INT16_SCHEMA)),
() ->
assertEquals(
((short) valueOptionalDefault.defaultValue()),
((BsonInt32) converter.toBson(null, valueOptionalDefault)).getValue()));
}));
return tests;
}
@TestFactory
@DisplayName("tests for int32 field conversions")
List<DynamicTest> testInt32FieldConverter() {
SinkFieldConverter converter = new Int32FieldConverter();
List<DynamicTest> tests = new ArrayList<>();
asList(Integer.MIN_VALUE, 0, Integer.MAX_VALUE)
.forEach(
el ->
tests.add(
dynamicTest(
"conversion with " + converter.getClass().getSimpleName() + " for " + el,
() ->
assertEquals(
(int) el, ((BsonInt32) converter.toBson(el)).getValue()))));
tests.add(
dynamicTest(
"optional type conversions",
() -> {
Schema valueOptionalDefault = SchemaBuilder.int32().optional().defaultValue(0);
assertAll(
"checks",
() ->
assertThrows(
DataException.class, () -> converter.toBson(null, Schema.INT32_SCHEMA)),
() ->
assertEquals(
new BsonNull(), converter.toBson(null, Schema.OPTIONAL_INT32_SCHEMA)),
() ->
assertEquals(
valueOptionalDefault.defaultValue(),
((BsonInt32) converter.toBson(null, valueOptionalDefault)).getValue()));
}));
return tests;
}
@TestFactory
@DisplayName("tests for int64 field conversions")
List<DynamicTest> testInt64FieldConverter() {
SinkFieldConverter converter = new Int64FieldConverter();
List<DynamicTest> tests = new ArrayList<>();
asList(Long.MIN_VALUE, 0L, Long.MAX_VALUE)
.forEach(
el ->
tests.add(
dynamicTest(
"conversion with " + converter.getClass().getSimpleName() + " for " + el,
() ->
assertEquals(
(long) el, ((BsonInt64) converter.toBson(el)).getValue()))));
tests.add(
dynamicTest(
"optional type conversions",
() -> {
Schema valueOptionalDefault = SchemaBuilder.int64().optional().defaultValue(0L);
assertAll(
"checks",
() ->
assertThrows(
DataException.class, () -> converter.toBson(null, Schema.INT64_SCHEMA)),
() ->
assertEquals(
new BsonNull(), converter.toBson(null, Schema.OPTIONAL_INT64_SCHEMA)),
() ->
assertEquals(
(long) valueOptionalDefault.defaultValue(),
((BsonInt64) converter.toBson(null, valueOptionalDefault)).getValue()));
}));
return tests;
}
@TestFactory
@DisplayName("tests for float32 field conversions")
List<DynamicTest> testFloat32FieldConverter() {
SinkFieldConverter converter = new Float32FieldConverter();
List<DynamicTest> tests = new ArrayList<>();
asList(Float.MIN_VALUE, 0f, Float.MAX_VALUE)
.forEach(
el ->
tests.add(
dynamicTest(
"conversion with " + converter.getClass().getSimpleName() + " for " + el,
() ->
assertEquals(
(float) el, ((BsonDouble) converter.toBson(el)).getValue()))));
tests.add(
dynamicTest(
"optional type conversions",
() -> {
Schema valueOptionalDefault = SchemaBuilder.float32().optional().defaultValue(0.0f);
assertAll(
"checks",
() ->
assertThrows(
DataException.class, () -> converter.toBson(null, Schema.FLOAT32_SCHEMA)),
() ->
assertEquals(
new BsonNull(), converter.toBson(null, Schema.OPTIONAL_FLOAT32_SCHEMA)),
() ->
assertEquals(
((Float) valueOptionalDefault.defaultValue()).doubleValue(),
((BsonDouble) converter.toBson(null, valueOptionalDefault)).getValue()));
}));
return tests;
}
@TestFactory
@DisplayName("tests for float64 field conversions")
List<DynamicTest> testFloat64FieldConverter() {
SinkFieldConverter converter = new Float64FieldConverter();
List<DynamicTest> tests = new ArrayList<>();
asList(Double.MIN_VALUE, 0d, Double.MAX_VALUE)
.forEach(
el ->
tests.add(
dynamicTest(
"conversion with " + converter.getClass().getSimpleName() + " for " + el,
() ->
assertEquals(
(double) el, ((BsonDouble) converter.toBson(el)).getValue()))));
tests.add(
dynamicTest(
"optional type conversions",
() -> {
Schema valueOptionalDefault = SchemaBuilder.float64().optional().defaultValue(0.0d);
assertAll(
"checks",
() ->
assertThrows(
DataException.class, () -> converter.toBson(null, Schema.FLOAT64_SCHEMA)),
() ->
assertEquals(
new BsonNull(), converter.toBson(null, Schema.OPTIONAL_FLOAT64_SCHEMA)),
() ->
assertEquals(
valueOptionalDefault.defaultValue(),
((BsonDouble) converter.toBson(null, valueOptionalDefault)).getValue()));
}));
return tests;
}
@TestFactory
@DisplayName("tests for string field conversions")
List<DynamicTest> testStringFieldConverter() {
SinkFieldConverter converter = new StringFieldConverter();
List<DynamicTest> tests = new ArrayList<>();
asList("fooFOO", "", "blahBLAH")
.forEach(
el ->
tests.add(
dynamicTest(
"conversion with " + converter.getClass().getSimpleName() + " for " + el,
() -> assertEquals(el, ((BsonString) converter.toBson(el)).getValue()))));
tests.add(
dynamicTest(
"optional type conversions",
() -> {
Schema valueOptionalDefault = SchemaBuilder.string().optional().defaultValue("");
assertAll(
"checks",
() ->
assertThrows(
DataException.class, () -> converter.toBson(null, Schema.STRING_SCHEMA)),
() ->
assertEquals(
new BsonNull(), converter.toBson(null, Schema.OPTIONAL_STRING_SCHEMA)),
() ->
assertEquals(
valueOptionalDefault.defaultValue(),
((BsonString) converter.toBson(null, valueOptionalDefault)).getValue()));
}));
return tests;
}
@TestFactory
@DisplayName("tests for bytes field conversions based on byte[]")
List<DynamicTest> testBytesFieldConverterByteArray() {
SinkFieldConverter converter = new BytesFieldConverter();
List<DynamicTest> tests = new ArrayList<>();
asList(new byte[] {-128, -127, 0}, new byte[] {}, new byte[] {0, 126, 127})
.forEach(
el ->
tests.add(
dynamicTest(
"conversion with "
+ converter.getClass().getSimpleName()
+ " for "
+ Arrays.toString(el),
() -> assertEquals(el, ((BsonBinary) converter.toBson(el)).getData()))));
tests.add(
dynamicTest(
"optional type conversions",
() -> {
Schema valueOptionalDefault =
SchemaBuilder.bytes().optional().defaultValue(new byte[] {});
assertAll(
"checks",
() ->
assertThrows(
DataException.class, () -> converter.toBson(null, Schema.BYTES_SCHEMA)),
() ->
assertEquals(
new BsonNull(), converter.toBson(null, Schema.OPTIONAL_BYTES_SCHEMA)),
() ->
assertEquals(
valueOptionalDefault.defaultValue(),
((BsonBinary) converter.toBson(null, valueOptionalDefault)).getData()));
}));
return tests;
}
@Test
@DisplayName("when 'after' field null in value doc then DataException")
void testNullAfterFieldInValueDocument() {
assertThrows(
DataException.class,
() ->
RDBMS_UPDATE.perform(
new SinkDocument(
BsonDocument.parse("{id: 1234}"),
new BsonDocument("op", new BsonString("u")).append("after", new BsonNull()))));
}
@Test
@DisplayName("when value doc is missing operation type then DataException")
void testMissingCdcOperationType() {
SinkDocument cdcEvent =
new SinkDocument(
new BsonDocument("id", new BsonInt32(1234)), new BsonDocument("po", BsonNull.VALUE));
assertThrows(DataException.class, () -> HANDLER_DEFAULT_MAPPING.handle(cdcEvent));
}
private void handleStructField(BsonDocument doc, Struct struct, Field field) {
logger.trace("handling complex type 'struct'");
if(struct!=null) {
logger.trace(struct.toString());
doc.put(field.name(), toBsonDoc(field.schema(), struct));
} else {
logger.trace("no field in struct -> adding null");
doc.put(field.name(), BsonNull.VALUE);
}
}