![JAR search and dependency download from the Maven repository](/logo.png)
org.apache.juneau.utils.BeanDiff Maven / Gradle / Ivy
// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
// * to you 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.apache.juneau.utils;
import static org.apache.juneau.internal.CollectionUtils.*;
import static org.apache.juneau.internal.ObjectUtils.*;
import java.util.*;
import org.apache.juneau.*;
import org.apache.juneau.annotation.Bean;
import org.apache.juneau.collections.*;
import org.apache.juneau.marshaller.*;
/**
* Utility class for comparing two versions of a POJO.
*
*
*
*
* // Two beans to compare.
* MyBean bean1 , bean2 ;
*
* // Get differences.
* BeanDiff beanDiff = BeanDiff.create (bean1 , bean2 ).exclude("fooProperty" ).build();
*
* // Check for differences.
* boolean hasDiff = beanDiff .hasDiffs();
*
* JsonMap v1Diffs = beanDiff .getV1(); // Get version 1 differences.
* JsonMap v2Diffs = beanDiff .getV2(); // Get version 2 differences.
*
* // Display differences.
* System.err .println(beanDiff );
*
*
* See Also:
*
*/
@Bean(properties="v1,v2")
public class BeanDiff {
//-----------------------------------------------------------------------------------------------------------------
// Static
//-----------------------------------------------------------------------------------------------------------------
/**
* Create a new builder for this class.
*
* @param The bean types.
* @param first The first bean to compare.
* @param second The second bean to compare.
* @return A new builder.
*/
public static Builder create(T first, T second) {
return new Builder().first(first).second(second);
}
//-----------------------------------------------------------------------------------------------------------------
// Builder
//-----------------------------------------------------------------------------------------------------------------
/**
* Builder class.
*
* @param The bean type.
*/
public static class Builder {
T first, second;
BeanContext beanContext = BeanContext.DEFAULT;
Set include, exclude;
/**
* Specifies the first bean to compare.
*
* @param value The first bean to compare.
* @return This object.
*/
public Builder first(T value) {
this.first = value;
return this;
}
/**
* Specifies the second bean to compare.
*
* @param value The first bean to compare.
* @return This object.
*/
public Builder second(T value) {
this.second = value;
return this;
}
/**
* Specifies the bean context to use for introspecting beans.
*
*
* If not specified, uses {@link BeanContext#DEFAULT}.
*
* @param value The bean context to use for introspecting beans.
* @return This object.
*/
public Builder beanContext(BeanContext value) {
this.beanContext = value;
return this;
}
/**
* Specifies the properties to include in the comparison.
*
*
* If not specified, compares all properties.
*
* @param properties The properties to include in the comparison.
* @return This object.
*/
public Builder include(String...properties) {
include = set(properties);
return this;
}
/**
* Specifies the properties to include in the comparison.
*
*
* If not specified, compares all properties.
*
* @param properties The properties to include in the comparison.
* @return This object.
*/
public Builder include(Set properties) {
include = properties;
return this;
}
/**
* Specifies the properties to exclude from the comparison.
*
* @param properties The properties to exclude from the comparison.
* @return This object.
*/
public Builder exclude(String...properties) {
exclude = set(properties);
return this;
}
/**
* Specifies the properties to exclude from the comparison.
*
* @param properties The properties to exclude from the comparison.
* @return This object.
*/
public Builder exclude(Set properties) {
exclude = properties;
return this;
}
/**
* Build the differences.
*
* @return A new {@link BeanDiff} object.
*/
public BeanDiff build() {
return new BeanDiff(beanContext, first, second, include, exclude);
}
}
//-----------------------------------------------------------------------------------------------------------------
// Instance
//-----------------------------------------------------------------------------------------------------------------
private JsonMap v1 = new JsonMap(), v2 = new JsonMap();
/**
* Constructor.
*
* @param The bean types.
* @param bc The bean context to use for comparing beans.
* @param first The first bean to compare.
* @param second The second bean to compare.
* @param include
* Optional properties to include in the comparison.
*
If null , all properties are included.
* @param exclude
* Optional properties to exclude in the comparison.
*
If null , no properties are excluded.
*/
@SuppressWarnings("null")
public BeanDiff(BeanContext bc, T first, T second, Set include, Set exclude) {
if (first == null && second == null)
return;
BeanMap> bm1 = first == null ? null : bc.toBeanMap(first);
BeanMap> bm2 = second == null ? null : bc.toBeanMap(second);
Set keys = bm1 != null ? bm1.keySet() : bm2.keySet();
keys.forEach(k -> {
if ((include == null || include.contains(k)) && (exclude == null || ! exclude.contains(k))) {
Object o1 = bm1 == null ? null : bm1.get(k);
Object o2 = bm2 == null ? null : bm2.get(k);
if (ne(o1, o2)) {
if (o1 != null)
v1.put(k, o1);
if (o2 != null)
v2.put(k, o2);
}
}
});
}
/**
* Returns true if the beans had differences.
*
* @return true if the beans had differences.
*/
public boolean hasDiffs() {
return v1.size() > 0 || v2.size() > 0;
}
/**
* Returns the differences in the first bean.
*
* @return The differences in the first bean.
*/
public JsonMap getV1() {
return v1;
}
/**
* Returns the differences in the second bean.
*
* @return The differences in the second bean.
*/
public JsonMap getV2() {
return v2;
}
@Override
public String toString() {
return Json5.of(this);
}
}