/* * JBoss, Home of Professional Open Source * Copyright 2015, Red Hat, Inc., and individual contributors as indicated * by the @authors tag. * * Licensed 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.jboss.as.controller.operation.global; import static org.jboss.as.controller.SimpleAttributeDefinitionBuilder.create; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.COMPOSITE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.STEPS; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.VALUE; import java.util.List; import java.util.Map; import org.jboss.as.controller.AbstractAddStepHandler; import org.jboss.as.controller.AbstractWriteAttributeHandler; import org.jboss.as.controller.AttributeDefinition; import org.jboss.as.controller.CompositeOperationHandler; import org.jboss.as.controller.ExpressionResolver; import org.jboss.as.controller.ManagementModel; import org.jboss.as.controller.ModelOnlyWriteAttributeHandler; import org.jboss.as.controller.ObjectListAttributeDefinition; import org.jboss.as.controller.ObjectTypeAttributeDefinition; import org.jboss.as.controller.OperationContext; import org.jboss.as.controller.OperationFailedException; import org.jboss.as.controller.OperationStepHandler; import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.PropertiesAttributeDefinition; import org.jboss.as.controller.ReloadRequiredRemoveStepHandler; import org.jboss.as.controller.ResourceBuilder; import org.jboss.as.controller.ResourceDefinition; import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; import org.jboss.as.controller.StringListAttributeDefinition; import org.jboss.as.controller.descriptions.NonResolvingResourceDescriptionResolver; import org.jboss.as.controller.operations.global.GlobalNotifications; import org.jboss.as.controller.operations.global.GlobalOperationHandlers; import org.jboss.as.controller.registry.ManagementResourceRegistration; import org.jboss.as.controller.test.AbstractControllerTestBase; import org.jboss.dmr.ModelNode; import org.jboss.dmr.ModelType; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * @author Tomaz Cerar (c) 2015 Red Hat Inc. */ public class EnhancedSyntaxTestCase extends AbstractControllerTestBase { private static final StringListAttributeDefinition LIST_ATTRIBUTE = new StringListAttributeDefinition.Builder("my-list-attribute") .setAllowDuplicates(false) .setAllowNull(true) .build(); private static final StringListAttributeDefinition RUNTIME_LIST_ATTRIBUTE = new StringListAttributeDefinition.Builder("runtime-list-attribute") .setAllowNull(true) .setStorageRuntime() .build(); private static final PropertiesAttributeDefinition MAP_ATTRIBUTE = new PropertiesAttributeDefinition.Builder("map-attribute", true) .setAllowNull(true) .build(); private static final PropertiesAttributeDefinition RUNTIME_MAP_ATTRIBUTE = new PropertiesAttributeDefinition.Builder("runtime-map-attribute", true) .setAllowNull(true) .setStorageRuntime() .build(); private static final AttributeDefinition ATTR_1 = create("attr1", ModelType.STRING) .setAllowNull(true) .build(); private static final AttributeDefinition ATTR_2 = create("attr2", ModelType.BOOLEAN) .setAllowNull(false) .build(); private static final ObjectTypeAttributeDefinition COMPLEX_ATTRIBUTE = ObjectTypeAttributeDefinition.Builder.of("complex-attribute", ATTR_1, ATTR_2, MAP_ATTRIBUTE, RUNTIME_MAP_ATTRIBUTE).build(); private static final ObjectListAttributeDefinition OBJECT_LIST = ObjectListAttributeDefinition.Builder.of("object-list", COMPLEX_ATTRIBUTE).setAllowNull(true).build(); private static final ObjectTypeAttributeDefinition COMPLEX_ATTRIBUTE2 = ObjectTypeAttributeDefinition.Builder.of("complex-attribute2", OBJECT_LIST).build(); private static final AttributeDefinition NORMAL_LOOKING_EXTENDED = new SimpleAttributeDefinitionBuilder("normal.looking.extended", ModelType.STRING, true).build(); private static PathAddress TEST_ADDRESS = PathAddress.pathAddress("subsystem", "test"); private static ModelNode runtimeListAttributeValue; private static ModelNode runtimeMapAttributeValue; @Override protected void initModel(ManagementModel managementModel) { ManagementResourceRegistration rootRegistration = managementModel.getRootResourceRegistration(); // register the global operations to be able to call :read-attribute and :write-attribute GlobalOperationHandlers.registerGlobalOperations(rootRegistration, processType); // register the global notifications so there is no warning that emitted notifications are not described by the resource. GlobalNotifications.registerGlobalNotifications(rootRegistration, processType); rootRegistration.registerOperationHandler(CompositeOperationHandler.DEFINITION, CompositeOperationHandler.INSTANCE); ResourceDefinition profileDefinition = createDummyProfileResourceDefinition(); rootRegistration.registerSubModel(profileDefinition); } private static ResourceDefinition createDummyProfileResourceDefinition() { return ResourceBuilder.Factory.create(TEST_ADDRESS.getElement(0), new NonResolvingResourceDescriptionResolver()) .setAddOperation(new AbstractAddStepHandler() { @Override protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException { LIST_ATTRIBUTE.validateAndSet(operation, model); RUNTIME_LIST_ATTRIBUTE.validateAndSet(operation, model); MAP_ATTRIBUTE.validateAndSet(operation, model); RUNTIME_MAP_ATTRIBUTE.validateAndSet(operation, model); COMPLEX_ATTRIBUTE.validateAndSet(operation, model); OBJECT_LIST.validateAndSet(operation, model); COMPLEX_ATTRIBUTE2.validateAndSet(operation, model); NORMAL_LOOKING_EXTENDED.validateAndSet(operation, model); } }) .setRemoveOperation(ReloadRequiredRemoveStepHandler.INSTANCE) .addReadWriteAttribute(LIST_ATTRIBUTE, null, new ModelOnlyWriteAttributeHandler(LIST_ATTRIBUTE)) .addReadWriteAttribute(RUNTIME_LIST_ATTRIBUTE, new OperationStepHandler() { @Override public void execute(OperationContext context, ModelNode operation) throws OperationFailedException { context.addStep((context1, operation1) -> context.getResult().set(runtimeListAttributeValue), OperationContext.Stage.RUNTIME); } }, new AbstractWriteAttributeHandler(RUNTIME_LIST_ATTRIBUTE) { @Override protected boolean applyUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName, ModelNode resolvedValue, ModelNode currentValue, HandbackHolder handbackHolder) throws OperationFailedException { runtimeListAttributeValue = operation.get(VALUE); return false; } @Override protected void revertUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName, ModelNode valueToRestore, ModelNode valueToRevert, Object handback) throws OperationFailedException { } }) .addReadWriteAttribute(MAP_ATTRIBUTE, null, new ModelOnlyWriteAttributeHandler(MAP_ATTRIBUTE)) .addReadWriteAttribute(RUNTIME_MAP_ATTRIBUTE, new OperationStepHandler() { @Override public void execute(OperationContext context, ModelNode operation) throws OperationFailedException { context.addStep((context1, operation1) -> context.getResult().set(runtimeMapAttributeValue), OperationContext.Stage.RUNTIME); } }, new AbstractWriteAttributeHandler(RUNTIME_MAP_ATTRIBUTE) { @Override protected boolean applyUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName, ModelNode resolvedValue, ModelNode currentValue, HandbackHolder handbackHolder) throws OperationFailedException { runtimeMapAttributeValue = operation.get(VALUE); return false; } @Override protected void revertUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName, ModelNode valueToRestore, ModelNode valueToRevert, Object handback) throws OperationFailedException { } }).addReadWriteAttribute(COMPLEX_ATTRIBUTE, null, new ModelOnlyWriteAttributeHandler(COMPLEX_ATTRIBUTE)) .addReadWriteAttribute(OBJECT_LIST, null, new ModelOnlyWriteAttributeHandler(OBJECT_LIST)) .addReadWriteAttribute(COMPLEX_ATTRIBUTE2, null, new ModelOnlyWriteAttributeHandler(COMPLEX_ATTRIBUTE2)) .addReadWriteAttribute(NORMAL_LOOKING_EXTENDED, null, new ModelOnlyWriteAttributeHandler(NORMAL_LOOKING_EXTENDED)) .build(); } /* Map read enhancements # return value of map-attribute with key "myKey" :read-attribute(name=map-attribute.myKey) List read enhancements # return element under index 5 of list-attribute :read-attribute(name=list-attribute[5]) */ @Before public void setup() throws OperationFailedException { executeCheckNoFailure(createOperation("add", TEST_ADDRESS)); runtimeListAttributeValue = new ModelNode(); runtimeMapAttributeValue = new ModelNode(); } @After public void cleanup() throws OperationFailedException { executeCheckNoFailure(createOperation("remove", TEST_ADDRESS)); } @Test public void testReadAttribute() throws OperationFailedException { ModelNode op = createOperation("map-put", TEST_ADDRESS); op.get("name").set(MAP_ATTRIBUTE.getName()); op.get("key").set("map-key"); op.get("value").set("map-value"); executeCheckNoFailure(op); op = createOperation("map-get", TEST_ADDRESS); op.get("name").set(MAP_ATTRIBUTE.getName()); op.get("key").set("map-key"); Assert.assertEquals("map-value", executeForResult(op).asString()); // return value of map-attribute with key "myKey" // :read-attribute(name=map-attribute.myKey) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(MAP_ATTRIBUTE.getName() + ".map-key"); Assert.assertEquals("map-value", executeForResult(op).asString()); op.get("name").set(MAP_ATTRIBUTE.getName() + ".wrong-key"); executeForFailure(op); //test list elements op = createOperation("list-add", TEST_ADDRESS); op.get("name").set(LIST_ATTRIBUTE.getName()); op.get("value").set("value1"); executeCheckNoFailure(op); //add second value op.get("value").set("value2"); executeCheckNoFailure(op); op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(LIST_ATTRIBUTE.getName()); Assert.assertTrue(executeForResult(op).isDefined()); // return value of list-attribute on index 0 // :read-attribute(name=map-attribute.myKey) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(LIST_ATTRIBUTE.getName() + "[0]"); Assert.assertEquals("value1", executeForResult(op).asString()); op.get("name").set(LIST_ATTRIBUTE.getName() + "[1]"); Assert.assertEquals("value2", executeForResult(op).asString()); } @Test public void testComplexAttributes() throws OperationFailedException { //test set ModelNode op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE.getName()); ModelNode value = new ModelNode(); value.get(ATTR_1.getName()).set("attr1-string"); value.get(ATTR_2.getName()).set(true); op.get("value").set(value); executeCheckNoFailure(op); //test read-attribute(name=complex-attribute.attr1) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE.getName() + "." + ATTR_1.getName()); Assert.assertEquals("attr1-string", executeForResult(op).asString()); //test read-attribute(name=complex-attribute.attr2) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE.getName() + "." + ATTR_2.getName()); Assert.assertTrue(executeForResult(op).asBoolean()); //test List<Object> op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(OBJECT_LIST.getName()); value = new ModelNode(); for (int i = 0; i <= 5; i++) { ModelNode item = value.add(); item.get(ATTR_1.getName()).set("value" + i); item.get(ATTR_2.getName()).set(true); } op.get("value").set(value); executeCheckNoFailure(op); //test read-attribute(name=object-list[1]) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(OBJECT_LIST.getName() + "[1]"); Assert.assertTrue(executeForResult(op).isDefined()); //test read-attribute(name=object-list[1].attr1) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(OBJECT_LIST.getName() + "[3].attr1"); Assert.assertEquals("value3", executeForResult(op).asString()); //test read-attribute(name=object-list[-3].attr1) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(OBJECT_LIST.getName() + "[-3].attr1"); executeCheckForFailure(op); //complex attribute with list with complex attributes op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE2.getName()); value = new ModelNode(); ModelNode listValue = value.get(OBJECT_LIST.getName()); for (int i = 0; i <= 5; i++) { ModelNode item = listValue.add(); item.get(ATTR_1.getName()).set("value" + i); item.get(ATTR_2.getName()).set(true); ModelNode mapValue = item.get(MAP_ATTRIBUTE.getName()); mapValue.get("key1").set("value1"); mapValue.get("key2").set("value2"); } op.get("value").set(value); executeCheckNoFailure(op); //test read-attribute(name=complex-attribute2.object-list[1].attr1) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE2.getName() + "." + OBJECT_LIST.getName() + "[3].attr1"); Assert.assertEquals("value3", executeForResult(op).asString()); //test :read-attribute(name=complex-attribute2.object-list[1].map-attribute.key1) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE2.getName() + "." + OBJECT_LIST.getName() + "[1].map-attribute.key1"); Assert.assertEquals("value1", executeForResult(op).asString()); //test :map-get(name=complex-attribute2.object-list[1].map-attribute key=key1) op = createOperation("map-get", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE2.getName() + "." + OBJECT_LIST.getName() + "[1].map-attribute"); op.get("key").set("key1"); Assert.assertEquals("value1", executeForResult(op).asString()); //test :list-get(name=complex-attribute2.object-list index=1) op = createOperation("list-get", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE2.getName() + "." + OBJECT_LIST.getName()); op.get("index").set(1); Assert.assertEquals(3, executeForResult(op).asList().size()); //there should be 3 attributes on this list element } @Test public void testWriteAttribute() throws OperationFailedException { //test :write-attribute(name="map-attribute.map-key" value="map-value") ModelNode op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(MAP_ATTRIBUTE.getName() + ".map-key"); op.get("value").set("map-value"); executeCheckNoFailure(op); op = createOperation("map-get", TEST_ADDRESS); op.get("name").set(MAP_ATTRIBUTE.getName()); op.get("key").set("map-key"); Assert.assertEquals("map-value", executeForResult(op).asString()); op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(MAP_ATTRIBUTE.getName() + ".map-key.sub-key"); //invalid and need to fail op.get("value").set("map-value"); executeForFailure(op); //test list elements op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(LIST_ATTRIBUTE.getName() + "[-1]"); op.get("value").set("value1"); executeCheckNoFailure(op); //add second value op.get("value").set("value2"); executeCheckNoFailure(op); op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(LIST_ATTRIBUTE.getName()); ModelNode res = executeForResult(op); Assert.assertTrue(res.isDefined()); // return value of list-attribute on index 0 // :read-attribute(name=map-attribute.myKey) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(LIST_ATTRIBUTE.getName() + "[0]"); Assert.assertEquals("value1", executeForResult(op).asString()); op.get("name").set(LIST_ATTRIBUTE.getName() + "[1]"); Assert.assertEquals("value2", executeForResult(op).asString()); } @Test public void testComplexWrite() throws OperationFailedException { //test write-attribute(name="complex-attribute.attr1, value="attr1-string") ModelNode op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE.getName() + "." + ATTR_1.getName()); op.get("value").set("attr1-string"); executeCheckNoFailure(op); //test write-attribute(name="complex-attribute.attr2, value=true) op.get("name").set(COMPLEX_ATTRIBUTE.getName() + "." + ATTR_2.getName()); op.get("value").set(true); executeCheckNoFailure(op); //test read-attribute(name=complex-attribute.attr1) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE.getName() + "." + ATTR_1.getName()); Assert.assertEquals("attr1-string", executeForResult(op).asString()); //test read-attribute(name=complex-attribute.attr2) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE.getName() + "." + ATTR_2.getName()); Assert.assertTrue(executeForResult(op).asBoolean()); //test List<Object> op = createOperation("write-attribute", TEST_ADDRESS); for (int i = 0; i <= 5; i++) { op.get("name").set(OBJECT_LIST.getName() + "[-1].attr1"); // add new element op.get("value").set("value"+i); executeCheckNoFailure(op); } //test read-attribute(name=object-list[1]) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(OBJECT_LIST.getName() + "[1]"); Assert.assertTrue(executeForResult(op).isDefined()); //test read-attribute(name=object-list[1].attr1) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(OBJECT_LIST.getName() + "[3].attr1"); Assert.assertEquals("value3", executeForResult(op).asString()); op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(OBJECT_LIST.getName() + "[3].attr1"); // update element on index 3 op.get("value").set("updated"); executeCheckNoFailure(op); op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(OBJECT_LIST.getName() + "[3].attr1"); Assert.assertEquals("updated", executeForResult(op).asString()); //complex attribute with list with complex attributes op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE2.getName()); ModelNode value = new ModelNode(); ModelNode listValue = value.get(OBJECT_LIST.getName()); for (int i = 0; i <= 5; i++) { ModelNode item = listValue.add(); item.get(ATTR_1.getName()).set("value" + i); item.get(ATTR_2.getName()).set(true); ModelNode mapValue = item.get(MAP_ATTRIBUTE.getName()); mapValue.get("key1").set("value1"); mapValue.get("key2").set("value2"); } op.get("value").set(value); executeCheckNoFailure(op); //test read-attribute(name=complex-attribute2.object-list[1].attr1) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE2.getName() + "." + OBJECT_LIST.getName() + "[3].attr1"); Assert.assertEquals("value3", executeForResult(op).asString()); //test :read-attribute(name=complex-attribute2.object-list[1].map-attribute.key1) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE2.getName() + "." + OBJECT_LIST.getName() + "[1].map-attribute.key1"); Assert.assertEquals("value1", executeForResult(op).asString()); //test :write-attribute(name=complex-attribute2.object-list[1].map-attribute.key1) op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE2.getName() + "." + OBJECT_LIST.getName() + "[3].map-attribute.key1"); op.get("value").set("updated-value"); executeCheckNoFailure(op); op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE2.getName() + "." + OBJECT_LIST.getName() + "[3].map-attribute.key1"); Assert.assertEquals("updated-value", executeForResult(op).asString()); //test :write-attribute(name=complex-attribute2.object-list[-1].map-attribute.key1) op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE2.getName() + "." + OBJECT_LIST.getName() + "[-1].map-attribute.key1"); op.get("value").set("added-value"); executeCheckNoFailure(op); op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE2.getName() + "." + OBJECT_LIST.getName() + "[6].map-attribute.key1"); Assert.assertEquals("added-value", executeForResult(op).asString()); //test :map-get(name=complex-attribute2.object-list[t].map-attribute key=key1) op = createOperation("map-get", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE2.getName() + "." + OBJECT_LIST.getName() + "[6].map-attribute"); op.get("key").set("key1"); Assert.assertEquals("added-value", executeForResult(op).asString()); //test :list-get(name=complex-attribute2.object-list index=5) op = createOperation("list-get", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE2.getName() + "." + OBJECT_LIST.getName()); op.get("index").set(1); Assert.assertEquals(3, executeForResult(op).asList().size()); //there should be 3 attributes on this list element //test :map-put(name=complex-attribute2.object-list[t].map-attribute key=map-put-key value="map-put-value") op = createOperation("map-put", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE2.getName() + "." + OBJECT_LIST.getName() + "[6].map-attribute"); op.get("key").set("map-put-key"); op.get("value").set("map-put-value"); executeCheckNoFailure(op); op = createOperation("map-get", TEST_ADDRESS); op.get("name").set(COMPLEX_ATTRIBUTE2.getName() + "." + OBJECT_LIST.getName() + "[6].map-attribute"); op.get("key").set("map-put-key"); Assert.assertEquals("map-put-value", executeForResult(op).asString()); } @Test public void testNormalAttributeLookingExtended() throws Exception { final ModelNode wa = createOperation("write-attribute", TEST_ADDRESS); wa.get("name").set(NORMAL_LOOKING_EXTENDED.getName()); wa.get("value").set("test123"); executeCheckNoFailure(wa); final ModelNode ra = createOperation("read-attribute", TEST_ADDRESS); ra.get("name").set(NORMAL_LOOKING_EXTENDED.getName()); Assert.assertEquals("test123", executeForResult(ra).asString()); executeCheckNoFailure(createOperation("remove", TEST_ADDRESS)); final ModelNode add = createOperation("add", TEST_ADDRESS); add.get(NORMAL_LOOKING_EXTENDED.getName()).set("test456"); executeCheckNoFailure(add); Assert.assertEquals("test456", executeForResult(ra).asString()); } @Test public void testComplexListValue()throws Exception{ //test List<Object> ModelNode op = createOperation("list-add", TEST_ADDRESS); op.get("name").set(OBJECT_LIST.getName()); ModelNode value = new ModelNode(); value.get(ATTR_1.getName()).set("complex value"); value.get(ATTR_2.getName()).set(true); op.get("value").set(value); executeCheckNoFailure(op); ModelNode readOp = createOperation("read-attribute", TEST_ADDRESS); readOp.get("name").set(OBJECT_LIST.getName()); ModelNode result = executeForResult(readOp); Assert.assertEquals(1, result.asList().size()); executeCheckNoFailure(op); result = executeForResult(readOp); Assert.assertEquals(2, result.asList().size()); } @Test public void testRuntimeMapAttributeRead() throws Exception { ModelNode op = createOperation("map-put", TEST_ADDRESS); op.get("name").set(RUNTIME_MAP_ATTRIBUTE.getName()); op.get("key").set("map-key"); op.get("value").set("map-value"); executeCheckNoFailure(op); // :map-get(name=runtime-map-attribute, key=map-key) op = createOperation("map-get", TEST_ADDRESS); op.get("name").set(RUNTIME_MAP_ATTRIBUTE.getName()); op.get("key").set("map-key"); Assert.assertEquals("map-value", executeForResult(op).asString()); // :read-attribute(name=runtime-map-attribute) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(RUNTIME_MAP_ATTRIBUTE.getName()); Assert.assertEquals("{\"map-key\" => \"map-value\"}", executeForResult(op).asString()); // :read-attribute(name=runtime-map-attribute.map-key) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(RUNTIME_MAP_ATTRIBUTE.getName() + ".map-key"); Assert.assertEquals("map-value", executeForResult(op).asString()); op.get("name").set(RUNTIME_MAP_ATTRIBUTE.getName() + ".wrong-key"); executeForFailure(op); } @Test public void testRuntimeMapAttributeWrite() throws Exception { // :write-attribute(name=runtime-map-attribute.map-key) ModelNode op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(RUNTIME_MAP_ATTRIBUTE.getName() + ".map-key"); op.get("value").set("map-value"); executeCheckNoFailure(op); Map<String, String> map = PropertiesAttributeDefinition.unwrapModel(ExpressionResolver.TEST_RESOLVER, runtimeMapAttributeValue); Assert.assertEquals(1, map.size()); Assert.assertEquals("map-value", map.get("map-key")); op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(RUNTIME_MAP_ATTRIBUTE.getName() + ".map-key2"); op.get("value").set("map-value2"); executeCheckNoFailure(op); map = PropertiesAttributeDefinition.unwrapModel(ExpressionResolver.TEST_RESOLVER, runtimeMapAttributeValue); Assert.assertEquals(2, map.size()); Assert.assertEquals("map-value", map.get("map-key")); Assert.assertEquals("map-value2", map.get("map-key2")); } @Test public void testRuntimeListAttributeRead() throws Exception { ModelNode op = createOperation("list-add", TEST_ADDRESS); op.get("name").set(RUNTIME_LIST_ATTRIBUTE.getName()); op.get("value").set("list-value"); executeCheckNoFailure(op); op = createOperation("list-get", TEST_ADDRESS); op.get("name").set(RUNTIME_LIST_ATTRIBUTE.getName()); op.get("index").set(0); Assert.assertEquals("list-value", executeForResult(op).asString()); // :read-attribute(name=runtime-list-attribute) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(RUNTIME_LIST_ATTRIBUTE.getName()); Assert.assertEquals("[\"list-value\"]", executeForResult(op).asString()); // :read-attribute(name=runtime-list-attribute[0]) op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(RUNTIME_LIST_ATTRIBUTE.getName() + "[0]"); Assert.assertEquals("list-value", executeForResult(op).asString()); // :read-attribute(name=runtime-list-attribute[1]) op.get("name").set(RUNTIME_LIST_ATTRIBUTE.getName() + "[1]"); // index out of range Assert.assertEquals(ModelType.UNDEFINED, executeForResult(op).getType()); } @Test public void testRuntimeListAttributeWrite() throws Exception { ModelNode op = createOperation("list-add", TEST_ADDRESS); op.get("name").set(RUNTIME_LIST_ATTRIBUTE.getName()); op.get("value").set("list-value"); executeCheckNoFailure(op); List<String> list = StringListAttributeDefinition.unwrapValue(ExpressionResolver.TEST_RESOLVER, runtimeListAttributeValue); Assert.assertEquals(1, list.size()); Assert.assertEquals("list-value", list.get(0)); // :write-attribute(name=runtime-list-attribute[-1]) op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(RUNTIME_LIST_ATTRIBUTE.getName() + "[-1]"); op.get("value").set("list-value2"); executeCheckNoFailure(op); list = StringListAttributeDefinition.unwrapValue(ExpressionResolver.TEST_RESOLVER, runtimeListAttributeValue); Assert.assertEquals(2, list.size()); Assert.assertEquals("list-value", list.get(0)); Assert.assertEquals("list-value2", list.get(1)); // :write-attribute(name=runtime-list-attribute[0]) op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(RUNTIME_LIST_ATTRIBUTE.getName() + "[0]"); op.get("value").set("list-value3"); executeCheckNoFailure(op); list = StringListAttributeDefinition.unwrapValue(ExpressionResolver.TEST_RESOLVER, runtimeListAttributeValue); Assert.assertEquals(2, list.size()); Assert.assertEquals("list-value3", list.get(0)); Assert.assertEquals("list-value2", list.get(1)); } @Test public void testCompositeListWrite() throws Exception { performCompositeListWrite(LIST_ATTRIBUTE.getName()); performCompositeListWrite(RUNTIME_LIST_ATTRIBUTE.getName()); } private void performCompositeListWrite(String attrName) throws Exception { ModelNode compositeOp = createOperation(COMPOSITE, PathAddress.EMPTY_ADDRESS); ModelNode op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(attrName + "[-1]"); op.get("value").set("list-value"); compositeOp.get(STEPS).add(op); op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(attrName + "[-1]"); op.get("value").set("list-value2"); compositeOp.get(STEPS).add(op); executeCheckNoFailure(compositeOp); op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(attrName); ModelNode result = executeForResult(op); Assert.assertEquals(2, result.asList().size()); Assert.assertEquals("list-value", result.asList().get(0).asString()); Assert.assertEquals("list-value2", result.asList().get(1).asString()); } @Test public void testCompositeMapWrite() throws Exception { performCompositeMapWrite(MAP_ATTRIBUTE.getName()); performCompositeMapWrite(RUNTIME_MAP_ATTRIBUTE.getName()); } private void performCompositeMapWrite(String attrName) throws Exception { ModelNode compositeOp = createOperation(COMPOSITE, PathAddress.EMPTY_ADDRESS); ModelNode op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(attrName + ".map-key"); op.get("value").set("map-value"); compositeOp.get(STEPS).add(op); op = createOperation("write-attribute", TEST_ADDRESS); op.get("name").set(attrName + ".map-key2"); op.get("value").set("map-value2"); compositeOp.get(STEPS).add(op); executeCheckNoFailure(compositeOp); op = createOperation("read-attribute", TEST_ADDRESS); op.get("name").set(attrName); ModelNode result = executeForResult(op); Assert.assertEquals(2, result.keys().size()); Assert.assertEquals("map-value", result.get("map-key").asString()); Assert.assertEquals("map-value2", result.get("map-key2").asString()); } }