/*******************************************************************************
 * Copyright (c) 2015-2016 Oak Ridge National Laboratory.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package org.csstudio.display.builder.model;

import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.positionX;
import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.positionY;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;

import java.util.concurrent.atomic.AtomicInteger;

import org.junit.Test;

/** JUnit test of widget property subscriptions
 *  @author Kay Kasemir
 */
@SuppressWarnings("nls")
public class WidgetPropertySubscriptionUnitTest
{
    /** Check subscription updates */
    @Test
    public void testBasicSubscription()
    {
        final AtomicInteger updates = new AtomicInteger(0);
        final Widget widget = new Widget("generic");
        final WidgetPropertyListener<Integer> listener = (property, old_value, new_value) ->
        {
            updates.incrementAndGet();
            System.out.println(property.getName() + " changed to " + new_value);
        };
        widget.positionX().addPropertyListener(listener);

        // Noting, yet
        assertThat(updates.get(), equalTo(0));

        // Change once
        widget.positionX().setValue(21);
        assertThat(updates.get(), equalTo(1));

        // Change again
        widget.getProperty(positionX).setValue(22);
        assertThat(updates.get(), equalTo(2));

        // No change, same value
        widget.getProperty(positionX).setValue(22);
        assertThat(updates.get(), equalTo(2));
    }

    /** Check subscription updates */
    @Test
    public void testSpecificSubscription()
    {
        final Widget widget = new Widget("generic");

        final AtomicInteger x_updates = new AtomicInteger(0);
        final AtomicInteger y_updates = new AtomicInteger(0);

        widget.positionX().addPropertyListener((p, o, n) ->
        {
            x_updates.incrementAndGet();
            System.out.println(p.getName() + " = " + n);
        });
        widget.positionY().addUntypedPropertyListener((p, o, n) ->
        {
            y_updates.incrementAndGet();
            System.out.println(p.getName() + " = " + n);
        });

        // Noting, yet
        assertThat(x_updates.get(), equalTo(0));
        assertThat(y_updates.get(), equalTo(0));

        // Change one
        widget.getProperty(positionX).setValue(21);
        assertThat(x_updates.get(), equalTo(1));
        assertThat(y_updates.get(), equalTo(0));

        // Change other
        widget.getProperty(positionY).setValue(21);
        assertThat(x_updates.get(), equalTo(1));
        assertThat(y_updates.get(), equalTo(1));
    }
}

@@ -754,16 +754,68 @@
 ualTo;%0D%0A
+import static org.hamcrest.CoreMatchers.nullValue;%0D%0A
 import s
@@ -903,16 +903,191 @@
 teger;%0D%0A
+import java.util.concurrent.atomic.AtomicReference;%0D%0A%0D%0Aimport org.csstudio.display.builder.model.macros.Macros;%0D%0Aimport org.csstudio.display.builder.model.widgets.GroupWidget;
 %0D%0Aimport
@@ -3390,12 +3390,1579 @@
 %0D%0A    %7D%0D
+%0A%0D%0A    @Test%0D%0A    public void testMacroizedValueChanges()%0D%0A    %7B%0D%0A        // Group widget supports macros%0D%0A        final GroupWidget widget = new GroupWidget();%0D%0A%0D%0A        final Macros macros = new Macros();%0D%0A        macros.add(%22NAME%22, %22Fred%22);%0D%0A        widget.widgetMacros().setValue(macros);%0D%0A%0D%0A        final MacroizedWidgetProperty%3CString%3E name_prop = (MacroizedWidgetProperty%3CString%3E) widget.widgetName();%0D%0A        final AtomicInteger updates = new AtomicInteger();%0D%0A        final AtomicReference%3CString%3E received_value = new AtomicReference%3CString%3E(null);%0D%0A        name_prop.addPropertyListener((prop, old_value, new_value) -%3E%0D%0A        %7B%0D%0A            System.out.println(prop.getName() + %22 changes from %22 + old_value + %22 to %22 + new_value);%0D%0A            updates.incrementAndGet();%0D%0A            received_value.set(new_value);%0D%0A        %7D);%0D%0A%0D%0A        assertThat(updates.get(), equalTo(0));%0D%0A%0D%0A        // Setting the specification triggers a notification%0D%0A        name_prop.setSpecification(%22$(NAME)%22);%0D%0A        assertThat(updates.get(), equalTo(1));%0D%0A%0D%0A        // The listener received null%0D%0A        assertThat(received_value.get(), nullValue());%0D%0A%0D%0A        // _IF_ the listener called name_prop.getValue(), that%0D%0A        // would resolve macros, but also trigger another listener invocation.%0D%0A%0D%0A        // Fetching the value will resolve macros%0D%0A        // and that triggers another update%0D%0A        assertThat(name_prop.getValue(), equalTo(%22Fred%22));%0D%0A        assertThat(updates.get(), equalTo(2));%0D%0A        assertThat(received_value.get(), equalTo(%22Fred%22));%0D%0A    %7D%0D
 %0A%7D%0D%0A

Add unit test for current behavior of macroized property notifications