org.apache.sling.api.wrappers.CompositeValueMapTest.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.sling.api.wrappers.CompositeValueMapTest.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
package org.apache.sling.api.wrappers;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.sling.api.resource.ValueMap;
import org.junit.Assert;
import org.junit.Test;

public class CompositeValueMapTest {

    // Test property names
    private static final String PROP_NAME_UNCHANGED = "unchangedProp";
    private static final String PROP_NAME_OVERRIDDEN = "overriddenProp";
    private static final String PROP_NAME_NEW_TYPE = "newTypeProp";
    private static final String PROP_NAME_ADDED = "addedProp";
    private static final String PROP_NAME_DOES_NOT_EXIST = "doesNotExistProp";

    // Default resource's property values
    private static final String PROP_DEFAULT_UNCHANGED = "Default value of property '" + PROP_NAME_UNCHANGED + "'";
    private static final String PROP_DEFAULT_OVERRIDDEN = "Default value of property '" + PROP_NAME_OVERRIDDEN
            + "'";
    private static final String PROP_DEFAULT_NEW_TYPE = "10";

    // Extended resource's property values
    private static final String PROP_EXTENDED_OVERRIDDEN = "Extended value of property '" + PROP_NAME_OVERRIDDEN
            + "'";
    private static final Long PROP_EXTENDED_NEW_TYPE = 10L;
    private static final String PROP_EXTENDED_ADDED = "Extended value of property '" + PROP_NAME_ADDED + "'";

    private Map<String, Object> defaultProps = getDefaultProps();
    private Map<String, Object> extendedProps = getExtendedProps();

    @Test
    public void testMerge() throws Exception {
        // Get value map for extended node using default node as defaults
        CompositeValueMap valueMap = new CompositeValueMap(getExtendedProps(), getDefaultProps());

        Set<CompositeValueMapTestResult> expectations = new HashSet<CompositeValueMapTestResult>();
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_UNCHANGED));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_OVERRIDDEN));
        expectations
                .add(new CompositeValueMapTestResult(PROP_NAME_NEW_TYPE, false, PROP_EXTENDED_NEW_TYPE.getClass()));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_ADDED));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_DOES_NOT_EXIST));

        verifyResults(valueMap, expectations);
    }

    @Test
    public void testMergeNoDefaults() throws Exception {
        // Get value map for extended node using an empty default
        CompositeValueMap valueMap = new CompositeValueMap(getExtendedProps(), null);

        Set<CompositeValueMapTestResult> expectations = new HashSet<CompositeValueMapTestResult>();
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_UNCHANGED, true)); // Property won't exist as there is no default
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_OVERRIDDEN));
        expectations
                .add(new CompositeValueMapTestResult(PROP_NAME_NEW_TYPE, false, PROP_EXTENDED_NEW_TYPE.getClass()));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_ADDED));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_DOES_NOT_EXIST));

        verifyResults(valueMap, expectations);
    }

    @Test
    public void testOverride() throws Exception {
        // Get value map for extended node using default node as defaults
        // and override only mode
        CompositeValueMap valueMap = new CompositeValueMap(getExtendedProps(), getDefaultProps(), false);

        Set<CompositeValueMapTestResult> expectations = new HashSet<CompositeValueMapTestResult>();
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_UNCHANGED));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_OVERRIDDEN));
        expectations
                .add(new CompositeValueMapTestResult(PROP_NAME_NEW_TYPE, false, PROP_EXTENDED_NEW_TYPE.getClass()));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_ADDED, true)); // Property won't exist as there is no default and it's an override
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_DOES_NOT_EXIST));

        verifyResults(valueMap, expectations);
    }

    @Test
    public void testOverrideNoDefaults() throws Exception {
        // Get value map for extended node using an empty default
        // and override only mode
        CompositeValueMap valueMap = new CompositeValueMap(getExtendedProps(), null, false);

        Assert.assertTrue("Final map should be empty", valueMap.isEmpty());
    }

    private ValueMap getDefaultProps() {
        final Map<String, Object> defaultProps = new HashMap<String, Object>();

        defaultProps.put(PROP_NAME_UNCHANGED, PROP_DEFAULT_UNCHANGED);
        defaultProps.put(PROP_NAME_OVERRIDDEN, PROP_DEFAULT_OVERRIDDEN);
        defaultProps.put(PROP_NAME_NEW_TYPE, PROP_DEFAULT_NEW_TYPE);

        return new ValueMapDecorator(defaultProps);
    }

    private ValueMap getExtendedProps() {
        final Map<String, Object> defaultProps = new HashMap<String, Object>();

        defaultProps.put(PROP_NAME_OVERRIDDEN, PROP_EXTENDED_OVERRIDDEN);
        defaultProps.put(PROP_NAME_NEW_TYPE, PROP_EXTENDED_NEW_TYPE);
        defaultProps.put(PROP_NAME_ADDED, PROP_EXTENDED_ADDED);

        return new ValueMapDecorator(defaultProps);
    }

    private void verifyResults(CompositeValueMap valueMap, Set<CompositeValueMapTestResult> expectations) {
        Map<String, Object> expectedMap = new HashMap<String, Object>();

        int expectedSize = 0;
        for (CompositeValueMapTestResult testResult : expectations) {
            String property = testResult.propertyName;

            if (testResult.doesNotExist()) {
                Assert.assertFalse("Property '" + property + "' should NOT exist", valueMap.containsKey(property));

            } else if (testResult.shouldBeDeleted()) {
                Assert.assertFalse("Property '" + property + "' should NOT be part of the final map",
                        valueMap.containsKey(property));
                Assert.assertNull("Property '" + property + "' should be null", valueMap.get(property));

            } else {
                Assert.assertTrue("Property '" + property + "' should be part of the final map",
                        valueMap.containsKey(property));
                expectedSize++;

                if (testResult.shouldBeUnchanged()) {
                    Assert.assertEquals("Property '" + property + "' should NOT have changed",
                            testResult.defaultValue, valueMap.get(property));
                    expectedMap.put(property, testResult.defaultValue);
                }

                if (testResult.shouldBeOverriden()) {
                    Assert.assertEquals("Property '" + property + "' should have changed", testResult.extendedValue,
                            valueMap.get(property));
                    expectedMap.put(property, testResult.extendedValue);
                }

                if (testResult.shouldHaveNewType()) {
                    Assert.assertTrue("Type of property '" + property + "' should have changed",
                            valueMap.get(property).getClass().equals(testResult.expectedNewType));
                    expectedMap.put(property, testResult.extendedValue);
                }

                if (testResult.shouldBeAdded()) {
                    Assert.assertEquals("Property '" + property + "' should have been added",
                            testResult.extendedValue, valueMap.get(property));
                    expectedMap.put(property, testResult.extendedValue);
                }
            }
        }

        Assert.assertEquals("Final map size does NOT match", expectedSize, valueMap.size());
        Assert.assertEquals("Final map entries do NOT match", expectedMap.entrySet(), valueMap.entrySet());
        Assert.assertEquals("Final map keys do NOT match", expectedMap.keySet(), valueMap.keySet());
        Assert.assertTrue(
                "Final map values do NOT match expected: <" + expectedMap.values() + "> but was: <"
                        + valueMap.values() + ">",
                CollectionUtils.isEqualCollection(expectedMap.values(), valueMap.values()));
    }

    /**
     * <code>CompositeValueMapTestResult</code> is an internal helper to analyze
     * test result and check if the value retrieved from the map matches the
     * expected value.
     */
    private class CompositeValueMapTestResult {
        private final String propertyName;
        private final Object defaultValue;
        private final Object extendedValue;
        private final boolean shouldBeDeleted;
        private final Class<?> expectedNewType;

        private CompositeValueMapTestResult(String propertyName) {
            this(propertyName, false);
        }

        private CompositeValueMapTestResult(String propertyName, boolean shouldBeDeleted) {
            this(propertyName, shouldBeDeleted, null);
        }

        private CompositeValueMapTestResult(String propertyName, boolean shouldBeDeleted,
                Class<?> expectedNewType) {
            this.propertyName = propertyName;
            this.defaultValue = defaultProps.get(propertyName);
            this.extendedValue = extendedProps.get(propertyName);
            this.shouldBeDeleted = shouldBeDeleted;
            this.expectedNewType = expectedNewType;
        }

        /**
         * Checks if the value should not have changed
         * @return <code>true</code> if the value should not have changed
         */
        boolean shouldBeUnchanged() {
            return defaultValue != null && extendedValue == null;
        }

        /**
         * Checks if the value should have been overridden
         * @return <code>true</code> if the value should have been overridden
         */
        boolean shouldBeOverriden() {
            return defaultValue != null && extendedValue != null;
        }

        /**
         * Checks if the value should have a new type
         * @return <code>true</code> if the value should have a new type
         */
        boolean shouldHaveNewType() {
            return expectedNewType != null;
        }

        /**
         * Checks if the property should have been added
         * @return <code>true</code> if the property should have been added
         */
        boolean shouldBeAdded() {
            return defaultValue == null && extendedValue != null;
        }

        /**
         * Checks if the property should have been deleted
         * @return <code>true</code> if the property should have been deleted
         */
        boolean shouldBeDeleted() {
            return shouldBeDeleted;
        }

        /**
         * Checks if the property should not exist
         * @return <code>true</code> if the property should not exist
         */
        boolean doesNotExist() {
            return defaultValue == null && extendedValue == null;
        }

    }

}