/*
* *************************************************************************************
* Copyright (C) 2008 EsperTech, Inc. All rights reserved. *
* http://esper.codehaus.org *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
* *************************************************************************************
*/
package com.espertech.esper.support.event;
import com.espertech.esper.client.*;
import com.espertech.esper.client.scopetest.EPAssertionUtil;
import com.espertech.esper.util.JavaClassHelper;
import junit.framework.Assert;
import java.io.StringWriter;
import java.util.*;
import java.lang.reflect.Array;
import org.w3c.dom.NodeList;
public class EventTypeAssertionUtil
{
public static void assertConsistency(EventBean eventBean)
{
assertConsistencyRecusive(eventBean, new HashSet<EventType>());
}
public static void assertConsistency(EventType eventType)
{
assertConsistencyRecursive(eventType, new HashSet<EventType>());
}
public static String print(EventBean theEvent)
{
StringWriter writer = new StringWriter();
print(theEvent, writer, 0, new Stack<String>());
return writer.toString();
}
private static void print(EventBean theEvent, StringWriter writer, int indent, Stack<String> propertyStack)
{
writeIndent(writer, indent);
writer.append("Properties : \n");
printProperties(theEvent, writer, indent + 2, propertyStack);
// count fragments
int countFragments = 0;
for (EventPropertyDescriptor desc : theEvent.getEventType().getPropertyDescriptors())
{
if (desc.isFragment())
{
countFragments++;
}
}
if (countFragments == 0)
{
return;
}
writeIndent(writer, indent);
writer.append("Fragments : (" + countFragments + ") \n");
for (EventPropertyDescriptor desc : theEvent.getEventType().getPropertyDescriptors())
{
if (!desc.isFragment())
{
continue;
}
writeIndent(writer, indent + 2);
writer.append(desc.getPropertyName());
writer.append(" : ");
if (desc.isRequiresIndex())
{
writer.append("\n");
int count = 0;
while(true){
try
{
writeIndent(writer, indent + 4);
writer.append("bean #");
writer.append(Integer.toString(count));
EventBean result = (EventBean) theEvent.getFragment(desc.getPropertyName() + "[" + count + "]");
if (result == null)
{
writer.append("(null EventBean)\n");
}
else
{
writer.append("\n");
propertyStack.push(desc.getPropertyName());
print(result, writer, indent + 6, propertyStack);
propertyStack.pop();
}
count++;
}
catch (PropertyAccessException ex)
{
writer.append("-- no access --\n");
break;
}
}
}
else
{
Object fragment = theEvent.getFragment(desc.getPropertyName());
if (fragment == null)
{
writer.append("(null)\n");
continue;
}
if (fragment instanceof EventBean)
{
EventBean fragmentBean = (EventBean)fragment;
writer.append("EventBean type ");
writer.append(fragmentBean.getEventType().getName());
writer.append("...\n");
// prevent getThis() loops
if (fragmentBean.getEventType() == theEvent.getEventType())
{
writeIndent(writer, indent + 2);
writer.append("Skipping");
}
else
{
propertyStack.push(desc.getPropertyName());
print(fragmentBean, writer, indent + 4, propertyStack);
propertyStack.pop();
}
}
else
{
EventBean[] fragmentBeans = (EventBean[])fragment;
writer.append("EventBean[] type ");
if (fragmentBeans.length == 0)
{
writer.append("(empty array)\n");
}
else
{
writer.append(fragmentBeans[0].getEventType().getName());
writer.append("...\n");
for (int i = 0; i < fragmentBeans.length; i++)
{
writeIndent(writer, indent + 4);
writer.append("bean #" + i + "...\n");
propertyStack.push(desc.getPropertyName());
print(fragmentBeans[i], writer, indent + 6, propertyStack);
propertyStack.pop();
}
}
}
}
}
}
private static void printProperties(EventBean eventBean, StringWriter writer, int indent, Stack<String> propertyStack)
{
EventPropertyDescriptor properties[] = eventBean.getEventType().getPropertyDescriptors();
// write simple properties
for (int i = 0; i < properties.length; i++)
{
String propertyName = properties[i].getPropertyName();
if (properties[i].isIndexed() || properties[i].isMapped())
{
continue;
}
writeIndent(writer, indent);
writer.append(propertyName);
writer.append(" : ");
Object resultGet = eventBean.get(propertyName);
writeValue(writer, resultGet);
writer.append("\n");
}
// write indexed properties
for (int i = 0; i < properties.length; i++)
{
String propertyName = properties[i].getPropertyName();
if (!properties[i].isIndexed())
{
continue;
}
writeIndent(writer, indent);
writer.append(propertyName);
String type = "array";
if (properties[i].isRequiresIndex())
{
type = type + " requires-index";
}
writer.append(" (" + type + ") : ");
if (properties[i].isRequiresIndex())
{
int count = 0;
writer.append("\n");
while(true){
try
{
writeIndent(writer, indent + 2);
writer.append("#");
writer.append(Integer.toString(count));
writer.append(" ");
Object result = eventBean.get(propertyName + "[" + count + "]");
writeValue(writer, result);
writer.append("\n");
count++;
}
catch (PropertyAccessException ex)
{
writer.append("-- no access --\n");
break;
}
}
}
else
{
Object result = eventBean.get(propertyName);
writeValue(writer, result);
writer.append("\n");
}
}
// write mapped properties
for (int i = 0; i < properties.length; i++)
{
String propertyName = properties[i].getPropertyName();
if (!properties[i].isMapped())
{
continue;
}
writeIndent(writer, indent);
writer.append(propertyName);
String type = "mapped";
if (properties[i].isRequiresMapkey())
{
type = type + " requires-mapkey";
}
writer.append(" (" + type + ") : ");
if (!properties[i].isRequiresMapkey())
{
Object result = eventBean.get(propertyName);
writeValue(writer, result);
writer.append("\n");
}
else
{
writer.append("??map key unknown??\n");
}
}
}
private static void assertConsistencyRecusive(EventBean eventBean, Set<EventType> alreadySeenTypes)
{
assertConsistencyRecursive(eventBean.getEventType(), alreadySeenTypes);
EventPropertyDescriptor properties[] = eventBean.getEventType().getPropertyDescriptors();
for (int i = 0; i < properties.length; i++)
{
String failedMessage = "failed assertion for property '" + properties[i].getPropertyName() + "' ";
String propertyName = properties[i].getPropertyName();
// assert getter
if ((!properties[i].isRequiresIndex()) && (!properties[i].isRequiresMapkey()))
{
EventPropertyGetter getter = eventBean.getEventType().getGetter(propertyName);
Object resultGetter = getter.get(eventBean);
Object resultGet = eventBean.get(propertyName);
if ((resultGetter == null) && (resultGet == null))
{
// fine
}
else if (resultGet instanceof NodeList)
{
Assert.assertEquals(failedMessage, ((NodeList)resultGet).getLength(), ((NodeList)resultGetter).getLength());
}
else if (resultGet.getClass().isArray())
{
Assert.assertEquals(failedMessage, Array.getLength(resultGet), Array.getLength(resultGetter));
}
else
{
Assert.assertEquals(failedMessage, resultGet, resultGetter);
}
if (resultGet != null)
{
Assert.assertTrue(failedMessage, JavaClassHelper.isSubclassOrImplementsInterface(resultGet.getClass(), properties[i].getPropertyType()));
}
}
// fragment
if (!properties[i].isFragment())
{
Assert.assertNull(failedMessage, eventBean.getFragment(propertyName));
continue;
}
Object fragment = eventBean.getFragment(propertyName);
Assert.assertNotNull(failedMessage, fragment);
FragmentEventType fragmentType = eventBean.getEventType().getFragmentType(propertyName);
Assert.assertNotNull(failedMessage, fragmentType);
if (!fragmentType.isIndexed())
{
Assert.assertTrue(failedMessage, fragment instanceof EventBean);
EventBean fragmentEvent = (EventBean) fragment;
assertConsistencyRecusive(fragmentEvent, alreadySeenTypes);
}
else
{
Assert.assertTrue(failedMessage, fragment instanceof EventBean[]);
EventBean[] events = (EventBean[]) fragment;
Assert.assertTrue(failedMessage, events.length > 0);
for (EventBean theEvent : events)
{
assertConsistencyRecusive(theEvent, alreadySeenTypes);
}
}
}
}
private static void assertConsistencyRecursive(EventType eventType, Set<EventType> alreadySeenTypes)
{
if (alreadySeenTypes.contains(eventType))
{
return;
}
alreadySeenTypes.add(eventType);
assertConsistencyProperties(eventType);
// test fragments
for (EventPropertyDescriptor descriptor : eventType.getPropertyDescriptors())
{
String failedMessage = "failed assertion for property '" + descriptor.getPropertyName() + "' ";
if (!descriptor.isFragment())
{
Assert.assertNull(failedMessage, eventType.getFragmentType(descriptor.getPropertyName()));
continue;
}
FragmentEventType fragment = eventType.getFragmentType(descriptor.getPropertyName());
if (!descriptor.isRequiresIndex())
{
Assert.assertNotNull(failedMessage, fragment);
if (fragment.isIndexed())
{
Assert.assertTrue(descriptor.isIndexed());
}
assertConsistencyRecursive(fragment.getFragmentType(), alreadySeenTypes);
}
else
{
fragment = eventType.getFragmentType(descriptor.getPropertyName() + "[0]");
Assert.assertNotNull(failedMessage, fragment);
Assert.assertTrue(descriptor.isIndexed());
assertConsistencyRecursive(fragment.getFragmentType(), alreadySeenTypes);
}
}
}
private static void assertConsistencyProperties(EventType eventType)
{
List<String> propertyNames = new ArrayList<String>();
EventPropertyDescriptor properties[] = eventType.getPropertyDescriptors();
for (int i = 0; i < properties.length; i++)
{
String propertyName = properties[i].getPropertyName();
propertyNames.add(propertyName);
String failedMessage = "failed assertion for property '" + propertyName + "' ";
// assert presence of descriptor
Assert.assertSame(properties[i], eventType.getPropertyDescriptor(propertyName));
// test properties that can simply be in a property expression
if ((!properties[i].isRequiresIndex()) && (!properties[i].isRequiresMapkey()))
{
Assert.assertTrue(failedMessage, eventType.isProperty(propertyName));
Assert.assertSame(failedMessage, eventType.getPropertyType(propertyName), properties[i].getPropertyType());
Assert.assertNotNull(failedMessage, eventType.getGetter(propertyName));
}
// test indexed property
if (properties[i].isIndexed())
{
String propertyNameIndexed = propertyName + "[0]";
Assert.assertTrue(failedMessage, eventType.isProperty(propertyNameIndexed));
Assert.assertNotNull(failedMessage, eventType.getPropertyType(propertyNameIndexed));
Assert.assertNotNull(failedMessage, eventType.getGetter(propertyNameIndexed));
}
// test mapped property
if (properties[i].isRequiresMapkey())
{
String propertyNameMapped = propertyName + "('a')";
Assert.assertTrue(failedMessage, eventType.isProperty(propertyNameMapped));
Assert.assertNotNull(failedMessage, eventType.getPropertyType(propertyNameMapped));
Assert.assertNotNull(failedMessage, eventType.getGetter(propertyNameMapped));
}
// consistent flags
Assert.assertFalse(failedMessage, properties[i].isIndexed() && properties[i].isMapped());
if (properties[i].isRequiresIndex())
{
Assert.assertTrue(failedMessage, properties[i].isIndexed());
}
if (properties[i].isRequiresMapkey())
{
Assert.assertTrue(failedMessage, properties[i].isMapped());
}
}
// assert same property names
EPAssertionUtil.assertEqualsAnyOrder(eventType.getPropertyNames(), propertyNames.toArray());
}
private static void writeIndent(StringWriter writer, int indent)
{
for (int i = 0; i < indent; i++)
{
writer.write(' ');
}
}
private static void writeValue(StringWriter writer, Object result)
{
if (result == null)
{
writer.append("(null)");
return;
}
if (result.getClass().isArray())
{
writer.append("Array len=");
writer.append(Integer.toString(Array.getLength(result)));
writer.append("{");
String delimiter = "";
for (int i = 0; i < Array.getLength(result); i++)
{
writer.append(delimiter);
writeValue(writer, Array.get(result, i));
delimiter = ", ";
}
writer.append("}");
}
else
{
writer.append(result.toString());
}
}
}