ensure unique classIds for fields within Abstract[List|Tree]Boxes

https://bugs.eclipse.org/bugs/show_bug.cgi?id=463553

Change-Id: I60e2ed1412c99799249189f2ef0c7a0a966a050a
Reviewed-on: https://git.eclipse.org/r/78382
Tested-by: Hudson CI
Reviewed-by: Andi Bur <andi.bur@gmail.com>
diff --git a/org.eclipse.scout.rt.client.test/src/org/eclipse/scout/rt/client/ui/form/fields/listbox/ListBoxInFormTest.java b/org.eclipse.scout.rt.client.test/src/org/eclipse/scout/rt/client/ui/form/fields/listbox/ListBoxInFormTest.java
new file mode 100644
index 0000000..4ee51ce
--- /dev/null
+++ b/org.eclipse.scout.rt.client.test/src/org/eclipse/scout/rt/client/ui/form/fields/listbox/ListBoxInFormTest.java
@@ -0,0 +1,79 @@
+package org.eclipse.scout.rt.client.ui.form.fields.listbox;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import org.eclipse.scout.commons.ITypeWithClassId;
+import org.eclipse.scout.commons.StringUtility;
+import org.eclipse.scout.testing.client.runner.ScoutClientTestRunner;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * @since 5.2
+ */
+@RunWith(ScoutClientTestRunner.class)
+public class ListBoxInFormTest {
+
+  private static final String LIST_BOX_FILTER_BOX_CLASS_ID = "a2e982d1-ea01-4d11-8655-d10c9935d8b9";
+  private static final String LIST_BOX_ACTIVE_STATE_BOX_CLASS_ID = "2c4e4cf0-7bcf-46f1-a00f-19ecd2719fff";
+  private static final String LIST_BOX_CHECKED_STATE_BOX_CLASS_ID = "e62c300f-f49d-4318-95ce-44a60558cfbf";
+
+  private ListBoxTestForm m_form;
+
+  @Before
+  public void before() throws Exception {
+    m_form = new ListBoxTestForm();
+  }
+
+  @Test
+  public void testListBoxClassIds() {
+    assertEquals(ListBoxTestForm.FIRST_LIST_BOX_CLASS_ID, m_form.getFirstListBox().classId());
+    assertEquals(ListBoxTestForm.SECOND_LIST_BOX_CLASS_ID, m_form.getSecondListBox().classId());
+  }
+
+  @Test
+  public void testListBoxFilterBoxClassIds() {
+    String firstClassId = m_form.getFirstListBox().getListBoxFilterBox().classId();
+    String secondClassId = m_form.getSecondListBox().getListBoxFilterBox().classId();
+    assertNotEquals(firstClassId, secondClassId);
+
+    assertEquals(LIST_BOX_FILTER_BOX_CLASS_ID + ITypeWithClassId.ID_CONCAT_SYMBOL + ListBoxTestForm.FIRST_LIST_BOX_CLASS_ID, firstClassId);
+    assertEquals(LIST_BOX_FILTER_BOX_CLASS_ID + ITypeWithClassId.ID_CONCAT_SYMBOL + ListBoxTestForm.SECOND_LIST_BOX_CLASS_ID, secondClassId);
+  }
+
+  @Test
+  public void testListBoxFilterBoxActiveStateRadioButtonGroupClassIds() {
+    String firstClassId = m_form.getFirstListBox().getListBoxFilterBox().getActiveStateRadioButtonGroup().classId();
+    String secondClassId = m_form.getSecondListBox().getListBoxFilterBox().getActiveStateRadioButtonGroup().classId();
+    assertNotEquals(firstClassId, secondClassId);
+
+    assertEquals(StringUtility.join(ITypeWithClassId.ID_CONCAT_SYMBOL,
+        LIST_BOX_ACTIVE_STATE_BOX_CLASS_ID,
+        LIST_BOX_FILTER_BOX_CLASS_ID,
+        ListBoxTestForm.FIRST_LIST_BOX_CLASS_ID), firstClassId);
+
+    assertEquals(StringUtility.join(ITypeWithClassId.ID_CONCAT_SYMBOL,
+        LIST_BOX_ACTIVE_STATE_BOX_CLASS_ID,
+        LIST_BOX_FILTER_BOX_CLASS_ID,
+        ListBoxTestForm.SECOND_LIST_BOX_CLASS_ID), secondClassId);
+  }
+
+  @Test
+  public void testListBoxFilterBoxCheckedStateRadioButtonGroupClassIds() {
+    String firstClassId = m_form.getFirstListBox().getListBoxFilterBox().getCheckedStateRadioButtonGroup().classId();
+    String secondClassId = m_form.getSecondListBox().getListBoxFilterBox().getCheckedStateRadioButtonGroup().classId();
+    assertNotEquals(firstClassId, secondClassId);
+
+    assertEquals(StringUtility.join(ITypeWithClassId.ID_CONCAT_SYMBOL,
+        LIST_BOX_CHECKED_STATE_BOX_CLASS_ID,
+        LIST_BOX_FILTER_BOX_CLASS_ID,
+        ListBoxTestForm.FIRST_LIST_BOX_CLASS_ID), firstClassId);
+
+    assertEquals(StringUtility.join(ITypeWithClassId.ID_CONCAT_SYMBOL,
+        LIST_BOX_CHECKED_STATE_BOX_CLASS_ID,
+        LIST_BOX_FILTER_BOX_CLASS_ID,
+        ListBoxTestForm.SECOND_LIST_BOX_CLASS_ID), secondClassId);
+  }
+}
diff --git a/org.eclipse.scout.rt.client.test/src/org/eclipse/scout/rt/client/ui/form/fields/listbox/ListBoxTestForm.java b/org.eclipse.scout.rt.client.test/src/org/eclipse/scout/rt/client/ui/form/fields/listbox/ListBoxTestForm.java
new file mode 100644
index 0000000..7b42b62
--- /dev/null
+++ b/org.eclipse.scout.rt.client.test/src/org/eclipse/scout/rt/client/ui/form/fields/listbox/ListBoxTestForm.java
@@ -0,0 +1,49 @@
+package org.eclipse.scout.rt.client.ui.form.fields.listbox;
+
+import org.eclipse.scout.commons.annotations.ClassId;
+import org.eclipse.scout.commons.annotations.Order;
+import org.eclipse.scout.commons.exception.ProcessingException;
+import org.eclipse.scout.rt.client.ui.form.AbstractForm;
+import org.eclipse.scout.rt.client.ui.form.fields.groupbox.AbstractGroupBox;
+import org.eclipse.scout.rt.client.ui.form.fields.listbox.ListBoxTestForm.MainBox.FirstListBox;
+import org.eclipse.scout.rt.client.ui.form.fields.listbox.ListBoxTestForm.MainBox.SecondListBox;
+
+/**
+ * @since 5.2
+ */
+@ClassId("39a01dec-9a6b-420f-ae6c-eacd216a8c53")
+public class ListBoxTestForm extends AbstractForm {
+
+  public static final String FIRST_LIST_BOX_CLASS_ID = "5ce66cc6-c89e-4ec2-a177-2ab4324e0f95";
+  public static final String SECOND_LIST_BOX_CLASS_ID = "5bf22280-6796-4947-8505-49d490b48f20";
+
+  public ListBoxTestForm() throws ProcessingException {
+    super();
+  }
+
+  public FirstListBox getFirstListBox() {
+    return getFieldByClass(FirstListBox.class);
+  }
+
+  public SecondListBox getSecondListBox() {
+    return getFieldByClass(SecondListBox.class);
+  }
+
+  public MainBox getMainBox() {
+    return (MainBox) getRootGroupBox();
+  }
+
+  @ClassId("ba015995-f2b0-46c9-8c82-672fcddb24af")
+  public class MainBox extends AbstractGroupBox {
+
+    @Order(1000)
+    @ClassId(FIRST_LIST_BOX_CLASS_ID)
+    public class FirstListBox extends AbstractListBox<Long> {
+    }
+
+    @Order(2000)
+    @ClassId(SECOND_LIST_BOX_CLASS_ID)
+    public class SecondListBox extends AbstractListBox<Long> {
+    }
+  }
+}
diff --git a/org.eclipse.scout.rt.client.test/src/org/eclipse/scout/rt/client/ui/form/fields/treebox/TreeBoxInFormTest.java b/org.eclipse.scout.rt.client.test/src/org/eclipse/scout/rt/client/ui/form/fields/treebox/TreeBoxInFormTest.java
new file mode 100644
index 0000000..cc2afa2
--- /dev/null
+++ b/org.eclipse.scout.rt.client.test/src/org/eclipse/scout/rt/client/ui/form/fields/treebox/TreeBoxInFormTest.java
@@ -0,0 +1,79 @@
+package org.eclipse.scout.rt.client.ui.form.fields.treebox;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import org.eclipse.scout.commons.ITypeWithClassId;
+import org.eclipse.scout.commons.StringUtility;
+import org.eclipse.scout.testing.client.runner.ScoutClientTestRunner;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * @since 5.2
+ */
+@RunWith(ScoutClientTestRunner.class)
+public class TreeBoxInFormTest {
+
+  private static final String TREE_BOX_FILTER_BOX_CLASS_ID = "5cfd2944-5dfd-4b66-ae45-419bb1b71378";
+  private static final String TREE_BOX_ACTIVE_STATE_BOX_CLASS_ID = "36299662-6bd3-47e2-b3bc-9d54be265de4";
+  private static final String TREE_BOX_CHECKED_STATE_BOX_CLASS_ID = "a292b6e6-0e77-4852-a346-dc27f72b9f57";
+
+  private TreeBoxTestForm m_form;
+
+  @Before
+  public void before() throws Exception {
+    m_form = new TreeBoxTestForm();
+  }
+
+  @Test
+  public void testTreeBoxClassIds() {
+    assertEquals(TreeBoxTestForm.FIRST_TREE_BOX_CLASS_ID, m_form.getFirstTreeBox().classId());
+    assertEquals(TreeBoxTestForm.SECOND_TREE_BOX_CLASS_ID, m_form.getSecondTreeBox().classId());
+  }
+
+  @Test
+  public void testTreeBoxFilterBoxClassIds() {
+    String firstClassId = m_form.getFirstTreeBox().getTreeBoxFilterBox().classId();
+    String secondClassId = m_form.getSecondTreeBox().getTreeBoxFilterBox().classId();
+    assertNotEquals(firstClassId, secondClassId);
+
+    assertEquals(TREE_BOX_FILTER_BOX_CLASS_ID + ITypeWithClassId.ID_CONCAT_SYMBOL + TreeBoxTestForm.FIRST_TREE_BOX_CLASS_ID, firstClassId);
+    assertEquals(TREE_BOX_FILTER_BOX_CLASS_ID + ITypeWithClassId.ID_CONCAT_SYMBOL + TreeBoxTestForm.SECOND_TREE_BOX_CLASS_ID, secondClassId);
+  }
+
+  @Test
+  public void testTreeBoxFilterBoxActiveStateRadioButtonGroupClassIds() {
+    String firstClassId = m_form.getFirstTreeBox().getTreeBoxFilterBox().getActiveStateRadioButtonGroup().classId();
+    String secondClassId = m_form.getSecondTreeBox().getTreeBoxFilterBox().getActiveStateRadioButtonGroup().classId();
+    assertNotEquals(firstClassId, secondClassId);
+
+    assertEquals(StringUtility.join(ITypeWithClassId.ID_CONCAT_SYMBOL,
+        TREE_BOX_ACTIVE_STATE_BOX_CLASS_ID,
+        TREE_BOX_FILTER_BOX_CLASS_ID,
+        TreeBoxTestForm.FIRST_TREE_BOX_CLASS_ID), firstClassId);
+
+    assertEquals(StringUtility.join(ITypeWithClassId.ID_CONCAT_SYMBOL,
+        TREE_BOX_ACTIVE_STATE_BOX_CLASS_ID,
+        TREE_BOX_FILTER_BOX_CLASS_ID,
+        TreeBoxTestForm.SECOND_TREE_BOX_CLASS_ID), secondClassId);
+  }
+
+  @Test
+  public void testTreeBoxFilterBoxCheckedStateRadioButtonGroupClassIds() {
+    String firstClassId = m_form.getFirstTreeBox().getTreeBoxFilterBox().getCheckedStateRadioButtonGroup().classId();
+    String secondClassId = m_form.getSecondTreeBox().getTreeBoxFilterBox().getCheckedStateRadioButtonGroup().classId();
+    assertNotEquals(firstClassId, secondClassId);
+
+    assertEquals(StringUtility.join(ITypeWithClassId.ID_CONCAT_SYMBOL,
+        TREE_BOX_CHECKED_STATE_BOX_CLASS_ID,
+        TREE_BOX_FILTER_BOX_CLASS_ID,
+        TreeBoxTestForm.FIRST_TREE_BOX_CLASS_ID), firstClassId);
+
+    assertEquals(StringUtility.join(ITypeWithClassId.ID_CONCAT_SYMBOL,
+        TREE_BOX_CHECKED_STATE_BOX_CLASS_ID,
+        TREE_BOX_FILTER_BOX_CLASS_ID,
+        TreeBoxTestForm.SECOND_TREE_BOX_CLASS_ID), secondClassId);
+  }
+}
diff --git a/org.eclipse.scout.rt.client.test/src/org/eclipse/scout/rt/client/ui/form/fields/treebox/TreeBoxTestForm.java b/org.eclipse.scout.rt.client.test/src/org/eclipse/scout/rt/client/ui/form/fields/treebox/TreeBoxTestForm.java
new file mode 100644
index 0000000..7ba2f31
--- /dev/null
+++ b/org.eclipse.scout.rt.client.test/src/org/eclipse/scout/rt/client/ui/form/fields/treebox/TreeBoxTestForm.java
@@ -0,0 +1,49 @@
+package org.eclipse.scout.rt.client.ui.form.fields.treebox;
+
+import org.eclipse.scout.commons.annotations.ClassId;
+import org.eclipse.scout.commons.annotations.Order;
+import org.eclipse.scout.commons.exception.ProcessingException;
+import org.eclipse.scout.rt.client.ui.form.AbstractForm;
+import org.eclipse.scout.rt.client.ui.form.fields.groupbox.AbstractGroupBox;
+import org.eclipse.scout.rt.client.ui.form.fields.treebox.TreeBoxTestForm.MainBox.FirstTreeBox;
+import org.eclipse.scout.rt.client.ui.form.fields.treebox.TreeBoxTestForm.MainBox.SecondTreeBox;
+
+/**
+ * @since 5.2
+ */
+@ClassId("64911272-1640-4a1d-95f9-d9257b773f5d")
+public class TreeBoxTestForm extends AbstractForm {
+
+  public static final String FIRST_TREE_BOX_CLASS_ID = "2b490d07-069a-4974-afd2-4c97e3b0e05c";
+  public static final String SECOND_TREE_BOX_CLASS_ID = "e8a73e93-ee93-43a0-9659-9988e5f7ead6";
+
+  public TreeBoxTestForm() throws ProcessingException {
+    super();
+  }
+
+  public FirstTreeBox getFirstTreeBox() {
+    return getFieldByClass(FirstTreeBox.class);
+  }
+
+  public SecondTreeBox getSecondTreeBox() {
+    return getFieldByClass(SecondTreeBox.class);
+  }
+
+  public MainBox getMainBox() {
+    return (MainBox) getRootGroupBox();
+  }
+
+  @ClassId("8acccbdc-41c7-40b1-ae0b-c4c46682788a")
+  public class MainBox extends AbstractGroupBox {
+
+    @Order(1000)
+    @ClassId(FIRST_TREE_BOX_CLASS_ID)
+    public class FirstTreeBox extends AbstractTreeBox<Long> {
+    }
+
+    @Order(2000)
+    @ClassId(SECOND_TREE_BOX_CLASS_ID)
+    public class SecondTreeBox extends AbstractTreeBox<Long> {
+    }
+  }
+}
diff --git a/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/AbstractFormField.java b/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/AbstractFormField.java
index f8ca06b..812e13d 100644
--- a/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/AbstractFormField.java
+++ b/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/AbstractFormField.java
@@ -1218,7 +1218,7 @@
     // compute enclosing field path
     ICompositeField p = getParentField();
     while (p != null) {
-      if (p instanceof AbstractCompositeField && ((AbstractCompositeField) p).isTemplateField()) {
+      if (!(p instanceof AbstractCompositeField) || ((AbstractCompositeField) p).isTemplateField()) {
         enclosingFieldList.add(0, p);
       }
       p = p.getParentField();
diff --git a/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/listbox/AbstractListBox.java b/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/listbox/AbstractListBox.java
index 4a0e996..b6b1740 100644
--- a/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/listbox/AbstractListBox.java
+++ b/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/listbox/AbstractListBox.java
@@ -946,6 +946,7 @@
   }
 
   @Order(1)
+  @ClassId("a2e982d1-ea01-4d11-8655-d10c9935d8b9")
   public class ListBoxFilterBox extends AbstractListBoxFilterBox {
     @Override
     protected IListBox getListBox() {
diff --git a/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/listbox/AbstractListBoxFilterBox.java b/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/listbox/AbstractListBoxFilterBox.java
index bcd3f18..3e7256f 100644
--- a/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/listbox/AbstractListBoxFilterBox.java
+++ b/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/listbox/AbstractListBoxFilterBox.java
@@ -121,6 +121,7 @@
   }
 
   @Order(10)
+  @ClassId("e62c300f-f49d-4318-95ce-44a60558cfbf")
   public class CheckedStateRadioButtonGroup extends AbstractRadioButtonGroup<Boolean> {
 
     @Override
@@ -157,6 +158,7 @@
     }
 
     @Order(10)
+    @ClassId("3e47a9b5-aa90-4e2d-8901-23047d689a59")
     public class CheckedButton extends AbstractRadioButton<Boolean> {
 
       @Override
@@ -181,6 +183,7 @@
     }
 
     @Order(20)
+    @ClassId("b37f25c6-ab52-4ff2-a167-7980d0f4f71b")
     public class AllButton extends AbstractRadioButton<Boolean> {
 
       @Override
@@ -207,6 +210,7 @@
   }
 
   @Order(20)
+  @ClassId("2c4e4cf0-7bcf-46f1-a00f-19ecd2719fff")
   public class ActiveStateRadioButtonGroup extends AbstractRadioButtonGroup<TriState> {
 
     @Override
@@ -242,6 +246,7 @@
     }
 
     @Order(10)
+    @ClassId("ad7425e4-9fa6-4dd6-944b-1f138586eff2")
     public class ActiveButton extends AbstractRadioButton<TriState> {
 
       @Override
@@ -266,6 +271,7 @@
     }
 
     @Order(20)
+    @ClassId("dd6c5a35-ea0e-459d-919f-9155d46a63eb")
     public class InactiveButton extends AbstractRadioButton<TriState> {
 
       @Override
@@ -290,6 +296,7 @@
     }
 
     @Order(30)
+    @ClassId("526bc98f-9b10-4285-bf3a-3feb6d560e22")
     public class ActiveAndInactiveButton extends AbstractRadioButton<TriState> {
 
       @Override
diff --git a/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/treebox/AbstractTreeBox.java b/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/treebox/AbstractTreeBox.java
index edec373..5e70b5c 100644
--- a/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/treebox/AbstractTreeBox.java
+++ b/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/treebox/AbstractTreeBox.java
@@ -1111,6 +1111,7 @@
   }
 
   @Order(1)
+  @ClassId("5cfd2944-5dfd-4b66-ae45-419bb1b71378")
   public class TreeBoxFilterBox extends AbstractTreeBoxFilterBox {
     @Override
     protected ITreeBox getTreeBox() {
diff --git a/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/treebox/AbstractTreeBoxFilterBox.java b/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/treebox/AbstractTreeBoxFilterBox.java
index fed7470..ba58045 100644
--- a/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/treebox/AbstractTreeBoxFilterBox.java
+++ b/org.eclipse.scout.rt.client/src/org/eclipse/scout/rt/client/ui/form/fields/treebox/AbstractTreeBoxFilterBox.java
@@ -129,6 +129,7 @@
   }
 
   @Order(10)
+  @ClassId("a292b6e6-0e77-4852-a346-dc27f72b9f57")
   public class CheckedStateRadioButtonGroup extends AbstractRadioButtonGroup<Boolean> {
 
     @Override
@@ -180,6 +181,7 @@
     }
 
     @Order(10)
+    @ClassId("356f3fa3-6b10-4b1c-a708-aa33c24fb353")
     public class CheckedButton extends AbstractRadioButton<Boolean> {
 
       @Override
@@ -204,6 +206,7 @@
     }
 
     @Order(20)
+    @ClassId("d434f8ad-3800-46ac-b0fd-c3fd46d64095")
     public class AllButton extends AbstractRadioButton<Boolean> {
 
       @Override
@@ -230,6 +233,7 @@
   }
 
   @Order(20)
+  @ClassId("36299662-6bd3-47e2-b3bc-9d54be265de4")
   public class ActiveStateRadioButtonGroup extends AbstractRadioButtonGroup<TriState> {
 
     @Override
@@ -280,6 +284,7 @@
     }
 
     @Order(10)
+    @ClassId("fddfd6c9-882e-44bc-aa23-f6b5e1234168")
     public class ActiveButton extends AbstractRadioButton<TriState> {
 
       @Override
@@ -304,6 +309,7 @@
     }
 
     @Order(20)
+    @ClassId("67948fb1-014e-4557-a30d-cb6250ae6154")
     public class InactiveButton extends AbstractRadioButton<TriState> {
 
       @Override
@@ -328,6 +334,7 @@
     }
 
     @Order(30)
+    @ClassId("773e2eaf-71e1-4619-84aa-f38754e73dfd")
     public class ActiveAndInactiveButton extends AbstractRadioButton<TriState> {
 
       @Override