Package org.kie.services.client.api.command

Source Code of org.kie.services.client.api.command.RemoteCommandObjectTest

package org.kie.services.client.api.command;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.verify;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.UUID;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import org.jbpm.services.task.commands.AddTaskCommand;
import org.junit.Test;
import org.kie.internal.jaxb.StringKeyObjectValueMapXmlAdapter;
import org.kie.remote.client.jaxb.AcceptedClientCommands;
import org.kie.remote.jaxb.gen.ActivateTaskCommand;
import org.kie.remote.jaxb.gen.DeleteCommand;
import org.kie.remote.jaxb.gen.TaskCommand;
import org.mockito.Mockito;
import org.reflections.Reflections;
import org.reflections.scanners.FieldAnnotationsScanner;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sun.xml.bind.marshaller.CharacterEscapeHandler;

public class RemoteCommandObjectTest {

    private static final Logger logger = LoggerFactory.getLogger(RemoteCommandObjectTest.class);

    private static Reflections reflections = new Reflections(ClasspathHelper.forPackage("org.kie.remote.command"),
            ClasspathHelper.forPackage("org.jbpm.services.task.commands"),
            ClasspathHelper.forPackage("org.jbpm.process.audit.command"),
            ClasspathHelper.forPackage("org.kie.remote.jaxb.gen"),
            new TypeAnnotationsScanner(),
            new FieldAnnotationsScanner(), new SubTypesScanner());

    private DatatypeFactory datatypeFactory;
   
    public RemoteCommandObjectTest() throws Exception {
        datatypeFactory = DatatypeFactory.newInstance();
    }
   
    @Test
    public void isAcceptableCommandTest() throws Exception {
       assertTrue( "The .isAcceptedCommandClass method is not functioning correctly: generated classes",
               AcceptedClientCommands.isAcceptedCommandClass(org.kie.remote.jaxb.gen.AddTaskCommand.class));
       assertFalse( "The .isAcceptedCommandClass method is not functioning correctly: original command classes",
               AcceptedClientCommands.isAcceptedCommandClass(org.jbpm.services.task.commands.AddTaskCommand.class));
    }
   
    @Test
    public void reflectionMappingTest() throws Exception {
        Set<Class<?>> classes = reflections.getTypesAnnotatedWith(XmlAccessorType.class);
        assertFalse(classes.isEmpty());

        List<Class<?>> classList = new LinkedList<Class<?>>(classes);
        Collections.sort(classList, new Comparator<Class<?>>() {
            public int compare( Class<?> o1, Class<?> o2 ) {
                return o1.getSimpleName().compareTo(o2.getSimpleName());
            }
        });
        classes = new LinkedHashSet<Class<?>>(classList);
       
        Map<Class, Class> kieCmdGenCmdClassMap = new LinkedHashMap<Class, Class>();
        for( Class<?> cmdClass : classes ) {
            if( ! cmdClass.getSimpleName().endsWith("Command") ) {
               continue;
            }
            if( ! AcceptedClientCommands.isAcceptedCommandClass(cmdClass) ) { 
                continue;
            }
            Class genCmdClass = Class.forName("org.kie.remote.jaxb.gen." + cmdClass.getSimpleName());
            assertTrue( genCmdClass.getSimpleName() + " is not an accepted command?",
                    AcceptedClientCommands.isAcceptedCommandClass(genCmdClass) );
            kieCmdGenCmdClassMap.put(cmdClass, genCmdClass);
        }
        assertFalse("No generated command classes could be found to test.",  kieCmdGenCmdClassMap.isEmpty());

        for( Entry<Class, Class> classEntry : kieCmdGenCmdClassMap.entrySet() ) {
            compareKieClassInstanceToGenClassInstance(classEntry.getKey(), classEntry.getValue());
        }
    }

    private void compareKieClassInstanceToGenClassInstance( Class kieCmdClass, Class genCmdClass ) throws Exception {
        Object genCmd = fillCommand(genCmdClass);
        if( DeleteCommand.class.equals(genCmdClass) ) {
            ((DeleteCommand) genCmd).setFactHandle( ":1:2:3:4:5:TRAIT" );
        }
        Object copyKieCmd = roundTripFromFlatToOrigCmd(genCmd, genCmdClass, kieCmdClass);
       
        for( Field field : kieCmdClass.getDeclaredFields() ) {
            if( field.getAnnotation(XmlTransient.class) != null) {
               continue;
            }
            field.setAccessible(true);
            Object kieCmdFieldVal = field.get(copyKieCmd);
            assertNotNull( kieCmdClass.getSimpleName() + "."  + field.getName(), kieCmdFieldVal );
        }
       
    }

    private static Random random = new Random();

    private Object fillCommand( Class cmdClass ) throws Exception {
        Object cmdObj = cmdClass.getConstructor().newInstance();
        Field[] fields = cmdClass.getDeclaredFields();
        for( Field field : fields ) {
            if( Modifier.isStatic(field.getModifiers()) ) {
                continue;
            }
            fillField(field, cmdObj);
        }
        if( cmdClass.getSuperclass() != null ) {
            for( Field taskField : cmdClass.getSuperclass().getDeclaredFields() ) {
                if( Modifier.isStatic(taskField.getModifiers()) ) {
                    continue;
                }
                fillField(taskField, cmdObj);

            }
        }
        return cmdObj;
    }

    private void fillField( Field field, Object obj ) throws Exception {
        field.setAccessible(true);
        String fieldTypeName = field.getType().getName();
        Class fieldType = field.getType();
        if( fieldTypeName.startsWith("java") || !fieldTypeName.contains(".") ) {
            if( fieldType.equals(String.class) ) {
                if( "className".equals(field.getName()) ) {
                    field.set(obj, String.class.getName() );
                } else {
                    field.set(obj, UUID.randomUUID().toString());
                }
            } else if( fieldType.equals(Integer.class) || fieldType.equals(int.class) ) {
                field.set(obj, random.nextInt());
            } else if( fieldType.equals(Long.class) || fieldType.equals(long.class) ) {
                field.set(obj, random.nextLong());
            } else if( fieldType.equals(Boolean.class) || fieldType.equals(boolean.class) ) {
                field.set(obj, random.nextBoolean());
            } else if( fieldType.equals(Map.class) ) {
                Map<String, Object> val = new HashMap<String, Object>();
                for( int i = 0; i < 3; ++i ) {
                    val.put(UUID.randomUUID().toString(), random.nextLong());
                }
                field.set(obj, val);
            } else if( fieldType.equals(Date.class) ) {
                field.set(obj, new Date());
            } else if( fieldType.equals(List.class) ) {
                ParameterizedType fieldGenericType = (ParameterizedType) field.getGenericType();
                Type listType = fieldGenericType.getActualTypeArguments()[0];
                List<Object> list = new ArrayList<Object>();
                Class listItemClass = Class.forName(((Class) listType).getName());
                for( int i = 0; i < 2; ++i ) {
                    Object listItem = null;
                    if( listItemClass.isEnum() ) {
                        Object[] enumConstants = listItemClass.getEnumConstants();
                        listItem = enumConstants[random.nextInt(enumConstants.length)];
                    } else if( listItemClass.getName().startsWith("java") ) {
                        if( Long.class.equals(listItemClass) ) {
                            listItem = random.nextLong();
                        } else if( String.class.equals(listItemClass) ) {
                            listItem = UUID.randomUUID().toString();
                        } else if( Object.class.equals(listItemClass) ) {
                            listItem = "Object";
                        } else {
                            fail(listItemClass.getName());
                        }
                    } else {
                        if( TaskCommand.class.equals(listItemClass) ) {
                            ActivateTaskCommand cmd = new ActivateTaskCommand();
                            cmd.setTaskId(random.nextLong());
                            cmd.setUserId(UUID.randomUUID().toString());   
                            listItem = cmd;
                        } else {
                            listItem = listItemClass.getConstructor().newInstance();
                            for( Field listItemField : listItemClass.getDeclaredFields() ) {
                                fillField(listItemField, listItem);
                            }
                        }
                    }
                    list.add(listItem);
                }
                field.set(obj, list);
            } else if( fieldType.equals(XMLGregorianCalendar.class) ) {
                XMLGregorianCalendar date = datatypeFactory.newXMLGregorianCalendar(new GregorianCalendar());
                field.set(obj, date);
            } else if( fieldType.equals(Object.class) ) {
                field.set(obj, "Object");
            } else if( fieldType.equals(byte[].class) ) {
                byte [] value = StringKeyObjectValueMapXmlAdapter.serializeObject("Object", "test");
                field.set(obj, value);
            } else {
                fail("> " + obj.getClass().getSimpleName() + "." + field.getName() + ": " + fieldType.getName());
            }
        } else if( fieldType.isEnum() ) {
            Object [] enumConstants = fieldType.getEnumConstants();
            field.set(obj, enumConstants[random.nextInt(enumConstants.length)]);
        } else {
            if( fieldType.equals(org.kie.remote.jaxb.gen.TaskCommand.class) ) {
                ActivateTaskCommand cmd = new ActivateTaskCommand();
                cmd.setTaskId(2l);
                cmd.setUserId(UUID.randomUUID().toString());
                field.set(obj, cmd);
            } else {
                if( field.getAnnotation(XmlTransient.class) != null ) {
                    return;
                }
                 Object subObj = fieldType.getConstructor().newInstance();
                 field.set(obj, subObj);
                 for( Field subField : field.getType().getDeclaredFields() ) {
                     fillField( subField, subObj);
                 }
                // fail(kieCmd.getClass().getSimpleName() + "." + field.getName() + ": " + field.getType());
            }
        }
    }

    private Object roundTripFromFlatToOrigCmd( Object flatCmd, Class flatCmdClass, Class origCmdClass ) throws Exception {
        String xmlStr = serialize(flatCmd, flatCmdClass);
        logger.debug("{}:\n{}---", flatCmdClass.getSimpleName(), xmlStr);
        return deserialize(xmlStr, origCmdClass);
    }

    private String serialize( Object object, Class cmdClass ) throws Exception {
        Marshaller marshaller = null;
        marshaller = getJaxbContext(cmdClass).createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CharacterEscapeHandler() {
            public void escape( char[] ac, int i, int j, boolean flag, Writer writer ) throws IOException {
                writer.write(ac, i, j);
            }
        });

        StringWriter stringWriter = new StringWriter();
        try {
            marshaller.marshal(object, stringWriter);
        } catch( Exception e ) {
            e.printStackTrace();
            fail( "Could not marshal " + cmdClass.getSimpleName() );
        }
        String output = stringWriter.toString();

        return output;
    }

    private <T> T deserialize( String xmlStr, Class<T> cmdClass ) throws Exception {
        Unmarshaller unmarshaller = null;
        unmarshaller = getJaxbContext(cmdClass).createUnmarshaller();
        ByteArrayInputStream xmlStrInputStream = new ByteArrayInputStream(xmlStr.getBytes(Charset.forName("UTF-8")));
        T jaxbObj = (T) unmarshaller.unmarshal(xmlStrInputStream);
        return jaxbObj;
    }

    private JAXBContext getJaxbContext( Class... classes ) throws Exception {
        return JAXBContext.newInstance(classes);
    }

    @Test
    public void preprocessTest() throws Exception {
        RemoteConfiguration config = new RemoteConfiguration("adsf", new URL("http://localhost:80808"), "user", "pwd" );
        KieSessionClientCommandObject spyCmdObj = Mockito.spy(new KieSessionClientCommandObject(config));
       
        List<Object> objList = new ArrayList<Object>();
        Field paramClassesField = AcceptedClientCommands.class.getDeclaredField("sendObjectParameterCommandClasses");
        paramClassesField.setAccessible(true);
        Set<Class> sendObjectParameterClasses = (Set<Class>) paramClassesField.get(null);
       
        for( Class clientClass : sendObjectParameterClasses ) {
            Object inst = clientClass.getConstructor(new Class[0]).newInstance(new Object[0]);
            spyCmdObj.preprocessCommand(inst, objList);
            logger.debug( "Are {} instances checked for user-defined classes?", clientClass.getSimpleName() );
            verify(spyCmdObj, atLeastOnce()).addPossiblyNullObject(any(), any(List.class));
        }
    }
}
TOP

Related Classes of org.kie.services.client.api.command.RemoteCommandObjectTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.