blob: 091e36886708283aa03934519d3f463ab6a82ba4 [file] [log] [blame]
/*
* Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation
package org.eclipse.persistence.internal.nosql.adapters.mongo;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;
import org.bson.BsonReader;
import org.bson.BsonTimestamp;
import org.bson.BsonType;
import org.bson.BsonWriter;
import org.bson.codecs.BsonTypeClassMap;
import org.bson.codecs.Codec;
import org.bson.codecs.DecoderContext;
import org.bson.codecs.DocumentCodecProvider;
import org.bson.codecs.EncoderContext;
import org.bson.codecs.configuration.CodecRegistries;
import org.bson.codecs.configuration.CodecRegistry;
import com.mongodb.MongoClient;
/**
* Provides java.sql.Timestamp, java.sql.Date and java.sql.Time codecs.
*
* @see <a href="http://mongodb.github.io/mongo-java-driver/3.0/bson/codecs/">Codec and CodecRegistry</a>
* @see <a href="https://jira.mongodb.org/browse/JAVA-1741">JAVA-1741: 3.x: How to save java.sql.Timestamp?</a>
*/
public class MongoCodecs {
private static volatile CodecRegistry codecRegistry;
public static CodecRegistry codecRegistry() {
if (codecRegistry == null) {
synchronized (MongoCodecs.class) {
if (codecRegistry == null) {
Map<BsonType, Class<?>> replacements = new HashMap<BsonType, Class<?>>();
replacements.put(BsonType.TIMESTAMP, Timestamp.class);
// make it use ByteArrayCodec instead of BinaryCodec
// see also https://jira.mongodb.org/browse/JAVA-2025
replacements.put(BsonType.BINARY, byte[].class);
// TODO: replacement for java.sql.Date and java.sql.Time
// need a way to add two distinct replacements
// can't use DATE_TIME, used for java.util.Date
BsonTypeClassMap bsonTypeClassMap = new BsonTypeClassMap(replacements);
DocumentCodecProvider documentCodecProvider =
new DocumentCodecProvider(bsonTypeClassMap);
codecRegistry = CodecRegistries.fromRegistries(
CodecRegistries.fromCodecs(
new TimestampCodec(),
new DateCodec(),
new TimeCodec()),
CodecRegistries.fromProviders(documentCodecProvider),
MongoClient.getDefaultCodecRegistry());
}
}
}
return codecRegistry;
}
public static class TimestampCodec implements Codec<Timestamp> {
@Override
public void encode(BsonWriter writer, Timestamp value, EncoderContext encoderContext) {
writer.writeTimestamp(new BsonTimestamp((int)(value.getTime() / 1000), 0));
}
@Override
public Timestamp decode(BsonReader reader, DecoderContext decoderContext) {
return new Timestamp(reader.readTimestamp().getTime() * 1000L);
}
@Override
public Class<Timestamp> getEncoderClass() {
return Timestamp.class;
}
}
static class DateCodec implements Codec<Date> {
@Override
public void encode(BsonWriter writer, Date value, EncoderContext encoderContext) {
writer.writeDateTime(value.getTime());
}
@Override
public Date decode(BsonReader reader, DecoderContext decoderContext) {
return new Date(reader.readDateTime());
}
@Override
public Class<Date> getEncoderClass() {
return Date.class;
}
}
static class TimeCodec implements Codec<Time> {
@Override
public void encode(BsonWriter writer, Time value, EncoderContext encoderContext) {
writer.writeDateTime(value.getTime());
}
@Override
public Time decode(BsonReader reader, DecoderContext decoderContext) {
return new Time(reader.readDateTime());
}
@Override
public Class<Time> getEncoderClass() {
return Time.class;
}
}
}