/*
* Copyright 2016 MongoDB, 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 org.mongodb.morphia;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.bson.types.ObjectId;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
import org.mongodb.morphia.annotations.Embedded;
import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;
import org.mongodb.morphia.annotations.Reference;
import org.mongodb.morphia.mapping.MappedField;
import org.mongodb.morphia.query.Query;
import org.mongodb.morphia.query.QueryImpl;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.junit.Assert.assertTrue;
import static org.mongodb.morphia.converters.DefaultConverters.JAVA_8;
@SuppressWarnings("Since15")
public class TestSerializedFormat extends TestBase {
@Test
@SuppressWarnings("deprecation")
public void testQueryFormat() {
Assume.assumeTrue("This test requires Java 8", JAVA_8);
Query<ReferenceType> query = getDs().find(ReferenceType.class)
.field("id").equal(new ObjectId(0, 0, (short) 0, 0))
.field("referenceType").equal(new ReferenceType(2, "far"))
.field("embeddedType").equal(new EmbeddedReferenceType(3, "strikes"))
.field("string").equal("some value")
.field("embeddedArray").elemMatch(getDs().find(EmbeddedReferenceType.class)
.filter("number", 3).filter("text", "strikes"))
.field("embeddedSet").elemMatch(getDs().find(EmbeddedReferenceType.class)
.filter("number", 3).filter("text", "strikes"))
.field("embeddedList").elemMatch(getDs().find(EmbeddedReferenceType.class)
.filter("number", 3).filter("text", "strikes"))
.field("map.bar").equal(new EmbeddedReferenceType(1, "chance"))
.field("mapOfList.bar").in(singletonList(new EmbeddedReferenceType(1, "chance")))
.field("mapOfList.foo").elemMatch(getDs().find(EmbeddedReferenceType.class)
.filter("number", 1)
.filter("text", "chance"))
.field("selfReference").equal(new ReferenceType(1, "blah"))
.field("mixedTypeList").elemMatch(getDs().find(EmbeddedReferenceType.class)
.filter("number", 3).filter("text", "strikes"))
.field("mixedTypeList").in(singletonList(new EmbeddedReferenceType(1, "chance")))
.field("mixedTypeMap.foo").equal(new ReferenceType(3, "strikes"))
.field("mixedTypeMap.bar").equal(new EmbeddedReferenceType(3, "strikes"))
.field("mixedTypeMapOfList.bar").in(singletonList(new EmbeddedReferenceType(1, "chance")))
.field("mixedTypeMapOfList.foo").elemMatch(getDs().find(EmbeddedReferenceType.class)
.filter("number", 3)
.filter("text", "strikes"))
.field("referenceMap.foo").equal(new ReferenceType(1, "chance"))
.field("referenceMap.bar").equal(new EmbeddedReferenceType(1, "chance"));
DBObject dbObject = ((QueryImpl) query).getQueryObject();
Assert.assertEquals(BasicDBObject.parse(readFully("/QueryStructure.json")), dbObject);
}
private void verifyCoverage(final DBObject dbObject) {
for (MappedField field : getMorphia().getMapper().getMappedClass(ReferenceType.class).getPersistenceFields()) {
String name = field.getNameToStore();
boolean found = dbObject.containsField(name);
if (!found) {
for (String s : dbObject.keySet()) {
found |= s.startsWith(name + ".");
}
}
assertTrue("Not found in dbObject: " + name, found);
}
}
@Test
public void testSavedEntityFormat() {
Assume.assumeTrue("This test requires Java 8", JAVA_8);
ReferenceType entity = new ReferenceType(1, "I'm a field value");
entity.setReferenceType(new ReferenceType(42, "reference"));
entity.setEmbeddedType(new EmbeddedReferenceType(18, "embedded"));
entity.setEmbeddedSet(new HashSet<EmbeddedReferenceType>(asList(new EmbeddedReferenceType(42, "Douglas Adams"),
new EmbeddedReferenceType(1, "Love"))));
entity.setEmbeddedList(asList(new EmbeddedReferenceType(42, "Douglas Adams"), new EmbeddedReferenceType(1, "Love")));
entity.setEmbeddedArray(new EmbeddedReferenceType[]{new EmbeddedReferenceType(42, "Douglas Adams"),
new EmbeddedReferenceType(1, "Love")});
entity.getMap().put("first", new EmbeddedReferenceType(42, "Douglas Adams"));
entity.getMap().put("second", new EmbeddedReferenceType(1, "Love"));
entity.getMapOfList().put("first", asList(new EmbeddedReferenceType(42, "Douglas Adams"), new EmbeddedReferenceType(1, "Love")));
entity.getMapOfList().put("second", asList(new EmbeddedReferenceType(1, "Love"), new EmbeddedReferenceType(42, "Douglas Adams")));
entity.getMapOfSet().put("first", new HashSet<EmbeddedReferenceType>(asList(new EmbeddedReferenceType(42, "Douglas Adams"),
new EmbeddedReferenceType(1, "Love"))));
entity.getMapOfSet().put("second", new HashSet<EmbeddedReferenceType>(asList(new EmbeddedReferenceType(42, "Douglas Adams"),
new EmbeddedReferenceType(1, "Love"))));
entity.setSelfReference(entity);
entity.setIdOnly(entity);
entity.setReferenceArray(new ReferenceType[]{new ReferenceType(2, "text 2"), new ReferenceType(3, "text 3")});
entity.setReferenceList(asList(new ReferenceType(2, "text 2"), new ReferenceType(3, "text 3")));
entity.setReferenceSet(new HashSet<ReferenceType>(asList(new ReferenceType(2, "text 2"), new ReferenceType(3, "text 3"))));
entity.getReferenceMap().put("first", new ReferenceType(2, "text 2"));
entity.getReferenceMap().put("second", new ReferenceType(3, "text 3"));
entity.getReferenceMapOfList().put("first", asList(new ReferenceType(2, "text 2"), new ReferenceType(3, "text 3")));
entity.getReferenceMapOfList().put("second", singletonList(new ReferenceType(3, "text 3")));
entity.setMixedTypeArray(new ReferenceType[]{new ReferenceType(2, "text 2"), new ClassNameReferenceType(3, "text 3")});
entity.setMixedTypeList(asList(new ReferenceType(2, "text 2"), new ClassNameReferenceType(3, "text 3")));
entity.setMixedTypeSet(new HashSet<ReferenceType>(asList(new ReferenceType(2, "text 2"),
new ClassNameReferenceType(3, "text 3"))));
entity.getMixedTypeMap().put("first", new ReferenceType(2, "text 2"));
entity.getMixedTypeMap().put("second", new ClassNameReferenceType(3, "text 3"));
entity.getMixedTypeMapOfList().put("first", asList(new ReferenceType(2, "text 2"),
new ClassNameReferenceType(3, "text 3")));
entity.getMixedTypeMapOfList().put("second", singletonList(new ClassNameReferenceType(3, "text 3")));
getDs().save(entity);
DBObject dbObject = getDs().getCollection(ReferenceType.class).findOne();
Assert.assertEquals(BasicDBObject.parse(readFully("/ReferenceType.json")), dbObject);
verifyCoverage(dbObject);
}
private String readFully(final String name) {
return new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(name)))
.lines()
.collect(java.util.stream.Collectors.joining("\n"));
}
}
@SuppressWarnings({"WeakerAccess", "unused"})
@Entity("ondisk")
class ReferenceType {
@Id
private Integer id;
private ReferenceType referenceType;
private EmbeddedReferenceType embeddedType;
private String string;
private EmbeddedReferenceType[] embeddedArray;
private Set<EmbeddedReferenceType> embeddedSet;
private List<EmbeddedReferenceType> embeddedList;
private Map<String, EmbeddedReferenceType> map = new TreeMap<String, EmbeddedReferenceType>();
private Map<String, List<EmbeddedReferenceType>> mapOfList = new TreeMap<String, List<EmbeddedReferenceType>>();
private Map<String, Set<EmbeddedReferenceType>> mapOfSet = new TreeMap<String, Set<EmbeddedReferenceType>>();
@Reference
private ReferenceType selfReference;
@Reference(idOnly = true)
private ReferenceType idOnly;
private ReferenceType[] referenceArray;
private Set<ReferenceType> referenceSet;
private List<ReferenceType> referenceList;
private Map<String, ReferenceType> referenceMap = new TreeMap<String, ReferenceType>();
private Map<String, List<ReferenceType>> referenceMapOfList = new TreeMap<String, List<ReferenceType>>();
private ReferenceType[] mixedTypeArray;
private Set<? extends ReferenceType> mixedTypeSet;
private List<? extends ReferenceType> mixedTypeList;
private Map<String, ? super ReferenceType> mixedTypeMap = new TreeMap<String, ReferenceType>();
private Map<String, List<? extends ReferenceType>> mixedTypeMapOfList = new TreeMap<String, List<? extends ReferenceType>>();
public ReferenceType() {
}
public ReferenceType(final int id, final String string) {
this.id = id;
this.string = string;
}
public ReferenceType getReferenceType() {
return referenceType;
}
public void setReferenceType(final ReferenceType referenceType) {
this.referenceType = referenceType;
}
public EmbeddedReferenceType getEmbeddedType() {
return embeddedType;
}
public void setEmbeddedType(final EmbeddedReferenceType embeddedType) {
this.embeddedType = embeddedType;
}
public EmbeddedReferenceType[] getEmbeddedArray() {
return embeddedArray;
}
public void setEmbeddedArray(final EmbeddedReferenceType[] embeddedArray) {
this.embeddedArray = embeddedArray;
}
public List<EmbeddedReferenceType> getEmbeddedList() {
return embeddedList;
}
public void setEmbeddedList(final List<EmbeddedReferenceType> embeddedList) {
this.embeddedList = embeddedList;
}
public Set<EmbeddedReferenceType> getEmbeddedSet() {
return embeddedSet;
}
public void setEmbeddedSet(final Set<EmbeddedReferenceType> embeddedSet) {
this.embeddedSet = embeddedSet;
}
public int getId() {
return id;
}
public void setId(final int id) {
this.id = id;
}
public ReferenceType getIdOnly() {
return idOnly;
}
public void setIdOnly(final ReferenceType idOnly) {
this.idOnly = idOnly;
}
public Map<String, EmbeddedReferenceType> getMap() {
return map;
}
public void setMap(final Map<String, EmbeddedReferenceType> map) {
this.map = map;
}
public Map<String, List<EmbeddedReferenceType>> getMapOfList() {
return mapOfList;
}
public void setMapOfList(final Map<String, List<EmbeddedReferenceType>> mapOfList) {
this.mapOfList = mapOfList;
}
public Map<String, Set<EmbeddedReferenceType>> getMapOfSet() {
return mapOfSet;
}
public void setMapOfSet(final Map<String, Set<EmbeddedReferenceType>> mapOfSet) {
this.mapOfSet = mapOfSet;
}
public ReferenceType[] getMixedTypeArray() {
return mixedTypeArray;
}
public void setMixedTypeArray(final ReferenceType[] mixedTypeArray) {
this.mixedTypeArray = mixedTypeArray;
}
public List<? extends ReferenceType> getMixedTypeList() {
return mixedTypeList;
}
public void setMixedTypeList(final List<? extends ReferenceType> mixedTypeList) {
this.mixedTypeList = mixedTypeList;
}
public Map<String, ? super ReferenceType> getMixedTypeMap() {
return mixedTypeMap;
}
public void setMixedTypeMap(final Map<String, ? super ReferenceType> mixedTypeMap) {
this.mixedTypeMap = mixedTypeMap;
}
public Map<String, List<? extends ReferenceType>> getMixedTypeMapOfList() {
return mixedTypeMapOfList;
}
public void setMixedTypeMapOfList(
final Map<String, List<? extends ReferenceType>> mixedTypeMapOfList) {
this.mixedTypeMapOfList = mixedTypeMapOfList;
}
public Set<? extends ReferenceType> getMixedTypeSet() {
return mixedTypeSet;
}
public void setMixedTypeSet(final Set<? extends ReferenceType> mixedTypeSet) {
this.mixedTypeSet = mixedTypeSet;
}
public ReferenceType[] getReferenceArray() {
return referenceArray;
}
public void setReferenceArray(final ReferenceType[] referenceArray) {
this.referenceArray = referenceArray;
}
public List<ReferenceType> getReferenceList() {
return referenceList;
}
public void setReferenceList(final List<ReferenceType> referenceList) {
this.referenceList = referenceList;
}
public Map<String, ReferenceType> getReferenceMap() {
return referenceMap;
}
public void setReferenceMap(final Map<String, ReferenceType> referenceMap) {
this.referenceMap = referenceMap;
}
public Map<String, List<ReferenceType>> getReferenceMapOfList() {
return referenceMapOfList;
}
public void setReferenceMapOfList(final Map<String, List<ReferenceType>> referenceMapOfList) {
this.referenceMapOfList = referenceMapOfList;
}
public Set<ReferenceType> getReferenceSet() {
return referenceSet;
}
public void setReferenceSet(final Set<ReferenceType> referenceSet) {
this.referenceSet = referenceSet;
}
public ReferenceType getSelfReference() {
return selfReference;
}
public void setSelfReference(final ReferenceType selfReference) {
this.selfReference = selfReference;
}
public String getString() {
return string;
}
public void setString(final String string) {
this.string = string;
}
@Override
public int hashCode() {
return id;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ReferenceType)) {
return false;
}
final ReferenceType that = (ReferenceType) o;
if (!id.equals(that.id)) {
return false;
}
if (string != null ? !string.equals(that.string) : that.string != null) {
return false;
}
// Probably incorrect - comparing Object[] arrays with Arrays.equals
if (!Arrays.equals(embeddedArray, that.embeddedArray)) {
return false;
}
if (embeddedSet != null ? !embeddedSet.equals(that.embeddedSet) : that.embeddedSet != null) {
return false;
}
if (embeddedList != null ? !embeddedList.equals(that.embeddedList) : that.embeddedList != null) {
return false;
}
if (map != null ? !map.equals(that.map) : that.map != null) {
return false;
}
if (mapOfList != null ? !mapOfList.equals(that.mapOfList) : that.mapOfList != null) {
return false;
}
if (mapOfSet != null ? !mapOfSet.equals(that.mapOfSet) : that.mapOfSet != null) {
return false;
}
if (selfReference != null ? !selfReference.equals(that.selfReference) : that.selfReference != null) {
return false;
}
if (idOnly != null ? !idOnly.equals(that.idOnly) : that.idOnly != null) {
return false;
}
// Probably incorrect - comparing Object[] arrays with Arrays.equals
if (!Arrays.equals(referenceArray, that.referenceArray)) {
return false;
}
if (referenceSet != null ? !referenceSet.equals(that.referenceSet) : that.referenceSet != null) {
return false;
}
if (referenceList != null ? !referenceList.equals(that.referenceList) : that.referenceList != null) {
return false;
}
if (referenceMap != null ? !referenceMap.equals(that.referenceMap) : that.referenceMap != null) {
return false;
}
return referenceMapOfList != null ? referenceMapOfList.equals(that.referenceMapOfList) : that.referenceMapOfList == null;
}
}
@Entity
@SuppressWarnings("unused")
class ClassNameReferenceType extends ReferenceType {
public ClassNameReferenceType() {
}
public ClassNameReferenceType(final int id, final String string) {
super(id, string);
}
}
@Embedded
@SuppressWarnings({"unused", "WeakerAccess"})
class EmbeddedReferenceType {
private Integer number;
private String text;
public EmbeddedReferenceType(final int number, final String text) {
this.number = number;
this.text = text;
}
public EmbeddedReferenceType() {
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (!(o instanceof EmbeddedReferenceType)) {
return false;
}
final EmbeddedReferenceType that = (EmbeddedReferenceType) o;
if (number != null ? !number.equals(that.number) : that.number != null) {
return false;
}
return text != null ? text.equals(that.text) : that.text == null;
}
@Override
public int hashCode() {
int result = number != null ? number.hashCode() : 0;
result = 31 * result + (text != null ? text.hashCode() : 0);
return result;
}
}