package com.googlecode.objectify.test;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Cache;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Index;
import com.googlecode.objectify.annotation.Subclass;
import com.googlecode.objectify.annotation.Unindex;
import com.googlecode.objectify.cmd.Query;
import com.googlecode.objectify.test.entity.Name;
import com.googlecode.objectify.test.entity.Someone;
import com.googlecode.objectify.test.entity.Town;
import com.googlecode.objectify.test.entity.Trivial;
import com.googlecode.objectify.test.util.TestBase;
import org.testng.annotations.Test;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import static com.googlecode.objectify.test.util.TestObjectifyService.ds;
import static com.googlecode.objectify.test.util.TestObjectifyService.fact;
import static com.googlecode.objectify.test.util.TestObjectifyService.ofy;
/**
*/
public class EmbeddingTests extends TestBase
{
public static class PartiallyIndexedStruct {
@Index Someone indexedPerson;
@Unindex Someone unindexedPerson;
@Index String indexedString;
@Unindex String unidexedString;
public PartiallyIndexedStruct() { }
PartiallyIndexedStruct(Someone indexedPerson, Someone unindexedPerson, String indexedString, String unidexedString) {
this.indexedPerson = indexedPerson;
this.unindexedPerson = unindexedPerson;
this.indexedString = indexedString;
this.unidexedString = unidexedString;
}
}
@Entity
@Cache
public static class PartiallyIndexedEntity {
@Id Long id;
@Index PartiallyIndexedStruct indexed;
@Unindex PartiallyIndexedStruct unindexed;
public PartiallyIndexedEntity() { }
PartiallyIndexedEntity(PartiallyIndexedStruct indexed, PartiallyIndexedStruct unindexed) {
this.indexed = indexed;
this.unindexed = unindexed;
}
}
@Subclass
public static class PartiallyIndexedStructSubclass extends PartiallyIndexedStruct {
public PartiallyIndexedStructSubclass() { }
public PartiallyIndexedStructSubclass(Someone indexedPerson, Someone unindexedPerson, String indexedString, String unidexedString) {
super(indexedPerson, unindexedPerson, indexedString, unidexedString);
}
}
public static class Names {
Name[] names;
}
public static class Team {
Names members;
}
@Entity
@Cache
public static class TeamEntity extends Team {
@Id
Long id;
}
public static class League {
Team[] teams;
}
@Test
public void testNullHandling() throws Exception {
fact().register(Town.class);
// null mayor
Town t1 = new Town();
t1.mayor = new Someone(null, 30);
Key<Town> t1Key = ofy().save().entity(t1).now();
Town t2 = ofy().load().key(t1Key).now();
assert t2.mayor != null;
assert t2.mayor.name == null;
// mayor with null names
t1 = new Town();
t1.mayor = new Someone(new Name(null, null), 30);
t1Key = ofy().save().entity(t1).now();
t2 = ofy().load().key(t1Key).now();
assert t2.mayor != null;
assert t2.mayor.name != null;
assert t2.mayor.name.firstName == null;
assert t2.mayor.name.lastName == null;
assert t2.mayor.age == 30;
}
@Test
public void testUnindexed() throws Exception {
fact().register(PartiallyIndexedEntity.class);
PartiallyIndexedEntity obj = new PartiallyIndexedEntity(
new PartiallyIndexedStruct(
new Someone(new Name("A", "B"), 30),
new Someone(new Name("C", "D"), 31), "1", "2"),
new PartiallyIndexedStruct(
new Someone(new Name("a", "b"), 32),
new Someone(new Name("c", "d"), 33), "3", "4")
);
checkUnindexed(obj);
}
@Test
public void testUnindexedPolymorphic() throws Exception {
fact().register(PartiallyIndexedEntity.class);
fact().register(PartiallyIndexedStructSubclass.class);
PartiallyIndexedEntity obj = new PartiallyIndexedEntity(
new PartiallyIndexedStructSubclass(
new Someone(new Name("A", "B"), 30),
new Someone(new Name("C", "D"), 31), "1", "2"),
new PartiallyIndexedStructSubclass(
new Someone(new Name("a", "b"), 32),
new Someone(new Name("c", "d"), 33), "3", "4")
);
checkUnindexed(obj);
}
private void checkUnindexed(PartiallyIndexedEntity obj) {
Key<PartiallyIndexedEntity> key = ofy().save().entity(obj).now();
subtestFoundByQuery(true, key, "indexed.indexedPerson.name.firstName", "A");
subtestFoundByQuery(true, key, "indexed.indexedPerson.name.lastName", "B");
subtestFoundByQuery(true, key, "indexed.indexedPerson.age", 30);
subtestFoundByQuery(false, key, "indexed.unindexedPerson.name.firstName", "C");
subtestFoundByQuery(false, key, "indexed.unindexedPerson.name.lastName", "D");
subtestFoundByQuery(false, key, "indexed.unindexedPerson.age", 31);
subtestFoundByQuery(true, key, "indexed.indexedString", "1");
subtestFoundByQuery(false, key, "indexed.unindexedString", "2");
subtestFoundByQuery(true, key, "unindexed.indexedPerson.name.firstName", "a");
subtestFoundByQuery(true, key, "unindexed.indexedPerson.name.lastName", "b");
subtestFoundByQuery(true, key, "unindexed.indexedPerson.age", 32);
subtestFoundByQuery(false, key, "unindexed.unindexedPerson.name.firstName", "c");
subtestFoundByQuery(false, key, "unindexed.unindexedPerson.name.lastName", "d");
subtestFoundByQuery(false, key, "unindexed.unindexedPerson.age", 33);
subtestFoundByQuery(true, key, "unindexed.indexedString", "3");
subtestFoundByQuery(false, key, "unindexed.unindexedString", "4");
}
private void subtestFoundByQuery(boolean expected, Key<?> key, String filter, Object value) {
Query<PartiallyIndexedEntity> q = ofy().load().type(PartiallyIndexedEntity.class);
q = q.filter(filter + " =", value);
Iterator<PartiallyIndexedEntity> results = q.iterator();
if (expected) {
assert results.hasNext();
PartiallyIndexedEntity result = results.next();
assert result.id.equals(key.getId());
assert !results.hasNext();
} else {
assert !results.hasNext();
}
}
@Test
public void testDeepEmbeddedArrays() throws Exception {
fact().register(TeamEntity.class);
TeamEntity t = new TeamEntity();
t.members = new Names();
t.members.names = new Name[]{new Name("Joe", "Smith"), new Name("Jane", "Foo")};
Key<TeamEntity> k = ofy().save().entity(t).now();
System.out.println(ds().get(k.getRaw()));
t = ofy().load().key(k).now();
assert t != null;
assert t.members != null;
assert t.members.names != null;
assert t.members.names.length == 2;
assert t.members.names[0].firstName.equals("Joe");
assert t.members.names[0].lastName.equals("Smith");
assert t.members.names[1].firstName.equals("Jane");
assert t.members.names[1].lastName.equals("Foo");
}
@SuppressWarnings({"serial", "unused"})
public static class KensMailingListEntry implements Serializable {
private Key<Trivial> clientKey;
private String emailAddr;
private Integer mailOffset;
public KensMailingListEntry() {}
}
@SuppressWarnings({"serial", "unused"})
@Entity
public static class KensClientListName implements Serializable {
@Id
private Long id;
private Key<Trivial> orgKey;
private String listName;
private List<KensMailingListEntry> listMembers = new ArrayList<>();
public KensClientListName() {}
}
@Test
public void kensTest() throws Exception {
fact().register(KensClientListName.class);
List<KensMailingListEntry> listMembers = new ArrayList<>();
KensMailingListEntry mle = new KensMailingListEntry();
listMembers.add(mle);
KensClientListName clientlistname = new KensClientListName();
clientlistname.listMembers = listMembers;
ofy().save().entity(clientlistname).now();
}
@Entity
public static class EntityEmbedsOtherEntity {
@Id Long id;
Trivial other;
}
@Test
public void testEntityEmbedsOtherEntity() throws Exception {
fact().register(EntityEmbedsOtherEntity.class);
EntityEmbedsOtherEntity embeds = new EntityEmbedsOtherEntity();
embeds.other = new Trivial(123L, "blah", 7);
EntityEmbedsOtherEntity fetched = ofy().saveClearLoad(embeds);
assert embeds.other.getId().equals(fetched.other.getId());
assert embeds.other.getSomeString().equals(fetched.other.getSomeString());
}
}