@Override @SuppressWarnings("unchecked") public void onValueChange(ValueChange valueChange) { GlobalId id = valueChange.getAffectedGlobalId(); Map<String, Object> prevO = getPrevious(); Map<String, Object> nextO = getNew(); if (id instanceof ValueObjectId) { ValueObjectId idV = (ValueObjectId) id; String[] path = idV.getFragment().split("/"); for (String p : path) { prevO.putIfAbsent(p, new HashMap<String, Object>()); prevO = (Map<String, Object>) prevO.get(p); nextO.putIfAbsent(p, new HashMap<String, Object>()); nextO = (Map<String, Object>) nextO.get(p); } } prevO.put(valueChange.getPropertyName(), valueChange.getLeft()); nextO.put(valueChange.getPropertyName(), valueChange.getRight()); }
@Override public Optional<ValueChange> compare(BigDecimal left, BigDecimal right, GlobalId affectedId, Property property) { if (equals(left, right)){ return Optional.empty(); } return Optional.of(new ValueChange(affectedId, property.getName(), left, right)); }
@Override public String prettyPrint(PrettyValuePrinter valuePrinter) { Validate.argumentIsNotNull(valuePrinter); return valuePrinter.formatWithQuotes(getPropertyNameWithPath()) + " changed from " + valuePrinter.formatWithQuotes(getLeft()) + " to " + valuePrinter.formatWithQuotes(getRight()); }
@Override public void onValueChange(ValueChange valueChange) { appendln(" value changed on '"+valueChange.getPropertyName()+"' property: '"+ PrettyValuePrinter.getDefault().format(valueChange.getLeft()) + "' -> '" + PrettyValuePrinter.getDefault().format(valueChange.getRight()) + "'"); }
/** {@link ValueChange} example */ @Test public void shouldDetectSalaryChange(){ //given Javers javers = JaversBuilder.javers().build(); Employee oldBoss = new Employee("Big Boss") .addSubordinates( new Employee("Noisy Manager"), new Employee("Great Developer", 10000)); Employee newBoss = new Employee("Big Boss") .addSubordinates( new Employee("Noisy Manager"), new Employee("Great Developer", 20000)); //when Diff diff = javers.compare(oldBoss, newBoss); //then ValueChange change = diff.getChangesByType(ValueChange.class).get(0); assertThat(change.getAffectedLocalId()).isEqualTo("Great Developer"); assertThat(change.getPropertyName()).isEqualTo("salary"); assertThat(change.getLeft()).isEqualTo(10000); assertThat(change.getRight()).isEqualTo(20000); System.out.println(diff); }
@Test public void shouldCompareTwoObjectsWithCharSequencePropertiesOfString() { //given Javers javers = JaversBuilder.javers().build(); AvroAddress oldVersion = new AvroAddress("New York", "First Avenue"); AvroAddress currentVersion = new AvroAddress("New York", "Second Avenue"); //when Diff diff = javers.compare(oldVersion, currentVersion); System.out.println(diff); //then ValueChange change = diff.getChangesByType(ValueChange.class).get(0); assertThat(diff.getChanges()).hasSize(1); assertThat(change.getPropertyName()).isEqualTo("street"); assertThat(change.getLeft()).isEqualTo(oldVersion.getStreet()); assertThat(change.getRight()).isEqualTo(currentVersion.getStreet()); } }
@Test public void shouldCompareTwoObjects() { //given Javers javers = JaversBuilder.javers().build(); Address address1 = new Address("New York","5th Avenue"); Address address2 = new Address("New York","6th Avenue"); //when Diff diff = javers.compare(address1, address2); //then //there should be one change of type {@link ValueChange} ValueChange change = diff.getChangesByType(ValueChange.class).get(0); assertThat(diff.getChanges()).hasSize(1); assertThat(change.getAffectedGlobalId().value()) .isEqualTo("org.javers.core.examples.model.Address/"); assertThat(change.getPropertyName()).isEqualTo("street"); assertThat(change.getLeft()).isEqualTo("5th Avenue"); assertThat(change.getRight()).isEqualTo("6th Avenue"); System.out.println(diff); } }
@Test public void shouldDeeplyCompareTwoTopLevelCollections() { //given Javers javers = JaversBuilder.javers().build(); List<Person> oldList = Lists.asList( new Person("tommy", "Tommy Smart") ); List<Person> newList = Lists.asList( new Person("tommy", "Tommy C. Smart") ); //when Diff diff = javers.compareCollections(oldList, newList, Person.class); //then //there should be one change of type {@link ValueChange} ValueChange change = diff.getChangesByType(ValueChange.class).get(0); assertThat(diff.getChanges()).hasSize(1); assertThat(change.getPropertyName()).isEqualTo("name"); assertThat(change.getLeft()).isEqualTo("Tommy Smart"); assertThat(change.getRight()).isEqualTo("Tommy C. Smart"); System.out.println(diff); } }
@Override public JsonElement toJson(ValueChange change, JsonSerializationContext context) { JsonObject jsonObject = createJsonObject(change, context); jsonObject.add(LEFT_VALUE_FIELD, context.serialize(change.getLeft())); jsonObject.add(RIGHT_VALUE_FIELD, context.serialize(change.getRight())); return jsonObject; }
@Override public ValueChange fromJson(JsonElement json, JsonDeserializationContext context) { JsonObject jsonObject = (JsonObject) json; PropertyChangeStub stub = deserializeStub(jsonObject, context); Object leftValue = context.deserialize(jsonObject.get(LEFT_VALUE_FIELD), stub.property.getGenericType()); Object rightValue = context.deserialize(jsonObject.get(RIGHT_VALUE_FIELD), stub.property.getGenericType()); CommitMetadata commitMetadata = deserializeCommitMetadata(jsonObject, context); return new ValueChange(stub.id, stub.getPropertyName(), leftValue, rightValue, ofNullable(commitMetadata)); }
@Test public void shouldSupportInterfaceProperty() { // given TestClassWithInterfaceProperty foo = new TestClassWithInterfaceProperty("1", new TestInterfaceImpl("Foo")); TestClassWithInterfaceProperty bar = new TestClassWithInterfaceProperty("1", new TestInterfaceImpl("Bar")); Javers javers = JaversBuilder.javers().build(); // when Diff diff = javers.compare(foo, bar); System.out.println(diff); // then assertTrue(diff.getChanges().size() == 1); ValueChange change = diff.getChangesByType(ValueChange.class).get(0); ValueObjectIdDTO voId = ValueObjectIdDTO.valueObjectId("1", TestClassWithInterfaceProperty.class, "interfaceProperty"); Assertions.assertThat(change.getAffectedGlobalId().value()).isEqualTo(voId.value()); Assertions.assertThat(change.getPropertyName()).isEqualTo("value"); Assertions.assertThat(change.getLeft()).isEqualTo("Foo"); Assertions.assertThat(change.getRight()).isEqualTo("Bar"); }
public PropertyChange calculateChanges(Object leftValue, Object rightValue, GlobalId affectedId, JaversProperty property) { OptionalType optionalType = ((JaversProperty) property).getType(); JaversType contentType = typeMapper.getJaversType(optionalType.getItemType()); Optional leftOptional = normalize((Optional) leftValue); Optional rightOptional = normalize((Optional) rightValue); if (contentType instanceof ManagedType){ GlobalId leftId = getAndDehydrate(leftOptional, contentType); GlobalId rightId = getAndDehydrate(rightOptional, contentType); if (Objects.equals(leftId, rightId)) { return null; } return new ReferenceChange(affectedId, property.getName(), leftId, rightId, leftValue, rightValue); } if (contentType instanceof PrimitiveOrValueType) { if (leftOptional.equals(rightOptional)) { return null; } return new ValueChange(affectedId, property.getName(), leftOptional, rightOptional); } throw new JaversException(UNSUPPORTED_OPTIONAL_CONTENT_TYPE, contentType); }
/** * @param property supported property (of PrimitiveType or ValueObjectType) */ @Override public ValueChange calculateChanges(NodePair pair, JaversProperty property) { Object leftValue = pair.getLeftPropertyValue(property); Object rightValue = pair.getRightPropertyValue(property); //special treatment for EmbeddedId - could be ValueObjects without good equals() implementation if (isIdProperty(pair, property)) { //For idProperty, only initial change is possible (from null to value). //If we have values on both sides, we know that they have the same String representation if (leftValue != null && rightValue != null) { return null; } } else { if (property.getType().equals(leftValue, rightValue)) { return null; } } return new ValueChange(pair.getGlobalId(), property.getName(), leftValue, rightValue); }