/*
 * 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.NoopConfigurationChangeListener;
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 NoopConfigurationChangeListener()
        {
            @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 NoopConfigurationChangeListener()
        {
            @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());
    }

}
