BaseBean.java
/*
* GovWay - A customizable API Gateway
* https://govway.org
*
* Copyright (c) 2005-2025 Link.it srl (https://link.it).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3, as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openspcoop2.utils.beans;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlTransient;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.openspcoop2.utils.UtilsException;
import org.openspcoop2.utils.UtilsRuntimeException;
import org.openspcoop2.utils.date.DateUtils;
import org.openspcoop2.utils.serialization.ISerializer;
import org.openspcoop2.utils.serialization.JavaSerializer;
import org.openspcoop2.utils.serialization.SerializationConfig;
import org.openspcoop2.utils.serialization.SerializationFactory;
import org.openspcoop2.utils.serialization.SerializationFactory.SERIALIZATION_TYPE;
import org.openspcoop2.utils.xml.JaxbUtils;
/**
* BaseBean
*
* @author Poli Andrea (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
@XmlTransient
public abstract class BaseBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final String TO_STRING_METHOD = "toString";
protected BaseBean(){
// nop
}
private void logExceptionStackTrace(Exception e) {
e.printStackTrace(System.err);
}
/* ********** GENERIC UTILS ********* */
private Object getFieldValue(String fieldName,Object object) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{
Class<?> c = getClass();
StringBuilder methodName = new StringBuilder("get");
String firstChar = fieldName.charAt(0)+"";
methodName.append(firstChar.toUpperCase());
if(fieldName.length()>1){
methodName.append(fieldName.substring(1));
}
Method method = null;
try{
method = c.getMethod(methodName.toString());
}catch(java.lang.NoSuchMethodException nsme){
if("get_default".equals(methodName.toString())){
// provo a recuperare getDefault
try{
method = c.getMethod("getDefault");
}catch(Exception t){
throw nsme; // rilancio eccezione originale
}
}
else{
throw nsme; // rilancio eccezione originale
}
}
return method.invoke(object);
}
private Object setFieldValue(String fieldName,Object object,Class<?> parameterType,Object parameterValue) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{
Class<?> c = getClass();
StringBuilder methodName = new StringBuilder("set");
String firstChar = fieldName.charAt(0)+"";
methodName.append(firstChar.toUpperCase());
if(fieldName.length()>1){
methodName.append(fieldName.substring(1));
}
Method method = null;
try{
method = c.getMethod(methodName.toString(),parameterType);
}catch(java.lang.NoSuchMethodException nsme){
if("set_default".equals(methodName.toString())){
// provo a recuperare setDefault
try{
method = c.getMethod("setDefault",parameterType);
}catch(Exception t){
throw nsme; // rilancio eccezione originale
}
}
else{
throw nsme; // rilancio eccezione originale
}
}
return method.invoke(object,parameterValue);
}
// Non lo si vuole realizzare, si demanda eventualmente alla classe che lo implementa
// Se lo si aggiunge poi viene invocato l'equals e per alcuni field per cui non esiste il metodo get si ottiene errore (es. transazioneBean)
/**@Override
public int hashCode(){
return this.getClass().getName().hashCode();
}*/
/* ********** EQUALS ********* */
@Override
public boolean equals(Object object){
return this.equalsEngine(object,null);
}
public boolean equals(Object object,boolean checkLongId){
List<String> listFieldsNotCheck = new ArrayList<>();
if(!checkLongId){
listFieldsNotCheck.add("id");
}
return this.equalsEngine(object, listFieldsNotCheck);
}
public boolean equals(Object object,List<String> fieldsNotCheck){
return this.equalsEngine(object, fieldsNotCheck);
}
@SuppressWarnings("unchecked")
private boolean equalsEngine(Object object,List<String> fieldsNotCheck){
try{
if(object==null){
return false;
}
java.lang.reflect.Field[] fields = getClass().getDeclaredFields();
for(int i=0; i<fields.length;i++){
/**System.out.println("["+fields[i].getName()+"]");*/
if(java.lang.reflect.Modifier.isStatic(fields[i].getModifiers())){
/**System.out.println("IS STATIC");*/
continue;
}
if(fields[i].getType().isAssignableFrom(org.openspcoop2.utils.jaxb.DecimalWrapper.class)){
continue;
}
// field id non controllato se in fieldsNotCheckList
boolean ignoreField = false;
if(fieldsNotCheck!=null && !fieldsNotCheck.isEmpty()){
for (String fieldName : fieldsNotCheck) {
if(fieldName.equals(fields[i].getName())){
ignoreField = true;
break;
}
}
}
if(ignoreField){
continue;
}
Object fieldValueThis = this.getFieldValue(fields[i].getName(),this);
Object fieldValueObject = this.getFieldValue(fields[i].getName(),object);
/**System.out.println("LETTO VALORE["+fieldValue+"]");*/
if(fieldValueThis==null){
// FIELD
if(fieldValueObject!=null){
return false;
}
}else{
// ARRAY_LIST
if( (fields[i].getType().isAssignableFrom(java.util.ArrayList.class)) || (fields[i].getType().isAssignableFrom(java.util.List.class)) ){
java.util.List<?> listaThis = (java.util.List<?>) fieldValueThis;
java.util.List<?> listaParameter = (java.util.List<?>) fieldValueObject;
if(listaParameter==null)
return false;
if(listaThis.size() != listaParameter.size())
return false;
for(int j=0; j<listaThis.size(); j++){
if(listaThis.get(j)==null &&
listaParameter.get(j)!=null) {
return false;
}
}
// SORT
java.util.List<Object> listaThisSORT = new java.util.ArrayList<>();
java.util.List<Object> listaParameterSORT = new java.util.ArrayList<>();
try{
java.util.List<String> listaThisTMP = new java.util.ArrayList<>();
java.util.Map<String, Object> thisTmp = new java.util.HashMap<>();
java.util.Map<String, Object> parameterTmp = new java.util.HashMap<>();
for(int k=0; k<listaThis.size(); k++){
Object thisObject = listaThis.get(k);
Object paramObject = listaParameter.get(k);
if(thisObject==null && paramObject!=null)
throw new UtilsException("DIFF");
if(thisObject!=null && paramObject==null)
throw new UtilsException("DIFF");
if(thisObject!=null && paramObject!=null){
// THIS
String key = null;
if(thisObject.getClass().getName().startsWith(this.getClass().getPackage().getName())){
Class<?> c = thisObject.getClass();
java.lang.reflect.Method method = c.getMethod(TO_STRING_METHOD,boolean.class,boolean.class);
key = (String) method.invoke(thisObject,false,true);
}else{
key = thisObject.toString();
}
thisTmp.put(key, thisObject);
listaThisTMP.add(key);
// PARAM
if(paramObject.getClass().getName().startsWith(this.getClass().getPackage().getName())){
Class<?> c = paramObject.getClass();
java.lang.reflect.Method method = c.getMethod(TO_STRING_METHOD,boolean.class,boolean.class);
key = (String) method.invoke(paramObject,false,true);
}else{
key = paramObject.toString();
}
parameterTmp.put(key, paramObject);
}
}
java.util.Collections.sort(listaThisTMP);
for(int k=0; k<listaThisTMP.size(); k++){
String key = listaThisTMP.get(k);
Object thisObject = thisTmp.get(key);
Object paramObject = parameterTmp.get(key);
if(thisObject==null || paramObject==null){
// significa che manca un elemento
return false;
}
listaThisSORT.add(thisObject);
listaParameterSORT.add(paramObject);
}
}
catch(RuntimeException e){
// By SpotBugs
listaParameterSORT = (java.util.List<Object>) listaParameter;
listaThisSORT = (java.util.List<Object>) listaThis;
}
catch(Exception e){
listaThisSORT = (java.util.List<Object>) listaThis;
listaParameterSORT = (java.util.List<Object>) listaParameter;
}
for(int j=0; j<listaThisSORT.size(); j++){
Class<?> c = listaThisSORT.get(j).getClass();
boolean resultMethod = false;
if(listaThis.get(j).getClass().getName().startsWith(this.getClass().getPackage().getName())){
java.lang.reflect.Method method = c.getMethod("equals",Object.class,List.class);
resultMethod = (Boolean) method.invoke(listaThisSORT.get(j),listaParameterSORT.get(j),fieldsNotCheck);
}else{
resultMethod = listaThisSORT.get(j).equals(listaParameterSORT.get(j));
}
if(!resultMethod)
return false;
}
}else{
boolean resultMethod = false;
if(fields[i].getType().getName().startsWith(this.getClass().getPackage().getName())){
java.lang.reflect.Method method = fields[i].getType().getMethod("equals",Object.class,List.class);
resultMethod = (Boolean) method.invoke(fieldValueThis,fieldValueObject,fieldsNotCheck);
}else{
boolean checkUguaglianza = false;
if(fields[i].getType().isAssignableFrom(byte[].class)){
if(fieldValueObject!=null){
byte[] origi = (byte[]) fieldValueThis;
byte[] dest = (byte[]) fieldValueObject;
checkUguaglianza = (origi.length == dest.length);
if(checkUguaglianza){
for(int k=0;k<origi.length;k++){
if(origi[k]!=dest[k]){
checkUguaglianza = false;
break;
}
}
}
}
}else{
if(fields[i].getType().isAssignableFrom(java.util.Date.class)){
if(fieldValueObject==null) {
checkUguaglianza=false; // che fieldValue_this non sia null e' gia' stato controllato sopra
}
else {
java.util.Calendar calendarThis = new java.util.GregorianCalendar();
calendarThis.setTime((java.util.Date)fieldValueThis);
java.util.Calendar calendarObject = new java.util.GregorianCalendar();
calendarObject.setTime((java.util.Date)fieldValueObject);
checkUguaglianza = ( calendarThis.get(java.util.Calendar.YEAR) == calendarObject.get(java.util.Calendar.YEAR) ) &&
( calendarThis.get(java.util.Calendar.MONTH) == calendarObject.get(java.util.Calendar.MONTH) ) &&
( calendarThis.get(java.util.Calendar.DAY_OF_MONTH) == calendarObject.get(java.util.Calendar.DAY_OF_MONTH) ) &&
( calendarThis.get(java.util.Calendar.HOUR_OF_DAY) == calendarObject.get(java.util.Calendar.HOUR_OF_DAY) ) &&
( calendarThis.get(java.util.Calendar.MINUTE) == calendarObject.get(java.util.Calendar.MINUTE) ) &&
( calendarThis.get(java.util.Calendar.SECOND) == calendarObject.get(java.util.Calendar.SECOND) ) &&
( calendarThis.get(java.util.Calendar.MILLISECOND) == calendarObject.get(java.util.Calendar.MILLISECOND) ) ;
}
}else{
checkUguaglianza = fieldValueThis.equals(fieldValueObject);
}
}
resultMethod = checkUguaglianza;
}
if(!resultMethod)
return false;
}
}
}
return true;
}catch(Exception e){
logExceptionStackTrace(e);
throw new UtilsRuntimeException(e.toString(),e);
}
}
/* ********** WRITE TO ********* */
public void writeTo(OutputStream out) throws UtilsException{
this.writeTo(out, WriteToSerializerType.XML_JAXB);
}
public void writeTo(OutputStream out,WriteToSerializerType type) throws UtilsException{
this.writeToEngine(out, type, null);
}
public void writeTo(OutputStream out,WriteToSerializerType type, boolean pretty) throws UtilsException{
this.writeToEngine(out, type, pretty);
}
private void writeToEngine(OutputStream out,WriteToSerializerType type, Boolean pretty) throws UtilsException{
try{
switch (type) {
case XML_JAXB:
boolean xmlPretty = true; /** backward compatibility;*/
if(pretty!=null) {
xmlPretty = pretty.booleanValue();
}
JaxbUtils.objToXml(out, getClass(), this, xmlPretty);
break;
case JSON_JACKSON:
SerializationConfig config = new SerializationConfig();
if(pretty!=null) {
config.setPrettyPrint(pretty.booleanValue());
}
ISerializer jsonJacksonSerializer = SerializationFactory.getSerializer(SERIALIZATION_TYPE.JSON_JACKSON, config);
jsonJacksonSerializer.writeObject(this, out);
break;
case JAVA:
JavaSerializer javaSerializer = new JavaSerializer();
javaSerializer.writeObject(this, out);
break;
}
}catch(Exception e){
throw new UtilsException(e.getMessage(), e);
}
}
/* ********** serialize ********* */
public String toXml() throws UtilsException{
return this.serialize(WriteToSerializerType.XML_JAXB);
}
public String toJson() throws UtilsException{
return this.serialize(WriteToSerializerType.JSON_JACKSON);
}
// Non รจ utile. Al massimo si usa sopra come writeTo
/**public String toJava() throws UtilsException{
return this.serialize(WriteToSerializerType.JAVA);
}*/
public String serialize(WriteToSerializerType type) throws UtilsException{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
this.writeTo(bout, type);
return bout.toString();
}
/* ********** TO STRING ********* */
private static ToStringStyle defaultToStringStyle = ToStringStyle.MULTI_LINE_STYLE;
private static boolean defaultToStringOutputTransients = false;
private static boolean defaultToStringOutputStatics = false;
public static void setDefaultStyleToString(ToStringStyle style,boolean outputTransients,boolean outputStatics){
// Il default statico serve per impostare uno "stile" che viene ereditato da tutti gli oggetti che estendono il base bean.
// In questa maniera gli oggetti interni all'oggetto stesso vengono serializzati con lo stile impostato.
defaultToStringStyle = style;
defaultToStringOutputTransients = outputTransients;
defaultToStringOutputStatics = outputStatics;
}
@Override
public String toString(){
return this.toString(defaultToStringStyle, defaultToStringOutputTransients, defaultToStringOutputStatics, null);
}
public String toString(ToStringStyle style){
return this.toString(style, false, false, null);
}
public String toString(ToStringStyle style,boolean outputTransients,boolean outputStatics){
return this.toString(style, outputTransients, outputStatics, null);
}
public String toString(ToStringStyle style,boolean outputTransients,boolean outputStatics,Class<?>reflectUpToClass){
StringBuilder buffer = new StringBuilder();
this.toString(style, buffer, outputTransients, outputStatics, reflectUpToClass);
return buffer.toString();
}
public void toString(ToStringStyle style,StringBuilder buffer,boolean outputTransients,boolean outputStatics){
this.toString(style, buffer, outputTransients, outputStatics, null);
}
public void toString(ToStringStyle style,StringBuilder buffer,boolean outputTransients,boolean outputStatics,Class<?>reflectUpToClass){
StringBuffer bf = new StringBuffer();
ReflectionToStringBuilder builder = new ReflectionToStringBuilder(this, style, bf, reflectUpToClass, outputTransients, outputStatics);
builder.toString();
buffer.append(bf.toString());
}
// Old Method
public String toString_oldMethod(){
return toStringEngine(false, null);
}
public String toString(boolean reportHTML){
return toStringEngine(reportHTML,null);
}
public String toString(List<String> fieldsNotIncluded){
return toStringEngine(false,fieldsNotIncluded);
}
public String toString(boolean reportHTML,boolean includeLongId){
List<String> fieldsNotIncluded = new ArrayList<>();
if(!includeLongId){
fieldsNotIncluded.add("id");
}
return toStringEngine(reportHTML,fieldsNotIncluded);
}
public String toString(boolean reportHTML,List<String> fieldsNotIncluded){
return toStringEngine(reportHTML,fieldsNotIncluded);
}
private String toStringEngine(boolean reportHTML,List<String> fieldsNotIncluded){
try{
StringBuilder bf = new StringBuilder();
java.lang.reflect.Field[] fields = getClass().getDeclaredFields();
for(int i=0; i<fields.length;i++){
/**System.out.println("["+fields[i].getName()+"]");*/
if(java.lang.reflect.Modifier.isStatic(fields[i].getModifiers())){
/**System.out.println("IS STATIC");*/
continue;
}
if(fields[i].getType().isAssignableFrom(org.openspcoop2.utils.jaxb.DecimalWrapper.class)){
continue;
}
// field id non controllato se in fieldsNotCheckList
boolean ignoreField = false;
if(fieldsNotIncluded!=null && !fieldsNotIncluded.isEmpty()){
for (String fieldName : fieldsNotIncluded) {
if(fieldName.equals(fields[i].getName())){
ignoreField = true;
break;
}
}
}
if(ignoreField){
continue;
}
bf.append("---------- ");
bf.append(this.getClass().getName());
bf.append(".");
bf.append(fields[i].getName());
bf.append(" ----------");
if(reportHTML) bf.append("<br>"); else bf.append("\n");
Object fieldValue = this.getFieldValue(fields[i].getName(),this);
/**System.out.println("LETTO VALORE["+fieldValue+"]");*/
if(fieldValue==null){
bf.append("null");
}else{
if(fields[i].getType().isAssignableFrom(java.util.ArrayList.class) || fields[i].getType().isAssignableFrom(java.util.List.class)){
java.util.List<?> listaThis = (java.util.List<?>) fieldValue;
bf.append("List size("+listaThis.size()+")");
if(!listaThis.isEmpty()){
if(reportHTML) bf.append("<br>"); else bf.append("\n");
}
java.util.List<String> sortLISTKEY = new java.util.ArrayList<>();
for(int j=0; j<listaThis.size(); j++){
String key = null;
if(listaThis.get(j).getClass().getName().startsWith(this.getClass().getPackage().getName())){
Class<?> c = listaThis.get(j).getClass();
java.lang.reflect.Method method = c.getMethod(TO_STRING_METHOD,boolean.class,List.class);
key = (String) method.invoke(listaThis.get(j),reportHTML,fieldsNotIncluded);
}else{
key = listaThis.get(j).toString();
}
sortLISTKEY.add(key);
}
java.util.Collections.sort(sortLISTKEY);
for(int j=0; j<sortLISTKEY.size(); j++){
String key = sortLISTKEY.get(j);
bf.append("---------- ");
bf.append(this.getClass().getName());
bf.append(".");
bf.append(fields[i].getName());
bf.append("[");
bf.append(j);
bf.append("] ----------");
if(reportHTML) bf.append("<br>"); else bf.append("\n");
bf.append(key);
if(reportHTML) bf.append("<br>"); else bf.append("\n");
bf.append("----end--- ");
bf.append(this.getClass().getName());
bf.append(".");
bf.append(fields[i].getName());
bf.append("[");
bf.append(j);
bf.append("] ----end---");
if(reportHTML) bf.append("<br>"); else bf.append("\n");
}
}else{
if(fieldValue.getClass().getName().startsWith(this.getClass().getPackage().getName())){
Class<?> c = fieldValue.getClass();
java.lang.reflect.Method method = c.getMethod(TO_STRING_METHOD,boolean.class,List.class);
bf.append(method.invoke(fieldValue,reportHTML,fieldsNotIncluded));
}else{
if(fields[i].getType().isAssignableFrom(byte[].class)){
byte[] array = (byte[])fieldValue;
for(int k=0; k<array.length;k++){
bf.append(((char)array[k]));
}
}else if(fields[i].getType().isAssignableFrom(java.util.Date.class)){
java.util.Date date = (java.util.Date) fieldValue;
bf.append(DateUtils.getSimpleDateFormatMs().format(date));
}else{
bf.append(fieldValue.toString());
}
}
}
}
if(reportHTML) bf.append("<br>"); else bf.append("\n");
bf.append("---end---- ");
bf.append(this.getClass().getName());
bf.append(".");
bf.append(fields[i].getName());
bf.append(" ---end----");
if(reportHTML) bf.append("<br>"); else bf.append("\n");
}
return bf.toString();
}catch(Exception e){
logExceptionStackTrace(e);
throw new UtilsRuntimeException(e.toString(),e);
}
}
/* ********** DIFF ********* */
public String diff(Object object,StringBuilder bf){
return diffEngine(object,bf,false, null);
}
public String diff(Object object,StringBuilder bf,boolean reportHTML){
return diffEngine(object,bf,reportHTML,null);
}
public String diff(Object object,StringBuilder bf,List<String> fieldsNotIncluded){
return diffEngine(object,bf,false,fieldsNotIncluded);
}
public String diff(Object object,StringBuilder bf,boolean reportHTML,boolean includeLongId){
List<String> fieldsNotIncluded = new ArrayList<>();
if(!includeLongId){
fieldsNotIncluded.add("id");
}
return diffEngine(object,bf,reportHTML,fieldsNotIncluded);
}
public String diff(Object object,StringBuilder bf,boolean reportHTML,List<String> fieldsNotIncluded){
return diffEngine(object,bf,reportHTML,fieldsNotIncluded);
}
@SuppressWarnings("unchecked")
private String diffEngine(Object object,StringBuilder bf,boolean reportHTML,List<String> fieldsNotIncluded){
try{
if(object==null){
bf.append(this.getClass().getName());
bf.append("this is not null, parameter is null");
return bf.toString();
}
java.lang.reflect.Field[] fields = getClass().getDeclaredFields();
for(int i=0; i<fields.length;i++){
/**System.out.println("["+fields[i].getName()+"]");*/
if(java.lang.reflect.Modifier.isStatic(fields[i].getModifiers())){
/**System.out.println("IS STATIC");*/
continue;
}
if(fields[i].getType().isAssignableFrom(org.openspcoop2.utils.jaxb.DecimalWrapper.class)){
continue;
}
Object fieldValueThis = this.getFieldValue(fields[i].getName(),this);
Object fieldValueObject = this.getFieldValue(fields[i].getName(),object);
if(fields[i].getType().isAssignableFrom(java.util.ArrayList.class) || fields[i].getType().isAssignableFrom(java.util.List.class)){
// LISTA
java.util.List<?> listaThis = (java.util.List<?>) fieldValueThis;
java.util.List<?> listaParameter = (java.util.List<?>) fieldValueObject;
if(listaThis==null){
// this_list is null, parameter list is not null
if(listaParameter!=null){
bf.append(this.getClass().getName());
bf.append(".");
bf.append(fields[i].getName());
bf.append(" this_list:is null, parameter_list: is not null");
bf.append(" ,parameter_list_size:"+listaParameter.size());
if(reportHTML) bf.append("<br>"); else bf.append("\n");
}
}else{
// this_list is not null, parameter list is null
if(listaParameter==null){
bf.append(this.getClass().getName());
bf.append(".");
bf.append(fields[i].getName());
bf.append(" this_list: is not null, parameter_list: is null");
bf.append(" ,this_list_size:"+listaThis.size());
if(reportHTML) bf.append("<br>"); else bf.append("\n");
}
// this_list different size from parameter_list
else if(listaThis.size() != listaParameter.size()){
bf.append(this.getClass().getName());
bf.append(".");
bf.append(fields[i].getName());
bf.append(" this_list_size:"+listaThis.size()+", parameter_list_size:"+listaParameter.size());
if(reportHTML) bf.append("<br>"); else bf.append("\n");
}
// Controllo elementi della lista
else{
// SORT
java.util.List<Object> listaThisSORT = new java.util.ArrayList<>();
java.util.List<Object> listaParameterSORT = new java.util.ArrayList<>();
boolean listaNonCompleta = false;
try{
java.util.List<String> listaThisTMP = new java.util.ArrayList<>();
java.util.Map<String, Object> thisTmp = new java.util.HashMap<>();
java.util.Map<String, Object> parameterTmp = new java.util.HashMap<>();
for(int k=0; k<listaThis.size(); k++){
Object thisObject = listaThis.get(k);
Object paramObject = listaParameter.get(k);
if(thisObject==null && paramObject!=null)
throw new UtilsException("DIFF");
if(thisObject!=null && paramObject==null)
throw new UtilsException("DIFF");
if(thisObject!=null && paramObject!=null){
// THIS
String key = null;
if(thisObject.getClass().getName().startsWith(this.getClass().getPackage().getName())){
Class<?> c = thisObject.getClass();
java.lang.reflect.Method method = c.getMethod(TO_STRING_METHOD,boolean.class,boolean.class);
key = (String) method.invoke(thisObject,false,true);
}else{
key = thisObject.toString();
}
thisTmp.put(key, thisObject);
listaThisTMP.add(key);
// PARAM
if(paramObject.getClass().getName().startsWith(this.getClass().getPackage().getName())){
Class<?> c = paramObject.getClass();
java.lang.reflect.Method method = c.getMethod(TO_STRING_METHOD,boolean.class,boolean.class);
key = (String) method.invoke(paramObject,false,true);
}else{
key = paramObject.toString();
}
parameterTmp.put(key, paramObject);
}
}
java.util.Collections.sort(listaThisTMP);
for(int k=0; k<listaThisTMP.size(); k++){
String key = listaThisTMP.get(k);
Object thisObject = thisTmp.get(key);
Object paramObject = parameterTmp.get(key);
if(thisObject==null){
// significa che manca un elemento
listaThisSORT = (java.util.List<Object>) listaThis;
listaParameterSORT = (java.util.List<Object>) listaParameter;
bf.append("["+this.getClass().getName());
bf.append(".");
bf.append(fields[i].getName()+"] ");
bf.append("Match non trovato in this(size:"+thisTmp.size()+") per l'elemento: "+key);
if(!thisTmp.isEmpty()) {
int j=0;
for (String keyJ : thisTmp.keySet()) {
bf.append("ELEMENTO_THIS_["+j+"]=["+keyJ+"]");
j++;
}
}
listaNonCompleta = true;
break;
}
if(paramObject==null){
// significa che manca un elemento
listaThisSORT = (java.util.List<Object>) listaThis;
listaParameterSORT = (java.util.List<Object>) listaParameter;
bf.append("["+this.getClass().getName());
bf.append(".");
bf.append(fields[i].getName()+"] ");
bf.append("Match non trovato in param(size:"+parameterTmp.size()+") per l'elemento: "+key);
if(!parameterTmp.isEmpty()) {
int j=0;
for (String keyJ : parameterTmp.keySet()) {
bf.append("ELEMENTO_PARAM_["+j+"]=["+keyJ+"]");
j++;
}
}
listaNonCompleta = true;
break;
}
listaThisSORT.add(thisObject);
listaParameterSORT.add(paramObject);
}
}
catch(RuntimeException e){
// By SpotBugs
listaParameterSORT = (java.util.List<Object>) listaParameter;
listaThisSORT = (java.util.List<Object>) listaThis;
}
catch(Exception e){
listaThisSORT = (java.util.List<Object>) listaThis;
listaParameterSORT = (java.util.List<Object>) listaParameter;
}
if(!listaNonCompleta){
for(int j=0; j<listaThisSORT.size(); j++){
if(listaThisSORT.get(j)==null){
bf.append(this.getClass().getName());
bf.append(".");
bf.append(fields[i].getName()+"["+j+"]");
bf.append(" this_list: is null, parameter: is not null");
bf.append(" parameter_value:");
if(reportHTML) bf.append("<br>"); else bf.append("\n");
if(listaParameterSORT.get(j).getClass().getName().startsWith(this.getClass().getPackage().getName())){
Class<?> c = listaParameterSORT.get(j).getClass();
java.lang.reflect.Method method = c.getMethod(TO_STRING_METHOD,boolean.class);
bf.append(method.invoke(listaParameterSORT.get(j),reportHTML));
}else{
bf.append(listaParameterSORT.get(j).toString());
}
if(reportHTML) bf.append("<br>"); else bf.append("\n");
}else{
if(listaThisSORT.get(j).getClass().getName().startsWith(this.getClass().getPackage().getName())){
Class<?> c = listaThisSORT.get(j).getClass();
java.lang.reflect.Method method = c.getMethod("diff",Object.class,bf.getClass(),boolean.class,List.class);
method.invoke(listaThisSORT.get(j),listaParameterSORT.get(j),bf,reportHTML,fieldsNotIncluded);
}else{
boolean checkUguaglianza = false;
if(listaThisSORT.get(j).getClass().isAssignableFrom(byte[].class)){
if(listaParameterSORT.get(j)!=null){
byte[] origi = (byte[]) listaThisSORT.get(j);
byte[] dest = (byte[]) listaParameterSORT.get(j);
checkUguaglianza = (origi.length == dest.length);
if(checkUguaglianza){
for(int k=0;k<origi.length;k++){
if(origi[k]!=dest[k]){
checkUguaglianza = false;
break;
}
}
}
}
}else{
checkUguaglianza = listaThisSORT.get(j).equals(listaParameterSORT.get(j));
}
if(!checkUguaglianza){
bf.append(this.getClass().getName());
bf.append(".");
bf.append(fields[i].getName()+"["+j+"]");
bf.append(" this:");
if(listaThisSORT.get(j).getClass().isAssignableFrom(byte[].class)){
if(listaThisSORT.get(j)!=null){
byte[] array = (byte[])listaThisSORT.get(j);
for(int k=0; k<array.length;k++)
bf.append(((char)array[k]));
}
else
bf.append("null");
}else if(listaThisSORT.get(j).getClass().isAssignableFrom(java.util.Date.class)){
if(listaThisSORT.get(j)!=null){
java.util.Date date = (java.util.Date) listaThisSORT.get(j);
bf.append(DateUtils.getSimpleDateFormatMs().format(date));
}
else
bf.append("null");
}else{
bf.append(listaThisSORT.get(j));
}
bf.append(" parameter:");
if(listaParameterSORT.get(j).getClass().isAssignableFrom(byte[].class)){
if(listaParameterSORT.get(j)!=null){
byte[] array = (byte[])listaParameterSORT.get(j);
for(int k=0; k<array.length;k++)
bf.append(((char)array[k]));
}
else
bf.append("null");
}else if(listaParameterSORT.get(j).getClass().isAssignableFrom(java.util.Date.class)){
if(listaParameterSORT.get(j)!=null){
java.util.Date date = (java.util.Date) listaParameterSORT.get(j);
bf.append(DateUtils.getSimpleDateFormatMs().format(date));
}
else
bf.append("null");
}else{
bf.append(listaParameterSORT.get(j));
}
if(reportHTML) bf.append("<br>"); else bf.append("\n");
}
}
}
}
}
}
}
}
else{
// field id non controllato se in fieldsNotCheckList
boolean ignoreField = false;
if(fieldsNotIncluded!=null && !fieldsNotIncluded.isEmpty()){
for (String fieldName : fieldsNotIncluded) {
if(fieldName.equals(fields[i].getName())){
ignoreField = true;
break;
}
}
}
if(ignoreField){
continue;
}
// ELEMENTO SINGOLO
if(fieldValueThis==null){
// this is null, parameter is not null
if(fieldValueObject!=null){
bf.append(this.getClass().getName());
bf.append(".");
bf.append(fields[i].getName());
bf.append(" this:is null, parameter: is not null");
bf.append(" parameter_value:");
if(reportHTML) bf.append("<br>"); else bf.append("\n");
if(fieldValueObject.getClass().getName().startsWith(this.getClass().getPackage().getName())){
Class<?> c = fieldValueObject.getClass();
java.lang.reflect.Method method = c.getMethod(TO_STRING_METHOD,boolean.class);
bf.append(method.invoke(fieldValueObject,reportHTML));
}else{
if(fields[i].getType().isAssignableFrom(byte[].class)){
byte[] array = (byte[])fieldValueObject;
for(int k=0; k<array.length;k++)
bf.append(array[k]);
}else if(fields[i].getType().isAssignableFrom(java.util.Date.class)){
java.util.Date date = (java.util.Date) fieldValueObject;
bf.append(DateUtils.getSimpleDateFormatMs().format(date));
}else{
bf.append(fieldValueObject);
}
}
if(reportHTML) bf.append("<br>"); else bf.append("\n");
}
}else{
if(fields[i].getType().getName().startsWith(this.getClass().getPackage().getName())){
java.lang.reflect.Method method = fields[i].getType().getMethod("diff",Object.class,bf.getClass(),boolean.class,List.class);
method.invoke(fieldValueThis,fieldValueObject,bf,reportHTML,fieldsNotIncluded);
}else{
boolean checkUguaglianza = false;
if(fields[i].getType().isAssignableFrom(byte[].class)){
if(fieldValueObject!=null){
byte[] origi = (byte[]) fieldValueThis;
byte[] dest = (byte[]) fieldValueObject;
checkUguaglianza = (origi.length == dest.length);
if(checkUguaglianza){
for(int k=0;k<origi.length;k++){
if(origi[k]!=dest[k]){
checkUguaglianza = false;
break;
}
}
}
}
}else{
if(fields[i].getType().isAssignableFrom(java.util.Date.class)){
if(fieldValueObject!=null){
java.util.Calendar calendarThis = new java.util.GregorianCalendar();
calendarThis.setTime((java.util.Date)fieldValueThis);
java.util.Calendar calendarObject = new java.util.GregorianCalendar();
calendarObject.setTime((java.util.Date)fieldValueObject);
checkUguaglianza = ( calendarThis.get(java.util.Calendar.YEAR) == calendarObject.get(java.util.Calendar.YEAR) ) &&
( calendarThis.get(java.util.Calendar.MONTH) == calendarObject.get(java.util.Calendar.MONTH) ) &&
( calendarThis.get(java.util.Calendar.DAY_OF_MONTH) == calendarObject.get(java.util.Calendar.DAY_OF_MONTH) ) &&
( calendarThis.get(java.util.Calendar.HOUR_OF_DAY) == calendarObject.get(java.util.Calendar.HOUR_OF_DAY) ) &&
( calendarThis.get(java.util.Calendar.MINUTE) == calendarObject.get(java.util.Calendar.MINUTE) ) &&
( calendarThis.get(java.util.Calendar.SECOND) == calendarObject.get(java.util.Calendar.SECOND) ) &&
( calendarThis.get(java.util.Calendar.MILLISECOND) == calendarObject.get(java.util.Calendar.MILLISECOND) );
}
}else{
checkUguaglianza = fieldValueThis.equals(fieldValueObject);
}
}
if(!checkUguaglianza){
bf.append(this.getClass().getName());
bf.append(".");
bf.append(fields[i].getName());
bf.append(" this:");
if(fields[i].getType().isAssignableFrom(byte[].class)){
byte[] array = (byte[])fieldValueThis;
for(int k=0; k<array.length;k++)
bf.append(((char)array[k]));
}else if(fields[i].getType().isAssignableFrom(java.util.Date.class)){
java.util.Date date = (java.util.Date) fieldValueThis;
bf.append(DateUtils.getSimpleDateFormatMs().format(date));
}else{
bf.append(fieldValueThis);
}
bf.append(" parameter:");
if(fields[i].getType().isAssignableFrom(byte[].class)){
if(fieldValueObject!=null){
byte[] array = (byte[])fieldValueObject;
for(int k=0; k<array.length;k++)
bf.append(((char)array[k]));
}
else
bf.append("null");
}else if(fields[i].getType().isAssignableFrom(java.util.Date.class)){
if(fieldValueObject!=null){
java.util.Date date = (java.util.Date) fieldValueObject;
bf.append(DateUtils.getSimpleDateFormatMs().format(date));
}else
bf.append("null");
}else{
bf.append(fieldValueObject);
}
if(reportHTML) bf.append("<br>"); else bf.append("\n");
}
}
}
}
}
return bf.toString();
}catch(Exception e){
logExceptionStackTrace(e);
throw new UtilsRuntimeException(e.toString(),e);
}
}
/* ********** CLONE ********* */
@Override
public Object clone() {
Object clone = null;
try{
//clono l'oggetto
clone = super.clone();
//clone = this.getClass().newInstance(); NON FUNZIONA NON VENGONO COPIATI I VARI FIELDS
/*
* Per ogni field se il field presente nella classe implementa
* l'interfaccia cloneable allora eseguo il metodo clone di quel field
*/
java.lang.reflect.Field[] fields = this.getClass().getDeclaredFields();
if(fields!=null && fields.length>0){
for (int i = 0; i < fields.length; i++) {
/**System.out.println("["+fields[i].getName()+"]");*/
if(java.lang.reflect.Modifier.isStatic(fields[i].getModifiers())){
/**System.out.println("IS STATIC");*/
continue;
}
if(fields[i].getType().isAssignableFrom(org.openspcoop2.utils.jaxb.DecimalWrapper.class)){
continue;
}
java.lang.reflect.Field field = fields[i];
Object fieldValue = this.getFieldValue(field.getName(), this);
if(fieldValue==null){
continue;
}
/**System.out.println("ESAMINO FIELD ["+field.getName()+"] type["+field.getType().getName()+"] isEnum["+(field.getType().isEnum())+"]");*/
if(field.getType().isAssignableFrom(byte[].class)){
//caso particolare arrya di byte
byte[] originale = (byte[]) fieldValue;
if(originale!=null){
byte[] arrayClone = new byte[originale.length];
for (int j = 0; j < arrayClone.length; j++) {
arrayClone[j]=originale[j];
}
this.setFieldValue(field.getName(), clone, field.getType(), arrayClone);
}
}
else if(field.getType().isEnum()){
// Imposto nel nuovo oggetto il valore dell'enum
//setto il field clonato nel clone
this.setFieldValue(field.getName(), clone, field.getType(), fieldValue);
}
else if(isSupportedCloneList(field)){
List<?> listOriginale = (List<?>) fieldValue;
if(listOriginale!=null){
List<?> listClone = this.cloneList(listOriginale);
//setto il field clonato nel clone
this.setFieldValue(field.getName(), clone, field.getType(), listClone);
}
}
else {
//recupero interfacce implementate da questo field
Class<?>[] interfacce = field.getType().getInterfaces();
for (int j = 0; j < interfacce.length; j++) {
//se il field che sto controllando implementa l'interfaccia cloneable e il field che voglio clonare non e' null
//richiamo il clone
if(interfacce[j].isAssignableFrom(java.lang.Cloneable.class) && fieldValue!=null ){
//recupero il metodo clone dal field
java.lang.reflect.Method method = field.getType().getMethod("clone");
//effettuo il clone del field
java.lang.Cloneable ris = (java.lang.Cloneable) method.invoke(fieldValue);
//setto il field clonato nel clone
this.setFieldValue(field.getName(), clone, field.getType(), ris);
}
}
}
}
}
}catch (Exception e) {
logExceptionStackTrace(e);
throw new UtilsRuntimeException(e.toString(),e);
}
return clone;
}
private boolean isSupportedCloneList(java.lang.reflect.Field field){
return field.getType().isAssignableFrom(java.util.List.class) ||
field.getType().isAssignableFrom(java.util.ArrayList.class) ||
field.getType().isAssignableFrom(java.util.Vector.class) ||
field.getType().isAssignableFrom(java.util.Stack.class) ||
field.getType().isAssignableFrom(java.util.LinkedList.class) ||
field.getType().isAssignableFrom(java.util.concurrent.CopyOnWriteArrayList.class);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private List cloneList(List<?> listOriginale) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
List listClone = null;
if(listOriginale.getClass().isAssignableFrom(java.util.ArrayList.class)){
listClone = new java.util.ArrayList<>();
}
else if(listOriginale.getClass().isAssignableFrom(java.util.Vector.class)){
listClone = new java.util.Vector<>();
}
else if(listOriginale.getClass().isAssignableFrom(java.util.Stack.class)){
listClone = new java.util.Stack<>();
}
else if(listOriginale.getClass().isAssignableFrom(java.util.LinkedList.class)){
listClone = new java.util.LinkedList<>();
}
else if(listOriginale.getClass().isAssignableFrom(java.util.concurrent.CopyOnWriteArrayList.class)){
listClone = new java.util.concurrent.CopyOnWriteArrayList<>();
}
if(listClone!=null){
for (int j = 0; j < listOriginale.size(); j++) {
Object oOriginale = listOriginale.get(j);
if(oOriginale!=null){
if(oOriginale instanceof java.lang.Cloneable){
//recupero il metodo clone dal field
java.lang.reflect.Method method = oOriginale.getClass().getMethod("clone");
//effettuo il clone del field
java.lang.Cloneable oCloned = (java.lang.Cloneable) method.invoke(oOriginale);
//aggiungo il field clonato nella lista
listClone.add(oCloned);
}
else if(oOriginale instanceof String) {
String sOriginale = (String) oOriginale;
String sCloned = new String(sOriginale.toCharArray());
//aggiungo il field clonato nella lista
listClone.add(sCloned);
}
}
else{
listClone.add(null);
}
}
}
return listClone;
}
}