svn commit: r1652852 [3/22] - in /ofbiz/trunk: applications/content/src/org/ofbiz/content/cms/ applications/content/src/org/ofbiz/content/content/ applications/content/src/org/ofbiz/content/data/ applications/content/src/org/ofbiz/content/output/ appli...

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r1652852 [3/22] - in /ofbiz/trunk: applications/content/src/org/ofbiz/content/cms/ applications/content/src/org/ofbiz/content/content/ applications/content/src/org/ofbiz/content/data/ applications/content/src/org/ofbiz/content/output/ appli...

adrianc
Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/CommonWidgetModels.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/CommonWidgetModels.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/CommonWidgetModels.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/CommonWidgetModels.java Sun Jan 18 21:03:40 2015
@@ -0,0 +1,629 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.widget.model;
+
+import java.math.BigDecimal;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.UtilCodec;
+import org.ofbiz.base.util.UtilDateTime;
+import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.base.util.UtilXml;
+import org.ofbiz.base.util.collections.FlexibleMapAccessor;
+import org.ofbiz.base.util.string.FlexibleStringExpander;
+import org.ofbiz.entity.Delegator;
+import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.model.ModelEntity;
+import org.ofbiz.entity.model.ModelField;
+import org.ofbiz.service.GenericServiceException;
+import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ModelParam;
+import org.ofbiz.service.ModelService;
+import org.w3c.dom.Element;
+
+/**
+ * A collection of shared/reused widget models.
+ *
+ */
+public final class CommonWidgetModels {
+
+    public static final String module = CommonWidgetModels.class.getName();
+
+    private CommonWidgetModels() {
+    }
+
+    public static class AutoEntityParameters {
+        private String entityName;
+        List<String> excludeList = new ArrayList<String>();
+        boolean includeNonPk;
+        boolean includePk;
+        private String includeType;
+        boolean sendIfEmpty;
+
+        public AutoEntityParameters(Element autoElement) {
+            entityName = UtilXml.checkEmpty(autoElement.getAttribute("entity-name"));
+            sendIfEmpty = "true".equals(autoElement.getAttribute("send-if-empty"));
+            includeType = UtilXml.checkEmpty(autoElement.getAttribute("include"));
+            includePk = "pk".equals(includeType) || "all".equals(includeType);
+            includeNonPk = "nonpk".equals(includeType) || "all".equals(includeType);
+            List<? extends Element> excludes = UtilXml.childElementList(autoElement, "exclude");
+            if (excludes != null) {
+                for (Element exclude : excludes) {
+                    if (UtilValidate.isNotEmpty(exclude.getAttribute("field-name"))) {
+                        excludeList.add(exclude.getAttribute("field-name"));
+                    }
+                }
+            }
+        }
+
+        @SuppressWarnings("unchecked")
+        public Map<String, String> getParametersMap(Map<String, Object> context, String defaultEntityName) {
+            Map<String, String> autEntityParams = new HashMap<String, String>();
+            Delegator delegator = (Delegator) context.get("delegator");
+            if (delegator == null) {
+                Debug.logError(
+                        "We can not append auto entity Parameters since we could not find delegator in the current context",
+                        module);
+                return autEntityParams;
+            }
+            if (UtilValidate.isEmpty(entityName))
+                entityName = defaultEntityName;
+            FlexibleStringExpander toExpand = FlexibleStringExpander.getInstance(entityName);
+            ModelEntity entity = delegator.getModelEntity(toExpand.expandString(context));
+            if (entity == null) {
+                Debug.logError("We can not append auto entity Parameters since we could not find entity with name [" + entityName
+                        + "]", module);
+                return autEntityParams;
+            }
+
+            Iterator<ModelField> fieldsIter = entity.getFieldsIterator();
+            if (fieldsIter != null) {
+                while (fieldsIter.hasNext()) {
+                    ModelField field = fieldsIter.next();
+                    String fieldName = field.getName();
+                    FlexibleMapAccessor<Object> fma = FlexibleMapAccessor.getInstance(fieldName);
+                    boolean shouldExclude = excludeList.contains(fieldName);
+                    if ((!shouldExclude) && (!field.getIsAutoCreatedInternal())
+                            && ((field.getIsPk() && includePk) || (!field.getIsPk() && includeNonPk))) {
+                        Object flexibleValue = fma.get(context);
+                        if (UtilValidate.isEmpty(flexibleValue) && context.containsKey("parameters")) {
+                            flexibleValue = fma.get((Map<String, Object>) context.get("parameters"));
+                        }
+                        if (UtilValidate.isNotEmpty(flexibleValue) || sendIfEmpty) {
+                            autEntityParams.put(fieldName, String.valueOf(flexibleValue));
+                        }
+                    }
+                }
+            }
+            return autEntityParams;
+        }
+    }
+
+    public static class AutoServiceParameters {
+        List<String> excludeList = new ArrayList<String>();
+        boolean includeNonPk;
+        boolean includePk;
+        boolean sendIfEmpty;
+        private String serviceName;
+
+        public AutoServiceParameters(Element autoElement) {
+            serviceName = UtilXml.checkEmpty(autoElement.getAttribute("service-name"));
+            sendIfEmpty = "true".equals(autoElement.getAttribute("send-if-empty"));
+            List<? extends Element> excludes = UtilXml.childElementList(autoElement, "exclude");
+            if (excludes != null) {
+                for (Element exclude : excludes) {
+                    if (UtilValidate.isNotEmpty(exclude.getAttribute("field-name"))) {
+                        excludeList.add(exclude.getAttribute("field-name"));
+                    }
+                }
+            }
+        }
+
+        @SuppressWarnings("unchecked")
+        public Map<String, String> getParametersMap(Map<String, Object> context, String defaultServiceName) {
+            Map<String, String> autServiceParams = new HashMap<String, String>();
+            LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher");
+            if (dispatcher == null) {
+                Debug.logError(
+                        "We can not append auto service Parameters since we could not find dispatcher in the current context",
+                        module);
+                return autServiceParams;
+            }
+            if (UtilValidate.isEmpty(serviceName))
+                serviceName = defaultServiceName;
+            FlexibleStringExpander toExpand = FlexibleStringExpander.getInstance(serviceName);
+            ModelService service = null;
+            try {
+                service = dispatcher.getDispatchContext().getModelService(toExpand.toString());
+            } catch (GenericServiceException e) {
+                Debug.logError("Resolve service throw an error : " + e, module);
+            }
+            if (service == null) {
+                Debug.logError("We can not append auto service Parameters since we could not find service with name ["
+                        + serviceName + "]", module);
+                return autServiceParams;
+            }
+            Iterator<ModelParam> paramsIter = service.getInModelParamList().iterator();
+            if (paramsIter != null) {
+                while (paramsIter.hasNext()) {
+                    ModelParam param = paramsIter.next();
+                    if (param.getInternal())
+                        continue;
+                    String paramName = param.getName();
+                    FlexibleMapAccessor<Object> fma = FlexibleMapAccessor.getInstance(paramName);
+                    if (!excludeList.contains(paramName)) {
+                        Object flexibleValue = fma.get(context);
+                        if (UtilValidate.isEmpty(flexibleValue) && context.containsKey("parameters")) {
+                            flexibleValue = fma.get((Map<String, ? extends Object>) context.get("parameters"));
+                        }
+                        if (UtilValidate.isNotEmpty(flexibleValue) || sendIfEmpty) {
+                            autServiceParams.put(paramName, String.valueOf(flexibleValue));
+                        }
+                    }
+                }
+            }
+            return autServiceParams;
+        }
+    }
+
+    public static final class Image {
+        private final FlexibleStringExpander alt;
+        private final FlexibleStringExpander borderExdr;
+        private final FlexibleStringExpander heightExdr;
+        private final FlexibleStringExpander idExdr;
+        private final String name;
+        private final FlexibleStringExpander srcExdr;
+        private final FlexibleStringExpander styleExdr;
+        private final FlexibleStringExpander titleExdr;
+        private final String urlMode;
+        private final FlexibleStringExpander widthExdr;
+
+        public Image(Element imageElement) {
+            this.name = imageElement.getAttribute("name");
+            String src = imageElement.getAttribute("image-location");
+            if (src.isEmpty()) {
+                src = imageElement.getAttribute("src");
+            } else {
+                // Form field version, log warning.
+            }
+            this.srcExdr = FlexibleStringExpander.getInstance(src);
+            this.idExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("id"));
+            this.styleExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("style"));
+            this.widthExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("width"));
+            this.heightExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("height"));
+            this.borderExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("border"));
+            String alt = imageElement.getAttribute("alternate");
+            if (alt.isEmpty()) {
+                alt = imageElement.getAttribute("alt"); // Common version, no warning.
+            } else {
+                // Form field version, log warning.
+            }
+            this.alt = FlexibleStringExpander.getInstance(alt);
+            String urlMode = imageElement.getAttribute("url-mode");
+            if (urlMode.isEmpty()) {
+                urlMode = "content";
+            }
+            this.urlMode = urlMode;
+            String title = imageElement.getAttribute("image-title");
+            if (title.isEmpty()) {
+                title = imageElement.getAttribute("title");
+            } else {
+                // Form field version, log warning.
+            }
+            this.titleExdr = FlexibleStringExpander.getInstance(title);
+        }
+
+        public FlexibleStringExpander getAlt() {
+            return alt;
+        }
+
+        public String getAlt(Map<String, Object> context) {
+            String alt = this.alt.expandString(context);
+            // FIXME: Encoding should be done by the renderer, not by the model.
+            UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
+            if (simpleEncoder != null) {
+                alt = simpleEncoder.encode(alt);
+            }
+            return alt;
+        }
+
+        public String getBorder(Map<String, Object> context) {
+            return this.borderExdr.expandString(context);
+        }
+
+        public FlexibleStringExpander getBorderExdr() {
+            return borderExdr;
+        }
+
+        public String getHeight(Map<String, Object> context) {
+            return this.heightExdr.expandString(context);
+        }
+
+        public FlexibleStringExpander getHeightExdr() {
+            return heightExdr;
+        }
+
+        public String getId(Map<String, Object> context) {
+            return this.idExdr.expandString(context);
+        }
+
+        public FlexibleStringExpander getIdExdr() {
+            return idExdr;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public String getSrc(Map<String, Object> context) {
+            return this.srcExdr.expandString(context);
+        }
+
+        public FlexibleStringExpander getSrcExdr() {
+            return srcExdr;
+        }
+
+        public String getStyle(Map<String, Object> context) {
+            return this.styleExdr.expandString(context);
+        }
+
+        public FlexibleStringExpander getStyleExdr() {
+            return styleExdr;
+        }
+
+        public FlexibleStringExpander getTitleExdr() {
+            return titleExdr;
+        }
+
+        public String getUrlMode() {
+            return this.urlMode;
+        }
+
+        public String getWidth(Map<String, Object> context) {
+            return this.widthExdr.expandString(context);
+        }
+
+        public FlexibleStringExpander getWidthExdr() {
+            return widthExdr;
+        }
+    }
+
+    public static final class Link {
+        // FIXME: This is a bad practice. Client code should not need to "know" what this value is.
+        public static final String DEFAULT_URL_MODE = "intra-app";
+        private final AutoEntityParameters autoEntityParameters;
+        private final AutoServiceParameters autoServiceParameters;
+        private final boolean encode;
+        private final boolean fullPath;
+        private final FlexibleStringExpander idExdr;
+        private final Image image;
+        private final String linkType; // anchor or hidden form
+        private final FlexibleStringExpander nameExdr;
+        private final List<Parameter> parameterList;
+        private final FlexibleStringExpander prefixExdr;
+        private final boolean secure;
+        private final Integer size;
+        private final FlexibleStringExpander styleExdr;
+        private final FlexibleStringExpander targetExdr;
+        private final FlexibleStringExpander targetWindowExdr;
+        private final FlexibleStringExpander textExdr;
+        private final String urlMode;
+        // FIXME: These don't belong in this class
+        private final String height;
+        private final String width;
+
+        public Link(Element linkElement) {
+            this.textExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("text"));
+            this.idExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("id"));
+            this.styleExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("style"));
+            this.nameExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("name"));
+            this.targetExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("target"));
+            this.targetWindowExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("target-window"));
+            this.prefixExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("prefix"));
+            this.urlMode = linkElement.getAttribute("url-mode");
+            this.fullPath = "true".equals(linkElement.getAttribute("full-path"));
+            this.secure = "true".equals(linkElement.getAttribute("secure"));
+            this.encode = "true".equals(linkElement.getAttribute("encode"));
+            Element imageElement = UtilXml.firstChildElement(linkElement, "image");
+            if (imageElement != null) {
+                this.image = new Image(imageElement);
+            } else {
+                // TODO: Look for ModelFormField attributes
+                this.image = null;
+            }
+            this.linkType = linkElement.getAttribute("link-type");
+            List<? extends Element> parameterElementList = UtilXml.childElementList(linkElement, "parameter");
+            if (parameterElementList.isEmpty()) {
+                this.parameterList = Collections.emptyList();
+            } else {
+                List<Parameter> parameterList = new ArrayList<Parameter>(
+                        parameterElementList.size());
+                for (Element parameterElement : parameterElementList) {
+                    parameterList.add(new Parameter(parameterElement));
+                }
+                this.parameterList = Collections.unmodifiableList(parameterList);
+            }
+            Element autoServiceParamsElement = UtilXml.firstChildElement(linkElement, "auto-parameters-service");
+            if (autoServiceParamsElement != null) {
+                this.autoServiceParameters = new AutoServiceParameters(autoServiceParamsElement);
+            } else {
+                this.autoServiceParameters = null;
+            }
+            Element autoEntityParamsElement = UtilXml.firstChildElement(linkElement, "auto-parameters-entity");
+            if (autoEntityParamsElement != null) {
+                this.autoEntityParameters = new AutoEntityParameters(autoEntityParamsElement);
+            } else {
+                this.autoEntityParameters = null;
+            }
+            Integer size = null;
+            String sizeAttr = linkElement.getAttribute("size");
+            if (!sizeAttr.isEmpty()) {
+                size = Integer.valueOf(sizeAttr);
+            }
+            this.size = size;
+            this.width = linkElement.getAttribute("width");
+            this.height = linkElement.getAttribute("height");
+        }
+
+        // Portal constructor
+        public Link(GenericValue portalPage, List<Parameter> parameterList, String target, Locale locale) {
+            this.autoEntityParameters = null;
+            this.autoServiceParameters = null;
+            this.encode = false;
+            this.fullPath = false;
+            this.idExdr = FlexibleStringExpander.getInstance("");
+            this.image = null;
+            this.linkType = "";
+            this.nameExdr = FlexibleStringExpander.getInstance("");
+            this.parameterList = Collections.unmodifiableList(parameterList);
+            this.prefixExdr = FlexibleStringExpander.getInstance("");
+            this.secure = false;
+            this.styleExdr = FlexibleStringExpander.getInstance("");
+            this.targetExdr = FlexibleStringExpander.getInstance(target);
+            this.targetWindowExdr = FlexibleStringExpander.getInstance("");
+            this.textExdr = FlexibleStringExpander.getInstance((String) portalPage.get("portalPageName", locale));
+            this.urlMode = "intra-app";
+            this.size = null;
+            this.width = "";
+            this.height = "";
+        }
+
+        public AutoEntityParameters getAutoEntityParameters() {
+            return autoEntityParameters;
+        }
+
+        public AutoServiceParameters getAutoServiceParameters() {
+            return autoServiceParameters;
+        }
+
+        public boolean getEncode() {
+            return this.encode;
+        }
+
+        public boolean getFullPath() {
+            return this.fullPath;
+        }
+
+        public String getHeight() {
+            return this.height;
+        }
+
+        public String getId(Map<String, Object> context) {
+            return this.idExdr.expandString(context);
+        }
+
+        public FlexibleStringExpander getIdExdr() {
+            return idExdr;
+        }
+
+        public Image getImage() {
+            return this.image;
+        }
+
+        public String getLinkType() {
+            return this.linkType;
+        }
+
+        public String getName() {
+            return nameExdr.getOriginal();
+        }
+
+        public String getName(Map<String, Object> context) {
+            return this.nameExdr.expandString(context);
+        }
+
+        public FlexibleStringExpander getNameExdr() {
+            return nameExdr;
+        }
+
+        public List<Parameter> getParameterList() {
+            return parameterList;
+        }
+
+        public Map<String, String> getParameterMap(Map<String, Object> context) {
+            Map<String, String> fullParameterMap = new HashMap<String, String>();
+            for (Parameter parameter : this.parameterList) {
+                fullParameterMap.put(parameter.getName(), parameter.getValue(context));
+            }
+            if (autoServiceParameters != null) {
+                fullParameterMap.putAll(autoServiceParameters.getParametersMap(context, null));
+            }
+            if (autoEntityParameters != null) {
+                fullParameterMap.putAll(autoEntityParameters.getParametersMap(context, null));
+            }
+            return fullParameterMap;
+        }
+
+        public String getPrefix(Map<String, Object> context) {
+            return this.prefixExdr.expandString(context);
+        }
+
+        public FlexibleStringExpander getPrefixExdr() {
+            return prefixExdr;
+        }
+
+        public boolean getSecure() {
+            return this.secure;
+        }
+
+        public Integer getSize() {
+            return size;
+        }
+
+        public String getStyle(Map<String, Object> context) {
+            return this.styleExdr.expandString(context);
+        }
+
+        public FlexibleStringExpander getStyleExdr() {
+            return styleExdr;
+        }
+
+        public String getTarget(Map<String, Object> context) {
+            Map<String, Object> expanderContext = context;
+            UtilCodec.SimpleEncoder simpleEncoder = context == null ? null : (UtilCodec.SimpleEncoder) context
+                    .get("simpleEncoder");
+            if (simpleEncoder != null) {
+                expanderContext = UtilCodec.HtmlEncodingMapWrapper.getHtmlEncodingMapWrapper(context, simpleEncoder);
+            }
+            return this.targetExdr.expandString(expanderContext);
+        }
+
+        public FlexibleStringExpander getTargetExdr() {
+            return targetExdr;
+        }
+
+        public String getTargetWindow(Map<String, Object> context) {
+            return this.targetWindowExdr.expandString(context);
+        }
+
+        public FlexibleStringExpander getTargetWindowExdr() {
+            return targetWindowExdr;
+        }
+
+        public String getText(Map<String, Object> context) {
+            String text = this.textExdr.expandString(context);
+            // FIXME: Encoding should be done by the renderer, not by the model.
+            UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
+            if (simpleEncoder != null) {
+                text = simpleEncoder.encode(text);
+            }
+            return text;
+        }
+
+        public FlexibleStringExpander getTextExdr() {
+            return textExdr;
+        }
+
+        public String getUrlMode() {
+            return this.urlMode;
+        }
+
+        public String getWidth() {
+            return this.width;
+        }
+    }
+
+    /**
+     * Models the &lt;parameter&gt; element.
+     *
+     * @see <code>widget-form.xsd</code>
+     */
+    public static class Parameter {
+        protected FlexibleMapAccessor<Object> fromField;
+        protected String name;
+        protected FlexibleStringExpander value;
+
+        public Parameter(Element element) {
+            this.name = element.getAttribute("param-name");
+            this.value = UtilValidate.isNotEmpty(element.getAttribute("value")) ? FlexibleStringExpander.getInstance(element
+                    .getAttribute("value")) : null;
+            this.fromField = UtilValidate.isNotEmpty(element.getAttribute("from-field")) ? FlexibleMapAccessor
+                    .getInstance(element.getAttribute("from-field")) : null;
+        }
+
+        public Parameter(String paramName, String paramValue, boolean isField) {
+            this.name = paramName;
+            if (isField) {
+                this.fromField = FlexibleMapAccessor.getInstance(paramValue);
+            } else {
+                this.value = FlexibleStringExpander.getInstance(paramValue);
+            }
+        }
+
+        public FlexibleMapAccessor<Object> getFromField() {
+            return fromField;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public FlexibleStringExpander getValue() {
+            return value;
+        }
+
+        public String getValue(Map<String, Object> context) {
+            if (this.value != null) {
+                return this.value.expandString(context);
+            }
+            Object retVal = null;
+            if (this.fromField != null && this.fromField.get(context) != null) {
+                retVal = this.fromField.get(context);
+            } else {
+                retVal = context.get(this.name);
+            }
+            if (retVal != null) {
+                TimeZone timeZone = (TimeZone) context.get("timeZone");
+                if (timeZone == null)
+                    timeZone = TimeZone.getDefault();
+                String returnValue = null;
+                // format string based on the user's time zone (not locale because these are parameters)
+                if (retVal instanceof Double || retVal instanceof Float || retVal instanceof BigDecimal) {
+                    returnValue = retVal.toString();
+                } else if (retVal instanceof java.sql.Date) {
+                    DateFormat df = UtilDateTime.toDateFormat(UtilDateTime.DATE_FORMAT, timeZone, null);
+                    returnValue = df.format((java.util.Date) retVal);
+                } else if (retVal instanceof java.sql.Time) {
+                    DateFormat df = UtilDateTime.toTimeFormat(UtilDateTime.TIME_FORMAT, timeZone, null);
+                    returnValue = df.format((java.util.Date) retVal);
+                } else if (retVal instanceof java.sql.Timestamp) {
+                    DateFormat df = UtilDateTime.toDateTimeFormat(UtilDateTime.DATE_TIME_FORMAT, timeZone, null);
+                    returnValue = df.format((java.util.Date) retVal);
+                } else if (retVal instanceof java.util.Date) {
+                    DateFormat df = UtilDateTime.toDateTimeFormat("EEE MMM dd hh:mm:ss z yyyy", timeZone, null);
+                    returnValue = df.format((java.util.Date) retVal);
+                } else {
+                    returnValue = retVal.toString();
+                }
+                return returnValue;
+            } else {
+                return null;
+            }
+        }
+    }
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/FieldInfo.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/FieldInfo.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/FieldInfo.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/FieldInfo.java Sun Jan 18 21:03:40 2015
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.widget.model;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.widget.renderer.FormStringRenderer;
+import org.w3c.dom.Element;
+
+/**
+ * Form field abstract class.
+ */
+public abstract class FieldInfo {
+
+    public static final String module = FieldInfo.class.getName();
+
+    public static final int DISPLAY = 1;
+    public static final int HYPERLINK = 2;
+    public static final int TEXT = 3;
+    public static final int TEXTAREA = 4;
+    public static final int DATE_TIME = 5;
+    public static final int DROP_DOWN = 6;
+    public static final int CHECK = 7;
+    public static final int RADIO = 8;
+    public static final int SUBMIT = 9;
+    public static final int RESET = 10;
+    public static final int HIDDEN = 11;
+    public static final int IGNORED = 12;
+    public static final int TEXTQBE = 13;
+    public static final int DATEQBE = 14;
+    public static final int RANGEQBE = 15;
+    public static final int LOOKUP = 16;
+    public static final int FILE = 17;
+    public static final int PASSWORD = 18;
+    public static final int IMAGE = 19;
+    public static final int DISPLAY_ENTITY = 20;
+    // the numbering here represents the priority of the source;
+    //when setting a new fieldInfo on a modelFormField it will only set
+    //the new one if the fieldSource is less than or equal to the existing
+    //fieldSource, which should always be passed as one of the following...
+    public static final int SOURCE_EXPLICIT = 1;
+    public static final int SOURCE_AUTO_ENTITY = 2;
+    public static final int SOURCE_AUTO_SERVICE = 3;
+    private static Map<String, Integer> fieldTypeByName = createFieldTypeMap();
+
+    private static Map<String, Integer> createFieldTypeMap() {
+        Map<String, Integer> fieldTypeByName = new HashMap<String, Integer>();
+        fieldTypeByName.put("display", Integer.valueOf(1));
+        fieldTypeByName.put("hyperlink", Integer.valueOf(2));
+        fieldTypeByName.put("text", Integer.valueOf(3));
+        fieldTypeByName.put("textarea", Integer.valueOf(4));
+        fieldTypeByName.put("date-time", Integer.valueOf(5));
+        fieldTypeByName.put("drop-down", Integer.valueOf(6));
+        fieldTypeByName.put("check", Integer.valueOf(7));
+        fieldTypeByName.put("radio", Integer.valueOf(8));
+        fieldTypeByName.put("submit", Integer.valueOf(9));
+        fieldTypeByName.put("reset", Integer.valueOf(10));
+        fieldTypeByName.put("hidden", Integer.valueOf(11));
+        fieldTypeByName.put("ignored", Integer.valueOf(12));
+        fieldTypeByName.put("text-find", Integer.valueOf(13));
+        fieldTypeByName.put("date-find", Integer.valueOf(14));
+        fieldTypeByName.put("range-find", Integer.valueOf(15));
+        fieldTypeByName.put("lookup", Integer.valueOf(16));
+        fieldTypeByName.put("file", Integer.valueOf(17));
+        fieldTypeByName.put("password", Integer.valueOf(18));
+        fieldTypeByName.put("image", Integer.valueOf(19));
+        fieldTypeByName.put("display-entity", Integer.valueOf(20));
+        fieldTypeByName.put("container", Integer.valueOf(21));
+        return Collections.unmodifiableMap(fieldTypeByName);
+    }
+
+    public static int findFieldTypeFromName(String name) {
+        Integer fieldTypeInt = FieldInfo.fieldTypeByName.get(name);
+        if (fieldTypeInt != null) {
+            return fieldTypeInt;
+        } else {
+            throw new IllegalArgumentException("Could not get fieldType for field type name " + name);
+        }
+    }
+
+    private final int fieldType;
+    private final int fieldSource;
+    private final ModelFormField modelFormField;
+
+    /** XML Constructor */
+    protected FieldInfo(Element element, ModelFormField modelFormField) {
+        this.fieldSource = FieldInfo.SOURCE_EXPLICIT;
+        this.fieldType = findFieldTypeFromName(element.getTagName());
+        this.modelFormField = modelFormField;
+    }
+
+    /** Value Constructor */
+    protected FieldInfo(int fieldSource, int fieldType, ModelFormField modelFormField) {
+        this.fieldType = fieldType;
+        this.fieldSource = fieldSource;
+        this.modelFormField = modelFormField;
+    }
+
+    public abstract void accept(ModelFieldVisitor visitor) throws Exception;
+
+    /**
+     * Returns a new instance of this object.
+     *
+     * @param modelFormField
+     */
+    public abstract FieldInfo copy(ModelFormField modelFormField);
+
+    public int getFieldSource() {
+        return fieldSource;
+    }
+
+    public int getFieldType() {
+        return fieldType;
+    }
+
+    public ModelFormField getModelFormField() {
+        return modelFormField;
+    }
+
+    public abstract void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
+            throws IOException;
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        ModelFieldVisitor visitor = new XmlWidgetFieldVisitor(sb);
+        try {
+            accept(visitor);
+        } catch (Exception e) {
+            Debug.logWarning(e, "Exception thrown in XmlWidgetFieldVisitor: ", module);
+        }
+        return sb.toString();
+    }
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/FormFactory.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/FormFactory.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/FormFactory.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/FormFactory.java Sun Jan 18 21:03:40 2015
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.widget.model;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.ofbiz.base.location.FlexibleLocation;
+import org.ofbiz.base.util.UtilHttp;
+import org.ofbiz.base.util.UtilXml;
+import org.ofbiz.base.util.cache.UtilCache;
+import org.ofbiz.entity.Delegator;
+import org.ofbiz.entity.model.ModelReader;
+import org.ofbiz.service.DispatchContext;
+import org.ofbiz.service.LocalDispatcher;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+
+/**
+ * Widget Library - Form factory class
+ */
+public class FormFactory {
+
+    public static final String module = FormFactory.class.getName();
+    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)
+            throws IOException, SAXException, ParserConfigurationException {
+        URL formFileUrl = FlexibleLocation.resolveLocation(resourceName);
+        Document formFileDoc = UtilXml.readXmlDocument(formFileUrl, true, true);
+        return readFormDocument(formFileDoc, entityModelReader, dispatchContext, resourceName);
+    }
+
+    public static ModelForm getFormFromLocation(String resourceName, String formName, ModelReader entityModelReader, DispatchContext dispatchContext)
+            throws IOException, SAXException, ParserConfigurationException {
+        StringBuilder sb = new StringBuilder(dispatchContext.getDelegator().getDelegatorName());
+        sb.append(":").append(resourceName).append("#").append(formName);
+        String cacheKey = sb.toString();
+        ModelForm modelForm = formLocationCache.get(cacheKey);
+        if (modelForm == null) {
+            URL formFileUrl = FlexibleLocation.resolveLocation(resourceName);
+            Document formFileDoc = UtilXml.readXmlDocument(formFileUrl, true, true);
+            if (formFileDoc == null) {
+                throw new IllegalArgumentException("Could not find resource [" + resourceName + "]");
+            }
+            modelForm = createModelForm(formFileDoc, entityModelReader, dispatchContext, resourceName, formName);
+            modelForm = formLocationCache.putIfAbsentAndGet(cacheKey, modelForm);
+        }
+        if (modelForm == null) {
+            throw new IllegalArgumentException("Could not find form with name [" + formName + "] in class resource [" + resourceName + "]");
+        }
+        return modelForm;
+    }
+
+    public static ModelForm getFormFromWebappContext(String resourceName, String formName, HttpServletRequest request)
+            throws IOException, SAXException, ParserConfigurationException {
+        String webappName = UtilHttp.getApplicationName(request);
+        String cacheKey = webappName + "::" + resourceName + "::" + formName;
+        ModelForm modelForm = formWebappCache.get(cacheKey);
+        if (modelForm == null) {
+            ServletContext servletContext = (ServletContext) request.getAttribute("servletContext");
+            Delegator delegator = (Delegator) request.getAttribute("delegator");
+            LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
+            URL formFileUrl = servletContext.getResource(resourceName);
+            Document formFileDoc = UtilXml.readXmlDocument(formFileUrl, true, true);
+            Element formElement = UtilXml.firstChildElement(formFileDoc.getDocumentElement(), "form", "name", formName);
+            modelForm = new ModelForm(formElement, resourceName, delegator.getModelReader(), dispatcher.getDispatchContext());
+            modelForm = formWebappCache.putIfAbsentAndGet(cacheKey, modelForm);
+        }
+        if (modelForm == null) {
+            throw new IllegalArgumentException("Could not find form with name [" + formName + "] in webapp resource [" + resourceName + "] in the webapp [" + webappName + "]");
+        }
+        return modelForm;
+    }
+
+    public static Map<String, ModelForm> readFormDocument(Document formFileDoc, ModelReader entityModelReader, DispatchContext dispatchContext, String formLocation) {
+        Map<String, ModelForm> modelFormMap = new HashMap<String, ModelForm>();
+        if (formFileDoc != null) {
+            // read document and construct ModelForm for each form element
+            Element rootElement = formFileDoc.getDocumentElement();
+            List<? extends Element> formElements = UtilXml.childElementList(rootElement, "form");
+            for (Element formElement : formElements) {
+                String formName = formElement.getAttribute("name");
+                String cacheKey = formLocation + "#" + formName;
+                ModelForm modelForm = formLocationCache.get(cacheKey);
+                if (modelForm == null) {
+                    modelForm = createModelForm(formElement, entityModelReader, dispatchContext, formLocation, formName);
+                    modelForm = formLocationCache.putIfAbsentAndGet(cacheKey, modelForm);
+                }
+                modelFormMap.put(formName, modelForm);
+            }
+        }
+        return modelFormMap;
+    }
+
+    public static ModelForm createModelForm(Document formFileDoc, ModelReader entityModelReader, DispatchContext dispatchContext, String formLocation, String formName) {
+        Element formElement = UtilXml.firstChildElement(formFileDoc.getDocumentElement(), "form", "name", formName);
+        return createModelForm(formElement, entityModelReader, dispatchContext, formLocation, formName);
+    }
+
+    public static ModelForm createModelForm(Element formElement, ModelReader entityModelReader, DispatchContext dispatchContext, String formLocation, String formName) {
+        ModelForm modelForm = new ModelForm(formElement, formLocation, entityModelReader, dispatchContext);
+        return modelForm;
+    }
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/HtmlWidget.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/HtmlWidget.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/HtmlWidget.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/HtmlWidget.java Sun Jan 18 21:03:40 2015
@@ -0,0 +1,311 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.widget.model;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.GeneralException;
+import org.ofbiz.base.util.UtilCodec;
+import org.ofbiz.base.util.UtilGenerics;
+import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.base.util.UtilXml;
+import org.ofbiz.base.util.cache.UtilCache;
+import org.ofbiz.base.util.collections.MapStack;
+import org.ofbiz.base.util.string.FlexibleStringExpander;
+import org.ofbiz.base.util.template.FreeMarkerWorker;
+import org.ofbiz.widget.renderer.ScreenRenderer;
+import org.ofbiz.widget.renderer.ScreenStringRenderer;
+import org.ofbiz.widget.renderer.html.HtmlWidgetRenderer;
+import org.w3c.dom.Element;
+
+import freemarker.ext.beans.BeansWrapper;
+import freemarker.ext.beans.CollectionModel;
+import freemarker.ext.beans.StringModel;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+import freemarker.template.Version;
+
+/**
+ * Widget Library - Screen model HTML class.
+ */
+@SuppressWarnings("serial")
+public class HtmlWidget extends ModelScreenWidget {
+    public static final String module = HtmlWidget.class.getName();
+
+    private static final UtilCache<String, Template> specialTemplateCache = UtilCache.createUtilCache("widget.screen.template.ftl.general", 0, 0, false);
+    protected static Configuration specialConfig = FreeMarkerWorker.makeConfiguration(new ExtendedWrapper(FreeMarkerWorker.version));
+
+    // not sure if this is the best way to get FTL to use my fancy MapModel derivative, but should work at least...
+    public static class ExtendedWrapper extends BeansWrapper {
+        public ExtendedWrapper(Version version) {
+            super(version);
+        }
+
+        @Override
+        public TemplateModel wrap(Object object) throws TemplateModelException {
+            // This StringHtmlWrapperForFtl option seems to be the best option
+            // and handles most things without causing too many problems
+            if (object instanceof String) {
+                return new StringHtmlWrapperForFtl((String) object, this);
+            } else if (object instanceof Collection && !(object instanceof Map)) {
+                // An additional wrapper to ensure ${aCollection} is properly encoded for html
+                return new CollectionHtmlWrapperForFtl((Collection<?>) object, this);
+            }
+            return super.wrap(object);
+        }
+    }
+
+    public static class StringHtmlWrapperForFtl extends StringModel {
+        public StringHtmlWrapperForFtl(String str, BeansWrapper wrapper) {
+            super(str, wrapper);
+        }
+        @Override
+        public String getAsString() {
+            return UtilCodec.getEncoder("html").encode(super.getAsString());
+        }
+    }
+
+    public static class CollectionHtmlWrapperForFtl extends CollectionModel {
+
+        public CollectionHtmlWrapperForFtl(Collection<?> collection, BeansWrapper wrapper) {
+            super(collection, wrapper);
+        }
+
+        @Override
+        public String getAsString() {
+            return UtilCodec.getEncoder("html").encode(super.getAsString());
+        }
+
+    }
+
+    // End Static, begin class section
+
+    private final List<ModelScreenWidget> subWidgets;
+
+    public HtmlWidget(ModelScreen modelScreen, Element htmlElement) {
+        super(modelScreen, htmlElement);
+        List<? extends Element> childElementList = UtilXml.childElementList(htmlElement);
+        if (childElementList.isEmpty()) {
+            this.subWidgets = Collections.emptyList();
+        } else {
+            List<ModelScreenWidget> subWidgets = new ArrayList<ModelScreenWidget>(childElementList.size());
+            for (Element childElement : childElementList) {
+                if ("html-template".equals(childElement.getNodeName())) {
+                    subWidgets.add(new HtmlTemplate(modelScreen, childElement));
+                } else if ("html-template-decorator".equals(childElement.getNodeName())) {
+                    subWidgets.add(new HtmlTemplateDecorator(modelScreen, childElement));
+                } else {
+                    throw new IllegalArgumentException("Tag not supported under the platform-specific -> html tag with name: "
+                            + childElement.getNodeName());
+                }
+            }
+            this.subWidgets = Collections.unmodifiableList(subWidgets);
+        }
+    }
+
+    public List<ModelScreenWidget> getSubWidgets() {
+        return subWidgets;
+    }
+
+    @Override
+    public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
+        for (ModelScreenWidget subWidget : subWidgets) {
+            subWidget.renderWidgetString(writer, context, screenStringRenderer);
+        }
+    }
+
+    public static void renderHtmlTemplate(Appendable writer, FlexibleStringExpander locationExdr, Map<String, Object> context) {
+        String location = locationExdr.expandString(context);
+        //Debug.logInfo("Rendering template at location [" + location + "] with context: \n" + context, module);
+
+        if (UtilValidate.isEmpty(location)) {
+            throw new IllegalArgumentException("Template location is empty");
+        }
+
+        if (location.endsWith(".ftl")) {
+            try {
+                Map<String, ? extends Object> parameters = UtilGenerics.checkMap(context.get("parameters"));
+                boolean insertWidgetBoundaryComments = ModelWidget.widgetBoundaryCommentsEnabled(parameters);
+                if (insertWidgetBoundaryComments) {
+                    writer.append(HtmlWidgetRenderer.formatBoundaryComment("Begin", "Template", location));
+                }
+
+                //FreeMarkerWorker.renderTemplateAtLocation(location, context, writer);
+                Template template = null;
+                if (location.endsWith(".fo.ftl")) { // FOP can't render correctly escaped characters
+                    template = FreeMarkerWorker.getTemplate(location);
+                } else {
+                    template = FreeMarkerWorker.getTemplate(location, specialTemplateCache, specialConfig);
+                }
+                FreeMarkerWorker.renderTemplate(template, context, writer);
+
+                if (insertWidgetBoundaryComments) {
+                    writer.append(HtmlWidgetRenderer.formatBoundaryComment("End", "Template", location));
+                }
+            } catch (IllegalArgumentException e) {
+                String errMsg = "Error rendering included template at location [" + location + "]: " + e.toString();
+                Debug.logError(e, errMsg, module);
+                writeError(writer, errMsg);
+            } catch (MalformedURLException e) {
+                String errMsg = "Error rendering included template at location [" + location + "]: " + e.toString();
+                Debug.logError(e, errMsg, module);
+                writeError(writer, errMsg);
+            } catch (TemplateException e) {
+                String errMsg = "Error rendering included template at location [" + location + "]: " + e.toString();
+                Debug.logError(e, errMsg, module);
+                writeError(writer, errMsg);
+            } catch (IOException e) {
+                String errMsg = "Error rendering included template at location [" + location + "]: " + e.toString();
+                Debug.logError(e, errMsg, module);
+                writeError(writer, errMsg);
+            }
+        } else {
+            throw new IllegalArgumentException("Rendering not yet supported for the template at location: " + location);
+        }
+    }
+
+    // TODO: We can make this more fancy, but for now this is very functional
+    public static void writeError(Appendable writer, String message) {
+        try {
+            writer.append(message);
+        } catch (IOException e) {
+        }
+    }
+
+    public static class HtmlTemplate extends ModelScreenWidget {
+        protected FlexibleStringExpander locationExdr;
+
+        public HtmlTemplate(ModelScreen modelScreen, Element htmlTemplateElement) {
+            super(modelScreen, htmlTemplateElement);
+            this.locationExdr = FlexibleStringExpander.getInstance(htmlTemplateElement.getAttribute("location"));
+        }
+
+        public String getLocation(Map<String, Object> context) {
+            return locationExdr.expandString(context);
+        }
+
+        @Override
+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {
+            renderHtmlTemplate(writer, this.locationExdr, context);
+        }
+
+        @Override
+        public void accept(ModelWidgetVisitor visitor) throws Exception {
+            visitor.visit(this);
+        }
+
+        public FlexibleStringExpander getLocationExdr() {
+            return locationExdr;
+        }
+    }
+
+    public static class HtmlTemplateDecorator extends ModelScreenWidget {
+        protected FlexibleStringExpander locationExdr;
+        protected Map<String, ModelScreenWidget> sectionMap = new HashMap<String, ModelScreenWidget>();
+
+        public HtmlTemplateDecorator(ModelScreen modelScreen, Element htmlTemplateDecoratorElement) {
+            super(modelScreen, htmlTemplateDecoratorElement);
+            this.locationExdr = FlexibleStringExpander.getInstance(htmlTemplateDecoratorElement.getAttribute("location"));
+
+            List<? extends Element> htmlTemplateDecoratorSectionElementList = UtilXml.childElementList(htmlTemplateDecoratorElement, "html-template-decorator-section");
+            for (Element htmlTemplateDecoratorSectionElement: htmlTemplateDecoratorSectionElementList) {
+                String name = htmlTemplateDecoratorSectionElement.getAttribute("name");
+                this.sectionMap.put(name, new HtmlTemplateDecoratorSection(modelScreen, htmlTemplateDecoratorSectionElement));
+            }
+        }
+
+        @Override
+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {
+            // isolate the scope
+            MapStack<String> contextMs;
+            if (!(context instanceof MapStack<?>)) {
+                contextMs = MapStack.create(context);
+                context = contextMs;
+            } else {
+                contextMs = UtilGenerics.cast(context);
+            }
+
+            // create a standAloneStack, basically a "save point" for this SectionsRenderer, and make a new "screens" object just for it so it is isolated and doesn't follow the stack down
+            MapStack<String> standAloneStack = contextMs.standAloneChildStack();
+            standAloneStack.put("screens", new ScreenRenderer(writer, standAloneStack, screenStringRenderer));
+            SectionsRenderer sections = new SectionsRenderer(this.sectionMap, standAloneStack, writer, screenStringRenderer);
+
+            // put the sectionMap in the context, make sure it is in the sub-scope, ie after calling push on the MapStack
+            contextMs.push();
+            context.put("sections", sections);
+
+            renderHtmlTemplate(writer, this.locationExdr, context);
+            contextMs.pop();
+        }
+
+        @Override
+        public void accept(ModelWidgetVisitor visitor) throws Exception {
+            visitor.visit(this);
+        }
+
+        public FlexibleStringExpander getLocationExdr() {
+            return locationExdr;
+        }
+
+        public Map<String, ModelScreenWidget> getSectionMap() {
+            return sectionMap;
+        }
+    }
+
+    public static class HtmlTemplateDecoratorSection extends ModelScreenWidget {
+        protected List<ModelScreenWidget> subWidgets;
+
+        public HtmlTemplateDecoratorSection(ModelScreen modelScreen, Element htmlTemplateDecoratorSectionElement) {
+            super(modelScreen, htmlTemplateDecoratorSectionElement);
+            List<? extends Element> subElementList = UtilXml.childElementList(htmlTemplateDecoratorSectionElement);
+            this.subWidgets = ModelScreenWidget.readSubWidgets(getModelScreen(), subElementList);
+        }
+
+        @Override
+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
+            // render sub-widgets
+            renderSubWidgetsString(this.subWidgets, writer, context, screenStringRenderer);
+        }
+
+        @Override
+        public void accept(ModelWidgetVisitor visitor) throws Exception {
+            visitor.visit(this);
+        }
+
+        public List<ModelScreenWidget> getSubWidgets() {
+            return subWidgets;
+        }
+    }
+
+    @Override
+    public void accept(ModelWidgetVisitor visitor) throws Exception {
+        visitor.visit(this);
+    }
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/IterateSectionWidget.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/IterateSectionWidget.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/IterateSectionWidget.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/IterateSectionWidget.java Sun Jan 18 21:03:40 2015
@@ -0,0 +1,387 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.widget.model;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.GeneralException;
+import org.ofbiz.base.util.UtilGenerics;
+import org.ofbiz.base.util.UtilHttp;
+import org.ofbiz.base.util.UtilMisc;
+import org.ofbiz.base.util.UtilProperties;
+import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.base.util.UtilXml;
+import org.ofbiz.base.util.collections.FlexibleMapAccessor;
+import org.ofbiz.base.util.collections.MapStack;
+import org.ofbiz.base.util.string.FlexibleStringExpander;
+import org.ofbiz.webapp.control.RequestHandler;
+import org.ofbiz.widget.WidgetWorker;
+import org.ofbiz.widget.renderer.ScreenStringRenderer;
+import org.w3c.dom.Element;
+
+
+/**
+ * Widget Library - Screen model HTML class
+ */
+@SuppressWarnings("serial")
+public class IterateSectionWidget extends ModelScreenWidget {
+
+    public static final String module = IterateSectionWidget.class.getName();
+    public static int DEFAULT_PAGE_SIZE = 5;
+    public static int MAX_PAGE_SIZE = 10000;
+
+    private final List<ModelScreenWidget.Section> sectionList;
+    private final FlexibleMapAccessor<Object> listNameExdr;
+    private final FlexibleStringExpander entryNameExdr;
+    private final FlexibleStringExpander keyNameExdr;
+    private final FlexibleStringExpander paginateTarget;
+    private final FlexibleStringExpander paginate;
+    private final int viewSize;
+
+    public IterateSectionWidget(ModelScreen modelScreen, Element iterateSectionElement) {
+        super(modelScreen, iterateSectionElement);
+        String listName = iterateSectionElement.getAttribute("list");
+        if (listName.isEmpty()) {
+            listName = iterateSectionElement.getAttribute("list-name");
+        }
+        this.listNameExdr = FlexibleMapAccessor.getInstance(listName);
+        String entryName = iterateSectionElement.getAttribute("entry");
+        if (entryName.isEmpty()) {
+            entryName = iterateSectionElement.getAttribute("entry-name");
+        }
+        this.entryNameExdr = FlexibleStringExpander.getInstance(entryName);
+        String keyName = iterateSectionElement.getAttribute("key");
+        if (keyName.isEmpty()) {
+            keyName = iterateSectionElement.getAttribute("key-name");
+        }
+        this.keyNameExdr = FlexibleStringExpander.getInstance(keyName);
+        this.paginateTarget = FlexibleStringExpander.getInstance(iterateSectionElement.getAttribute("paginate-target"));
+        this.paginate = FlexibleStringExpander.getInstance(iterateSectionElement.getAttribute("paginate"));
+        int viewSize = DEFAULT_PAGE_SIZE;
+        String viewSizeStr = iterateSectionElement.getAttribute("view-size");
+        if (!viewSizeStr.isEmpty()) {
+            viewSize = Integer.parseInt(viewSizeStr);
+        }
+        this.viewSize = viewSize;
+        List<? extends Element> childElementList = UtilXml.childElementList(iterateSectionElement);
+        if (childElementList.isEmpty()) {
+            this.sectionList = Collections.emptyList();
+        } else {
+            List<ModelScreenWidget.Section> sectionList = new ArrayList<ModelScreenWidget.Section>(childElementList.size());
+            for (Element sectionElement: childElementList) {
+                ModelScreenWidget.Section section = new ModelScreenWidget.Section(modelScreen, sectionElement, false);
+                sectionList.add(section);
+            }
+            this.sectionList = Collections.unmodifiableList(sectionList);
+        }
+    }
+
+    public List<ModelScreenWidget.Section> getSectionList() {
+        return sectionList;
+    }
+
+    @Override
+    public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
+        int viewIndex = 0;
+        int viewSize = this.viewSize;
+        int lowIndex = -1;
+        int highIndex = -1;
+        int listSize = 0;
+        int actualPageSize = 0;
+
+        boolean isEntrySet = false;
+        // create a standAloneStack, basically a "save point" for this SectionsRenderer, and make a new "screens" object just for it so it is isolated and doesn't follow the stack down
+        MapStack<String> contextMs = MapStack.create(context);
+
+        String entryName = this.entryNameExdr.expandString(context);
+        String keyName = this.keyNameExdr.expandString(context);
+        Object obj = listNameExdr.get(context);
+        if (obj == null) {
+            Debug.logError("No object found for listName:" + listNameExdr.toString(), module);
+            return;
+        }
+        List<?> theList = null;
+        if (obj instanceof Map<?, ?>) {
+            Set<Map.Entry<String, Object>> entrySet = UtilGenerics.<Map<String, Object>>cast(obj).entrySet();
+            Object [] a = entrySet.toArray();
+            theList = Arrays.asList(a);
+            isEntrySet = true;
+        } else if (obj instanceof List<?>) {
+            theList = (List<?>)obj;
+        } else {
+            Debug.logError("Object not list or map type", module);
+            return;
+        }
+        listSize = theList.size();
+        WidgetWorker.incrementPaginatorNumber(context);
+        int startPageNumber = WidgetWorker.getPaginatorNumber(context);
+
+        if (getPaginate(context)) {
+            try {
+                Map<String, String> params = UtilGenerics.cast(context.get("parameters"));
+                String viewIndexString = params.get("VIEW_INDEX" + "_" + WidgetWorker.getPaginatorNumber(context));
+                String viewSizeString = params.get("VIEW_SIZE" + "_" + WidgetWorker.getPaginatorNumber(context));
+                viewIndex = Integer.parseInt(viewIndexString);
+                viewSize = Integer.parseInt(viewSizeString);
+            } catch (Exception e) {
+                try {
+                    viewIndex = ((Integer) context.get("viewIndex")).intValue();
+                } catch (Exception e2) {
+                    viewIndex = 0;
+                }
+            }
+            context.put("viewIndex", Integer.valueOf(viewIndex));
+            lowIndex = viewIndex * viewSize;
+            highIndex = (viewIndex + 1) * viewSize;
+        } else {
+            viewIndex = 0;
+            viewSize = MAX_PAGE_SIZE;
+            lowIndex = 0;
+            highIndex = MAX_PAGE_SIZE;
+        }
+        Iterator<?> iter = theList.iterator();
+        int itemIndex = -1;
+        int iterateIndex = 0;
+        while (iter.hasNext()) {
+            itemIndex++;
+            if (itemIndex >= highIndex) {
+                break;
+            }
+            Object item = iter.next();
+            if (itemIndex < lowIndex) {
+                continue;
+            }
+            if (isEntrySet) {
+                Map.Entry<String, ?> entry = UtilGenerics.cast(item);
+                contextMs.put(entryName, entry.getValue());
+                contextMs.put(keyName, entry.getKey());
+            } else {
+                contextMs.put(entryName, item);
+            }
+            contextMs.put("itemIndex", Integer.valueOf(itemIndex));
+
+            if (iterateIndex < listSize) {
+                contextMs.put("iterateId",String.valueOf(entryName+iterateIndex));
+                iterateIndex++;
+            }
+            for (ModelScreenWidget.Section section: this.sectionList) {
+                section.renderWidgetString(writer, contextMs, screenStringRenderer);
+            }
+        }
+
+        if ((itemIndex + 1) < highIndex) {
+            highIndex = itemIndex + 1;
+        }
+        actualPageSize = highIndex - lowIndex;
+        if (getPaginate(context)) {
+            try {
+                Integer lastPageNumber = null;
+                Map<String, Object> globalCtx = UtilGenerics.checkMap(context.get("globalContext"));
+                if (globalCtx != null) {
+                    lastPageNumber = (Integer)globalCtx.get("PAGINATOR_NUMBER");
+                    globalCtx.put("PAGINATOR_NUMBER", Integer.valueOf(startPageNumber));
+                }
+                renderNextPrev(writer, context, listSize, actualPageSize);
+                if (globalCtx != null) {
+                    globalCtx.put("PAGINATOR_NUMBER", lastPageNumber);
+                }
+            } catch (IOException e) {
+                Debug.logError(e, module);
+                throw new RuntimeException(e.getMessage());
+            }
+        }
+
+    }
+    /*
+     * @return
+     */
+    public String getPaginateTarget(Map<String, Object> context) {
+        return this.paginateTarget.expandString(context);
+    }
+
+    public boolean getPaginate(Map<String, Object> context) {
+        if (!this.paginate.isEmpty() && UtilValidate.isNotEmpty(this.paginate.expandString(context))) {
+            return Boolean.valueOf(this.paginate.expandString(context)).booleanValue();
+        } else {
+            return true;
+        }
+    }
+
+    public int getViewSize() {
+        return viewSize;
+    }
+
+    public void renderNextPrev(Appendable writer, Map<String, Object> context, int listSize, int actualPageSize) throws IOException {
+        String targetService = this.getPaginateTarget(context);
+        if (targetService == null) {
+            targetService = "${targetService}";
+        }
+
+        Map<String, Object> inputFields = UtilGenerics.checkMap(context.get("requestParameters"));
+        Map<String, Object> queryStringMap = UtilGenerics.toMap(context.get("queryStringMap"));
+        if (UtilValidate.isNotEmpty(queryStringMap)) {
+            inputFields.putAll(queryStringMap);
+        }
+
+        String queryString = UtilHttp.urlEncodeArgs(inputFields);
+        int paginatorNumber = WidgetWorker.getPaginatorNumber(context);
+        queryString = UtilHttp.stripViewParamsFromQueryString(queryString, "" + paginatorNumber);
+
+
+
+
+        if (UtilValidate.isEmpty(targetService)) {
+            Debug.logWarning("TargetService is empty.", module);
+            return;
+        }
+
+        int viewIndex = -1;
+        try {
+            viewIndex = ((Integer) context.get("viewIndex")).intValue();
+        } catch (Exception e) {
+            viewIndex = 0;
+        }
+
+        int viewSize = -1;
+        try {
+            viewSize = ((Integer) context.get("viewSize")).intValue();
+        } catch (Exception e) {
+            viewSize = this.getViewSize();
+        }
+
+
+        /*
+        int highIndex = -1;
+        try {
+            highIndex = modelForm.getHighIndex();
+        } catch (Exception e) {
+            highIndex = 0;
+        }
+
+        int lowIndex = -1;
+        try {
+            lowIndex = modelForm.getLowIndex();
+        } catch (Exception e) {
+            lowIndex = 0;
+        }
+         */
+
+        int lowIndex = viewIndex * viewSize;
+        int highIndex = (viewIndex + 1) * viewSize;
+        // if this is all there seems to be (if listSize < 0, then size is unknown)
+        if (actualPageSize >= listSize && listSize > 0) {
+            return;
+        }
+
+        HttpServletRequest request = (HttpServletRequest) context.get("request");
+        HttpServletResponse response = (HttpServletResponse) context.get("response");
+
+        ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
+        RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
+
+        writer.append("<table border=\"0\" width=\"100%\" cellpadding=\"2\">\n");
+        writer.append("  <tr>\n");
+        writer.append("    <td align=\"right\">\n");
+        writer.append("      <b>\n");
+        if (viewIndex > 0) {
+            writer.append(" <a href=\"");
+            StringBuilder linkText = new StringBuilder(targetService);
+            if (linkText.indexOf("?") < 0)  linkText.append("?");
+            else linkText.append("&amp;");
+            //if (queryString != null && !queryString.equals("null")) linkText += queryString + "&";
+            if (UtilValidate.isNotEmpty(queryString)) {
+                linkText.append(queryString).append("&amp;");
+            }
+            linkText.append("VIEW_SIZE_"+ paginatorNumber + "=").append(viewSize).append("&amp;VIEW_INDEX_" + paginatorNumber + "=").append(viewIndex - 1).append("\"");
+
+            // make the link
+            writer.append(rh.makeLink(request, response, linkText.toString(), false, false, false));
+            String previous = UtilProperties.getMessage("CommonUiLabels", "CommonPrevious", (Locale) context.get("locale"));
+            writer.append(" class=\"buttontext\">[").append(previous).append("]</a>\n");
+
+        }
+        if (listSize > 0) {
+            Map<String, Integer> messageMap = UtilMisc.toMap("lowCount", Integer.valueOf(lowIndex + 1), "highCount", Integer.valueOf(lowIndex + actualPageSize), "total", Integer.valueOf(listSize));
+            String commonDisplaying = UtilProperties.getMessage("CommonUiLabels", "CommonDisplaying", messageMap, (Locale) context.get("locale"));
+            writer.append(" <span class=\"tabletext\">").append(commonDisplaying).append("</span> \n");
+        }
+        if (highIndex < listSize) {
+            writer.append(" <a href=\"");
+            StringBuilder linkText = new StringBuilder(targetService);
+            if (linkText.indexOf("?") < 0)  linkText.append("?");
+            else linkText.append("&amp;");
+            if (UtilValidate.isNotEmpty(queryString)) {
+                linkText.append(queryString).append("&amp;");
+            }
+            linkText.append("VIEW_SIZE_" + paginatorNumber + "=").append(viewSize).append("&amp;VIEW_INDEX_" + paginatorNumber + "=").append(viewIndex + 1).append("\"");
+
+            // make the link
+            writer.append(rh.makeLink(request, response, linkText.toString(), false, false, false));
+            String next = UtilProperties.getMessage("CommonUiLabels", "CommonNext", (Locale) context.get("locale"));
+            writer.append(" class=\"buttontext\">[").append(next).append("]</a>\n");
+
+        }
+        writer.append("      </b>\n");
+        writer.append("    </td>\n");
+        writer.append("  </tr>\n");
+        writer.append("</table>\n");
+
+    }
+
+    @Override
+    public void accept(ModelWidgetVisitor visitor) throws Exception {
+        visitor.visit(this);
+    }
+
+    public FlexibleMapAccessor<Object> getListNameExdr() {
+        return listNameExdr;
+    }
+
+    public FlexibleStringExpander getEntryNameExdr() {
+        return entryNameExdr;
+    }
+
+    public FlexibleStringExpander getKeyNameExdr() {
+        return keyNameExdr;
+    }
+
+    public FlexibleStringExpander getPaginateTarget() {
+        return paginateTarget;
+    }
+
+    public FlexibleStringExpander getPaginate() {
+        return paginate;
+    }
+
+}
+
+

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/MenuFactory.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/MenuFactory.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/MenuFactory.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/MenuFactory.java Sun Jan 18 21:03:40 2015
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.widget.model;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.ofbiz.base.location.FlexibleLocation;
+import org.ofbiz.base.util.UtilHttp;
+import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.base.util.UtilXml;
+import org.ofbiz.base.util.cache.UtilCache;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+
+/**
+ * Widget Library - Menu factory class
+ */
+public class MenuFactory {
+
+    public static final String module = MenuFactory.class.getName();
+
+    public static final UtilCache<String, Map<String, ModelMenu>> menuWebappCache = UtilCache.createUtilCache("widget.menu.webappResource", 0, 0, false);
+    public static final UtilCache<String, Map<String, ModelMenu>> menuLocationCache = UtilCache.createUtilCache("widget.menu.locationResource", 0, 0, false);
+
+    public static ModelMenu getMenuFromWebappContext(String resourceName, String menuName, HttpServletRequest request)
+            throws IOException, SAXException, ParserConfigurationException {
+        String webappName = UtilHttp.getApplicationName(request);
+        String cacheKey = webappName + "::" + resourceName;
+
+        Map<String, ModelMenu> modelMenuMap = menuWebappCache.get(cacheKey);
+        if (modelMenuMap == null) {
+            synchronized (MenuFactory.class) {
+                modelMenuMap = menuWebappCache.get(cacheKey);
+                if (modelMenuMap == null) {
+                    ServletContext servletContext = (ServletContext) request.getAttribute("servletContext");
+
+                    URL menuFileUrl = servletContext.getResource(resourceName);
+                    Document menuFileDoc = UtilXml.readXmlDocument(menuFileUrl, true, true);
+                    modelMenuMap = readMenuDocument(menuFileDoc, cacheKey);
+                    menuWebappCache.put(cacheKey, modelMenuMap);
+                }
+            }
+        }
+
+        if (UtilValidate.isEmpty(modelMenuMap)) {
+            throw new IllegalArgumentException("Could not find menu file in webapp resource [" + resourceName + "] in the webapp [" + webappName + "]");
+        }
+
+        ModelMenu modelMenu = modelMenuMap.get(menuName);
+        if (modelMenu == null) {
+            throw new IllegalArgumentException("Could not find menu with name [" + menuName + "] in webapp resource [" + resourceName + "] in the webapp [" + webappName + "]");
+        }
+        return modelMenu;
+    }
+
+    public static Map<String, ModelMenu> readMenuDocument(Document menuFileDoc, String menuLocation) {
+        Map<String, ModelMenu> modelMenuMap = new HashMap<String, ModelMenu>();
+        if (menuFileDoc != null) {
+            // read document and construct ModelMenu for each menu element
+            Element rootElement = menuFileDoc.getDocumentElement();
+            for (Element menuElement: UtilXml.childElementList(rootElement, "menu")){
+                ModelMenu modelMenu = new ModelMenu(menuElement, menuLocation);
+                modelMenuMap.put(modelMenu.getName(), modelMenu);
+            }
+         }
+        return modelMenuMap;
+    }
+
+    public static ModelMenu getMenuFromLocation(String resourceName, String menuName) throws IOException, SAXException, ParserConfigurationException {
+        Map<String, ModelMenu> modelMenuMap = menuLocationCache.get(resourceName);
+        if (modelMenuMap == null) {
+            synchronized (MenuFactory.class) {
+                modelMenuMap = menuLocationCache.get(resourceName);
+                if (modelMenuMap == null) {
+                    URL menuFileUrl = FlexibleLocation.resolveLocation(resourceName);
+                    Document menuFileDoc = UtilXml.readXmlDocument(menuFileUrl, true, true);
+                    modelMenuMap = readMenuDocument(menuFileDoc, resourceName);
+                    menuLocationCache.put(resourceName, modelMenuMap);
+                }
+            }
+        }
+
+        if (UtilValidate.isEmpty(modelMenuMap)) {
+            throw new IllegalArgumentException("Could not find menu file in location [" + resourceName + "]");
+        }
+
+        ModelMenu modelMenu = modelMenuMap.get(menuName);
+        if (modelMenu == null) {
+            throw new IllegalArgumentException("Could not find menu with name [" + menuName + "] in location [" + resourceName + "]");
+        }
+        return modelMenu;
+    }
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelAction.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelAction.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelAction.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelAction.java Sun Jan 18 21:03:40 2015
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.widget.model;
+
+import java.util.Map;
+
+import org.ofbiz.base.util.GeneralException;
+
+public interface ModelAction {
+
+    void accept(ModelActionVisitor visitor) throws Exception;
+
+    /**
+     * Executes this action.
+     *
+     * @param context
+     * @throws GeneralException
+     */
+    void runAction(Map<String, Object> context) throws GeneralException;
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelActionVisitor.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelActionVisitor.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelActionVisitor.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelActionVisitor.java Sun Jan 18 21:03:40 2015
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") throws Exception ; you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.widget.model;
+
+/**
+ *  A <code>ModelAction</code> visitor.
+ */
+public interface ModelActionVisitor {
+
+    void visit(ModelFormAction.CallParentActions callParentActions) throws Exception;
+
+    void visit(AbstractModelAction.EntityAnd entityAnd) throws Exception;
+
+    void visit(AbstractModelAction.EntityCondition entityCondition) throws Exception;
+
+    void visit(AbstractModelAction.EntityOne entityOne) throws Exception;
+
+    void visit(AbstractModelAction.GetRelated getRelated) throws Exception;
+
+    void visit(AbstractModelAction.GetRelatedOne getRelatedOne) throws Exception;
+
+    void visit(AbstractModelAction.PropertyMap propertyMap) throws Exception;
+
+    void visit(AbstractModelAction.PropertyToField propertyToField) throws Exception;
+
+    void visit(AbstractModelAction.Script script) throws Exception;
+
+    void visit(AbstractModelAction.Service service) throws Exception;
+
+    void visit(AbstractModelAction.SetField setField) throws Exception;
+
+    void visit(ModelFormAction.Service service) throws Exception;
+
+    void visit(ModelMenuAction.SetField setField) throws Exception;
+
+    void visit(ModelTreeAction.Script script) throws Exception;
+
+    void visit(ModelTreeAction.Service service) throws Exception;
+
+    void visit(ModelTreeAction.EntityAnd entityAnd) throws Exception;
+
+    void visit(ModelTreeAction.EntityCondition entityCondition) throws Exception;
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelCondition.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelCondition.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelCondition.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelCondition.java Sun Jan 18 21:03:40 2015
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.widget.model;
+
+import java.util.Map;
+
+public interface ModelCondition {
+
+    void accept(ModelConditionVisitor visitor) throws Exception;
+
+    boolean eval(Map<String, Object> context);
+}