Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
javers/javers-core/src/test/groovy/org/javers/core/examples/JqlExample.groovy
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
644 lines (513 sloc)
23.7 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.javers.core.examples | |
import org.javers.core.FakeDateProvider | |
import org.javers.core.Changes | |
import org.javers.core.JaversBuilder | |
import org.javers.core.commit.CommitId | |
import org.javers.core.diff.changetype.ValueChange | |
import org.javers.core.examples.model.Address | |
import org.javers.core.examples.model.Employee | |
import org.javers.core.examples.model.Person | |
import org.javers.core.metamodel.annotation.Id | |
import org.javers.core.metamodel.object.CdoSnapshot | |
import org.javers.core.model.DummyAddress | |
import org.javers.core.model.DummyUserDetails | |
import org.javers.core.model.SnapshotEntity | |
import org.javers.repository.jql.QueryBuilder | |
import org.javers.shadow.Shadow | |
import spock.lang.Specification | |
import java.time.LocalDate | |
import java.time.ZoneId | |
import java.time.ZonedDateTime | |
/** | |
* @author bartosz.walacik | |
*/ | |
class JqlExample extends Specification { | |
class Entity { | |
@Id int id | |
Entity ref | |
} | |
def "should query for Shadows with different scopes, lightweight example, multiple commits"(){ | |
given: 'In the first scenario, our 4 entities are committed in 3 commits' | |
def javers = JaversBuilder.javers().build() | |
// E1 -> E2 -> E3 -> E4 | |
def e4 = new Entity(id:4) | |
def e3 = new Entity(id:3, ref:e4) | |
def e2 = new Entity(id:2, ref:e3) | |
def e1 = new Entity(id:1, ref:e2) | |
javers.commit("author", e4) // commit 1.0 with e4 snapshot | |
javers.commit("author", e3) // commit 2.0 with e3 snapshot | |
javers.commit("author", e1) // commit 3.0 with snapshots of e1 and e2 | |
when: 'shallow scope query' | |
def shadows = javers.findShadows(QueryBuilder.byInstanceId(1, Entity).build()) | |
def shadowE1 = shadows.get(0).get() | |
then: 'only e1 is loaded' | |
shadowE1 instanceof Entity | |
shadowE1.id == 1 | |
shadowE1.ref == null | |
when: 'commit-deep scope query' | |
shadows = javers.findShadows(QueryBuilder.byInstanceId(1, Entity) | |
.withScopeCommitDeep().build()) | |
shadowE1 = shadows.get(0).get() | |
then: 'only e1 and e2 are loaded, both was committed in commit 3.0' | |
shadowE1.id == 1 | |
shadowE1.ref.id == 2 | |
shadowE1.ref.ref == null | |
when: 'deep+1 scope query' | |
def query = QueryBuilder.byInstanceId(1, Entity).withScopeDeepPlus(1).build() | |
shadows = javers.findShadows(query) | |
println 'deep+1 scope query: ' + query | |
shadowE1 = shadows.get(0).get() | |
then: 'only e1 and e2 are loaded' | |
shadowE1.id == 1 | |
shadowE1.ref.id == 2 | |
shadowE1.ref.ref == null | |
when: 'deep+3 scope query' | |
shadows = javers.findShadows(QueryBuilder.byInstanceId(1, Entity) | |
.withScopeDeepPlus(3).build()) | |
shadowE1 = shadows.get(0).get() | |
then: 'all object are loaded' | |
shadowE1.id == 1 | |
shadowE1.ref.id == 2 | |
shadowE1.ref.ref.id == 3 | |
shadowE1.ref.ref.ref.id == 4 | |
} | |
def "should query for Shadows with different scopes, lightweight example, single commit"(){ | |
given: 'In the second scenario, our four entities are committed in the single commit' | |
def javers = JaversBuilder.javers().build() | |
// E1 -> E2 -> E3 -> E4 | |
def e4 = new Entity(id:4) | |
def e3 = new Entity(id:3, ref:e4) | |
def e2 = new Entity(id:2, ref:e3) | |
def e1 = new Entity(id:1, ref:e2) | |
javers.commit("author", e1) // commit 1.0 with snapshots of e1, e2, e3 and e4 | |
when: 'shallow scope query' | |
def shadows = javers.findShadows(QueryBuilder.byInstanceId(1, Entity).build()) | |
def shadowE1 = shadows.get(0).get() | |
then: 'only e1 is loaded' | |
shadowE1 instanceof Entity | |
shadowE1.id == 1 | |
shadowE1.ref == null | |
when: 'commit-deep scope query' | |
shadows = javers.findShadows(QueryBuilder.byInstanceId(1, Entity) | |
.withScopeCommitDeep().build()) | |
shadowE1 = shadows.get(0).get() | |
then: 'all object are loaded' | |
shadowE1.id == 1 | |
shadowE1.ref.id == 2 | |
shadowE1.ref.ref.id == 3 | |
shadowE1.ref.ref.ref.id == 4 | |
} | |
def "should query for Changes made on any object"() { | |
given: | |
def javers = JaversBuilder.javers().build() | |
def bob = new Employee(name: "bob", | |
salary: 1000, | |
primaryAddress: new Address("London")) | |
javers.commit("author", bob) // initial commit | |
bob.salary = 1200 // changes | |
bob.primaryAddress.city = "Paris" // | |
javers.commit("author", bob) // second commit | |
when: | |
Changes changes = javers.findChanges( QueryBuilder.anyDomainObject().build() ) | |
println changes.prettyPrint() | |
then: | |
def lastCommitChanges = changes.groupByCommit()[0].changes | |
assert lastCommitChanges.size() == 2 | |
ValueChange salaryChange = lastCommitChanges.find{it.propertyName == "salary"} | |
ValueChange cityChange = lastCommitChanges.find{it.propertyName == "city"} | |
assert salaryChange.left == 1000 | |
assert salaryChange.right == 1200 | |
assert cityChange.left == "London" | |
assert cityChange.right == "Paris" | |
} | |
def "should query for Shadows of an object"() { | |
given: | |
def javers = JaversBuilder.javers().build() | |
def bob = new Employee(name: "bob", | |
salary: 1000, | |
primaryAddress: new Address("London")) | |
javers.commit("author", bob) // initial commit | |
bob.salary = 1200 // changes | |
bob.primaryAddress.city = "Paris" // | |
javers.commit("author", bob) // second commit | |
when: | |
List<Shadow<Employee>> shadows = javers.findShadows( | |
QueryBuilder.byInstance(bob).build()) | |
then: | |
assert shadows.size() == 2 | |
Employee bobNew = shadows[0].get() // Employee shadows are instances | |
Employee bobOld = shadows[1].get() // of Employee.class | |
bobNew.salary == 1200 | |
bobOld.salary == 1000 | |
bobNew.primaryAddress.city == "Paris" // Employee shadows are linked | |
bobOld.primaryAddress.city == "London" // to Address Shadows | |
shadows[0].commitMetadata.id.majorId == 2 | |
shadows[1].commitMetadata.id.majorId == 1 | |
} | |
def "should query for Shadows with different scopes"(){ | |
given: | |
def javers = JaversBuilder.javers().build() | |
// /-> John -> Steve | |
// Bob | |
// \-> #address | |
def steve = new Employee(name: 'steve') | |
def john = new Employee(name: 'john', boss: steve) | |
def bob = new Employee(name: 'bob', boss: john, primaryAddress: new Address('London')) | |
javers.commit('author', steve) // commit 1.0 with snapshot of Steve | |
javers.commit('author', bob) // commit 2.0 with snapshots of Bob, Bob#address and John | |
bob.salary = 1200 // the change | |
javers.commit('author', bob) // commit 3.0 with snapshot of Bob | |
when: 'shallow scope query' | |
def shadows = javers.findShadows(QueryBuilder.byInstance(bob).build()) | |
Employee bobShadow = shadows[0].get() //get the latest version of Bob | |
then: | |
assert shadows.size() == 2 //we have 2 shadows of Bob | |
assert bobShadow.name == 'bob' | |
// referenced entities are outside the query scope so they are nulled | |
assert bobShadow.boss == null | |
// child Value Objects are always in scope | |
assert bobShadow.primaryAddress.city == 'London' | |
when: 'commit-deep scope query' | |
shadows = javers.findShadows(QueryBuilder.byInstance(bob) | |
.withScopeCommitDeep().build()) | |
bobShadow = shadows[0].get() | |
then: | |
assert bobShadow.boss.name == 'john' // John is inside the query scope, so his | |
// shadow is loaded and linked to Bob | |
assert bobShadow.boss.boss == null // Steve is still outside the scope | |
assert bobShadow.primaryAddress.city == 'London' | |
when: 'deep+2 scope query' | |
shadows = javers.findShadows(QueryBuilder.byInstance(bob) | |
.withScopeDeepPlus(2).build()) | |
bobShadow = shadows[0].get() | |
then: 'all objects are loaded' | |
assert bobShadow.boss.name == 'john' | |
assert bobShadow.boss.boss.name == 'steve' // Steve is loaded thanks to deep+2 scope | |
assert bobShadow.primaryAddress.city == 'London' | |
} | |
def "should query for Snapshots of an object"(){ | |
given: | |
def javers = JaversBuilder.javers().build() | |
def bob = new Employee(name: "bob", | |
salary: 1000, | |
age: 29, | |
boss: new Employee("john")) | |
javers.commit("author", bob) // initial commit | |
bob.salary = 1200 // changes | |
bob.age = 30 // | |
javers.commit("author", bob) // second commit | |
when: | |
def snapshots = javers.findSnapshots( QueryBuilder.byInstance(bob).build() ) | |
then: | |
assert snapshots.size() == 2 | |
assert snapshots[0].commitMetadata.id.majorId == 2 | |
assert snapshots[0].changed == ["salary", "age"] | |
assert snapshots[0].getPropertyValue("salary") == 1200 | |
assert snapshots[0].getPropertyValue("age") == 30 | |
// references are dehydrated | |
assert snapshots[0].getPropertyValue("boss").value() == "Employee/john" | |
assert snapshots[1].commitMetadata.id.majorId == 1 | |
assert snapshots[1].getPropertyValue("salary") == 1000 | |
assert snapshots[1].getPropertyValue("age") == 29 | |
assert snapshots[1].getPropertyValue("boss").value() == "Employee/john" | |
} | |
def "should query for Entity changes by instance Id"() { | |
given: | |
def javers = JaversBuilder.javers().build() | |
javers.commit("author", new Employee(name:"bob", age:30, salary:1000) ) | |
javers.commit("author", new Employee(name:"bob", age:31, salary:1200) ) | |
javers.commit("author", new Employee(name:"john",age:25) ) | |
when: | |
Changes changes = javers. | |
findChanges( QueryBuilder.byInstanceId("bob", Employee.class).build() ) | |
println changes.prettyPrint() | |
then: | |
assert changes.size() == 6 | |
} | |
def "should query for ValueObject changes by owning Entity instance and class"() { | |
given: | |
def javers = JaversBuilder.javers().build() | |
javers.commit("author", new Employee(name:"bob", postalAddress: new Address(city:"Paris"))) | |
javers.commit("author", new Employee(name:"bob", primaryAddress: new Address(city:"London"))) | |
javers.commit("author", new Employee(name:"bob", primaryAddress: new Address(city:"Paris"))) | |
javers.commit("author", new Employee(name:"lucy", primaryAddress: new Address(city:"New York"))) | |
javers.commit("author", new Employee(name:"lucy", primaryAddress: new Address(city:"Washington"))) | |
when: | |
println "query for ValueObject changes by owning Entity instance Id" | |
Changes changes = javers | |
.findChanges( QueryBuilder.byValueObjectId("bob",Employee.class,"primaryAddress").build()) | |
println changes.prettyPrint() | |
then: | |
assert changes.size() == 2 | |
when: | |
println "query for ValueObject changes by owning Entity class" | |
changes = javers | |
.findChanges( QueryBuilder.byValueObject(Employee.class,"primaryAddress").build()) | |
println changes.prettyPrint() | |
then: | |
assert changes.size() == 4 | |
} | |
def "should query for ValueObject changes when stored in a List"() { | |
given: | |
def javers = JaversBuilder.javers().build() | |
javers.commit("author", | |
new Person(login: "bob", addresses: [new Address(city: "London"), new Address(city: "Luton")])) | |
javers.commit("author", | |
new Person(login: "bob", addresses: [new Address(city: "Paris"), new Address(city: "Luton")])) | |
when: | |
Changes changes = javers | |
.findChanges(QueryBuilder.byValueObjectId("bob",Person.class, "addresses/0").build()) | |
then: | |
println changes.prettyPrint() | |
assert changes.size() == 2 | |
} | |
def "should query for ValueObject changes when stored as Map values"() { | |
given: | |
def javers = JaversBuilder.javers().build() | |
javers.commit("author", new Person(login: "bob", addressMap: ["HOME":new Address(city: "Paris")])) | |
javers.commit("author", new Person(login: "bob", addressMap: ["HOME":new Address(city: "London")])) | |
when: | |
Changes changes = javers | |
.findChanges(QueryBuilder.byValueObjectId("bob", Person.class, "addressMap/HOME").build()) | |
then: | |
println changes.prettyPrint() | |
assert changes.size() == 2 | |
} | |
def "should query for Object changes by its class"() { | |
given: | |
def javers = JaversBuilder.javers().build() | |
javers.commit("me", new DummyUserDetails(id:1, dummyAddress: new DummyAddress(city: "London"))) | |
javers.commit("me", new DummyUserDetails(id:1, dummyAddress: new DummyAddress(city: "Paris"))) | |
javers.commit("me", new SnapshotEntity(id:2, valueObjectRef: new DummyAddress(city: "Rome"))) | |
javers.commit("me", new SnapshotEntity(id:2, valueObjectRef: new DummyAddress(city: "Palma"))) | |
javers.commit("me", new SnapshotEntity(id:2, intProperty:2)) | |
when: | |
Changes changes = javers.findChanges( QueryBuilder.byClass(DummyAddress.class).build() ) | |
then: | |
println changes.prettyPrint() | |
assert changes.size() == 4 | |
} | |
def "should query for any domain object changes"() { | |
given: | |
def javers = JaversBuilder.javers().build() | |
javers.commit("author", new Employee(name:"bob", age:30) ) | |
javers.commit("author", new Employee(name:"bob", age:31) ) | |
javers.commit("author", new DummyUserDetails(id:1, someValue:"old") ) | |
javers.commit("author", new DummyUserDetails(id:1, someValue:"new") ) | |
when: | |
Changes changes = javers.findChanges( QueryBuilder.anyDomainObject().build() ) | |
then: | |
println changes.prettyPrint() | |
assert changes.size() == 8 | |
} | |
def "should query for changes (and snapshots) with property filter"() { | |
given: | |
def javers = JaversBuilder.javers().build() | |
javers.commit("me", new Employee(name:"bob", age:30, salary:1000) ) | |
javers.commit("me", new Employee(name:"bob", age:31, salary:1100) ) | |
javers.commit("me", new Employee(name:"bob", age:31, salary:1200) ) | |
when: | |
def query = QueryBuilder.byInstanceId("bob", Employee.class) | |
.withChangedProperty("salary").build() | |
Changes changes = javers.findChanges(query) | |
then: | |
println changes.prettyPrint() | |
assert changes.size() == 3 | |
assert javers.findSnapshots(query).size() == 3 | |
} | |
def "should query for changes (and snapshots) with properties filter"() { | |
given: | |
def javers = JaversBuilder.javers().build() | |
javers.commit("me", new Employee(name:"bob", age:30, salary:1000) ) | |
javers.commit("me", new Employee(name:"bob", age:31, salary:1100) ) | |
javers.commit("me", new Employee(name:"bob", age:31, salary:1200) ) | |
when: | |
def query = QueryBuilder.byInstanceId("bob", Employee.class) | |
.withChangedPropertyIn("salary", "age").build() | |
Changes changes = javers.findChanges(query) | |
then: | |
println changes.prettyPrint() | |
assert changes.size() == 5 | |
assert javers.findSnapshots(query).size() == 3 | |
} | |
def "should query for changes (and snapshots) with limit filter"() { | |
given: | |
def javers = JaversBuilder.javers().build() | |
javers.commit( "me", new Employee(name:"bob", salary: 900) ) | |
javers.commit( "me", new Employee(name:"bob", salary: 1000) ) | |
javers.commit( "me", new Employee(name:"bob", salary: 1100) ) | |
javers.commit( "me", new Employee(name:"bob", salary: 1200) ) | |
when: | |
def query = QueryBuilder.byInstanceId("bob", Employee.class).limit(2).build() | |
Changes changes = javers.findChanges(query) | |
then: | |
println changes.prettyPrint() | |
assert changes.size() == 2 | |
assert javers.findSnapshots(query).size() == 2 | |
} | |
def "Skip parameter in findChanges, findSnapshots, and findShadows"() { | |
given: | |
def javers = JaversBuilder.javers().build() | |
javers.commit( "me", new Employee(name:"bob", age:20, salary: 2000) ) | |
javers.commit( "me", new Employee(name:"bob", age:30, salary: 3000) ) | |
javers.commit( "me", new Employee(name:"bob", age:40, salary: 4000) ) | |
javers.commit( "me", new Employee(name:"bob", age:50, salary: 5000) ) | |
def query = QueryBuilder.byInstanceId("bob", Employee.class).skip(2).build() | |
when: "findChanges()" | |
Changes changes = javers.findChanges( query ) | |
then: | |
println changes.prettyPrint() | |
assert changes.size() == 6 | |
when: "findSnapshots()" | |
List<CdoSnapshot> snapshots = javers.findSnapshots( query ) | |
then: | |
snapshots.each {println it} | |
assert snapshots.size() == 2 | |
assert snapshots[0].getPropertyValue("salary") == 3000 | |
when: "findShadows()" | |
List<Shadow<Employee>> shadows = javers.findShadows( query ) | |
then: | |
shadows.each {println it} | |
assert shadows.size() == 2 | |
assert shadows[0].get().salary == 3000 | |
} | |
def "should query for changes (and snapshots) with author filter"() { | |
given: | |
def javers = JaversBuilder.javers().build() | |
javers.commit( "Jim", new Employee(name:"bob", age:29, salary: 900) ) | |
javers.commit( "Pam", new Employee(name:"bob", age:30, salary: 1000) ) | |
javers.commit( "Jim", new Employee(name:"bob", age:31, salary: 1100) ) | |
javers.commit( "Pam", new Employee(name:"bob", age:32, salary: 1200) ) | |
when: | |
def query = QueryBuilder.byInstanceId("bob", Employee.class).byAuthor("Pam").build() | |
Changes changes = javers.findChanges( query ) | |
then: | |
println changes.prettyPrint() | |
assert changes.size() == 4 | |
assert javers.findSnapshots(query).size() == 2 | |
} | |
def "should query for changes (and snapshots) with commit property filters"() { | |
given: | |
def javers = JaversBuilder.javers().build() | |
def bob = new Employee(name: "bob", position: "Assistant", salary: 900) | |
javers.commit( "author", bob, ["tenant": "ACME", "event": "birthday"] ) | |
bob.position = "Specialist" | |
bob.salary = 1600 | |
javers.commit( "author", bob, ["tenant": "ACME", "event": "promotion"] ) | |
def pam = new Employee(name: "pam", position: "Secretary", salary: 1300) | |
javers.commit( "author", pam, ["tenant": "Dunder Mifflin", "event": "hire"] ) | |
bob.position = "Saleswoman" | |
bob.salary = 1700 | |
javers.commit( "author", pam, ["tenant": "Dunder Mifflin", "event": "promotion"] ) | |
when: | |
def query = QueryBuilder.anyDomainObject() | |
.withCommitProperty("tenant", "ACME") | |
.withCommitProperty("event", "promotion").build() | |
Changes changes = javers.findChanges( query ) | |
then: | |
println changes.prettyPrint() | |
assert changes.size() == 2 | |
assert javers.findSnapshots(query).size() == 1 | |
} | |
def "should query for changes (and snapshots) with commitDate filter"(){ | |
given: | |
def fakeDateProvider = new FakeDateProvider() | |
def javers = JaversBuilder.javers().withDateTimeProvider(fakeDateProvider).build() | |
(0..5).each{ i -> | |
def now = ZonedDateTime.of(2015+i,01,1,0,0,0,0, ZoneId.of("UTC")) | |
fakeDateProvider.set( now ) | |
def bob = new Employee(name:"bob", age:20+i) | |
javers.commit("author", bob) | |
println "committing bob on $now" | |
} | |
when: | |
def query = QueryBuilder.byInstanceId("bob", Employee.class) | |
.from(LocalDate.of(2016,01,1)) | |
.to (LocalDate.of(2018,01,1)).build() | |
Changes changes = javers.findChanges( query ) | |
then: | |
println changes.prettyPrint() | |
assert changes.size() == 3 | |
assert javers.findSnapshots(query).size() == 3 | |
} | |
def "should query for changes (and snapshots) with commitId filter"(){ | |
given: | |
def javers = JaversBuilder.javers().build() | |
(1..3).each { | |
javers.commit("author", new Employee(name:"john", age:20+it)) | |
javers.commit("author", new Employee(name:"bob", age:20+it)) | |
} | |
when: | |
def query = QueryBuilder.byInstanceId("bob", Employee.class ) | |
.withCommitId( CommitId.valueOf(4) ).build() | |
Changes changes = javers.findChanges(query) | |
then: | |
println changes.prettyPrint() | |
assert changes.size() == 1 | |
assert changes[0].left == 21 | |
assert changes[0].right == 22 | |
assert javers.findSnapshots(query).size() == 1 | |
} | |
def "should query for changes (and snapshots) with version filter"(){ | |
given: | |
def javers = JaversBuilder.javers().build() | |
(1..5).each { | |
javers.commit("author", new Employee(name: "john",age: 20+it)) | |
javers.commit("author", new Employee(name: "bob", age: 20+it)) | |
} | |
when: | |
def query = QueryBuilder.byInstanceId("bob", Employee.class).withVersion(4).build() | |
Changes changes = javers.findChanges( query ) | |
then: | |
println changes.prettyPrint() | |
assert changes.size() == 1 | |
assert changes[0].left == 23 | |
assert changes[0].right == 24 | |
assert javers.findSnapshots(query).size() == 1 | |
} | |
def "should query for changes with/without initialChanges"() { | |
when: | |
def javers = JaversBuilder.javers().build() | |
javers.commit( "author", new Employee(name:"bob", age:30, salary: 1000) ) | |
javers.commit( "author", new Employee(name:"bob", age:30, salary: 1200) ) | |
Changes changes = javers | |
.findChanges( QueryBuilder.byInstanceId("bob", Employee.class).build() ) | |
then: | |
println "with initialChanges:" | |
println changes.prettyPrint() | |
assert changes.size() == 5 | |
when: | |
javers = JaversBuilder.javers() | |
.withInitialChanges(false).build() // ! | |
javers.commit( "author", new Employee(name:"bob", age:30, salary: 1000) ) | |
javers.commit( "author", new Employee(name:"bob", age:30, salary: 1200) ) | |
changes = javers | |
.findChanges( QueryBuilder.byInstanceId("bob", Employee.class).build() ) | |
then: | |
println "without initialChanges:" | |
println changes.prettyPrint() | |
assert changes.size() == 2 | |
} | |
def "should query for changes made on Entity and its ValueObjects by InstanceId and Class"(){ | |
given: | |
def javers = JaversBuilder.javers().build() | |
def bob = new Employee(name:"bob", age:30, salary: 1000, | |
primaryAddress: new Address(city:"Paris"), | |
postalAddress: new Address(city:"Paris")) | |
javers.commit("author", bob) | |
bob.age = 31 | |
bob.primaryAddress.city = "London" | |
javers.commit("author", bob) | |
when: "query by instance Id" | |
def query = QueryBuilder.byInstanceId("bob", Employee.class).withChildValueObjects().build() | |
Changes changes = javers.findChanges( query ) | |
then: | |
println changes.prettyPrint() | |
assert changes.size() == 8 | |
when: "query by Entity class" | |
query = QueryBuilder.byClass(Employee.class).withChildValueObjects().build() | |
changes = javers.findChanges( query ) | |
then: | |
assert changes.size() == 8 | |
} | |
} |