org.pentaho.reporting.platform.plugin.ParameterXmlContentHandlerTest.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.reporting.platform.plugin.ParameterXmlContentHandlerTest.java

Source

/*
 * This program is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License, version 2 as published by the Free Software
 * Foundation.
 *
 * You should have received a copy of the GNU General Public License along with this
 * program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html
 * or from the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * 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.
 *
 *
 * Copyright 2006 - 2017 Hitachi Vantara.  All rights reserved.
 */

package org.pentaho.reporting.platform.plugin;

import com.google.common.collect.Lists;
import org.apache.commons.collections.map.HashedMap;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.pentaho.reporting.engine.classic.core.ClassicEngineBoot;
import org.pentaho.reporting.engine.classic.core.CompoundDataFactory;
import org.pentaho.reporting.engine.classic.core.DataFactory;
import org.pentaho.reporting.engine.classic.core.DataRow;
import org.pentaho.reporting.engine.classic.core.DefaultReportEnvironment;
import org.pentaho.reporting.engine.classic.core.DefaultResourceBundleFactory;
import org.pentaho.reporting.engine.classic.core.MasterReport;
import org.pentaho.reporting.engine.classic.core.ReportDataFactoryException;
import org.pentaho.reporting.engine.classic.core.ReportEnvironment;
import org.pentaho.reporting.engine.classic.core.ResourceBundleFactory;
import org.pentaho.reporting.engine.classic.core.StaticDataRow;
import org.pentaho.reporting.engine.classic.core.TableDataFactory;
import org.pentaho.reporting.engine.classic.core.metadata.DataFactoryMetaData;
import org.pentaho.reporting.engine.classic.core.modules.misc.tablemodel.GeneratorTableModel;
import org.pentaho.reporting.engine.classic.core.parameters.DefaultListParameter;
import org.pentaho.reporting.engine.classic.core.parameters.DefaultParameterContext;
import org.pentaho.reporting.engine.classic.core.parameters.ParameterAttributeNames;
import org.pentaho.reporting.engine.classic.core.parameters.ParameterContext;
import org.pentaho.reporting.engine.classic.core.parameters.ParameterDefinitionEntry;
import org.pentaho.reporting.engine.classic.core.parameters.PlainParameter;
import org.pentaho.reporting.engine.classic.core.parameters.ReportParameterDefinition;
import org.pentaho.reporting.engine.classic.core.parameters.ValidationMessage;
import org.pentaho.reporting.engine.classic.core.parameters.ValidationResult;
import org.pentaho.reporting.engine.classic.core.util.ReportParameterValues;
import org.pentaho.reporting.engine.classic.core.util.beans.BeanException;
import org.pentaho.reporting.libraries.base.config.Configuration;
import org.pentaho.reporting.libraries.base.util.HashNMap;
import org.pentaho.reporting.libraries.resourceloader.ResourceKey;
import org.pentaho.reporting.libraries.resourceloader.ResourceManager;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static org.junit.Assert.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
 * see backlog-7980
 * <p>
 * Created by dima.prokopenko@gmail.com on 6/27/2016.
 */
public class ParameterXmlContentHandlerTest {

    private static XPathFactory xpathFactory = XPathFactory.newInstance();
    private ParameterXmlContentHandler handler;
    private MasterReport report;
    private ReportParameterDefinition definition;
    private CompoundDataFactory factory;

    @BeforeClass
    public static void beforeClass() {
        ClassicEngineBoot.getInstance().start();
    }

    // helper method
    private String toString(final Document doc) {
        try {
            final StringWriter stringWriter = new StringWriter();
            final TransformerFactory factory = TransformerFactory.newInstance();
            final Transformer transformer = factory.newTransformer();
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

            transformer.transform(new DOMSource(doc), new StreamResult(stringWriter));
            return stringWriter.toString();
        } catch (final Exception ex) {
            // no op
            return "fail";
        }
    }

    @Before
    public void before() {
        final ParameterContentGenerator generator = mock(ParameterContentGenerator.class);
        handler = new ParameterXmlContentHandler(generator, true);

        report = mock(MasterReport.class);

        final Configuration conf = mock(Configuration.class);

        final ResourceManager rmanager = new ResourceManager();
        final ResourceKey rkey = new ResourceKey("", "", Collections.emptyMap());
        final ResourceBundleFactory resBFactory = mock(ResourceBundleFactory.class);
        final ReportEnvironment environment = mock(ReportEnvironment.class);

        when(report.getConfiguration()).thenReturn(conf);
        when(report.getResourceManager()).thenReturn(rmanager);
        when(report.getContentBase()).thenReturn(rkey);
        when(report.getResourceBundleFactory()).thenReturn(resBFactory);
        when(report.getReportEnvironment()).thenReturn(environment);

        definition = mock(ReportParameterDefinition.class);
        when(report.getParameterDefinition()).thenReturn(definition);

        factory = mock(CompoundDataFactory.class);
        // preparation of data factory to fetch parameter names
        // the actual factory for query will be returned when 'getDataFactoryForQuery' called.
        when(factory.isNormalized()).thenReturn(true);
        when(factory.derive()).thenReturn(factory);
        when(report.getDataFactory()).thenReturn(factory);
    }

    @Test
    public void testGetSelections() throws ReportDataFactoryException, BeanException {
        final Map<String, Object> inputs = new HashMap<String, Object>() {
            {
                put("changed_unverified", "value");
                put("unchanged_unverified", "value1");
                put("verified", "value2");
                put("plain", "value3");
            }
        };

        final Set<Object> changedParameters = Collections.singleton("changed_unverified");

        final ParameterDefinitionEntry changed = new DefaultListParameter("query", "keyColumn", "textColumn",
                "changed_unverified", false, false, String.class);
        final ParameterDefinitionEntry unchanged = new DefaultListParameter("query", "keyColumn", "textColumn",
                "unchanged_unverified", false, false, String.class);
        final ParameterDefinitionEntry verified = new DefaultListParameter("query", "keyColumn", "textColumn",
                "verified", false, true, String.class);
        final ParameterDefinitionEntry plain = new PlainParameter("plain", String.class);

        //Initial call
        final Object changedResult = handler.getSelections(changed, null, inputs);
        final Object unchangedResult = handler.getSelections(unchanged, null, inputs);
        final Object verifiedResult = handler.getSelections(verified, null, inputs);
        final Object plainResult = handler.getSelections(plain, null, inputs);

        assertEquals("value", changedResult);
        assertEquals("value1", unchangedResult);
        assertEquals("value2", verifiedResult);
        assertEquals("value3", plainResult);

        //Changed call
        final Object changedResult1 = handler.getSelections(changed, changedParameters, inputs);
        final Object unchangedResult1 = handler.getSelections(unchanged, changedParameters, inputs);
        final Object verifiedResult1 = handler.getSelections(verified, changedParameters, inputs);
        final Object plainResult1 = handler.getSelections(plain, changedParameters, inputs);

        assertEquals("value", changedResult1);
        assertEquals(null, unchangedResult1);
        assertEquals("value2", verifiedResult1);
        assertEquals("value3", plainResult1);
    }

    @Test
    public void testParameterDependencies() throws ReportDataFactoryException {

        final ReportParameterValues computedParameterValues = mock(ReportParameterValues.class);
        final ParameterContext parameterContext = mock(ParameterContext.class);

        final ParameterDefinitionEntry[] entries = getDefinitions();
        when(definition.getParameterDefinitions()).thenReturn(entries);

        // this factory will be used to get parameter names
        final CompoundDataFactory localFactory1 = mock(CompoundDataFactory.class);
        when(factory.getDataFactoryForQuery(eq("query1"))).thenReturn(localFactory1);
        final DataFactoryMetaData meth1 = mock(DataFactoryMetaData.class);
        when(localFactory1.getMetaData()).thenReturn(meth1);
        when(meth1.getReferencedFields(any(DataFactory.class), anyString(), any(DataRow.class)))
                .thenReturn(new String[] { "f1", "f2" });

        final CompoundDataFactory localFactory2 = mock(CompoundDataFactory.class);
        when(factory.getDataFactoryForQuery(eq("query2"))).thenReturn(localFactory2);
        final DataFactoryMetaData meth2 = mock(DataFactoryMetaData.class);
        when(localFactory2.getMetaData()).thenReturn(meth2);
        when(meth2.getReferencedFields(any(DataFactory.class), anyString(), any(DataRow.class)))
                .thenReturn(new String[] { "g1", "g2" });

        final HashNMap<String, String> parameters = handler.getDependentParameters(computedParameterValues,
                parameterContext, report);

        assertNotNull(parameters);
        assertFalse(parameters.isEmpty());
        assertEquals(4, parameters.keySet().size());

        final List<String> list1 = Lists.newArrayList(parameters.getAll("f1"));
        assertFalse(list1.isEmpty());
        assertEquals(1, list1.size());
        assertTrue(list1.contains("name1"));

        final List<String> list11 = Lists.newArrayList(parameters.getAll("f2"));
        assertFalse(list11.isEmpty());
        assertEquals(1, list11.size());
        assertTrue(list11.contains("name1"));

        final List<String> list2 = Lists.newArrayList(parameters.getAll("g1"));
        assertFalse(list2.isEmpty());
        assertEquals(1, list2.size());
        assertTrue(list2.contains("name2"));

        final List<String> list22 = Lists.newArrayList(parameters.getAll("g1"));
        assertFalse(list22.isEmpty());
        assertEquals(1, list22.size());
        assertTrue(list22.contains("name2"));
    }

    private ParameterDefinitionEntry[] getDefinitions() {
        final ParameterDefinitionEntry entry1 = mock(ParameterDefinitionEntry.class);
        when(entry1.getName()).thenReturn("someName");

        final ParameterDefinitionEntry entry2 = new DefaultListParameter("query1", "keyColumn1", "textColumn1",
                "name1", false, true, String.class);

        final ParameterDefinitionEntry entry3 = new DefaultListParameter("query2", "keyColumn2", "textColumn2",
                "name2", false, true, String.class);

        return new ParameterDefinitionEntry[] { entry1, entry2, entry3 };
    }

    @Test
    public void testComputeNormalizeLinage() {
        final ParameterContext pc = mock(ParameterContext.class);
        final ParameterDefinitionEntry pe = mock(ParameterDefinitionEntry.class);
        final HashNMap<String, String> map = new HashNMap<>();

        when(pe.getName()).thenReturn("aname");

        when(pe.getParameterAttribute(eq(ParameterAttributeNames.Core.NAMESPACE),
                eq(ParameterAttributeNames.Core.DEFAULT_VALUE_FORMULA), eq(pc))).thenReturn("=LEN([sPostal1])");

        when(pe.getParameterAttribute(eq(ParameterAttributeNames.Core.NAMESPACE),
                eq(ParameterAttributeNames.Core.POST_PROCESSOR_FORMULA), eq(pc))).thenReturn("=LEN([sPostal2])");

        when(pe.getParameterAttribute(eq(ParameterAttributeNames.Core.NAMESPACE),
                eq(ParameterAttributeNames.Core.DISPLAY_VALUE_FORMULA), eq(pc))).thenReturn("=LEN([sPostal3])");

        handler.computeNormalLineage(pc, pe, map);

        assertNotNull(map);
        assertFalse(map.isEmpty());
        assertEquals(3, map.keySet().size());

        final List<List<String>> list = new ArrayList<>();
        list.add(Lists.newArrayList(map.getAll("sPostal1")));
        list.add(Lists.newArrayList(map.getAll("sPostal2")));
        list.add(Lists.newArrayList(map.getAll("sPostal3")));

        list.stream().forEach(i -> assertNotNull(i));
        list.stream().forEach(i -> assertFalse(i.isEmpty()));
        list.stream().forEach(i -> assertEquals(1, i.size()));

        final List empty = list.stream().filter(i -> i.contains("aname") && (i.size() == 1))
                .collect(Collectors.toList());
        assertEquals(3, list.size());
    }

    /**
     * Test that 'skip' validation messages does not mess up with errors.
     * <p>
     * generated xml should look like:
     * <errors>
     * <error message="" parameter="parameter3"/>
     * <error message="not good at all" parameter="parameter2"/>
     * <error message="not good" parameter="parameter1"/>
     * <global-error message="kernel panic"/>
     * </errors>
     *
     * @throws ParserConfigurationException
     */
    @Test
    public void createErrorElementsTest() throws ParserConfigurationException, XPathExpressionException {
        final ValidationResult vr = new ValidationResult();
        vr.addError("parameter1", new ValidationMessage("not good"));
        vr.addError("parameter2", new ValidationMessage("not good at all"));
        vr.addError(new ValidationMessage("kernel panic"));

        // save parameter name - attribute value mapping
        final Map<String, String> attrMap = new HashMap();
        attrMap.put("parameter3", "");
        attrMap.put("parameter2", "not good at all");
        attrMap.put("parameter1", "not good");

        handler.document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        final Element el = handler.createErrorElements(vr);
        handler.document.appendChild(el);

        assertNotNull(el);
        assertEquals(3, el.getChildNodes().getLength());

        // use xpath for future validation just to get rid of numerous for() loops in DOM api
        final XPath xpath = xpathFactory.newXPath();

        final NodeList found = NodeList.class
                .cast(xpath.evaluate("/errors/error", handler.document, XPathConstants.NODESET));
        assertNotNull(found);

        for (int i = 0; i < found.getLength(); i++) {
            final Node node = found.item(i);
            assertEquals("error", node.getNodeName());
            final Element oneError = (Element) node;
            final String paramName = oneError.getAttribute("parameter");
            assertTrue(attrMap.containsKey(paramName));
            assertEquals(attrMap.get(paramName), oneError.getAttribute("message"));
        }

        final Node globalError = (Node) xpath.evaluate("/errors/global-error", handler.document,
                XPathConstants.NODE);
        assertNotNull(globalError);

        assertEquals("global-error", globalError.getNodeName());

        final Element globalErrEl = Element.class.cast(globalError);

        assertEquals("kernel panic", globalErrEl.getAttribute("message"));
    }

    /**
     * Creates simple parameter xml. Output should look like:
     * <pre>
     * {@code
     *
     * <parameter is-list="true" is-mandatory="false" is-multi-select="true" is-strict="true" name="name"
     * type="java.lang.String">
     * <attribute name="role" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core"
     * value="user"/>
     * <values>
     *   <value label="c20" null="false" selected="false" type="java.lang.String" value="c10"/>
     *   <value label="c21" null="false" selected="false" type="java.lang.String" value="c11"/>
     * </values>
     * </parameter> }
     * </pre>
     *
     * @throws BeanException
     * @throws ReportDataFactoryException
     * @throws ParserConfigurationException
     */
    @Test
    public void createParameterElementTest() throws BeanException, ReportDataFactoryException,
            ParserConfigurationException, XPathExpressionException {
        final DefaultListParameter parameter = new DefaultListParameter("query", "c1", "c2", "name", true, true,
                String.class);

        final ParameterContext context = getTestParameterContext();

        handler.document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

        final HashNMap<String, String> dependencies = new HashNMap<>();
        dependencies.add("name", "dep1");
        dependencies.add("name", "dep2");

        final Element element = handler.createParameterElement(parameter, context, null, dependencies, false);
        assertNotNull(element);
        handler.document.appendChild(element);
        handler.createParameterDependencies(element, parameter, new HashNMap());

        final String xml = toString(handler.document);

        examineStandardXml(handler.document);
        assertTrue(isThereAttributes(handler.document));
    }

    /**
     * Creates simple parameter xml. Output should look like:
     * <p>
     * <pre>
     *   {@code
     *
     * <parameter is-list="true" is-mandatory="false" is-multi-select="true" is-strict="true" name="name"
     * type="java.lang.String">
     *  <attribute name="role" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core"
     *  value="user"/>
     *  <attribute name="must-validate-on-server" namespace="http://reporting.pentaho
     *  .org/namespaces/engine/parameter-attributes/server" value="true"/>
     *  <attribute name="has-downstream-dependent-parameter" namespace="http://reporting.pentaho
     *  .org/namespaces/engine/parameter-attributes/server" value="true"/>
     *  <values>
     *   <value label="c20" null="false" selected="false" type="java.lang.String" value="c10"/>
     *   <value label="c21" null="false" selected="false" type="java.lang.String" value="c11"/>
     *  </values>
     *  <dependencies>
     *   <name>dep1</name>
     *   <name>dep2</name>
     *  </dependencies>
     * </parameter>
     *   }
     * </pre>
     *
     * @throws BeanException
     * @throws ReportDataFactoryException
     * @throws ParserConfigurationException
     * @throws XPathExpressionException
     */
    @Test
    public void createParameterWithDependenciesTest() throws BeanException, ReportDataFactoryException,
            ParserConfigurationException, XPathExpressionException {
        final DefaultListParameter parameter = new DefaultListParameter("query", "c1", "c2", "name", true, true,
                String.class);

        final ParameterContext context = getTestParameterContext();

        handler.document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

        final HashNMap<String, String> dependencies = new HashNMap<>();
        dependencies.add("name", "dep0");
        dependencies.add("name", "dep1");

        final Element element = handler.createParameterElement(parameter, context, null, dependencies, false);
        assertNotNull(element);
        handler.document.appendChild(element);
        handler.createParameterDependencies(element, parameter, dependencies);

        examineStandardXml(handler.document);
        assertTrue(isThereAttributes(handler.document));

        final String xml = toString(handler.document);

        // test dependencies specific elements:
        final XPath xpath = xpathFactory.newXPath();

        final NodeList list = (NodeList) xpath.evaluate("/parameter/dependencies/name", handler.document,
                XPathConstants.NODESET);
        assertNotNull(list);
        assertEquals(2, list.getLength());

        for (int i = 0; i < list.getLength(); i++) {
            final Node node = list.item(i);
            assertNotNull(node);
            assertEquals("dep" + i, node.getTextContent());
        }

        // specific attributes: must-validate-on-server
        Node attr1 = (Node) xpath.evaluate("/parameter/attribute[@name='must-validate-on-server']",
                handler.document, XPathConstants.NODE);
        assertNotNull(attr1);
        Element elAttr1 = (Element) attr1;
        assertEquals("true", elAttr1.getAttribute("value"));

        // specific attributes: has-downstream-dependent-parameter
        attr1 = (Node) xpath.evaluate("/parameter/attribute[@name='has-downstream-dependent-parameter']",
                handler.document, XPathConstants.NODE);
        assertNotNull(attr1);
        elAttr1 = (Element) attr1;
        assertEquals("true", elAttr1.getAttribute("value"));
    }

    private void examineStandardXml(final Document doc) throws XPathExpressionException {
        final XPath xpath = xpathFactory.newXPath();
        final NodeList nodeList = (NodeList) xpath.evaluate("/parameter/values/value", doc, XPathConstants.NODESET);
        assertNotNull(nodeList);
        assertEquals(2, nodeList.getLength());

        for (int i = 0; i < nodeList.getLength(); i++) {
            final Element item = (Element) nodeList.item(i);
            assertEquals("c1" + i, item.getAttribute("value"));
        }
    }

    /**
     * Creates very simple parameter context.
     *
     * @return
     * @throws ReportDataFactoryException
     */
    private DefaultParameterContext getTestParameterContext() throws ReportDataFactoryException {
        final GeneratorTableModel model = new GeneratorTableModel(new String[] { "c1", "c2" },
                new Class[] { String.class, String.class }, 2);
        final DataFactory df = new TableDataFactory("query", model);
        final DataRow dr = new StaticDataRow(new String[] { "1" }, new Object[] { 1 });
        final Configuration conf = ClassicEngineBoot.getInstance().getExtendedConfig();
        final ResourceBundleFactory factory = new DefaultResourceBundleFactory();
        final ResourceManager manager = new ResourceManager();
        final ResourceKey key = new ResourceKey("", "", Collections.emptyMap());
        final ReportEnvironment env = new DefaultReportEnvironment(conf);
        return new DefaultParameterContext(df, dr, conf, factory, manager, key, env);
    }

    @Test
    public void createParameterElementNoAttributesTest() throws BeanException, ReportDataFactoryException,
            ParserConfigurationException, XPathExpressionException {
        final DefaultListParameter parameter = new DefaultListParameter("query", "c1", "c2", "name", true, true,
                String.class);

        final ParameterContext context = getTestParameterContext();

        handler.document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

        final HashNMap<String, String> dependencies = new HashNMap<>();
        dependencies.add("name", "dep1");
        dependencies.add("name", "dep2");

        final Element element = handler.createParameterElement(parameter, context, null, dependencies,
                Boolean.TRUE);
        assertNotNull(element);
        handler.document.appendChild(element);
        handler.createParameterDependencies(element, parameter, new HashNMap());

        examineStandardXml(handler.document);
        assertFalse(isThereAttributes(handler.document));
    }

    @Test
    public void appendInitialParametersList() throws BeanException, ReportDataFactoryException,
            ParserConfigurationException, XPathExpressionException, CloneNotSupportedException {

        final LinkedHashMap<String, ParameterDefinitionEntry> parameterDefinitions = getParametersMap();

        final DefaultParameterContext context = getTestParameterContext();
        final ValidationResult vr = new ValidationResult();
        vr.setParameterValues(new ReportParameterValues());

        handler.document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

        final HashNMap<String, String> dependencies = new HashNMap<>();
        dependencies.add("first", "second");
        dependencies.add("second", "third");

        final Element parameters = handler.document.createElement("parameters");
        handler.document.appendChild(parameters);

        handler.appendParametersList(context, vr, parameters, dependencies, parameterDefinitions, new HashMap(),
                null);
        examineInitialParameters(handler.document);
    }

    @Test
    public void appendChangedParametersList() throws BeanException, ReportDataFactoryException,
            ParserConfigurationException, XPathExpressionException, CloneNotSupportedException {

        final LinkedHashMap<String, ParameterDefinitionEntry> parameterDefinitions = getParametersMap();

        final DefaultParameterContext context = getTestParameterContext();
        final ValidationResult vr = new ValidationResult();
        vr.setParameterValues(new ReportParameterValues());

        handler.document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

        final HashNMap<String, String> dependencies = new HashNMap<>();
        dependencies.add("first", "second");
        dependencies.add("first", "fourth");
        dependencies.add("second", "third");
        dependencies.add("third", "seventh");
        dependencies.add("second", "fourth");
        //How about some cycles?
        dependencies.add("fourth", "third");
        dependencies.add("third", "fourth");
        //Independent parameters
        dependencies.add("fifth", "sixth");

        final Element parameters = handler.document.createElement("parameters");
        handler.document.appendChild(parameters);

        handler.appendParametersList(context, vr, parameters, dependencies, parameterDefinitions, new HashMap(),
                new String[] { "first" });
        examineChangedDependentParameters(handler.document);
    }

    @Test
    public void appendChangedIndependentParametersList() throws BeanException, ReportDataFactoryException,
            ParserConfigurationException, XPathExpressionException, CloneNotSupportedException {

        final LinkedHashMap<String, ParameterDefinitionEntry> parameterDefinitions = getParametersMap();

        final DefaultParameterContext context = getTestParameterContext();
        final ValidationResult vr = new ValidationResult();
        vr.setParameterValues(new ReportParameterValues());

        handler.document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

        final HashNMap<String, String> dependencies = new HashNMap<>();
        dependencies.add("first", "second");
        dependencies.add("second", "third");

        final Element parameters = handler.document.createElement("parameters");
        handler.document.appendChild(parameters);

        handler.appendParametersList(context, vr, parameters, dependencies, parameterDefinitions, new HashedMap(),
                new String[] { "fourth" });
        examineChangedIndependentParameters(handler.document);
    }

    @Test
    public void resetInputParentChanged() throws BeanException, ReportDataFactoryException,
            ParserConfigurationException, XPathExpressionException, CloneNotSupportedException {

        final LinkedHashMap<String, ParameterDefinitionEntry> parameterDefinitions = getParametersMap(false);

        final DefaultParameterContext context = getTestParameterContext();
        final ValidationResult vr = new ValidationResult();
        vr.setParameterValues(new ReportParameterValues());

        handler.document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

        final HashNMap<String, String> dependencies = new HashNMap<>();
        dependencies.add("first", "second");
        dependencies.add("second", "third");

        final Element parameters = handler.document.createElement("parameters");
        handler.document.appendChild(parameters);

        final Map<String, Object> inputs = new HashMap<>();
        inputs.put("first", new String[] { "c11", "c10" });
        inputs.put("second", new String[] { "c11", "c10" });
        inputs.put("third", new String[] { "c11", "c10" });
        handler.appendParametersList(context, vr, parameters, dependencies, parameterDefinitions, inputs,
                new String[] { "first" });
        examineChangedResetParameters(handler.document);
    }

    @Test
    public void resetInputParentChangedChildSentFromUI() throws BeanException, ReportDataFactoryException,
            ParserConfigurationException, XPathExpressionException, CloneNotSupportedException {

        final LinkedHashMap<String, ParameterDefinitionEntry> parameterDefinitions = getParametersMap(false);

        final DefaultParameterContext context = getTestParameterContext();
        final ValidationResult vr = new ValidationResult();
        vr.setParameterValues(new ReportParameterValues());

        handler.document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

        final HashNMap<String, String> dependencies = new HashNMap<>();
        dependencies.add("first", "second");
        dependencies.add("second", "third");

        final Element parameters = handler.document.createElement("parameters");
        handler.document.appendChild(parameters);

        final Map<String, Object> inputs = new HashMap<>();
        inputs.put("first", new String[] { "c11", "c10" });
        inputs.put("second", new String[] { "c11", "c10" });
        inputs.put("third", new String[] { "c11", "c10" });
        handler.appendParametersList(context, vr, parameters, dependencies, parameterDefinitions, inputs,
                new String[] { "first", "second" });
        examineChangedResetParameters(handler.document);
    }

    @Test
    public void resetInputParentInTheMiddleChangedChildSentFromUI()
            throws BeanException, ReportDataFactoryException, ParserConfigurationException,
            XPathExpressionException, CloneNotSupportedException {

        final LinkedHashMap<String, ParameterDefinitionEntry> parameterDefinitions = getParametersMap(false);

        final DefaultParameterContext context = getTestParameterContext();
        final ValidationResult vr = new ValidationResult();
        vr.setParameterValues(new ReportParameterValues());

        handler.document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

        final HashNMap<String, String> dependencies = new HashNMap<>();
        dependencies.add("first", "second");
        dependencies.add("second", "third");

        final Element parameters = handler.document.createElement("parameters");
        handler.document.appendChild(parameters);

        final Map<String, Object> inputs = new HashMap<>();
        inputs.put("first", new String[] { "c11", "c10" });
        inputs.put("second", new String[] { "c11", "c10" });
        inputs.put("third", new String[] { "c11", "c10" });
        handler.appendParametersList(context, vr, parameters, dependencies, parameterDefinitions, inputs,
                new String[] { "third", "second" });
        examineChangedMiddleResetParameters(handler.document);
    }

    private LinkedHashMap<String, ParameterDefinitionEntry> getParametersMap() {
        return getParametersMap(true);
    }

    private LinkedHashMap<String, ParameterDefinitionEntry> getParametersMap(boolean isStrict) {
        final LinkedHashMap<String, ParameterDefinitionEntry> parameterDefinitions = new LinkedHashMap<>();
        final DefaultListParameter parameter = new DefaultListParameter("query", "c1", "c2", "first", true,
                isStrict, String.class);
        final DefaultListParameter parameter1 = new DefaultListParameter("query", "c1", "c2", "second", true,
                isStrict, String.class);
        final DefaultListParameter parameter2 = new DefaultListParameter("query", "c1", "c2", "third", true,
                isStrict, String.class);
        final DefaultListParameter parameter3 = new DefaultListParameter("query", "c1", "c2", "fourth", true,
                isStrict, String.class);
        final DefaultListParameter parameter4 = new DefaultListParameter("query", "c1", "c2", "fifth", true,
                isStrict, String.class);
        final DefaultListParameter parameter5 = new DefaultListParameter("query", "c1", "c2", "sixth", true,
                isStrict, String.class);
        final DefaultListParameter parameter6 = new DefaultListParameter("query", "c1", "c2", "seventh", true,
                isStrict, String.class);
        parameterDefinitions.put("first", parameter);
        parameterDefinitions.put("second", parameter1);
        parameterDefinitions.put("third", parameter2);
        parameterDefinitions.put("fourth", parameter3);
        parameterDefinitions.put("fifth", parameter4);
        parameterDefinitions.put("sixth", parameter5);
        parameterDefinitions.put("seventh", parameter6);
        return parameterDefinitions;
    }

    private void examineInitialParameters(final Document doc) throws XPathExpressionException {
        final XPath xpath = xpathFactory.newXPath();
        final NodeList root = (NodeList) xpath.evaluate("/parameters", doc, XPathConstants.NODESET);
        assertEquals(1, root.getLength());
        final Node minimized = root.item(0).getAttributes().getNamedItem("minimized");
        assertNull(minimized);
        final NodeList nodeList = (NodeList) xpath.evaluate("/parameters/parameter", doc, XPathConstants.NODESET);
        assertEquals(7, nodeList.getLength());
        final NodeList first = (NodeList) xpath.evaluate("/parameters/parameter[@name='first']", doc,
                XPathConstants.NODESET);
        assertEquals(1, first.getLength());
        final NodeList second = (NodeList) xpath.evaluate("/parameters/parameter[@name='second']", doc,
                XPathConstants.NODESET);
        assertEquals(1, second.getLength());
        final NodeList third = (NodeList) xpath.evaluate("/parameters/parameter[@name='third']", doc,
                XPathConstants.NODESET);
        assertEquals(1, third.getLength());
        final NodeList fourth = (NodeList) xpath.evaluate("/parameters/parameter[@name='fourth']", doc,
                XPathConstants.NODESET);
        assertEquals(1, fourth.getLength());
        final NodeList attributes = (NodeList) xpath.evaluate("/parameters/parameter/attribute", doc,
                XPathConstants.NODESET);
        assertTrue(attributes.getLength() != 0);
        final NodeList dependencies = (NodeList) xpath.evaluate("/parameters/parameter/dependencies", doc,
                XPathConstants.NODESET);
        assertTrue(dependencies.getLength() != 0);
    }

    private void examineChangedDependentParameters(final Document doc) throws XPathExpressionException {
        final XPath xpath = xpathFactory.newXPath();
        final NodeList root = (NodeList) xpath.evaluate("/parameters", doc, XPathConstants.NODESET);
        assertEquals(1, root.getLength());
        final Node minimized = root.item(0).getAttributes().getNamedItem("minimized");
        assertNotNull(minimized);
        final NodeList nodeList = (NodeList) xpath.evaluate("/parameters/parameter", doc, XPathConstants.NODESET);
        assertEquals(5, nodeList.getLength());
        final NodeList first = (NodeList) xpath.evaluate("/parameters/parameter[@name='first']", doc,
                XPathConstants.NODESET);
        assertEquals(1, first.getLength());
        final NodeList second = (NodeList) xpath.evaluate("/parameters/parameter[@name='second']", doc,
                XPathConstants.NODESET);
        assertEquals(1, second.getLength());
        final NodeList third = (NodeList) xpath.evaluate("/parameters/parameter[@name='third']", doc,
                XPathConstants.NODESET);
        assertEquals(1, third.getLength());
        final NodeList fourth = (NodeList) xpath.evaluate("/parameters/parameter[@name='fourth']", doc,
                XPathConstants.NODESET);
        assertEquals(1, fourth.getLength());
        final NodeList fifth = (NodeList) xpath.evaluate("/parameters/parameter[@name='fifth']", doc,
                XPathConstants.NODESET);
        assertEquals(0, fifth.getLength());
        final NodeList sixth = (NodeList) xpath.evaluate("/parameters/parameter[@name='sixth']", doc,
                XPathConstants.NODESET);
        assertEquals(0, sixth.getLength());
        final NodeList seventh = (NodeList) xpath.evaluate("/parameters/parameter[@name='seventh']", doc,
                XPathConstants.NODESET);
        assertEquals(1, seventh.getLength());
        final NodeList attributes = (NodeList) xpath.evaluate("/parameters/parameter/attribute", doc,
                XPathConstants.NODESET);
        assertFalse(attributes.getLength() != 0);
        final NodeList dependencies = (NodeList) xpath.evaluate("/parameters/parameter/dependencies", doc,
                XPathConstants.NODESET);
        assertFalse(dependencies.getLength() != 0);
    }

    private void examineChangedIndependentParameters(final Document doc) throws XPathExpressionException {
        final XPath xpath = xpathFactory.newXPath();
        final NodeList root = (NodeList) xpath.evaluate("/parameters", doc, XPathConstants.NODESET);
        assertEquals(1, root.getLength());
        final Node minimized = root.item(0).getAttributes().getNamedItem("minimized");
        assertNotNull(minimized);
        final NodeList nodeList = (NodeList) xpath.evaluate("/parameters/parameter", doc, XPathConstants.NODESET);
        assertEquals(1, nodeList.getLength());
        final NodeList first = (NodeList) xpath.evaluate("/parameters/parameter[@name='first']", doc,
                XPathConstants.NODESET);
        assertEquals(0, first.getLength());
        final NodeList second = (NodeList) xpath.evaluate("/parameters/parameter[@name='second']", doc,
                XPathConstants.NODESET);
        assertEquals(0, second.getLength());
        final NodeList third = (NodeList) xpath.evaluate("/parameters/parameter[@name='third']", doc,
                XPathConstants.NODESET);
        assertEquals(0, third.getLength());
        final NodeList fourth = (NodeList) xpath.evaluate("/parameters/parameter[@name='fourth']", doc,
                XPathConstants.NODESET);
        assertEquals(1, fourth.getLength());
        final NodeList attributes = (NodeList) xpath.evaluate("/parameters/parameter/attribute", doc,
                XPathConstants.NODESET);
        assertFalse(attributes.getLength() != 0);
        final NodeList dependencies = (NodeList) xpath.evaluate("/parameters/parameter/dependencies", doc,
                XPathConstants.NODESET);
        assertFalse(dependencies.getLength() != 0);
    }

    private void examineChangedResetParameters(final Document doc) throws XPathExpressionException {
        final XPath xpath = xpathFactory.newXPath();
        final NodeList root = (NodeList) xpath.evaluate("/parameters", doc, XPathConstants.NODESET);
        assertEquals(1, root.getLength());
        final Node minimized = root.item(0).getAttributes().getNamedItem("minimized");
        assertNotNull(minimized);
        final NodeList nodeList = (NodeList) xpath.evaluate("/parameters/parameter", doc, XPathConstants.NODESET);
        assertEquals(3, nodeList.getLength());
        final NodeList first = (NodeList) xpath.evaluate("/parameters/parameter[@name='first']", doc,
                XPathConstants.NODESET);
        assertEquals(1, first.getLength());
        final NodeList firstValues = (NodeList) xpath.evaluate("/parameters/parameter[@name='first']/values/value",
                doc, XPathConstants.NODESET);
        assertEquals(2, firstValues.getLength());
        final NodeList firstSelectedValues = (NodeList) xpath.evaluate(
                "/parameters/parameter[@name='first']/values/value[@selected='true']", doc, XPathConstants.NODESET);
        assertEquals(2, firstSelectedValues.getLength());
        final NodeList second = (NodeList) xpath.evaluate("/parameters/parameter[@name='second']", doc,
                XPathConstants.NODESET);
        assertEquals(1, second.getLength());
        final NodeList secondValues = (NodeList) xpath
                .evaluate("/parameters/parameter[@name='second']/values/value", doc, XPathConstants.NODESET);
        assertEquals(2, secondValues.getLength());
        //Values are reset
        final NodeList secondSelectedValues = (NodeList) xpath.evaluate(
                "/parameters/parameter[@name='second']/values/value[@selected='true']", doc,
                XPathConstants.NODESET);
        assertEquals(0, secondSelectedValues.getLength());
        final NodeList third = (NodeList) xpath.evaluate("/parameters/parameter[@name='third']", doc,
                XPathConstants.NODESET);
        assertEquals(1, third.getLength());
        final NodeList thirdValues = (NodeList) xpath.evaluate("/parameters/parameter[@name='third']/values/value",
                doc, XPathConstants.NODESET);
        assertEquals(2, thirdValues.getLength());
        //Deeper levels are also reset
        final NodeList thirdSelectedValues = (NodeList) xpath.evaluate(
                "/parameters/parameter[@name='third']/values/value[@selected='true']", doc, XPathConstants.NODESET);
        assertEquals(0, thirdSelectedValues.getLength());
        final NodeList fourth = (NodeList) xpath.evaluate("/parameters/parameter[@name='fourth']", doc,
                XPathConstants.NODESET);
        assertEquals(0, fourth.getLength());
        final NodeList attributes = (NodeList) xpath.evaluate("/parameters/parameter/attribute", doc,
                XPathConstants.NODESET);
        assertFalse(attributes.getLength() != 0);
        final NodeList dependencies = (NodeList) xpath.evaluate("/parameters/parameter/dependencies", doc,
                XPathConstants.NODESET);
        assertFalse(dependencies.getLength() != 0);
    }

    private void examineChangedMiddleResetParameters(final Document doc) throws XPathExpressionException {
        final XPath xpath = xpathFactory.newXPath();
        final NodeList root = (NodeList) xpath.evaluate("/parameters", doc, XPathConstants.NODESET);
        assertEquals(1, root.getLength());
        final Node minimized = root.item(0).getAttributes().getNamedItem("minimized");
        assertNotNull(minimized);
        final NodeList nodeList = (NodeList) xpath.evaluate("/parameters/parameter", doc, XPathConstants.NODESET);
        assertEquals(2, nodeList.getLength());
        final NodeList first = (NodeList) xpath.evaluate("/parameters/parameter[@name='first']", doc,
                XPathConstants.NODESET);
        assertEquals(0, first.getLength());
        final NodeList second = (NodeList) xpath.evaluate("/parameters/parameter[@name='second']", doc,
                XPathConstants.NODESET);
        assertEquals(1, second.getLength());
        final NodeList secondValues = (NodeList) xpath
                .evaluate("/parameters/parameter[@name='second']/values/value", doc, XPathConstants.NODESET);
        assertEquals(2, secondValues.getLength());
        //Values are not reset
        final NodeList secondSelectedValues = (NodeList) xpath.evaluate(
                "/parameters/parameter[@name='second']/values/value[@selected='true']", doc,
                XPathConstants.NODESET);
        assertEquals(2, secondSelectedValues.getLength());
        final NodeList third = (NodeList) xpath.evaluate("/parameters/parameter[@name='third']", doc,
                XPathConstants.NODESET);
        assertEquals(1, third.getLength());
        final NodeList thirdValues = (NodeList) xpath.evaluate("/parameters/parameter[@name='third']/values/value",
                doc, XPathConstants.NODESET);
        assertEquals(2, thirdValues.getLength());
        //Deeper levels are reset
        final NodeList thirdSelectedValues = (NodeList) xpath.evaluate(
                "/parameters/parameter[@name='third']/values/value[@selected='true']", doc, XPathConstants.NODESET);
        assertEquals(0, thirdSelectedValues.getLength());
        final NodeList fourth = (NodeList) xpath.evaluate("/parameters/parameter[@name='fourth']", doc,
                XPathConstants.NODESET);
        assertEquals(0, fourth.getLength());
        final NodeList attributes = (NodeList) xpath.evaluate("/parameters/parameter/attribute", doc,
                XPathConstants.NODESET);
        assertFalse(attributes.getLength() != 0);
        final NodeList dependencies = (NodeList) xpath.evaluate("/parameters/parameter/dependencies", doc,
                XPathConstants.NODESET);
        assertFalse(dependencies.getLength() != 0);
    }

    private boolean isThereAttributes(final Document doc) throws XPathExpressionException {
        final XPath xpath = xpathFactory.newXPath();
        final NodeList nodeList = (NodeList) xpath.evaluate("/parameter/attribute", doc, XPathConstants.NODESET);
        return nodeList.getLength() != 0;
    }
}