/*
* � Copyright IBM Corp. 2013
*
* Licensed 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.
*/
/*
* Author: Maire Kehoe (mkehoe@ie.ibm.com)
* Date: 27 Apr 2011
* SerializationFullComparator.java
*/
package com.ibm.xsp.test.framework.serialize;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Comparator;
import javax.faces.component.UIComponent;
import javax.faces.component.UIOutput;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import junit.framework.Assert;
import com.ibm.commons.util.StringUtil;
import com.ibm.xsp.binding.ComponentBindingObject;
import com.ibm.xsp.test.framework.XspTestUtil;
import com.sun.faces.context.FacesContextImpl;
public class SerializationFullComparator implements Comparator<Object> {
private static final boolean TRACE = false;
private SerializationCompareContext context;
public SerializationFullComparator(SerializationCompareContext context) {
this.context = context;
}
public int compare(Object comp1, Object comp2) {
String fails = compareWithFailsResult(comp1, comp2);
if( fails.length() == 0 ){
return 0;
}
Assert.fail(fails);
return -1;
}
/**
* @param comp1
* @param comp2
* @return
*/
public String compareWithFailsResult(Object comp1, Object comp2) {
String viewId = (null == context.message?
getViewId(context.createContext.getViewRoot())
: context.message);
// compare classnames
if (comp1.getClass() != comp2.getClass()) {
return (viewId + " " + comp1.getClass().getName() + " != "
+ comp2.getClass().getName());
}
if( comp1 instanceof UIComponent ){
// compare ids
if ( ! StringUtil.equals(((UIComponent)comp1).getId(), ((UIComponent)comp2).getId()) ) {
return (viewId + " id mismatch ");
}
}
String fails = "";
// compare getter results
Method[] methods = comp1.getClass().getMethods();
Object[] noargs = new Object[0];
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
if (!isSimpleGetter(method) || context.isSkipMethod(comp1.getClass(),method.getName())) {
continue;
}
if( comp1 instanceof ComponentBindingObject && "getComponent".equals(method.getName()) ){
continue;
}
if( comp1 instanceof UIOutput && "getValue".equals(method.getName())
&& ((UIOutput)comp1).getValueBinding("value") != null){
// output control value is computed or bound, don't compare
continue;
}
if( comp1 instanceof UIComponent && ("getChildren".equals(method.getName())
|| "getFacets".equals(method.getName())) ){
// finish iterating through the rest of the control methods
// before moving on to facet & child controls after this for loop.
continue;
}
try {
setCurrentContext(context.createContext);
Object value1;
try{
value1 = method.invoke(comp1, noargs);
}catch( InvocationTargetException inMethodEx){
// compare that the exceptions are equal
value1 = inMethodEx.getTargetException();
}
setCurrentContext(context.restoreContext);
Object value2;
try{
value2 = method.invoke(comp2, noargs);
}catch( InvocationTargetException inMethodEx){
// compare that the exceptions are equal
value2 = inMethodEx.getTargetException();
}
if (value1 instanceof UIComponent
&& !("getChildren".equals(method.getName())
|| "getFacets".equals(method.getName()))) {
if( TRACE ){
System.err.println("SerializationFullComparator.compare() method returned UIComponent: "
+ XspTestUtil.getShortClass(comp1)
+ "."
+ method.getName() + "() in " + viewId + " Not comparing.");
}
continue;
}
String failMsg = viewId
+ " "
+ XspTestUtil.getShortClass(comp1.getClass()
) + "." + method.getName() + "()";
fails += SerializationStructureCompare.compareWithFailsResult(
context, failMsg,
method.getName(), value1, value2
);
}
catch (Exception e) {
System.err.println("EXCEPTION Handling: " + method.getName() + " for " + viewId);
e.printStackTrace();
String problem = XspTestUtil.getShortClass(e)
+ " comparing "
+ method.getName()
+ "(): "
+ e.getMessage();
if( null != e.getMessage() && e.getMessage().startsWith(viewId) ){
// do not prefix;
}else if( ! (comp1 instanceof UIComponent) ){
problem = viewId +" "+ problem;
}
fails += problem;
}
}
if( comp1 instanceof UIComponent && comp2 instanceof UIComponent ){
UIComponent uiComp1 = (UIComponent) comp1;
UIComponent uiComp2 = (UIComponent) comp2;
char[] treeStructureMethods = {'f','c'}; // getFacets, getChildren
for (char treeStructureMethodChar : treeStructureMethods) {
String methodName = (treeStructureMethodChar == 'f')? "getFacets":"getChildren";
try {
setCurrentContext(context.createContext);
Object value1 = (treeStructureMethodChar == 'f')? uiComp1.getFacets() : uiComp1.getChildren();
setCurrentContext(context.restoreContext);
Object value2 = (treeStructureMethodChar == 'f')? uiComp2.getFacets() : uiComp2.getChildren();
String failMsg = viewId + " " + XspTestUtil.getShortClass(comp1.getClass()) + "." + methodName + "()";
fails += SerializationStructureCompare.compareWithFailsResult(
context, failMsg,
methodName, value1, value2
);
}
catch (Exception e) {
System.err.println("EXCEPTION Handling: " + methodName + " for " + viewId);
e.printStackTrace();
String problem = XspTestUtil.getShortClass(e)+ " comparing "+ methodName+ "(): "+ e.getMessage();
if( null != e.getMessage() && e.getMessage().startsWith(viewId) ){
// do not prefix;
}else if( ! (comp1 instanceof UIComponent) ){
problem = viewId +" "+ problem;
}
fails += problem;
}
}
}
return fails;
}
static private boolean isSimpleGetter(Method method) {
if ((method.getModifiers() & Modifier.PUBLIC) != Modifier.PUBLIC) {
return false;
}
if (method.getParameterTypes().length != 0) {
return false;
}
String name = method.getName();
if (!(name.startsWith("get") || name.startsWith("is"))) {
return false;
}
return true;
}
private static String getViewId(UIComponent c) {
if (c instanceof UIViewRoot) {
return ((UIViewRoot) c).getViewId();
} else if (c == null) {
return "null";
} else {
return getViewId(c.getParent());
}
}
private static void setCurrentContext(final FacesContext context){
new FacesContextImpl(){
{
setCurrentInstance(context);
}
}.getClass(); // getClass to prevent warning: The allocated object is never used
}
}