/*
 * 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.qpid.server.model.testmodels.singleton;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;

import javax.security.auth.Subject;

import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.AbstractConfiguredObject;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Model;
import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.SystemConfig;
import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
import org.apache.qpid.server.security.auth.UsernamePrincipal;
import org.apache.qpid.server.store.ConfiguredObjectRecord;
import org.apache.qpid.test.utils.QpidTestCase;

/**
 * Tests behaviour of AbstractConfiguredObject related to attributes including
 * persistence, defaulting, and attribute values derived from context variables.
 */
public class AbstractConfiguredObjectTest extends QpidTestCase
{
    private final Model _model = TestModel.getInstance();

    public void testAttributePersistence()
    {
        final String objectName = "testNonPersistAttributes";
        TestSingleton object =
                _model.getObjectFactory().create(TestSingleton.class,
                                                Collections.<String, Object>singletonMap(ConfiguredObject.NAME,
                                                                                         objectName)
                                               );

        assertEquals(objectName, object.getName());
        assertNull(object.getAutomatedNonPersistedValue());
        assertNull(object.getAutomatedPersistedValue());
        assertEquals(TestSingletonImpl.DERIVED_VALUE, object.getDerivedValue());

        ConfiguredObjectRecord record = object.asObjectRecord();

        assertEquals(objectName, record.getAttributes().get(ConfiguredObject.NAME));

        assertFalse(record.getAttributes().containsKey(TestSingleton.AUTOMATED_PERSISTED_VALUE));
        assertFalse(record.getAttributes().containsKey(TestSingleton.AUTOMATED_NONPERSISTED_VALUE));
        assertFalse(record.getAttributes().containsKey(TestSingleton.DERIVED_VALUE));

        Map<String, Object> updatedAttributes = new HashMap<>();

        final String newValue = "newValue";

        updatedAttributes.put(TestSingleton.AUTOMATED_PERSISTED_VALUE, newValue);
        updatedAttributes.put(TestSingleton.AUTOMATED_NONPERSISTED_VALUE, newValue);
        updatedAttributes.put(TestSingleton.DERIVED_VALUE, System.currentTimeMillis());  // Will be ignored
        object.setAttributes(updatedAttributes);

        assertEquals(newValue, object.getAutomatedPersistedValue());
        assertEquals(newValue, object.getAutomatedNonPersistedValue());

        record = object.asObjectRecord();
        assertEquals(objectName, record.getAttributes().get(ConfiguredObject.NAME));
        assertEquals(newValue, record.getAttributes().get(TestSingleton.AUTOMATED_PERSISTED_VALUE));

        assertFalse(record.getAttributes().containsKey(TestSingleton.AUTOMATED_NONPERSISTED_VALUE));
        assertFalse(record.getAttributes().containsKey(TestSingleton.DERIVED_VALUE));

    }

    public void testDefaultedAttributeValue()
    {
        final String objectName = "myName";

        Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestSingleton.NAME, objectName);

        TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
                                                                   attributes);

        assertEquals(objectName, object1.getName());
        assertEquals(TestSingleton.DEFAULTED_VALUE_DEFAULT, object1.getDefaultedValue());
    }

    public void testOverriddenDefaultedAttributeValue()
    {
        final String objectName = "myName";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(TestSingleton.NAME, objectName);
        attributes.put(TestSingleton.DEFAULTED_VALUE, "override");

        TestSingleton object = _model.getObjectFactory().create(TestSingleton.class,
                                                                   attributes);

        assertEquals(objectName, object.getName());
        assertEquals("override", object.getDefaultedValue());

    }

    public void testOverriddenDefaultedAttributeValueRevertedToDefault()
    {
        final String objectName = "myName";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(TestSingleton.NAME, objectName);
        attributes.put(TestSingleton.DEFAULTED_VALUE, "override");

        TestSingleton object = _model.getObjectFactory().create(TestSingleton.class,
                                                                   attributes);

        assertEquals(objectName, object.getName());
        assertEquals("override", object.getDefaultedValue());

        object.setAttributes(Collections.singletonMap(TestSingleton.DEFAULTED_VALUE, null));

        assertEquals(TestSingleton.DEFAULTED_VALUE_DEFAULT, object.getDefaultedValue());
    }

    public void testDefaultInitialization()
    {
        TestSingleton object =
                _model.getObjectFactory().create(TestSingleton.class,
                                                 Collections.<String, Object>singletonMap(ConfiguredObject.NAME,
                                                                                          "testDefaultInitialization")
                                                );
        assertEquals(object.getAttrWithDefaultFromContextNoInit(), TestSingleton.testGlobalDefault);
        assertEquals(object.getAttrWithDefaultFromContextCopyInit(), TestSingleton.testGlobalDefault);
        assertEquals(object.getAttrWithDefaultFromContextMaterializeInit(), TestSingleton.testGlobalDefault);

        assertFalse(object.getActualAttributes().containsKey("attrWithDefaultFromContextNoInit"));
        assertEquals("${"+TestSingleton.TEST_CONTEXT_DEFAULT+"}",object.getActualAttributes().get("attrWithDefaultFromContextCopyInit"));
        assertEquals(TestSingleton.testGlobalDefault,object.getActualAttributes().get("attrWithDefaultFromContextMaterializeInit"));


        Map<String, Object> attributes = new HashMap<>();
        attributes.put(ConfiguredObject.NAME, "testDefaultInitialization2");
        attributes.put(ConfiguredObject.CONTEXT, Collections.singletonMap(TestSingleton.TEST_CONTEXT_DEFAULT, "foo"));
        object = _model.getObjectFactory().create(TestSingleton.class,
                                         attributes
                                        );
        assertEquals("foo", object.getAttrWithDefaultFromContextNoInit());
        assertEquals("foo", object.getAttrWithDefaultFromContextCopyInit());
        assertEquals("foo", object.getAttrWithDefaultFromContextMaterializeInit());

        assertFalse(object.getActualAttributes().containsKey("attrWithDefaultFromContextNoInit"));
        assertEquals("${"+TestSingleton.TEST_CONTEXT_DEFAULT+"}",object.getActualAttributes().get("attrWithDefaultFromContextCopyInit"));
        assertEquals("foo",object.getActualAttributes().get("attrWithDefaultFromContextMaterializeInit"));


        setTestSystemProperty(TestSingleton.TEST_CONTEXT_DEFAULT, "bar");
        object = _model.getObjectFactory().create(TestSingleton.class,
                                        Collections.<String, Object>singletonMap(ConfiguredObject.NAME,
                                                                                 "testDefaultInitialization3")
                                       );

        assertEquals("bar", object.getAttrWithDefaultFromContextNoInit());
        assertEquals("bar", object.getAttrWithDefaultFromContextCopyInit());
        assertEquals("bar", object.getAttrWithDefaultFromContextMaterializeInit());

        assertFalse(object.getActualAttributes().containsKey("attrWithDefaultFromContextNoInit"));
        assertEquals("${"+TestSingleton.TEST_CONTEXT_DEFAULT+"}",object.getActualAttributes().get("attrWithDefaultFromContextCopyInit"));
        assertEquals("bar",object.getActualAttributes().get("attrWithDefaultFromContextMaterializeInit"));

    }

    public void testEnumAttributeValueFromString()
    {
        final String objectName = "myName";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(TestSingleton.NAME, objectName);
        attributes.put(TestSingleton.ENUM_VALUE, TestEnum.TEST_ENUM1.name());

        TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
                                                                    attributes);

        assertEquals(objectName, object1.getName());
        assertEquals(TestEnum.TEST_ENUM1, object1.getEnumValue());
    }

    public void testEnumAttributeValueFromEnum()
    {
        final String objectName = "myName";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(TestSingleton.NAME, objectName);
        attributes.put(TestSingleton.ENUM_VALUE, TestEnum.TEST_ENUM1);

        TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
                                                                    attributes);

        assertEquals(objectName, object1.getName());
        assertEquals(TestEnum.TEST_ENUM1, object1.getEnumValue());
    }

    public void testIntegerAttributeValueFromString()
    {
        final String objectName = "myName";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(TestSingleton.NAME, objectName);
        attributes.put(TestSingleton.INT_VALUE, "-4");

        TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
                                                                     attributes);

        assertEquals(objectName, object1.getName());
        assertEquals(-4, object1.getIntValue());
    }

    public void testIntegerAttributeValueFromInteger()
    {
        final String objectName = "myName";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(TestSingleton.NAME, objectName);
        attributes.put(TestSingleton.INT_VALUE, 5);

        TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
                                                                     attributes);

        assertEquals(objectName, object1.getName());
        assertEquals(5, object1.getIntValue());
    }

    public void testIntegerAttributeValueFromDouble()
    {
        final String objectName = "myName";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(TestSingleton.NAME, objectName);
        attributes.put(TestSingleton.INT_VALUE, 6.1);

        TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);

        assertEquals(objectName, object.getName());
        assertEquals(6, object.getIntValue());
    }

    public void testDateAttributeFromMillis()
    {
        final String objectName = "myName";
        long now = System.currentTimeMillis();

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(TestSingleton.NAME, objectName);
        attributes.put(TestSingleton.DATE_VALUE, now);

        TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);

        assertEquals(objectName, object.getName());
        assertEquals(new Date(now), object.getDateValue());
    }

    public void testDateAttributeFromIso8601()
    {
        final String objectName = "myName";
        String date = "1970-01-01Z";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(TestSingleton.NAME, objectName);
        attributes.put(TestSingleton.DATE_VALUE, date);

        TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);

        assertEquals(objectName, object.getName());
        assertEquals(new Date(0), object.getDateValue());
    }

    public void testStringAttributeValueFromContextVariableProvidedBySystemProperty()
    {
        String sysPropertyName = "testStringAttributeValueFromContextVariableProvidedBySystemProperty";
        String contextToken = "${" + sysPropertyName + "}";

        System.setProperty(sysPropertyName, "myValue");

        final String objectName = "myName";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(TestSingleton.NAME, objectName);
        attributes.put(TestSingleton.STRING_VALUE, contextToken);

        TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
                                                                    attributes);

        assertEquals(objectName, object1.getName());
        assertEquals("myValue", object1.getStringValue());

        // System property set empty string

        System.setProperty(sysPropertyName, "");
        TestSingleton object2 = _model.getObjectFactory().create(TestSingleton.class,
                                                                    attributes);

        assertEquals("", object2.getStringValue());

        // System property not set
        System.clearProperty(sysPropertyName);

        TestSingleton object3 = _model.getObjectFactory().create(TestSingleton.class,
                                                                    attributes);

        // yields the unexpanded token - not sure if this is really useful behaviour?
        assertEquals(contextToken, object3.getStringValue());
    }

    public void testMapAttributeValueFromContextVariableProvidedBySystemProperty()
    {
        String sysPropertyName = "testMapAttributeValueFromContextVariableProvidedBySystemProperty";
        String contextToken = "${" + sysPropertyName + "}";

        Map<String,String> expectedMap = new HashMap<>();
        expectedMap.put("field1", "value1");
        expectedMap.put("field2", "value2");

        System.setProperty(sysPropertyName, "{ \"field1\" : \"value1\", \"field2\" : \"value2\"}");

        final String objectName = "myName";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(TestSingleton.NAME, objectName);
        attributes.put(TestSingleton.MAP_VALUE, contextToken);

        TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
                                                                    attributes);

        assertEquals(objectName, object1.getName());
        assertEquals(expectedMap, object1.getMapValue());

        // System property not set
        System.clearProperty(sysPropertyName);
    }

    public void testStringAttributeValueFromContextVariableProvidedObjectsContext()
    {
        String contextToken = "${myReplacement}";

        final String objectName = "myName";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(ConfiguredObject.NAME, objectName);
        attributes.put(ConfiguredObject.CONTEXT, Collections.singletonMap("myReplacement", "myValue"));
        attributes.put(TestSingleton.STRING_VALUE, contextToken);

        TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
                                                                    attributes);
        // Check the object's context itself
        assertTrue(object1.getContext().containsKey("myReplacement"));
        assertEquals("myValue", object1.getContext().get("myReplacement"));

        assertEquals(objectName, object1.getName());
        assertEquals("myValue", object1.getStringValue());
    }

    public void testInvalidIntegerAttributeValueFromContextVariable()
    {
        final Map<String, Object> attributes = new HashMap<>();

        attributes.put(TestSingleton.NAME, "myName");
        attributes.put(TestSingleton.TYPE, TestSingletonImpl.TEST_SINGLETON_TYPE);
        attributes.put(TestSingleton.CONTEXT, Collections.singletonMap("contextVal", "notAnInteger"));
        attributes.put(TestSingleton.INT_VALUE, "${contextVal}");

        try
        {
            _model.getObjectFactory().create(TestSingleton.class, attributes);
            fail("creation of child object should have failed due to invalid value");
        }
        catch (IllegalArgumentException e)
        {
            // PASS
            String message = e.getMessage();
            assertTrue("Message does not contain the attribute name", message.contains("intValue"));
            assertTrue("Message does not contain the non-interpolated value", message.contains("contextVal"));
            assertTrue("Message does not contain the interpolated value", message.contains("contextVal"));

        }
    }

    public void testCreateEnforcesAttributeValidValues() throws Exception
    {
        final String objectName = getName();
        Map<String, Object> illegalCreateAttributes = new HashMap<>();
        illegalCreateAttributes.put(ConfiguredObject.NAME, objectName);
        illegalCreateAttributes.put(TestSingleton.VALID_VALUE, "illegal");

        try
        {
            _model.getObjectFactory().create(TestSingleton.class, illegalCreateAttributes);
            fail("Exception not thrown");
        }
        catch (IllegalConfigurationException ice)
        {
            // PASS
        }

        Map<String, Object> legalCreateAttributes = new HashMap<>();
        legalCreateAttributes.put(ConfiguredObject.NAME, objectName);
        legalCreateAttributes.put(TestSingleton.VALID_VALUE, TestSingleton.VALID_VALUE1);

        TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, legalCreateAttributes);
        assertEquals(TestSingleton.VALID_VALUE1, object.getValidValue());
    }

    public void testCreateEnforcesAttributeValidValuePattern() throws Exception
    {
        final String objectName = getName();
        Map<String, Object> illegalCreateAttributes = new HashMap<>();
        illegalCreateAttributes.put(ConfiguredObject.NAME, objectName);
        illegalCreateAttributes.put(TestSingleton.VALUE_WITH_PATTERN, "illegal");

        try
        {
            _model.getObjectFactory().create(TestSingleton.class, illegalCreateAttributes);
            fail("Exception not thrown");
        }
        catch (IllegalConfigurationException ice)
        {
            // PASS
        }

        illegalCreateAttributes = new HashMap<>();
        illegalCreateAttributes.put(ConfiguredObject.NAME, objectName);
        illegalCreateAttributes.put(TestSingleton.LIST_VALUE_WITH_PATTERN, Arrays.asList("1.1.1.1", "1"));

        try
        {
            _model.getObjectFactory().create(TestSingleton.class, illegalCreateAttributes);
            fail("Exception not thrown");
        }
        catch (IllegalConfigurationException ice)
        {
            // PASS
        }


        Map<String, Object> legalCreateAttributes = new HashMap<>();
        legalCreateAttributes.put(ConfiguredObject.NAME, objectName);
        legalCreateAttributes.put(TestSingleton.VALUE_WITH_PATTERN, "foozzzzzbar");
        legalCreateAttributes.put(TestSingleton.LIST_VALUE_WITH_PATTERN, Arrays.asList("1.1.1.1", "255.255.255.255"));

        TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, legalCreateAttributes);
        assertEquals("foozzzzzbar", object.getValueWithPattern());
    }


    public void testChangeEnforcesAttributeValidValues() throws Exception
    {
        final String objectName = getName();
        Map<String, Object> legalCreateAttributes = new HashMap<>();
        legalCreateAttributes.put(ConfiguredObject.NAME, objectName);
        legalCreateAttributes.put(TestSingleton.VALID_VALUE, TestSingleton.VALID_VALUE1);

        TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, legalCreateAttributes);
        assertEquals(TestSingleton.VALID_VALUE1, object.getValidValue());

        object.setAttributes(Collections.singletonMap(TestSingleton.VALID_VALUE, TestSingleton.VALID_VALUE2));
        assertEquals(TestSingleton.VALID_VALUE2, object.getValidValue());

        try
        {
            object.setAttributes(Collections.singletonMap(TestSingleton.VALID_VALUE, "illegal"));
            fail("Exception not thrown");
        }
        catch (IllegalConfigurationException iae)
        {
            // PASS
        }

        assertEquals(TestSingleton.VALID_VALUE2, object.getValidValue());

        object.setAttributes(Collections.singletonMap(TestSingleton.VALID_VALUE, null));
        assertNull(object.getValidValue());

    }

    public void testCreateEnforcesAttributeValidValuesWithSets() throws Exception
    {
        final String objectName = getName();
        final Map<String, Object> name = Collections.singletonMap(ConfiguredObject.NAME, (Object)objectName);

        Map<String, Object> illegalCreateAttributes = new HashMap<>(name);
        illegalCreateAttributes.put(TestSingleton.ENUMSET_VALUES, Collections.singleton(TestEnum.TEST_ENUM3));

        try
        {
            _model.getObjectFactory().create(TestSingleton.class, illegalCreateAttributes);
            fail("Exception not thrown");
        }
        catch (IllegalConfigurationException ice)
        {
            // PASS
        }

        {
            Map<String, Object> legalCreateAttributesEnums = new HashMap<>(name);
            legalCreateAttributesEnums.put(TestSingleton.ENUMSET_VALUES,
                                           Arrays.asList(TestEnum.TEST_ENUM2, TestEnum.TEST_ENUM3));

            TestSingleton obj = _model.getObjectFactory().create(TestSingleton.class, legalCreateAttributesEnums);
            assertTrue(obj.getEnumSetValues().containsAll(Arrays.asList(TestEnum.TEST_ENUM2, TestEnum.TEST_ENUM3)));
        }

        {
            Map<String, Object> legalCreateAttributesStrings = new HashMap<>(name);
            legalCreateAttributesStrings.put(TestSingleton.ENUMSET_VALUES,
                                             Arrays.asList(TestEnum.TEST_ENUM2.name(), TestEnum.TEST_ENUM3.name()));

            TestSingleton
                    obj = _model.getObjectFactory().create(TestSingleton.class, legalCreateAttributesStrings);
            assertTrue(obj.getEnumSetValues().containsAll(Arrays.asList(TestEnum.TEST_ENUM2, TestEnum.TEST_ENUM3)));
        }
    }


    public void testChangeEnforcesAttributeValidValuePatterns() throws Exception
    {
        final String objectName = getName();
        Map<String, Object> legalCreateAttributes = new HashMap<>();
        legalCreateAttributes.put(ConfiguredObject.NAME, objectName);
        legalCreateAttributes.put(TestSingleton.VALUE_WITH_PATTERN, "foozzzzzbar");
        legalCreateAttributes.put(TestSingleton.LIST_VALUE_WITH_PATTERN, Arrays.asList("1.1.1.1", "255.255.255.255"));

        TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, legalCreateAttributes);
        assertEquals("foozzzzzbar", object.getValueWithPattern());
        assertEquals(Arrays.asList("1.1.1.1", "255.255.255.255"), object.getListValueWithPattern());

        object.setAttributes(Collections.singletonMap(TestSingleton.VALUE_WITH_PATTERN, "foobar"));
        assertEquals("foobar", object.getValueWithPattern());

        object.setAttributes(Collections.singletonMap(TestSingleton.LIST_VALUE_WITH_PATTERN, Collections.singletonList("1.2.3.4")));
        assertEquals(Collections.singletonList("1.2.3.4"), object.getListValueWithPattern());


        try
        {
            object.setAttributes(Collections.singletonMap(TestSingleton.VALUE_WITH_PATTERN, "foobaz"));
            fail("Exception not thrown");
        }
        catch (IllegalConfigurationException iae)
        {
            // PASS
        }


        try
        {
            object.setAttributes(Collections.singletonMap(TestSingleton.LIST_VALUE_WITH_PATTERN, Arrays.asList("1.1.1.1", "1")));
            fail("Exception not thrown");
        }
        catch (IllegalConfigurationException iae)
        {
            // PASS
        }

        assertEquals("foobar", object.getValueWithPattern());
        assertEquals(Collections.singletonList("1.2.3.4"), object.getListValueWithPattern());


        object.setAttributes(Collections.singletonMap(TestSingleton.VALUE_WITH_PATTERN, null));
        assertNull(object.getValueWithPattern());

        object.setAttributes(Collections.singletonMap(TestSingleton.LIST_VALUE_WITH_PATTERN, Collections.emptyList()));
        assertEquals(Collections.emptyList(), object.getListValueWithPattern());

        object.setAttributes(Collections.singletonMap(TestSingleton.LIST_VALUE_WITH_PATTERN, null));
        assertNull(object.getListValueWithPattern());

    }

    public void testDefaultContextIsInContextKeys()
    {
        final String objectName = "myName";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(ConfiguredObject.NAME, objectName);

        TestSingleton object = _model.getObjectFactory().create(TestSingleton.class,
                                                                    attributes);


        assertTrue("context default not in contextKeys",
                   object.getContextKeys(true).contains(TestSingleton.TEST_CONTEXT_DEFAULT));
        assertEquals("default",
                     object.getContextValue(String.class, TestSingleton.TEST_CONTEXT_DEFAULT));

        setTestSystemProperty(TestSingleton.TEST_CONTEXT_DEFAULT, "notdefault");
        assertTrue("context default not in contextKeys",
                   object.getContextKeys(true).contains(TestSingleton.TEST_CONTEXT_DEFAULT));
        assertEquals("notdefault", object.getContextValue(String.class, TestSingleton.TEST_CONTEXT_DEFAULT));
    }

    public void testDefaultContextVariableWhichRefersToThis()
    {
        final String objectName = "myName";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(ConfiguredObject.NAME, objectName);

        TestSingleton object = _model.getObjectFactory().create(TestSingleton.class,
                                                                attributes);

        assertTrue("context default not in contextKeys",
                   object.getContextKeys(true).contains(TestSingleton.TEST_CONTEXT_DEFAULT_WITH_THISREF));

        String expected = "a context var that refers to an attribute " + objectName;
        assertEquals(expected, object.getContextValue(String.class, TestSingleton.TEST_CONTEXT_DEFAULT_WITH_THISREF));
    }

    public void testDerivedAttributeValue()
    {
        final String objectName = "myName";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(ConfiguredObject.NAME, objectName);

        TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
        assertEquals(TestSingletonImpl.DERIVED_VALUE, object.getDerivedValue());

        // Check that update is ignored
        object.setAttributes(Collections.singletonMap(TestSingleton.DERIVED_VALUE, System.currentTimeMillis()));

        assertEquals(TestSingletonImpl.DERIVED_VALUE, object.getDerivedValue());
    }

    public void testSecureValueRetrieval()
    {
        final String objectName = "myName";
        final String secret = "secret";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(ConfiguredObject.NAME, objectName);
        attributes.put(TestSingleton.SECURE_VALUE, secret);

        final TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);

        assertEquals(AbstractConfiguredObject.SECURED_STRING_VALUE, object.getAttribute(TestSingleton.SECURE_VALUE));
        assertEquals(secret, object.getSecureValue());

        //verify we can retrieve the actual secure value using system rights
        object.doAsSystem(
                     new PrivilegedAction<Object>()
                     {
                         @Override
                         public Object run()
                         {
                             assertEquals(secret, object.getAttribute(TestSingleton.SECURE_VALUE));
                             assertEquals(secret, object.getSecureValue());
                             return null;
                         }
                     });
    }

    public void testImmutableAttribute()
    {
        final String originalValue = "myvalue";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(ConfiguredObject.NAME, "myName");
        attributes.put(TestSingleton.IMMUTABLE_VALUE, originalValue);

        final TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);

        assertEquals("Immutable value unexpectedly changed", originalValue, object.getImmutableValue());

                     // Update to the same value is allowed
                     object.setAttributes(Collections.singletonMap(TestSingleton.IMMUTABLE_VALUE, originalValue));

        try
        {
            object.setAttributes(Collections.singletonMap(TestSingleton.IMMUTABLE_VALUE, "newvalue"));
            fail("Exception not thrown");
        }
        catch(IllegalConfigurationException e)
        {
            // PASS
        }
        assertEquals(originalValue, object.getImmutableValue());

        try
        {
            object.setAttributes(Collections.singletonMap(TestSingleton.IMMUTABLE_VALUE, null));
            fail("Exception not thrown");
        }
        catch(IllegalConfigurationException e)
        {
            // PASS
        }

        assertEquals("Immutable value unexpectedly changed", originalValue, object.getImmutableValue());
    }

    public void testImmutableAttributeNullValue()
    {
        Map<String, Object> attributes = new HashMap<>();
        attributes.put(ConfiguredObject.NAME, "myName");
        attributes.put(TestSingleton.IMMUTABLE_VALUE, null);

        final TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);

        assertNull(object.getImmutableValue());

        // Update to the same value is allowed
        object.setAttributes(Collections.singletonMap(TestSingleton.IMMUTABLE_VALUE, null));

        try
        {
            object.setAttributes(Collections.singletonMap(TestSingleton.IMMUTABLE_VALUE, "newvalue"));
            fail("Exception not thrown");
        }
        catch(IllegalConfigurationException e)
        {
            // PASS
        }
        assertNull("Immutable value unexpectedly changed", object.getImmutableValue());
    }

    /** Id and Type are key attributes in the model and are thus worthy of test of their own */
    public void testIdAndTypeAreImmutableAttribute()
    {
        Map<String, Object> attributes = new HashMap<>();
        attributes.put(ConfiguredObject.NAME, "myName");

        final TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
        UUID originalUuid = object.getId();
        String originalType = object.getType();

        try
        {
            object.setAttributes(Collections.singletonMap(TestSingleton.ID, UUID.randomUUID()));
            fail("Exception not thrown");
        }
        catch(IllegalConfigurationException e)
        {
            // PASS
        }

        assertEquals(originalUuid, object.getId());

        try
        {
            object.setAttributes(Collections.singletonMap(TestSingleton.TYPE, "newtype"));
            fail("Exception not thrown");
        }
        catch(IllegalConfigurationException e)
        {
            // PASS
        }

        assertEquals(originalType, object.getType());
    }

    public void testSetAttributesFiresListener()
    {
        final String objectName = "listenerFiring";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(ConfiguredObject.NAME, objectName);
        attributes.put(TestSingleton.STRING_VALUE, "first");

        final TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);

        final AtomicInteger listenerCount = new AtomicInteger();
        final LinkedHashMap<String, String> updates = new LinkedHashMap<>();
        object.addChangeListener(new AbstractConfigurationChangeListener()
        {
            @Override
            public void attributeSet(final ConfiguredObject<?> object,
                                     final String attributeName,
                                     final Object oldAttributeValue,
                                     final Object newAttributeValue)
            {
                listenerCount.incrementAndGet();
                String delta = String.valueOf(oldAttributeValue) + "=>" + String.valueOf(newAttributeValue);
                updates.put(attributeName, delta);
            }
        });

        // Set updated value (should cause listener to fire)
        object.setAttributes(Collections.singletonMap(TestSingleton.STRING_VALUE, "second"));

        assertEquals(1, listenerCount.get());
        String delta = updates.remove(TestSingleton.STRING_VALUE);
        assertEquals("first=>second", delta);

        // Set unchanged value (should not cause listener to fire)
        object.setAttributes(Collections.singletonMap(TestSingleton.STRING_VALUE, "second"));
        assertEquals(1, listenerCount.get());

        // Set value to null (should cause listener to fire)
        object.setAttributes(Collections.singletonMap(TestSingleton.STRING_VALUE, null));
        assertEquals(2, listenerCount.get());
        delta = updates.remove(TestSingleton.STRING_VALUE);
        assertEquals("second=>null", delta);

        // Set to null again (should not cause listener to fire)
        object.setAttributes(Collections.singletonMap(TestSingleton.STRING_VALUE, null));
        assertEquals(2, listenerCount.get());

        // Set updated value (should cause listener to fire)
        object.setAttributes(Collections.singletonMap(TestSingleton.STRING_VALUE, "third"));
        assertEquals(3, listenerCount.get());
        delta = updates.remove(TestSingleton.STRING_VALUE);
        assertEquals("null=>third", delta);
    }

    public void testSetAttributesInterpolateValues()
    {
        setTestSystemProperty("foo1", "myValue1");
        setTestSystemProperty("foo2", "myValue2");
        setTestSystemProperty("foo3", null);

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(ConfiguredObject.NAME, getTestName());
        attributes.put(TestSingleton.STRING_VALUE, "${foo1}");

        final TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);

        final AtomicInteger listenerCount = new AtomicInteger();
        object.addChangeListener(new AbstractConfigurationChangeListener()
        {
            @Override
            public void attributeSet(final ConfiguredObject<?> object,
                                     final String attributeName,
                                     final Object oldAttributeValue,
                                     final Object newAttributeValue)
            {
                listenerCount.incrementAndGet();
            }
        });

        assertEquals("myValue1", object.getStringValue());
        assertEquals("${foo1}", object.getActualAttributes().get(TestSingleton.STRING_VALUE));

        // Update the actual value ${foo1} => ${foo2}
        object.setAttributes(Collections.singletonMap(TestSingleton.STRING_VALUE, "${foo2}"));
        assertEquals(1, listenerCount.get());

        assertEquals("myValue2", object.getStringValue());
        assertEquals("${foo2}", object.getActualAttributes().get(TestSingleton.STRING_VALUE));

        // No change
        object.setAttributes(Collections.singletonMap(TestSingleton.STRING_VALUE, "${foo2}"));
        assertEquals(1, listenerCount.get());

        // Update the actual value ${foo2} => ${foo3} (which doesn't have a value)
        object.setAttributes(Collections.singletonMap(TestSingleton.STRING_VALUE, "${foo3}"));
        assertEquals(2, listenerCount.get());
        assertEquals("${foo3}", object.getStringValue());
        assertEquals("${foo3}", object.getActualAttributes().get(TestSingleton.STRING_VALUE));
    }

    public void testCreateAndLastUpdateDate() throws Exception
    {
        final String objectName = "myName";
        final Date now = new Date();

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(TestSingleton.NAME, objectName);

        TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);

        Date createdTime = object.getCreatedTime();
        assertTrue("Create date not populated", createdTime.compareTo(now) >= 0);
        assertEquals("Last updated not populated", createdTime, object.getLastUpdatedTime());

        Thread.sleep(10);
        object.setAttributes(Collections.singletonMap(TestSingleton.DESCRIPTION, "desc"));
        assertEquals("Created time should not be updated by update", createdTime, object.getCreatedTime());
        assertTrue("Last update time should be updated by update", object.getLastUpdatedTime().compareTo(createdTime) > 0);
    }

    public void testStatistics() throws Exception
    {
        final String objectName = "myName";

        Map<String, Object> attributes = new HashMap<>();
        attributes.put(TestSingleton.NAME, objectName);

        TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);

        final Map<String, Object> stats = object.getStatistics();
        assertEquals("Unexpected number of statistics", 1, stats.size());
        assertTrue("Expected statistic not found", stats.containsKey("longStatistic"));
    }

    public void testAuditInformation() throws Exception
    {
        final String creatingUser = "creatingUser";
        final String updatingUser = "updatingUser";
        final Subject creatorSubject = createTestAuthenticatedSubject(creatingUser);
        final Subject updaterSubject = createTestAuthenticatedSubject(updatingUser);
        final Date now = new Date();

        Thread.sleep(5);  // Let a small amount of time pass

        final Map<String, Object> attributes = new HashMap<>();
        attributes.put(TestSingleton.NAME, "myName");

        final TestSingleton object = Subject.doAs(creatorSubject,
                     new PrivilegedAction<TestSingleton>()
                     {
                         @Override
                         public TestSingleton run()
                         {
                             return _model.getObjectFactory().create(TestSingleton.class, attributes);
                         }
                     });

        assertEquals("Unexpected creating user after object creation", creatingUser, object.getCreatedBy());
        assertEquals("Unexpected last updating user after object creation", creatingUser, object.getLastUpdatedBy());

        final Date originalCreatedTime = object.getCreatedTime();
        final Date originalLastUpdatedTime = object.getLastUpdatedTime();
        assertTrue("Unexpected created time", originalCreatedTime.after(now));
        assertEquals("Unexpected created and updated time", originalCreatedTime, originalLastUpdatedTime);

        Thread.sleep(5);  // Let a small amount of time pass

        Subject.doAs(updaterSubject,
                     new PrivilegedAction<Void>()
                     {
                         @Override
                         public Void run()
                         {
                             object.setAttributes(Collections.singletonMap(TestSingleton.INT_VALUE, 5));
                             return null;
                         }
                     });

        assertEquals("Creating user should not be changed by update", creatingUser, object.getCreatedBy());
        assertEquals("Created time should not be changed by update", originalCreatedTime, object.getCreatedTime());

        assertEquals("Last updated by should be changed by update", updatingUser, object.getLastUpdatedBy());
        assertTrue("Last updated time by should be changed by update", originalLastUpdatedTime.before(object.getLastUpdatedTime()));
    }

    public void testAuditInformationIgnoresUserSuppliedAttributes() throws Exception
    {
        final String user = "user";
        final Subject userSubject = createTestAuthenticatedSubject(user);

        final Map<String, Object> attributes = new HashMap<>();
        attributes.put(TestSingleton.NAME, "myName");
        attributes.put(TestSingleton.CREATED_BY, "bogusCreator");
        attributes.put(TestSingleton.CREATED_TIME, new Date(0));
        attributes.put(TestSingleton.LAST_UPDATED_BY, "bogusUpdater");
        attributes.put(TestSingleton.LAST_UPDATED_TIME, new Date(0));

        final Date now = new Date();
        Thread.sleep(5);  // Let a small amount of time pass

        final TestSingleton object = Subject.doAs(userSubject,
                                                  new PrivilegedAction<TestSingleton>()
                                                  {
                                                      @Override
                                                      public TestSingleton run()
                                                      {
                                                          return _model.getObjectFactory().create(TestSingleton.class, attributes);
                                                      }
                                                  });

        assertEquals("Unexpected creating user after object creation", user,  object.getCreatedBy());
        assertEquals("Unexpected last updating user after object creation", user, object.getLastUpdatedBy());

        final Date originalCreatedTime = object.getCreatedTime();
        assertTrue("Unexpected created time", originalCreatedTime.after(now));
        final Date originalLastUpdatedTime = object.getLastUpdatedTime();
        assertEquals("Unexpected created and updated time", originalCreatedTime, originalLastUpdatedTime);


        Subject.doAs(userSubject,
                     new PrivilegedAction<Void>()
                     {
                         @Override
                         public Void run()
                         {
                             final Map<String, Object> updateMap = new HashMap<>();
                             updateMap.put(TestSingleton.INT_VALUE, 5);
                             updateMap.put(TestSingleton.CREATED_BY, "bogusCreator");
                             updateMap.put(TestSingleton.CREATED_TIME, new Date(0));
                             updateMap.put(TestSingleton.LAST_UPDATED_BY, "bogusUpdater");
                             updateMap.put(TestSingleton.LAST_UPDATED_TIME, new Date(0));

                             object.setAttributes(updateMap);
                             return null;
                         }
                     });

        Thread.sleep(50);  // Let a small amount of time pass

        assertEquals("Creating user should not be changed by update", user, object.getCreatedBy());
        assertEquals("Created time should not be changed by update", originalCreatedTime, object.getCreatedTime());

        assertEquals("Last updated by should be changed by update", user, object.getLastUpdatedBy());
        assertTrue("Last updated time by should be changed by update", originalLastUpdatedTime.before(object.getLastUpdatedTime()));
    }


    public void testAuditInformationPersistenceAndRecovery() throws Exception
    {
        final String creatingUser = "creatingUser";
        final Subject creatorSubject = createTestAuthenticatedSubject(creatingUser);
        final String objectName = "myName";

        final Map<String, Object> attributes = new HashMap<>();
        attributes.put(TestSingleton.NAME, objectName);

        final TestSingleton object = Subject.doAs(creatorSubject,
                                                  new PrivilegedAction<TestSingleton>()
                                                  {
                                                      @Override
                                                      public TestSingleton run()
                                                      {
                                                          return _model.getObjectFactory()
                                                                  .create(TestSingleton.class, attributes);
                                                      }
                                                  });

        final ConfiguredObjectRecord cor = object.asObjectRecord();
        final Map<String, Object> recordedAttributes = cor.getAttributes();

        assertTrue(recordedAttributes.containsKey(ConfiguredObject.LAST_UPDATED_BY));
        assertTrue(recordedAttributes.containsKey(ConfiguredObject.LAST_UPDATED_TIME));
        assertTrue(recordedAttributes.containsKey(ConfiguredObject.CREATED_BY));
        assertTrue(recordedAttributes.containsKey(ConfiguredObject.CREATED_TIME));

        assertEquals(creatingUser, recordedAttributes.get(ConfiguredObject.CREATED_BY));
        assertEquals(creatingUser, recordedAttributes.get(ConfiguredObject.LAST_UPDATED_BY));

        // Now recover the object

        final SystemConfig mockSystemConfig = mock(SystemConfig.class);
        when(mockSystemConfig.getId()).thenReturn(UUID.randomUUID());
        when(mockSystemConfig.getModel()).thenReturn(TestModel.getInstance());

        final TestSingleton recovered = (TestSingleton) _model.getObjectFactory().recover(cor, mockSystemConfig).resolve();
        recovered.open();

        assertEquals("Unexpected recovered object created by", object.getCreatedBy(), recovered.getCreatedBy());
        assertEquals("Unexpected recovered object created time", object.getCreatedTime(), recovered.getCreatedTime());

        assertEquals("Unexpected recovered object updated by", object.getLastUpdatedBy(), recovered.getLastUpdatedBy());
        assertEquals("Unexpected recovered object updated time", object.getLastUpdatedTime(), recovered.getLastUpdatedTime());
    }

    private Subject createTestAuthenticatedSubject(final String username)
    {
        return new Subject(true,
                           Collections.singleton(new AuthenticatedPrincipal(new UsernamePrincipal(username, null))),
                           Collections.emptySet(),
                           Collections.emptySet());
    }

}
