You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by nm...@apache.org on 2020/02/20 13:51:06 UTC

[ofbiz-framework] 02/04: Improved: Manage VisualTheme in ModelForm (OFBIZ-11335)

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

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

commit 1941a05a349865b8505ec373de3fce3b3a96c2a0
Author: Nicolas Malin <ni...@nereide.fr>
AuthorDate: Thu Feb 20 14:34:28 2020 +0100

    Improved: Manage VisualTheme in ModelForm
    (OFBIZ-11335)
    
    Related to issue OFBIZ-11335, extends form's factories and form's models
    to support a visualTheme during the model creation.
    
    This extend help centralize style information used by forms on a theme.
    For performance reason when the model is loaded in memory, all theme information
    need to be present to set immutable as possible to put it in cache
    (implies why the key cache contains now the visualThemeId).
---
 .../ofbiz/content/data/DataResourceWorker.java     |  3 +-
 .../webtools/artifactinfo/ArtifactInfoFactory.java |  7 +++-
 .../org/apache/ofbiz/widget/model/FormFactory.java | 48 ++++++++++++++-------
 .../org/apache/ofbiz/widget/model/GridFactory.java | 49 +++++++++++++++-------
 .../org/apache/ofbiz/widget/model/ModelForm.java   |  9 ++--
 .../apache/ofbiz/widget/model/ModelFormField.java  |  6 ++-
 .../org/apache/ofbiz/widget/model/ModelGrid.java   | 27 ++++++++----
 .../ofbiz/widget/model/ModelScreenWidget.java      |  7 +++-
 .../apache/ofbiz/widget/model/ModelSingleForm.java | 22 +++++++---
 9 files changed, 125 insertions(+), 53 deletions(-)

diff --git a/applications/content/src/main/java/org/apache/ofbiz/content/data/DataResourceWorker.java b/applications/content/src/main/java/org/apache/ofbiz/content/data/DataResourceWorker.java
index 114e763..f87936a 100644
--- a/applications/content/src/main/java/org/apache/ofbiz/content/data/DataResourceWorker.java
+++ b/applications/content/src/main/java/org/apache/ofbiz/content/data/DataResourceWorker.java
@@ -803,7 +803,8 @@ public class DataResourceWorker  implements org.apache.ofbiz.widget.content.Data
                     ModelReader entityModelReader = delegator.getModelReader();
                     String formText = getDataResourceText(dataResource, targetMimeTypeId, locale, templateContext, delegator, cache);
                     Document formXml = UtilXml.readXmlDocument(formText, true, true);
-                    Map<String, ModelForm> modelFormMap = FormFactory.readFormDocument(formXml, entityModelReader, dispatcher.getDispatchContext(), null);
+                    Map<String, ModelForm> modelFormMap = FormFactory.readFormDocument(formXml, entityModelReader,
+                            UtilHttp.getVisualTheme(request), dispatcher.getDispatchContext(), null);
 
                     if (UtilValidate.isNotEmpty(modelFormMap)) {
                         Map.Entry<String, ModelForm> entry = modelFormMap.entrySet().iterator().next(); // get first entry, only one form allowed per file
diff --git a/framework/webtools/src/main/java/org/apache/ofbiz/webtools/artifactinfo/ArtifactInfoFactory.java b/framework/webtools/src/main/java/org/apache/ofbiz/webtools/artifactinfo/ArtifactInfoFactory.java
index 62fb527..6afa3be 100644
--- a/framework/webtools/src/main/java/org/apache/ofbiz/webtools/artifactinfo/ArtifactInfoFactory.java
+++ b/framework/webtools/src/main/java/org/apache/ofbiz/webtools/artifactinfo/ArtifactInfoFactory.java
@@ -57,6 +57,7 @@ import org.apache.ofbiz.widget.model.FormFactory;
 import org.apache.ofbiz.widget.model.ModelForm;
 import org.apache.ofbiz.widget.model.ModelScreen;
 import org.apache.ofbiz.widget.model.ScreenFactory;
+import org.apache.ofbiz.widget.model.ThemeFactory;
 import org.xml.sax.SAXException;
 
 public class ArtifactInfoFactory {
@@ -185,7 +186,8 @@ public class ArtifactInfoFactory {
         return getModelForm(formNameAndLocation.substring(formNameAndLocation.indexOf("#") + 1), formNameAndLocation.substring(0, formNameAndLocation.indexOf("#")));
     }
     public ModelForm getModelForm(String formName, String formLocation) throws ParserConfigurationException, SAXException, IOException {
-        return FormFactory.getFormFromLocation(formLocation, formName, this.entityModelReader, this.dispatchContext);
+        return FormFactory.getFormFromLocation(formLocation, formName, this.entityModelReader,
+                ThemeFactory.getVisualThemeFromId("COMMON"), this.dispatchContext);
     }
 
     public ModelScreen getModelScreen(String screenName, String screenLocation) throws ParserConfigurationException, SAXException, IOException {
@@ -436,7 +438,8 @@ public class ArtifactInfoFactory {
                 String formLocation = "component://" + componentName + "/" + formFileRelativePath;
                 Map<String, ModelForm> modelFormMap = null;
                 try {
-                    modelFormMap = FormFactory.getFormsFromLocation(formLocation, getEntityModelReader(), getDispatchContext());
+                    modelFormMap = FormFactory.getFormsFromLocation(formLocation, getEntityModelReader(),
+                            ThemeFactory.getVisualThemeFromId("COMMON"), getDispatchContext());
                 } catch (Exception exc) {
                     Debug.logWarning(exc.getMessage(), module);
                 }
diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/FormFactory.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/FormFactory.java
index 78810cd..49d0ebe 100644
--- a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/FormFactory.java
+++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/FormFactory.java
@@ -35,6 +35,7 @@ import org.apache.ofbiz.entity.Delegator;
 import org.apache.ofbiz.entity.model.ModelReader;
 import org.apache.ofbiz.service.DispatchContext;
 import org.apache.ofbiz.service.LocalDispatcher;
+import org.apache.ofbiz.widget.renderer.VisualTheme;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.xml.sax.SAXException;
@@ -48,17 +49,19 @@ public class FormFactory {
     private static final UtilCache<String, ModelForm> formLocationCache = UtilCache.createUtilCache("widget.form.locationResource", 0, 0, false);
     private static final UtilCache<String, ModelForm> formWebappCache = UtilCache.createUtilCache("widget.form.webappResource", 0, 0, false);
 
-    public static Map<String, ModelForm> getFormsFromLocation(String resourceName, ModelReader entityModelReader, DispatchContext dispatchContext)
+    public static Map<String, ModelForm> getFormsFromLocation(String resourceName, ModelReader entityModelReader,
+                                                VisualTheme visualTheme, DispatchContext dispatchContext)
             throws IOException, SAXException, ParserConfigurationException {
         URL formFileUrl = FlexibleLocation.resolveLocation(resourceName);
         Document formFileDoc = UtilXml.readXmlDocument(formFileUrl, true, true);
-        return readFormDocument(formFileDoc, entityModelReader, dispatchContext, resourceName);
+        return readFormDocument(formFileDoc, entityModelReader, visualTheme, dispatchContext, resourceName);
     }
 
-    public static ModelForm getFormFromLocation(String resourceName, String formName, ModelReader entityModelReader, DispatchContext dispatchContext)
+    public static ModelForm getFormFromLocation(String resourceName, String formName, ModelReader entityModelReader,
+                                                VisualTheme visualTheme, DispatchContext dispatchContext)
             throws IOException, SAXException, ParserConfigurationException {
         StringBuilder sb = new StringBuilder(dispatchContext.getDelegator().getDelegatorName());
-        sb.append(":").append(resourceName).append("#").append(formName);
+        sb.append(":").append(resourceName).append("#").append(formName).append(visualTheme.getVisualThemeId());
         String cacheKey = sb.toString();
         ModelForm modelForm = formLocationCache.get(cacheKey);
         if (modelForm == null) {
@@ -67,7 +70,7 @@ public class FormFactory {
             if (formFileDoc == null) {
                 throw new IllegalArgumentException("Could not find resource [" + resourceName + "]");
             }
-            modelForm = createModelForm(formFileDoc, entityModelReader, dispatchContext, resourceName, formName);
+            modelForm = createModelForm(formFileDoc, entityModelReader, visualTheme, dispatchContext, resourceName, formName);
             modelForm = formLocationCache.putIfAbsentAndGet(cacheKey, modelForm);
         }
         if (modelForm == null) {
@@ -79,7 +82,15 @@ public class FormFactory {
     public static ModelForm getFormFromWebappContext(String resourceName, String formName, HttpServletRequest request)
             throws IOException, SAXException, ParserConfigurationException {
         String webappName = UtilHttp.getApplicationName(request);
-        String cacheKey = webappName + "::" + resourceName + "::" + formName;
+        VisualTheme visualTheme = UtilHttp.getVisualTheme(request);
+        String cacheKey = new StringBuilder().append(webappName)
+                .append("::")
+                .append(resourceName)
+                .append("::")
+                .append(formName)
+                .append("::")
+                .append(visualTheme.getVisualThemeId())
+                .toString();
         ModelForm modelForm = formWebappCache.get(cacheKey);
         if (modelForm == null) {
             Delegator delegator = (Delegator) request.getAttribute("delegator");
@@ -87,7 +98,7 @@ public class FormFactory {
             URL formFileUrl = request.getServletContext().getResource(resourceName);
             Document formFileDoc = UtilXml.readXmlDocument(formFileUrl, true, true);
             Element formElement = UtilXml.firstChildElement(formFileDoc.getDocumentElement(), "form", "name", formName);
-            modelForm = createModelForm(formElement, delegator.getModelReader(), dispatcher.getDispatchContext(), resourceName, formName);
+            modelForm = createModelForm(formElement, delegator.getModelReader(), visualTheme, dispatcher.getDispatchContext(), resourceName, formName);
             modelForm = formWebappCache.putIfAbsentAndGet(cacheKey, modelForm);
         }
         if (modelForm == null) {
@@ -96,7 +107,8 @@ public class FormFactory {
         return modelForm;
     }
 
-    public static Map<String, ModelForm> readFormDocument(Document formFileDoc, ModelReader entityModelReader, DispatchContext dispatchContext, String formLocation) {
+    public static Map<String, ModelForm> readFormDocument(Document formFileDoc, ModelReader entityModelReader,
+                                                VisualTheme visualTheme, DispatchContext dispatchContext, String formLocation) {
         Map<String, ModelForm> modelFormMap = new HashMap<>();
         if (formFileDoc != null) {
             // read document and construct ModelForm for each form element
@@ -107,10 +119,14 @@ public class FormFactory {
             List<? extends Element> formElements = UtilXml.childElementList(rootElement, "form");
             for (Element formElement : formElements) {
                 String formName = formElement.getAttribute("name");
-                String cacheKey = formLocation + "#" + formName;
+                String cacheKey = new StringBuilder().append(formLocation)
+                        .append("#")
+                        .append(formName)
+                        .append(visualTheme.getVisualThemeId())
+                        .toString();
                 ModelForm modelForm = formLocationCache.get(cacheKey);
                 if (modelForm == null) {
-                    modelForm = createModelForm(formElement, entityModelReader, dispatchContext, formLocation, formName);
+                    modelForm = createModelForm(formElement, entityModelReader, visualTheme, dispatchContext, formLocation, formName);
                     modelForm = formLocationCache.putIfAbsentAndGet(cacheKey, modelForm);
                 }
                 modelFormMap.put(formName, modelForm);
@@ -119,20 +135,22 @@ public class FormFactory {
         return modelFormMap;
     }
 
-    public static ModelForm createModelForm(Document formFileDoc, ModelReader entityModelReader, DispatchContext dispatchContext, String formLocation, String formName) {
+    public static ModelForm createModelForm(Document formFileDoc, ModelReader entityModelReader, VisualTheme visualTheme,
+                                            DispatchContext dispatchContext, String formLocation, String formName) {
         Element rootElement = formFileDoc.getDocumentElement();
         if (!"forms".equalsIgnoreCase(rootElement.getTagName())) {
             rootElement = UtilXml.firstChildElement(rootElement, "forms");
         }
         Element formElement = UtilXml.firstChildElement(rootElement, "form", "name", formName);
-        return createModelForm(formElement, entityModelReader, dispatchContext, formLocation, formName);
+        return createModelForm(formElement, entityModelReader, visualTheme, dispatchContext, formLocation, formName);
     }
 
-    public static ModelForm createModelForm(Element formElement, ModelReader entityModelReader, DispatchContext dispatchContext, String formLocation, String formName) {
+    public static ModelForm createModelForm(Element formElement, ModelReader entityModelReader, VisualTheme visualTheme,
+                                            DispatchContext dispatchContext, String formLocation, String formName) {
         String formType = formElement.getAttribute("type");
         if (formType.isEmpty() || "single".equals(formType) || "upload".equals(formType)) {
-            return new ModelSingleForm(formElement, formLocation, entityModelReader, dispatchContext);
+            return new ModelSingleForm(formElement, formLocation, entityModelReader, visualTheme, dispatchContext);
         }
-        return new ModelGrid(formElement, formLocation, entityModelReader, dispatchContext);
+        return new ModelGrid(formElement, formLocation, entityModelReader, visualTheme, dispatchContext);
     }
 }
diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/GridFactory.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/GridFactory.java
index 94350f3..458af2a 100644
--- a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/GridFactory.java
+++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/GridFactory.java
@@ -36,6 +36,7 @@ import org.apache.ofbiz.entity.Delegator;
 import org.apache.ofbiz.entity.model.ModelReader;
 import org.apache.ofbiz.service.DispatchContext;
 import org.apache.ofbiz.service.LocalDispatcher;
+import org.apache.ofbiz.widget.renderer.VisualTheme;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.xml.sax.SAXException;
@@ -50,17 +51,19 @@ public class GridFactory {
     private static final UtilCache<String, ModelGrid> gridLocationCache = UtilCache.createUtilCache("widget.grid.locationResource", 0, 0, false);
     private static final UtilCache<String, ModelGrid> gridWebappCache = UtilCache.createUtilCache("widget.grid.webappResource", 0, 0, false);
 
-    public static Map<String, ModelGrid> getGridsFromLocation(String resourceName, ModelReader entityModelReader, DispatchContext dispatchContext)
+    public static Map<String, ModelGrid> getGridsFromLocation(String resourceName, ModelReader entityModelReader,
+                                                              VisualTheme visualTheme, DispatchContext dispatchContext)
             throws IOException, SAXException, ParserConfigurationException {
         URL gridFileUrl = FlexibleLocation.resolveLocation(resourceName);
         Document gridFileDoc = UtilXml.readXmlDocument(gridFileUrl, true, true);
-        return readGridDocument(gridFileDoc, entityModelReader, dispatchContext, resourceName);
+        return readGridDocument(gridFileDoc, entityModelReader, visualTheme, dispatchContext, resourceName);
     }
 
-    public static ModelGrid getGridFromLocation(String resourceName, String gridName, ModelReader entityModelReader, DispatchContext dispatchContext)
+    public static ModelGrid getGridFromLocation(String resourceName, String gridName, ModelReader entityModelReader,
+                                                VisualTheme visualTheme, DispatchContext dispatchContext)
             throws IOException, SAXException, ParserConfigurationException {
         StringBuilder sb = new StringBuilder(dispatchContext.getDelegator().getDelegatorName());
-        sb.append(":").append(resourceName).append("#").append(gridName);
+        sb.append(":").append(resourceName).append("#").append(gridName).append(visualTheme.getVisualThemeId());
         String cacheKey = sb.toString();
         ModelGrid modelGrid = gridLocationCache.get(cacheKey);
         if (modelGrid == null) {
@@ -69,7 +72,8 @@ public class GridFactory {
             if (gridFileDoc == null) {
                 throw new IllegalArgumentException("Could not find resource [" + resourceName + "]");
             }
-            modelGrid = createModelGrid(gridFileDoc, entityModelReader, dispatchContext, resourceName, gridName);
+            modelGrid = createModelGrid(gridFileDoc, entityModelReader, visualTheme,
+                    dispatchContext, resourceName, gridName);
             modelGrid = gridLocationCache.putIfAbsentAndGet(cacheKey, modelGrid);
         }
         if (modelGrid == null) {
@@ -81,7 +85,15 @@ public class GridFactory {
     public static ModelGrid getGridFromWebappContext(String resourceName, String gridName, HttpServletRequest request)
             throws IOException, SAXException, ParserConfigurationException {
         String webappName = UtilHttp.getApplicationName(request);
-        String cacheKey = webappName + "::" + resourceName + "::" + gridName;
+        VisualTheme visualTheme = UtilHttp.getVisualTheme(request);
+        String cacheKey = new StringBuilder().append(webappName)
+                .append("::")
+                .append(resourceName)
+                .append("::")
+                .append(gridName)
+                .append("::")
+                .append(visualTheme.getVisualThemeId())
+                .toString();
         ModelGrid modelGrid = gridWebappCache.get(cacheKey);
         if (modelGrid == null) {
             ServletContext servletContext = request.getServletContext();
@@ -90,7 +102,8 @@ public class GridFactory {
             URL gridFileUrl = servletContext.getResource(resourceName);
             Document gridFileDoc = UtilXml.readXmlDocument(gridFileUrl, true, true);
             Element gridElement = UtilXml.firstChildElement(gridFileDoc.getDocumentElement(), "grid", "name", gridName);
-            modelGrid = createModelGrid(gridElement, delegator.getModelReader(), dispatcher.getDispatchContext(), resourceName, gridName);
+            modelGrid = createModelGrid(gridElement, delegator.getModelReader(), visualTheme,
+                    dispatcher.getDispatchContext(), resourceName, gridName);
             modelGrid = gridWebappCache.putIfAbsentAndGet(cacheKey, modelGrid);
         }
         if (modelGrid == null) {
@@ -99,7 +112,8 @@ public class GridFactory {
         return modelGrid;
     }
 
-    public static Map<String, ModelGrid> readGridDocument(Document gridFileDoc, ModelReader entityModelReader, DispatchContext dispatchContext, String gridLocation) {
+    public static Map<String, ModelGrid> readGridDocument(Document gridFileDoc, ModelReader entityModelReader,
+                                                VisualTheme visualTheme, DispatchContext dispatchContext, String gridLocation) {
         Map<String, ModelGrid> modelGridMap = new HashMap<>();
         if (gridFileDoc != null) {
             // read document and construct ModelGrid for each grid element
@@ -107,10 +121,15 @@ public class GridFactory {
             List<? extends Element> gridElements = UtilXml.childElementList(rootElement, "grid");
             for (Element gridElement : gridElements) {
                 String gridName = gridElement.getAttribute("name");
-                String cacheKey = gridLocation + "#" + gridName;
+                String cacheKey = new StringBuilder().append(gridLocation)
+                        .append("#")
+                        .append(gridName)
+                        .append(visualTheme.getVisualThemeId())
+                        .toString();
                 ModelGrid modelGrid = gridLocationCache.get(cacheKey);
                 if (modelGrid == null) {
-                    modelGrid = createModelGrid(gridElement, entityModelReader, dispatchContext, gridLocation, gridName);
+                    modelGrid = createModelGrid(gridElement, entityModelReader, visualTheme,
+                            dispatchContext, gridLocation, gridName);
                     modelGrid = gridLocationCache.putIfAbsentAndGet(cacheKey, modelGrid);
                 }
                 modelGridMap.put(gridName, modelGrid);
@@ -119,16 +138,18 @@ public class GridFactory {
         return modelGridMap;
     }
 
-    public static ModelGrid createModelGrid(Document gridFileDoc, ModelReader entityModelReader, DispatchContext dispatchContext, String gridLocation, String gridName) {
+    public static ModelGrid createModelGrid(Document gridFileDoc, ModelReader entityModelReader, VisualTheme visualTheme,
+                                            DispatchContext dispatchContext, String gridLocation, String gridName) {
         Element gridElement = UtilXml.firstChildElement(gridFileDoc.getDocumentElement(), "grid", "name", gridName);
         if (gridElement == null) {
             // Backwards compatibility - look for form definition
             gridElement = UtilXml.firstChildElement(gridFileDoc.getDocumentElement(), "form", "name", gridName);
         }
-        return createModelGrid(gridElement, entityModelReader, dispatchContext, gridLocation, gridName);
+        return createModelGrid(gridElement, entityModelReader, visualTheme, dispatchContext, gridLocation, gridName);
     }
 
-    public static ModelGrid createModelGrid(Element gridElement, ModelReader entityModelReader, DispatchContext dispatchContext, String gridLocation, String gridName) {
-        return new ModelGrid(gridElement, gridLocation, entityModelReader, dispatchContext);
+    public static ModelGrid createModelGrid(Element gridElement, ModelReader entityModelReader, VisualTheme visualTheme,
+                                            DispatchContext dispatchContext, String gridLocation, String gridName) {
+        return new ModelGrid(gridElement, gridLocation, entityModelReader, visualTheme, dispatchContext);
     }
 }
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 7556ee4..e9a139a 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
@@ -51,6 +51,7 @@ import org.apache.ofbiz.service.ModelParam;
 import org.apache.ofbiz.service.ModelService;
 import org.apache.ofbiz.widget.WidgetWorker;
 import org.apache.ofbiz.widget.renderer.FormStringRenderer;
+import org.apache.ofbiz.widget.renderer.VisualTheme;
 import org.codehaus.groovy.control.CompilationFailedException;
 import org.w3c.dom.Element;
 
@@ -193,10 +194,11 @@ public abstract class ModelForm extends ModelWidget {
     private final Set<String> useWhenFields;
 
     /** XML Constructor */
-    protected ModelForm(Element formElement, String formLocation, ModelReader entityModelReader, DispatchContext dispatchContext, String defaultType) {
+    protected ModelForm(Element formElement, String formLocation, ModelReader entityModelReader,
+                        VisualTheme visualTheme, DispatchContext dispatchContext, String defaultType) {
         super(formElement);
         this.formLocation = formLocation;
-        parentModel = getParentModel(formElement, entityModelReader, dispatchContext);
+        parentModel = getParentModel(formElement, entityModelReader, visualTheme, dispatchContext);
         int defaultViewSizeInt = DEFAULT_PAGE_SIZE;
         String viewSize = formElement.getAttribute("view-size");
         if (viewSize.isEmpty()) {
@@ -1236,7 +1238,8 @@ public abstract class ModelForm extends ModelWidget {
         return field;
     }
 
-    protected abstract ModelForm getParentModel(Element formElement, ModelReader entityModelReader, DispatchContext dispatchContext);
+    protected abstract ModelForm getParentModel(Element formElement, ModelReader entityModelReader,
+                                                VisualTheme visualTheme, DispatchContext dispatchContext);
 
     public String getParentFormLocation() {
         return this.parentModel == null ? null : this.parentModel.getFormLocation();
diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java
index 2e4968d..7d56524 100644
--- a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java
+++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java
@@ -2318,7 +2318,8 @@ public class ModelFormField {
             try {
                 org.apache.ofbiz.entity.model.ModelReader entityModelReader = ((org.apache.ofbiz.entity.Delegator)context.get("delegator")).getModelReader();
                 org.apache.ofbiz.service.DispatchContext dispatchContext = ((org.apache.ofbiz.service.LocalDispatcher)context.get("dispatcher")).getDispatchContext();
-                modelForm = FormFactory.getFormFromLocation(location, name, entityModelReader, dispatchContext);
+                VisualTheme visualTheme = (VisualTheme) context.get("visualTheme");
+                modelForm = FormFactory.getFormFromLocation(location, name, entityModelReader, visualTheme, dispatchContext);
             } catch (RuntimeException e) {
                 throw e;
             } catch (Exception e) {
@@ -2399,7 +2400,8 @@ public class ModelFormField {
             try {
                 org.apache.ofbiz.entity.model.ModelReader entityModelReader = ((org.apache.ofbiz.entity.Delegator)context.get("delegator")).getModelReader();
                 org.apache.ofbiz.service.DispatchContext dispatchContext = ((org.apache.ofbiz.service.LocalDispatcher)context.get("dispatcher")).getDispatchContext();
-                modelForm = GridFactory.getGridFromLocation(location, name, entityModelReader, dispatchContext);
+                VisualTheme visualTheme = (VisualTheme) context.get("visualTheme");
+                modelForm = GridFactory.getGridFromLocation(location, name, entityModelReader, visualTheme, dispatchContext);
             } catch (RuntimeException e) {
                 throw e;
             } catch (Exception e) {
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 712988f..086760e 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
@@ -20,10 +20,14 @@ 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.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;
 import org.w3c.dom.Element;
 
 /**
@@ -51,8 +55,9 @@ public class ModelGrid extends ModelForm {
     public static final String module = ModelGrid.class.getName();
 
     /** XML Constructor */
-    public ModelGrid(Element formElement, String formLocation, ModelReader entityModelReader, DispatchContext dispatchContext) {
-        super(formElement, formLocation, entityModelReader, dispatchContext, "list");
+    public ModelGrid(Element formElement, String formLocation, ModelReader entityModelReader,
+                     VisualTheme visualTheme, DispatchContext dispatchContext) {
+        super(formElement, formLocation, entityModelReader, visualTheme, dispatchContext, "list");
     }
 
     @Override
@@ -61,7 +66,8 @@ public class ModelGrid extends ModelForm {
     }
 
     @Override
-    protected ModelForm getParentModel(Element gridElement, ModelReader entityModelReader, DispatchContext dispatchContext) {
+    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");
@@ -69,10 +75,15 @@ public class ModelGrid extends ModelForm {
             // check if we have a resource name
             if (!parentResource.isEmpty()) {
                 try {
-                    parentModel = GridFactory.getGridFromLocation(parentResource, parentGrid, entityModelReader, dispatchContext);
+                    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);
+                    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
@@ -84,8 +95,8 @@ public class ModelGrid extends ModelForm {
                 }
                 for (Element parentElement : gridElements) {
                     if (parentElement.getAttribute("name").equals(parentGrid)) {
-                        parentModel = GridFactory.createModelGrid(parentElement, entityModelReader, dispatchContext,
-                                parentResource, parentGrid);
+                        parentModel = GridFactory.createModelGrid(parentElement, entityModelReader, visualTheme,
+                                dispatchContext, parentResource, parentGrid);
                         break;
                     }
                 }
diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelScreenWidget.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelScreenWidget.java
index 58ec24f..8303948 100644
--- a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelScreenWidget.java
+++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelScreenWidget.java
@@ -1082,8 +1082,9 @@ public abstract class ModelScreenWidget extends ModelWidget {
         public ModelForm getModelForm(Map<String, Object> context) throws IOException, SAXException, ParserConfigurationException {
             String name = this.getName(context);
             String location = this.getLocation(context);
+            VisualTheme visualTheme = (VisualTheme) context.get("visualTheme");
             return FormFactory.getFormFromLocation(location, name, getModelScreen().getDelegator(context).getModelReader(),
-                    getModelScreen().getDispatcher(context).getDispatchContext());
+                    visualTheme, getModelScreen().getDispatcher(context).getDispatchContext());
         }
 
         public String getName(Map<String, Object> context) {
@@ -1169,7 +1170,9 @@ public abstract class ModelScreenWidget extends ModelWidget {
             String name = this.getName(context);
             String location = this.getLocation(context);
             try {
-                modelForm = GridFactory.getGridFromLocation(location, name, getModelScreen().getDelegator(context).getModelReader(), getModelScreen().getDispatcher(context).getDispatchContext());
+                VisualTheme visualTheme = (VisualTheme) context.get("visualTheme");
+                modelForm = GridFactory.getGridFromLocation(location, name, getModelScreen().getDelegator(context).getModelReader(),
+                        visualTheme, getModelScreen().getDispatcher(context).getDispatchContext());
             } catch (RuntimeException e) {
                 throw e;
             } catch (Exception e) {
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 197bf17..1b925d0 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
@@ -20,10 +20,14 @@ 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.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;
 import org.w3c.dom.Element;
 
 /**
@@ -52,8 +56,8 @@ public class ModelSingleForm extends ModelForm {
 
     /** XML Constructor */
     public ModelSingleForm(Element formElement, String formLocation, ModelReader entityModelReader,
-            DispatchContext dispatchContext) {
-        super(formElement, formLocation, entityModelReader, dispatchContext, "single");
+                           VisualTheme visualTheme, DispatchContext dispatchContext) {
+        super(formElement, formLocation, entityModelReader, visualTheme, dispatchContext, "single");
     }
 
     @Override
@@ -62,7 +66,8 @@ public class ModelSingleForm extends ModelForm {
     }
 
     @Override
-    protected ModelForm getParentModel(Element formElement, ModelReader entityModelReader, DispatchContext dispatchContext) {
+    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");
@@ -70,7 +75,12 @@ public class ModelSingleForm extends ModelForm {
             // check if we have a resource name
             if (!parentResource.isEmpty()) {
                 try {
-                    parent = FormFactory.getFormFromLocation(parentResource, parentForm, entityModelReader, dispatchContext);
+                    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);
@@ -83,8 +93,8 @@ public class ModelSingleForm extends ModelForm {
                 //formElements.addAll(UtilXml.childElementList(rootElement, "abstract-form"));
                 for (Element parentElement : formElements) {
                     if (parentElement.getAttribute("name").equals(parentForm)) {
-                        parent = FormFactory.createModelForm(parentElement, entityModelReader, dispatchContext, parentResource,
-                                parentForm);
+                        parent = FormFactory.createModelForm(parentElement, entityModelReader, visualTheme,
+                                dispatchContext, parentResource, parentForm);
                         break;
                     }
                 }