This is an automated email from the ASF dual-hosted git repository.

mridulpathak pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new a5565dcbdc Close the form model hierarchy and stop field groups 
holding their form
a5565dcbdc is described below

commit a5565dcbdc387fb2aca184a5c22f5dc257cf6c24
Author: Mridul Pathak <[email protected]>
AuthorDate: Thu Oct 29 15:41:42 2026 +0530

    Close the form model hierarchy and stop field groups holding their form
    
    ModelForm called the abstract getParentModel from its constructor and 
handed itself to every FieldGroup it built, so a subclass's override ran before 
the subclass was initialised and each group carried a reference to the form 
being constructed. ModelGrid and ModelSingleForm now resolve their parent 
through one shared static resolveParentModel inside their super() arguments, 
and their two near-identical getParentModel overrides are removed with the 
abstract method. ModelForm's construc [...]
---
 .../org/apache/ofbiz/widget/model/ModelForm.java   | 147 ++++++++++++++-------
 .../org/apache/ofbiz/widget/model/ModelGrid.java   |  80 +----------
 .../apache/ofbiz/widget/model/ModelSingleForm.java |  82 +-----------
 .../apache/ofbiz/widget/renderer/FormRenderer.java |   8 +-
 .../apache/ofbiz/widget/model/ModelFormTest.java   |   5 +-
 5 files changed, 114 insertions(+), 208 deletions(-)

diff --git 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelForm.java 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelForm.java
index 724a6517a8..d64d5549dd 100644
--- 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelForm.java
+++ 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelForm.java
@@ -23,7 +23,6 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -33,6 +32,8 @@ import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
+import javax.xml.parsers.ParserConfigurationException;
+
 import org.apache.ofbiz.base.conversion.ConversionException;
 import org.apache.ofbiz.base.conversion.JSONConverters;
 import org.apache.ofbiz.base.lang.JSON;
@@ -63,6 +64,7 @@ import org.apache.ofbiz.widget.renderer.VisualTheme;
 import org.codehaus.groovy.control.CompilationFailedException;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
 
 /**
  * Abstract base class for the &lt;form&gt; and &lt;grid&gt; elements.
@@ -198,11 +200,11 @@ public abstract class ModelForm extends ModelWidget {
     private final Set<String> useWhenFields;
 
     /** XML Constructor */
-    protected ModelForm(Element formElement, String formLocation, ModelReader 
entityModelReader,
-                        VisualTheme visualTheme, DispatchContext 
dispatchContext, String defaultType) {
+    ModelForm(Element formElement, String formLocation, ModelReader 
entityModelReader,
+              VisualTheme visualTheme, DispatchContext dispatchContext, String 
defaultType, ModelForm parentModel) {
         super(formElement);
         this.formLocation = formLocation;
-        parentModel = getParentModel(formElement, entityModelReader, 
visualTheme, dispatchContext);
+        this.parentModel = parentModel;
         int defaultViewSizeInt = DEFAULT_PAGE_SIZE;
         String viewSize = formElement.getAttribute("view-size");
         if (viewSize.isEmpty()) {
@@ -491,19 +493,12 @@ public abstract class ModelForm extends ModelWidget {
             }
         }
         Map<String, FieldGroupBase> fieldGroupMap = new HashMap<>();
+        if (parentModel != null) {
+            fieldGroupMap.putAll(parentModel.fieldGroupMap);
+        }
         ArrayList<FieldGroupBase> fieldGroupList = new ArrayList<>();
         if (parentModel != null) {
-            // Copy the parent's field groups so that they render with this 
form; banners hold no form and are shared
-            Map<FieldGroupBase, FieldGroupBase> inheritedFieldGroups = new 
IdentityHashMap<>();
-            for (FieldGroupBase parentFieldGroup : parentModel.fieldGroupList) 
{
-                FieldGroupBase fieldGroup = parentFieldGroup instanceof 
FieldGroup
-                        ? new FieldGroup((FieldGroup) parentFieldGroup, this) 
: parentFieldGroup;
-                inheritedFieldGroups.put(parentFieldGroup, fieldGroup);
-                fieldGroupList.add(fieldGroup);
-            }
-            for (Map.Entry<String, FieldGroupBase> entry : 
parentModel.fieldGroupMap.entrySet()) {
-                fieldGroupMap.put(entry.getKey(), 
inheritedFieldGroups.getOrDefault(entry.getValue(), entry.getValue()));
-            }
+            fieldGroupList.addAll(parentModel.fieldGroupList);
         }
         ArrayList<String> lastOrderFields = new ArrayList<>();
         if (parentModel != null) {
@@ -629,7 +624,7 @@ public abstract class ModelForm extends ModelWidget {
         ArrayList<AutoFieldsService> autoFieldsServices = new ArrayList<>();
         ArrayList<AutoFieldsEntity> autoFieldsEntities = new ArrayList<>();
         ArrayList<SortField> sortOrderFields = new ArrayList<>();
-        this.defaultFieldGroup = new FieldGroup(null, this, sortOrderFields, 
fieldGroupMap);
+        this.defaultFieldGroup = new FieldGroup(null, sortOrderFields, 
fieldGroupMap);
         for (Element autoFieldsServiceElement : 
UtilXml.childElementList(formElement, "auto-fields-service")) {
             AutoFieldsService autoFieldsService = new 
AutoFieldsService(autoFieldsServiceElement);
             autoFieldsServices.add(autoFieldsService);
@@ -653,7 +648,7 @@ public abstract class ModelForm extends ModelWidget {
         // get the sort-order
         Element sortOrderElement = UtilXml.firstChildElement(formElement, 
"sort-order");
         if (sortOrderElement != null) {
-            FieldGroup lastFieldGroup = new FieldGroup(null, this, 
sortOrderFields, fieldGroupMap);
+            FieldGroup lastFieldGroup = new FieldGroup(null, sortOrderFields, 
fieldGroupMap);
             fieldGroupList.add(lastFieldGroup);
             // read in sort-field
             for (Element sortFieldElement : 
UtilXml.childElementList(sortOrderElement)) {
@@ -670,12 +665,12 @@ public abstract class ModelForm extends ModelWidget {
                 } else if ("banner".equals(tagName)) {
                     Banner thisBanner = new Banner(sortFieldElement);
                     fieldGroupList.add(thisBanner);
-                    lastFieldGroup = new FieldGroup(null, this, 
sortOrderFields, fieldGroupMap);
+                    lastFieldGroup = new FieldGroup(null, sortOrderFields, 
fieldGroupMap);
                     fieldGroupList.add(lastFieldGroup);
                 } else if ("field-group".equals(tagName)) {
-                    FieldGroup thisFieldGroup = new 
FieldGroup(sortFieldElement, this, sortOrderFields, fieldGroupMap);
+                    FieldGroup thisFieldGroup = new 
FieldGroup(sortFieldElement, sortOrderFields, fieldGroupMap);
                     fieldGroupList.add(thisFieldGroup);
-                    lastFieldGroup = new FieldGroup(null, this, 
sortOrderFields, fieldGroupMap);
+                    lastFieldGroup = new FieldGroup(null, sortOrderFields, 
fieldGroupMap);
                     fieldGroupList.add(lastFieldGroup);
                 }
             }
@@ -1542,8 +1537,79 @@ public abstract class ModelForm extends ModelWidget {
         return field;
     }
 
-    protected abstract ModelForm getParentModel(Element formElement, 
ModelReader entityModelReader,
-                                                VisualTheme visualTheme, 
DispatchContext dispatchContext);
+    /**
+     * Resolves the form or grid that a &lt;form&gt; or &lt;grid&gt; element 
extends. A parent with the widget's own tag
+     * is looked for first, then, for backwards compatibility, one with the 
other tag.
+     * @param widgetElement the element of the form or grid being built
+     * @param widgetTag "form" or "grid", the tag of the model being built
+     * @param entityModelReader the entity model reader
+     * @param visualTheme the visual theme
+     * @param dispatchContext the dispatch context
+     * @return the parent model, or null if the element extends nothing or the 
parent cannot be found
+     */
+    static ModelForm resolveParentModel(Element widgetElement, String 
widgetTag, ModelReader entityModelReader,
+                                        VisualTheme visualTheme, 
DispatchContext dispatchContext) {
+        String parentName = widgetElement.getAttribute("extends");
+        if (parentName.isEmpty()) {
+            return null;
+        }
+        String otherTag = "grid".equals(widgetTag) ? "form" : "grid";
+        String parentResource = widgetElement.getAttribute("extends-resource");
+        ModelForm parentModel = null;
+        if (!parentResource.isEmpty()) {
+            try {
+                FlexibleStringExpander parentResourceExp = 
FlexibleStringExpander.getInstance(parentResource);
+                Map<String, String> visualRessources = UtilMisc.toMap(
+                        "commonFormLocations", 
visualTheme.getModelTheme().getModelCommonForms());
+                parentResource = 
parentResourceExp.expandString(visualRessources);
+                parentModel = getModelFromLocation(widgetTag, parentResource, 
parentName, entityModelReader, visualTheme,
+                        dispatchContext);
+            } catch (Exception e) {
+                Debug.logError(e, "Failed to load parent " + widgetTag + " 
definition '" + parentName
+                        + "' at resource '" + parentResource + "'", MODULE);
+            }
+            if (parentModel == null) {
+                try {
+                    parentModel = getModelFromLocation(otherTag, 
parentResource, parentName, entityModelReader, visualTheme,
+                            dispatchContext);
+                } catch (Exception e) {
+                    Debug.logError(e, "Failed to load parent " + widgetTag + " 
definition '" + parentName
+                            + "' at resource '" + parentResource + "'", 
MODULE);
+                }
+            }
+        } else if (!parentName.equals(widgetElement.getAttribute("name"))) {
+            // try to find the parent definition in the same file
+            Element rootElement = 
widgetElement.getOwnerDocument().getDocumentElement();
+            Element parentElement = UtilXml.firstChildElement(rootElement, 
widgetTag, "name", parentName);
+            String parentTag = widgetTag;
+            if (parentElement == null) {
+                parentElement = UtilXml.firstChildElement(rootElement, 
otherTag, "name", parentName);
+                parentTag = otherTag;
+            }
+            if (parentElement == null) {
+                Debug.logError("Failed to find parent " + widgetTag + " 
definition '" + parentName + "' in same document.",
+                        MODULE);
+            } else if ("grid".equals(parentTag)) {
+                parentModel = GridFactory.createModelGrid(parentElement, 
entityModelReader, visualTheme, dispatchContext,
+                        parentResource, parentName);
+            } else {
+                parentModel = FormFactory.createModelForm(parentElement, 
entityModelReader, visualTheme, dispatchContext,
+                        parentResource, parentName);
+            }
+        } else {
+            Debug.logError("Recursive " + widgetTag + " definition found for 
'" + widgetElement.getAttribute("name") + ".'",
+                    MODULE);
+        }
+        return parentModel;
+    }
+
+    private static ModelForm getModelFromLocation(String tag, String 
resourceName, String name, ModelReader entityModelReader,
+            VisualTheme visualTheme, DispatchContext dispatchContext)
+            throws IOException, SAXException, ParserConfigurationException {
+        return "grid".equals(tag)
+                ? GridFactory.getGridFromLocation(resourceName, name, 
entityModelReader, visualTheme, dispatchContext)
+                : FormFactory.getFormFromLocation(resourceName, name, 
entityModelReader, visualTheme, dispatchContext);
+    }
 
     /**
      * Gets parent form location.
@@ -2008,7 +2074,7 @@ public abstract class ModelForm extends ModelWidget {
         }
     }
 
-    public static class Banner implements FieldGroupBase {
+    public static final class Banner implements FieldGroupBase {
         private final FlexibleStringExpander style;
         private final FlexibleStringExpander text;
         private final FlexibleStringExpander textStyle;
@@ -2103,7 +2169,7 @@ public abstract class ModelForm extends ModelWidget {
         }
     }
 
-    public static class FieldGroup implements FieldGroupBase {
+    public static final class FieldGroup implements FieldGroupBase {
         private static AtomicInteger baseSeqNo = new AtomicInteger(0);
         private static final String BASE_ID = "_G";
         private final String id;
@@ -2111,11 +2177,8 @@ public abstract class ModelForm extends ModelWidget {
         private final String title;
         private final boolean collapsible;
         private final boolean initiallyCollapsed;
-        private final ModelForm modelForm;
 
-        public FieldGroup(Element sortOrderElement, ModelForm modelForm, 
List<SortField> sortOrderFields,
-                Map<String, FieldGroupBase> fieldGroupMap) {
-            this.modelForm = modelForm;
+        private FieldGroup(Element sortOrderElement, List<SortField> 
sortOrderFields, Map<String, FieldGroupBase> fieldGroupMap) {
             String id;
             String style = "";
             String title = "";
@@ -2150,15 +2213,6 @@ public abstract class ModelForm extends ModelWidget {
             this.initiallyCollapsed = initiallyCollapsed;
         }
 
-        private FieldGroup(FieldGroup parentFieldGroup, ModelForm modelForm) {
-            this.modelForm = modelForm;
-            this.id = parentFieldGroup.id;
-            this.style = parentFieldGroup.style;
-            this.title = parentFieldGroup.title;
-            this.collapsible = parentFieldGroup.collapsible;
-            this.initiallyCollapsed = parentFieldGroup.initiallyCollapsed;
-        }
-
         /**
          * Collapsible boolean.
          * @return the boolean
@@ -2203,14 +2257,15 @@ public abstract class ModelForm extends ModelWidget {
          * Render end string.
          * @param writer             the writer
          * @param context            the context
+         * @param modelForm          the form being rendered
          * @param formStringRenderer the form string renderer
          * @throws IOException the io exception
          */
-        public void renderEndString(Appendable writer, Map<String, Object> 
context, FormStringRenderer formStringRenderer)
-                throws IOException {
+        public void renderEndString(Appendable writer, Map<String, Object> 
context, ModelForm modelForm,
+                FormStringRenderer formStringRenderer) throws IOException {
             formStringRenderer.renderFormatSingleWrapperClose(writer, context, 
modelForm);
             if (!modelForm.fieldGroupList.isEmpty()) {
-                if (shouldUse(context)) {
+                if (shouldUse(context, modelForm)) {
                     formStringRenderer.renderFieldGroupClose(writer, context, 
this);
                 }
             }
@@ -2220,13 +2275,14 @@ public abstract class ModelForm extends ModelWidget {
          * Render start string.
          * @param writer             the writer
          * @param context            the context
+         * @param modelForm          the form being rendered
          * @param formStringRenderer the form string renderer
          * @throws IOException the io exception
          */
-        public void renderStartString(Appendable writer, Map<String, Object> 
context, FormStringRenderer formStringRenderer)
-                throws IOException {
+        public void renderStartString(Appendable writer, Map<String, Object> 
context, ModelForm modelForm,
+                FormStringRenderer formStringRenderer) throws IOException {
             if (!modelForm.fieldGroupList.isEmpty()) {
-                if (shouldUse(context)) {
+                if (shouldUse(context, modelForm)) {
                     formStringRenderer.renderFieldGroupOpen(writer, context, 
this);
                 }
             }
@@ -2236,9 +2292,10 @@ public abstract class ModelForm extends ModelWidget {
         /**
          * Should use boolean.
          * @param context the context
+         * @param modelForm the form being rendered
          * @return the boolean
          */
-        public boolean shouldUse(Map<String, Object> context) {
+        public boolean shouldUse(Map<String, Object> context, ModelForm 
modelForm) {
             for (String fieldName : modelForm.fieldGroupMap.keySet()) {
                 FieldGroupBase group = modelForm.fieldGroupMap.get(fieldName);
                 if (group instanceof FieldGroup) {
@@ -2256,7 +2313,7 @@ public abstract class ModelForm extends ModelWidget {
         }
     }
 
-    public interface FieldGroupBase {
+    public sealed interface FieldGroupBase permits Banner, FieldGroup {
     }
 
     public static class SortField {
diff --git 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelGrid.java 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelGrid.java
index 11fac6eb91..0f4ef7ab33 100644
--- 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelGrid.java
+++ 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelGrid.java
@@ -18,14 +18,6 @@
  
*******************************************************************************/
 package org.apache.ofbiz.widget.model;
 
-import java.util.List;
-
-import java.util.Map;
-import org.apache.ofbiz.base.util.Debug;
-import org.apache.ofbiz.base.util.UtilMisc;
-import org.apache.ofbiz.base.util.UtilValidate;
-import org.apache.ofbiz.base.util.UtilXml;
-import org.apache.ofbiz.base.util.string.FlexibleStringExpander;
 import org.apache.ofbiz.entity.model.ModelReader;
 import org.apache.ofbiz.service.DispatchContext;
 import org.apache.ofbiz.widget.renderer.VisualTheme;
@@ -37,7 +29,7 @@ import org.w3c.dom.Element;
  * @see <code>widget-form.xsd</code>
  */
 @SuppressWarnings("serial")
-public class ModelGrid extends ModelForm {
+public final class ModelGrid extends ModelForm {
 
     /*
      * ----------------------------------------------------------------------- 
*
@@ -50,81 +42,15 @@ public class ModelGrid extends ModelForm {
      * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!
      */
 
-    private static final String MODULE = ModelGrid.class.getName();
-
     /** XML Constructor */
     public ModelGrid(Element formElement, String formLocation, ModelReader 
entityModelReader,
                      VisualTheme visualTheme, DispatchContext dispatchContext) 
{
-        super(formElement, formLocation, entityModelReader, visualTheme, 
dispatchContext, "list");
+        super(formElement, formLocation, entityModelReader, visualTheme, 
dispatchContext, "list",
+                resolveParentModel(formElement, "grid", entityModelReader, 
visualTheme, dispatchContext));
     }
 
     @Override
     public void accept(ModelWidgetVisitor visitor) throws Exception {
         visitor.visit(this);
     }
-
-    @Override
-    protected ModelForm getParentModel(Element gridElement, ModelReader 
entityModelReader,
-                                       VisualTheme visualTheme, 
DispatchContext dispatchContext) {
-        ModelForm parentModel = null;
-        String parentResource = gridElement.getAttribute("extends-resource");
-        String parentGrid = gridElement.getAttribute("extends");
-        if (!parentGrid.isEmpty()) {
-            // check if we have a resource name
-            if (!parentResource.isEmpty()) {
-                try {
-                    FlexibleStringExpander parentResourceExp = 
FlexibleStringExpander.getInstance(parentResource);
-                    Map<String, String> visualRessources = UtilMisc.toMap(
-                            "commonFormLocations", 
visualTheme.getModelTheme().getModelCommonForms());
-                    parentResource = 
parentResourceExp.expandString(visualRessources);
-                    parentModel = 
GridFactory.getGridFromLocation(parentResource, parentGrid, entityModelReader,
-                            visualTheme, dispatchContext);
-                } catch (Exception e) {
-                    Debug.logError(e, "Failed to load parent grid definition 
'" + parentGrid
-                            + "' at resource '" + parentResource + "'", 
MODULE);
-                }
-                if (parentModel == null) {
-                    // Backwards compatibility - look for form definitions
-                    try {
-                        parentModel = 
FormFactory.getFormFromLocation(parentResource, parentGrid, entityModelReader,
-                                visualTheme, dispatchContext);
-                    } catch (Exception e) {
-                        Debug.logError(e, "Failed to load parent grid 
definition '" + parentGrid
-                                + "' at resource '" + parentResource + "'", 
MODULE);
-                    }
-                }
-
-            } else if (!parentGrid.equals(gridElement.getAttribute("name"))) {
-                // try to find a grid definition in the same file
-                Element rootElement = 
gridElement.getOwnerDocument().getDocumentElement();
-                List<? extends Element> gridElements = 
UtilXml.childElementList(rootElement, "grid");
-                if (gridElements.stream()
-                        .noneMatch(grid -> 
grid.getAttribute("name").equals(parentGrid))) {
-                    // Backwards compatibility - look for form definitions
-                    gridElements = UtilXml.childElementList(rootElement, 
"form");
-                    Element parentElement = gridElements.stream()
-                            .filter(form -> 
form.getAttribute("name").equals(parentGrid))
-                            .findFirst().orElse(null);
-                    if (UtilValidate.isNotEmpty(parentElement)) {
-                        parentModel = 
FormFactory.createModelForm(parentElement, entityModelReader, visualTheme,
-                                dispatchContext, parentResource, parentGrid);
-                        return parentModel;
-                    }
-                }
-                for (Element parentElement : gridElements) {
-                    if (parentElement.getAttribute("name").equals(parentGrid)) 
{
-                        parentModel = 
GridFactory.createModelGrid(parentElement, entityModelReader, visualTheme,
-                                dispatchContext, parentResource, parentGrid);
-                        break;
-                    }
-                }
-                if (parentModel == null) {
-                    Debug.logError("Failed to find parent grid definition '" + 
parentGrid + "' in same document.", MODULE);
-                }
-            } else {
-                Debug.logError("Recursive grid definition found for '" + 
gridElement.getAttribute("name") + ".'", MODULE);
-            }
-        }
-        return parentModel;
-    }
 }
diff --git 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelSingleForm.java
 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelSingleForm.java
index e53d15cf8c..1ca4b3aca8 100644
--- 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelSingleForm.java
+++ 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelSingleForm.java
@@ -18,14 +18,6 @@
  
*******************************************************************************/
 package org.apache.ofbiz.widget.model;
 
-import java.util.List;
-
-import java.util.Map;
-import org.apache.ofbiz.base.util.Debug;
-import org.apache.ofbiz.base.util.UtilMisc;
-import org.apache.ofbiz.base.util.UtilValidate;
-import org.apache.ofbiz.base.util.UtilXml;
-import org.apache.ofbiz.base.util.string.FlexibleStringExpander;
 import org.apache.ofbiz.entity.model.ModelReader;
 import org.apache.ofbiz.service.DispatchContext;
 import org.apache.ofbiz.widget.renderer.VisualTheme;
@@ -37,7 +29,7 @@ import org.w3c.dom.Element;
  * @see <code>widget-form.xsd</code>
  */
 @SuppressWarnings("serial")
-public class ModelSingleForm extends ModelForm {
+public final class ModelSingleForm extends ModelForm {
 
     /*
      * ----------------------------------------------------------------------- 
*
@@ -50,83 +42,15 @@ public class ModelSingleForm extends ModelForm {
      * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!
      */
 
-    private static final String MODULE = ModelSingleForm.class.getName();
-
     /** XML Constructor */
     public ModelSingleForm(Element formElement, String formLocation, 
ModelReader entityModelReader,
                            VisualTheme visualTheme, DispatchContext 
dispatchContext) {
-        super(formElement, formLocation, entityModelReader, visualTheme, 
dispatchContext, "single");
+        super(formElement, formLocation, entityModelReader, visualTheme, 
dispatchContext, "single",
+                resolveParentModel(formElement, "form", entityModelReader, 
visualTheme, dispatchContext));
     }
 
     @Override
     public void accept(ModelWidgetVisitor visitor) throws Exception {
         visitor.visit(this);
     }
-
-    @Override
-    protected ModelForm getParentModel(Element formElement, ModelReader 
entityModelReader,
-                                       VisualTheme visualTheme, 
DispatchContext dispatchContext) {
-        ModelForm parent = null;
-        String parentResource = formElement.getAttribute("extends-resource");
-        String parentForm = formElement.getAttribute("extends");
-        if (!parentForm.isEmpty()) {
-            // check if we have a resource name
-            if (!parentResource.isEmpty()) {
-                try {
-                    FlexibleStringExpander parentResourceExp = 
FlexibleStringExpander.getInstance(parentResource);
-                    Map<String, String> visualRessources = UtilMisc.toMap(
-                            "commonFormLocations", 
visualTheme.getModelTheme().getModelCommonForms());
-                    parentResource = 
parentResourceExp.expandString(visualRessources);
-                    parent = FormFactory.getFormFromLocation(parentResource, 
parentForm, entityModelReader,
-                            visualTheme, dispatchContext);
-                } catch (Exception e) {
-                    Debug.logError(e, "Failed to load parent form definition 
'" + parentForm + "' at resource '" + parentResource
-                            + "'", MODULE);
-                }
-                if (parent == null) {
-                    try {
-                        // Backwards compatibility - look for grid definitions
-                        parent = 
GridFactory.getGridFromLocation(parentResource, parentForm, entityModelReader,
-                                visualTheme, dispatchContext);
-                    } catch (Exception e) {
-                        Debug.logError(e, "Failed to load parent form 
definition '" + parentForm + "' at resource '" + parentResource
-                                + "'", MODULE);
-                    }
-                }
-
-            } else if (!parentForm.equals(formElement.getAttribute("name"))) {
-                // try to find a form definition in the same file
-                Element rootElement = 
formElement.getOwnerDocument().getDocumentElement();
-                List<? extends Element> formElements = 
UtilXml.childElementList(rootElement, "form");
-                //Uncomment below to add support for abstract forms
-                //formElements.addAll(UtilXml.childElementList(rootElement, 
"abstract-form"));
-                if (formElements.stream()
-                        .noneMatch(form -> 
form.getAttribute("name").equals(parentForm))) {
-                    // Backwards compatibility - look for grid definitions
-                    formElements = UtilXml.childElementList(rootElement, 
"grid");
-                    Element parentElement = formElements.stream()
-                            .filter(grid -> 
grid.getAttribute("name").equals(parentForm))
-                            .findFirst().orElse(null);
-                    if (UtilValidate.isNotEmpty(parentElement)) {
-                        parent = GridFactory.createModelGrid(parentElement, 
entityModelReader, visualTheme,
-                                dispatchContext, parentResource, parentForm);
-                        return parent;
-                    }
-                }
-                for (Element parentElement : formElements) {
-                    if (parentElement.getAttribute("name").equals(parentForm)) 
{
-                        parent = FormFactory.createModelForm(parentElement, 
entityModelReader, visualTheme,
-                                dispatchContext, parentResource, parentForm);
-                        break;
-                    }
-                }
-                if (parent == null) {
-                    Debug.logError("Failed to find parent form definition '" + 
parentForm + "' in same document.", MODULE);
-                }
-            } else {
-                Debug.logError("Recursive form definition found for '" + 
formElement.getAttribute("name") + ".'", MODULE);
-            }
-        }
-        return parent;
-    }
 }
diff --git 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/FormRenderer.java
 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/FormRenderer.java
index 6e2f654767..46b339fa2d 100644
--- 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/FormRenderer.java
+++ 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/FormRenderer.java
@@ -1063,7 +1063,7 @@ public class FormRenderer {
                     }
                 }
                 if (currentFieldGroup != null && (lastFieldGroup == null || 
!lastFieldGroupName.equals(currentFieldGroupName))) {
-                    currentFieldGroup.renderStartString(writer, context, 
formStringRenderer);
+                    currentFieldGroup.renderStartString(writer, context, 
modelForm, formStringRenderer);
                     lastFieldGroup = currentFieldGroup;
                 }
             } else {
@@ -1099,7 +1099,7 @@ public class FormRenderer {
                             
formStringRenderer.renderFormatFieldRowClose(writer, context, modelForm);
                             haveRenderedOpenFieldRow = false;
                         }
-                        lastFieldGroup.renderEndString(writer, context, 
formStringRenderer);
+                        lastFieldGroup.renderEndString(writer, context, 
modelForm, formStringRenderer);
 
                         List<FieldGroupBase> inbetweenList = 
getInbetweenList(lastFieldGroup, currentFieldGroup);
                         for (FieldGroupBase obj : inbetweenList) {
@@ -1113,7 +1113,7 @@ public class FormRenderer {
                 }
 
                 if (lastFieldGroup == null || 
!lastFieldGroupName.equals(currentFieldGroupName)) {
-                    currentFieldGroup.renderStartString(writer, context, 
formStringRenderer);
+                    currentFieldGroup.renderStartString(writer, context, 
modelForm, formStringRenderer);
                     lastFieldGroup = currentFieldGroup;
                 }
             }
@@ -1229,7 +1229,7 @@ public class FormRenderer {
         }
 
         if (lastFieldGroup != null) {
-            lastFieldGroup.renderEndString(writer, context, 
formStringRenderer);
+            lastFieldGroup.renderEndString(writer, context, modelForm, 
formStringRenderer);
         }
         // render formatting wrapper close
         // should be handled by renderEndString
diff --git 
a/framework/widget/src/test/java/org/apache/ofbiz/widget/model/ModelFormTest.java
 
b/framework/widget/src/test/java/org/apache/ofbiz/widget/model/ModelFormTest.java
index 3a2c2782bd..6d8a8aaf60 100644
--- 
a/framework/widget/src/test/java/org/apache/ofbiz/widget/model/ModelFormTest.java
+++ 
b/framework/widget/src/test/java/org/apache/ofbiz/widget/model/ModelFormTest.java
@@ -129,12 +129,11 @@ public final class ModelFormTest {
         Assertions.assertNotNull(parent, "Child should have a parent");
         ModelForm.FieldGroup fieldGroup = (ModelForm.FieldGroup) 
child.getFieldGroupMap().get("a");
         Assertions.assertTrue(child.getFieldGroupList().contains(fieldGroup), 
"Field group should be in the child list");
-        Assertions.assertNotSame(parent.getFieldGroupMap().get("a"), 
fieldGroup, "Field group should be the child's own");
 
         FormStringRenderer renderer = Mockito.mock(FormStringRenderer.class);
         StringBuilder writer = new StringBuilder();
-        fieldGroup.renderStartString(writer, context, renderer);
-        fieldGroup.renderEndString(writer, context, renderer);
+        fieldGroup.renderStartString(writer, context, child, renderer);
+        fieldGroup.renderEndString(writer, context, child, renderer);
         verify(renderer).renderFormatSingleWrapperOpen(same(writer), 
same(context), same(child));
         verify(renderer).renderFormatSingleWrapperClose(same(writer), 
same(context), same(child));
         verify(renderer, never()).renderFormatSingleWrapperOpen(any(), any(), 
same(parent));

Reply via email to