<commit_before>package org.kie.remote.services.jaxb;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;

import org.drools.core.command.runtime.process.GetProcessInstanceByCorrelationKeyCommand;
import org.drools.core.command.runtime.process.StartProcessCommand;
import org.drools.core.command.runtime.rule.HaltCommand;
import org.jbpm.persistence.correlation.CorrelationKeyInfo;
import org.jbpm.persistence.correlation.CorrelationPropertyInfo;
import org.jbpm.services.task.commands.GetTaskAssignedAsBusinessAdminCommand;
import org.jbpm.services.task.commands.GetTaskContentCommand;
import org.jbpm.services.task.commands.GetTasksByProcessInstanceIdCommand;
import org.jbpm.services.task.commands.StartTaskCommand;
import org.jbpm.services.task.commands.TaskCommand;
import org.jbpm.test.JbpmJUnitBaseTestCase;
import org.junit.Test;
import org.kie.api.command.Command;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.manager.RuntimeEngine;
import org.kie.api.runtime.process.ProcessInstance;
import org.kie.api.task.model.TaskSummary;
import org.kie.remote.services.AcceptedServerCommands;
import org.kie.services.client.serialization.JaxbSerializationProvider;
import org.kie.services.client.serialization.jaxb.impl.AbstractJaxbCommandResponse;
import org.kie.services.client.serialization.jaxb.impl.JaxbCommandResponse;
import org.reflections.Reflections;
import org.reflections.scanners.FieldAnnotationsScanner;
import org.reflections.scanners.MethodAnnotationsScanner;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SuppressWarnings("unchecked")
public class JaxbRemoteServicesSerializationTest  extends JbpmJUnitBaseTestCase {

    protected static final Logger logger = LoggerFactory.getLogger(JaxbRemoteServicesSerializationTest.class);
   
    private static Reflections reflections = new Reflections(
            ClasspathHelper.forPackage("org.kie.remote.services.jaxb"),
            ClasspathHelper.forPackage("org.kie.services.client.serialization.jaxb.rest"),
            new TypeAnnotationsScanner(), new FieldAnnotationsScanner(), new MethodAnnotationsScanner(), new SubTypesScanner());
   

    protected JaxbSerializationProvider jaxbProvider = JaxbSerializationProvider.serverSideInstance();
    { 
        jaxbProvider.setPrettyPrint(true);
    }

    public void addClassesToSerializationProvider(Class<?>... extraClass) {
        jaxbProvider.addJaxbClasses(false, extraClass);
    }

    public <T> T testRoundTrip(T in) throws Exception {
        String xmlObject = jaxbProvider.serialize(in);
        logger.debug(xmlObject);
        return (T) jaxbProvider.deserialize(xmlObject);
    }

    
    /**
     * If you think this test is a mistake: beware, this test is smarter than you.
     */
    @Test
    public void acceptedCommandsCanBeSerializedTest() throws Exception {
        Field commandsField = JaxbCommandsRequest.class.getDeclaredField("commands");
        XmlElements xmlElemsAnno = (XmlElements) commandsField.getAnnotations()[0];
        XmlElement[] xmlElems = xmlElemsAnno.value();

        Set<Class> cmdSet = getAcceptedCommandClassSet();
        assertEquals(AcceptedServerCommands.class.getSimpleName() + " contains a different set of Commands than "
                + JaxbCommandsRequest.class.getSimpleName(), cmdSet.size(), xmlElems.length);
        Set<String> xmlElemNameSet = new HashSet<String>();
        for (XmlElement xmlElemAnno : xmlElems) {
            Class cmdClass = xmlElemAnno.type();
            String name = xmlElemAnno.name();
            assertTrue(name + " is used twice as a name.", xmlElemNameSet.add(name));
            assertTrue(cmdClass.getSimpleName() + " is present in " + AcceptedServerCommands.class.getSimpleName() + " but not in "
                    + JaxbCommandsRequest.class.getSimpleName(), cmdSet.remove(cmdClass));
        }
        for (Class cmdClass : cmdSet) {
            logger.error("Missing: " + cmdClass.getSimpleName());
        }
        assertEquals("See output for classes in " + AcceptedServerCommands.class.getSimpleName() + " that are not in "
                + JaxbCommandsRequest.class.getSimpleName(), 0, cmdSet.size());
    }
 
    @Test
    public void allCommandResponseTypesNeedXmlElemIdTest() throws Exception {
        Field commandsField = JaxbCommandsResponse.class.getDeclaredField("responses");
        XmlElements xmlElemsAnno = (XmlElements) commandsField.getAnnotations()[0];
        XmlElement[] xmlElems = xmlElemsAnno.value();

        Set<Class<?>> cmdSet = new HashSet<Class<?>>();
        { 
            Set<Class<? extends JaxbCommandResponse>> subTypes = reflections.getSubTypesOf(JaxbCommandResponse.class);
            cmdSet.addAll(subTypes);
        }
        {
            Set<Class<? extends AbstractJaxbCommandResponse>> subTypes = reflections.getSubTypesOf(AbstractJaxbCommandResponse.class);
            cmdSet.addAll(subTypes);
        }
        cmdSet.remove(AbstractJaxbCommandResponse.class);

        int numAnnos = xmlElems.length;
        int numClass = cmdSet.size();

        Set<String> xmlElemNameSet = new HashSet<String>();
        for (XmlElement xmlElemAnno : xmlElems) {
            Class cmdClass = xmlElemAnno.type();
            String name = xmlElemAnno.name();
            assertTrue(name + " is used twice as a name.", xmlElemNameSet.add(name));
            assertTrue(cmdClass.getSimpleName() + " is present in " + JaxbCommandsResponse.class.getSimpleName() + " but does not "
                    + "implement " + JaxbCommandResponse.class.getSimpleName(), cmdSet.remove(cmdClass));
        }
        for (Class cmdClass : cmdSet) {
            logger.error("Missing: " + cmdClass.getSimpleName());
        }
        assertTrue("See above output for difference between " + JaxbCommandResponse.class.getSimpleName() + " implementations "
                + "and classes listed in " + JaxbCommandsResponse.class.getSimpleName(), cmdSet.size() == 0);

        assertEquals((numClass > numAnnos ? "Not all classes" : "Non " + JaxbCommandResponse.class.getSimpleName() + " classes")
                + " are listed in the " + JaxbCommandResponse.class.getSimpleName() + ".response @XmlElements list.", numClass,
                numAnnos);
    }

    private Set<Class> getAcceptedCommandClassSet() throws Exception { 
        Field commandSetField = AcceptedServerCommands.class.getDeclaredField("acceptedCommands");
        commandSetField.setAccessible(true);
        return new HashSet<Class>((Set<Class>) commandSetField.get(null));
    }
    
    @Test
    public void commandsWithListReturnTypesAreInCmdTypesList() throws Exception {
        Set<Class> cmdSet = getAcceptedCommandClassSet();
        // remove "meta" command types
        assertTrue( "Removing " + GetTaskContentCommand.class.getSimpleName(), 
                cmdSet.remove(GetTaskContentCommand.class)); // handled on ~l.244 of JaxbCommandsResponse

        // retrieve cmd list types set
        String cmdListTypesFieldName = "cmdListTypes";
        Field cmdListTypesField = JaxbCommandsResponse.class.getDeclaredField(cmdListTypesFieldName);
        assertNotNull("Unable to find " + JaxbCommandsResponse.class.getSimpleName() + "." + cmdListTypesFieldName + " field!",
                cmdListTypesField);
        cmdListTypesField.setAccessible(true);
        Map<Class, Class> cmdListTypesMap = (Map<Class, Class>) cmdListTypesField.get(null);
        assertNotNull(cmdListTypesFieldName + " value is null!", cmdListTypesMap);

        // Check that all accepted commands with a list return type are in the cmd list types set
        Set<Class> classesChecked = new HashSet<Class>();
        classesChecked.addAll(cmdSet);
        for( Class cmdClass : cmdSet ) {
            Class origClass = cmdClass;
            if( cmdClass.getInterfaces().length == 0 ) {
                // no interfaces, look at superclass
                Type superClass = cmdClass.getGenericSuperclass();
                assertNotNull("No generic super class found for " + cmdClass.getSimpleName(), superClass);
                assertTrue("Super class [" + superClass + "] of " + origClass.getSimpleName() + " should be a generic class!",
                        superClass instanceof ParameterizedType);
                checkIfClassShouldBeInCmdListTypes(origClass, (ParameterizedType) superClass, cmdListTypesMap, classesChecked);
            } else {
                assertTrue(origClass.getSimpleName() + " should have a generic interface!",
                        cmdClass.getGenericInterfaces().length > 0);
                for( Type genericCmdInterface : cmdClass.getGenericInterfaces() ) {
                    if( genericCmdInterface instanceof ParameterizedType ) {
                        ParameterizedType pType = ((ParameterizedType) genericCmdInterface);
                        checkIfClassShouldBeInCmdListTypes(origClass, pType, cmdListTypesMap, classesChecked);
                    }
                }
            }
        }
        if( !classesChecked.isEmpty() ) {
            fail(classesChecked.iterator().next() + " was not checked!");
        }
    }

    private void checkIfClassShouldBeInCmdListTypes( Class origClass, ParameterizedType genericSuperClassOrInterface,<commit_msg>BZ-1103970 - UnsupportedOperationException when TaskService.getTasksAssignedAsPotentialOwner (old test deleted)<commit_after>package org.kie.remote.services.jaxb;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;

import org.drools.core.command.runtime.process.GetProcessInstanceByCorrelationKeyCommand;
import org.drools.core.command.runtime.process.StartProcessCommand;
import org.drools.core.command.runtime.rule.HaltCommand;
import org.jbpm.persistence.correlation.CorrelationKeyInfo;
import org.jbpm.persistence.correlation.CorrelationPropertyInfo;
import org.jbpm.services.task.commands.GetTaskAssignedAsBusinessAdminCommand;
import org.jbpm.services.task.commands.GetTaskContentCommand;
import org.jbpm.services.task.commands.GetTasksByProcessInstanceIdCommand;
import org.jbpm.services.task.commands.StartTaskCommand;
import org.jbpm.services.task.commands.TaskCommand;
import org.jbpm.test.JbpmJUnitBaseTestCase;
import org.junit.Test;
import org.kie.api.command.Command;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.manager.RuntimeEngine;
import org.kie.api.runtime.process.ProcessInstance;
import org.kie.api.task.model.TaskSummary;
import org.kie.remote.services.AcceptedServerCommands;
import org.kie.services.client.serialization.JaxbSerializationProvider;
import org.kie.services.client.serialization.jaxb.impl.AbstractJaxbCommandResponse;
import org.kie.services.client.serialization.jaxb.impl.JaxbCommandResponse;
import org.reflections.Reflections;
import org.reflections.scanners.FieldAnnotationsScanner;
import org.reflections.scanners.MethodAnnotationsScanner;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SuppressWarnings("unchecked")
public class JaxbRemoteServicesSerializationTest  extends JbpmJUnitBaseTestCase {

    protected static final Logger logger = LoggerFactory.getLogger(JaxbRemoteServicesSerializationTest.class);
   
    private static Reflections reflections = new Reflections(
            ClasspathHelper.forPackage("org.kie.remote.services.jaxb"),
            ClasspathHelper.forPackage("org.kie.services.client.serialization.jaxb.rest"),
            new TypeAnnotationsScanner(), new FieldAnnotationsScanner(), new MethodAnnotationsScanner(), new SubTypesScanner());
   

    protected JaxbSerializationProvider jaxbProvider = JaxbSerializationProvider.serverSideInstance();
    { 
        jaxbProvider.setPrettyPrint(true);
    }

    public void addClassesToSerializationProvider(Class<?>... extraClass) {
        jaxbProvider.addJaxbClasses(false, extraClass);
    }

    public <T> T testRoundTrip(T in) throws Exception {
        String xmlObject = jaxbProvider.serialize(in);
        logger.debug(xmlObject);
        return (T) jaxbProvider.deserialize(xmlObject);
    }

    
    /**
     * If you think this test is a mistake: beware, this test is smarter than you.
     */
    @Test
    public void acceptedCommandsCanBeSerializedTest() throws Exception {
        Field commandsField = JaxbCommandsRequest.class.getDeclaredField("commands");
        XmlElements xmlElemsAnno = (XmlElements) commandsField.getAnnotations()[0];
        XmlElement[] xmlElems = xmlElemsAnno.value();

        Set<Class> cmdSet = getAcceptedCommandClassSet();
        assertEquals(AcceptedServerCommands.class.getSimpleName() + " contains a different set of Commands than "
                + JaxbCommandsRequest.class.getSimpleName(), cmdSet.size(), xmlElems.length);
        Set<String> xmlElemNameSet = new HashSet<String>();
        for (XmlElement xmlElemAnno : xmlElems) {
            Class cmdClass = xmlElemAnno.type();
            String name = xmlElemAnno.name();
            assertTrue(name + " is used twice as a name.", xmlElemNameSet.add(name));
            assertTrue(cmdClass.getSimpleName() + " is present in " + AcceptedServerCommands.class.getSimpleName() + " but not in "
                    + JaxbCommandsRequest.class.getSimpleName(), cmdSet.remove(cmdClass));
        }
        for (Class cmdClass : cmdSet) {
            logger.error("Missing: " + cmdClass.getSimpleName());
        }
        assertEquals("See output for classes in " + AcceptedServerCommands.class.getSimpleName() + " that are not in "
                + JaxbCommandsRequest.class.getSimpleName(), 0, cmdSet.size());
    }
 
    @Test
    public void allCommandResponseTypesNeedXmlElemIdTest() throws Exception {
        Field commandsField = JaxbCommandsResponse.class.getDeclaredField("responses");
        XmlElements xmlElemsAnno = (XmlElements) commandsField.getAnnotations()[0];
        XmlElement[] xmlElems = xmlElemsAnno.value();

        Set<Class<?>> cmdSet = new HashSet<Class<?>>();
        { 
            Set<Class<? extends JaxbCommandResponse>> subTypes = reflections.getSubTypesOf(JaxbCommandResponse.class);
            cmdSet.addAll(subTypes);
        }
        {
            Set<Class<? extends AbstractJaxbCommandResponse>> subTypes = reflections.getSubTypesOf(AbstractJaxbCommandResponse.class);
            cmdSet.addAll(subTypes);
        }
        cmdSet.remove(AbstractJaxbCommandResponse.class);

        int numAnnos = xmlElems.length;
        int numClass = cmdSet.size();

        Set<String> xmlElemNameSet = new HashSet<String>();
        for (XmlElement xmlElemAnno : xmlElems) {
            Class cmdClass = xmlElemAnno.type();
            String name = xmlElemAnno.name();
            assertTrue(name + " is used twice as a name.", xmlElemNameSet.add(name));
            assertTrue(cmdClass.getSimpleName() + " is present in " + JaxbCommandsResponse.class.getSimpleName() + " but does not "
                    + "implement " + JaxbCommandResponse.class.getSimpleName(), cmdSet.remove(cmdClass));
        }
        for (Class cmdClass : cmdSet) {
            logger.error("Missing: " + cmdClass.getSimpleName());
        }
        assertTrue("See above output for difference between " + JaxbCommandResponse.class.getSimpleName() + " implementations "
                + "and classes listed in " + JaxbCommandsResponse.class.getSimpleName(), cmdSet.size() == 0);

        assertEquals((numClass > numAnnos ? "Not all classes" : "Non " + JaxbCommandResponse.class.getSimpleName() + " classes")
                + " are listed in the " + JaxbCommandResponse.class.getSimpleName() + ".response @XmlElements list.", numClass,
                numAnnos);
    }

    private Set<Class> getAcceptedCommandClassSet() throws Exception { 
        Field commandSetField = AcceptedServerCommands.class.getDeclaredField("acceptedCommands");
        commandSetField.setAccessible(true);
        return new HashSet<Class>((Set<Class>) commandSetField.get(null));
    }
    
    private void checkIfClassShouldBeInCmdListTypes( Class origClass, ParameterizedType genericSuperClassOrInterface,
{'fraction_non_alphanumeric': 0.09980603068241933, 'fraction_numerical': 0.0014106859460412625, 'mean_word_length': 3.578579117330463, 'pattern_counts': {'":': 0, '<': 44, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 50}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6895176', 'n_tokens_mistral': 4729, 'n_tokens_neox': 4656, 'n_words': 886}