Added: 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelWidgetCondition.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelWidgetCondition.java?rev=1652852&view=auto
==============================================================================
--- 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelWidgetCondition.java
 (added)
+++ 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelWidgetCondition.java
 Sun Jan 18 21:03:40 2015
@@ -0,0 +1,650 @@
+/*******************************************************************************
+ * 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.Serializable;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.apache.oro.text.regex.MalformedPatternException;
+import org.apache.oro.text.regex.Pattern;
+import org.apache.oro.text.regex.PatternMatcher;
+import org.apache.oro.text.regex.Perl5Matcher;
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.GeneralException;
+import org.ofbiz.base.util.ObjectType;
+import org.ofbiz.base.util.PatternFactory;
+import org.ofbiz.base.util.UtilGenerics;
+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.GenericValue;
+import org.ofbiz.entityext.permission.EntityPermissionChecker;
+import org.ofbiz.minilang.operation.BaseCompare;
+import org.ofbiz.security.Security;
+import org.ofbiz.service.DispatchContext;
+import org.ofbiz.service.GenericServiceException;
+import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ModelService;
+import org.ofbiz.service.ServiceUtil;
+import org.w3c.dom.Element;
+
+/**
+ * Abstract base class for the condition models.
+ */
+@SuppressWarnings("serial")
+public abstract class ModelWidgetCondition implements Serializable {
+
+    /*
+     * ----------------------------------------------------------------------- 
*
+     *                     DEVELOPERS PLEASE READ
+     * ----------------------------------------------------------------------- 
*
+     * 
+     * This model is intended to be a read-only data structure that represents
+     * an XML element. Outside of object construction, the class should not
+     * have any behaviors.
+     * 
+     * Instances of this class will be shared by multiple threads - therefore
+     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!
+     * 
+     */
+
+    public static final String module = ModelWidgetCondition.class.getName();
+    public static final ConditionFactory DEFAULT_CONDITION_FACTORY = new 
DefaultConditionFactory();
+
+    private final ModelWidget modelWidget;
+    private final Condition rootCondition;
+
+    protected ModelWidgetCondition(ConditionFactory factory, ModelWidget 
modelWidget, Element conditionElement) {
+        this.modelWidget = modelWidget;
+        Element firstChildElement = 
UtilXml.firstChildElement(conditionElement);
+        this.rootCondition = factory.newInstance(modelWidget, 
firstChildElement);
+    }
+
+    public boolean eval(Map<String, Object> context) {
+        return rootCondition.eval(context);
+    }
+
+    public ModelWidget getModelWidget() {
+        return modelWidget;
+    }
+
+    public static List<Condition> readSubConditions(ConditionFactory factory, 
ModelWidget modelWidget, Element conditionElement) {
+        List<? extends Element> subElementList = 
UtilXml.childElementList(conditionElement);
+        List<Condition> condList = new 
ArrayList<Condition>(subElementList.size());
+        for (Element subElement : subElementList) {
+            condList.add(factory.newInstance(modelWidget, subElement));
+        }
+        return Collections.unmodifiableList(condList);
+    }
+
+    /**
+     * Models the &lt;and&gt; element.
+     * 
+     * @see <code>widget-common.xsd</code>
+     */
+    public static class And extends ModelWidgetCondition implements Condition {
+        private final List<Condition> subConditions;
+
+        private And(ConditionFactory factory, ModelWidget modelWidget, Element 
condElement) {
+            super(factory, modelWidget, condElement);
+            this.subConditions = readSubConditions(factory, modelWidget, 
condElement);
+        }
+
+        @Override
+        public boolean eval(Map<String, Object> context) {
+            // return false for the first one in the list that is false, basic 
and algo
+            for (Condition subCondition : this.subConditions) {
+                if (!subCondition.eval(context)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    public static interface Condition {
+        boolean eval(Map<String, Object> context);
+    }
+
+    /**
+     * A factory for <code>Condition</code> instances.
+     *
+     */
+    public static interface ConditionFactory {
+        /**
+         * Returns a new <code>Condition</code> instance built from 
<code>conditionElement</code>.
+         * 
+         * @param modelWidget The <code>ModelWidget</code> that contains the 
<code>Condition</code> instance.
+         * @param conditionElement The XML element used to build the 
<code>Condition</code> instance.
+         * @return A new <code>Condition</code> instance built from 
<code>conditionElement</code>.
+         * @throws IllegalArgumentException if no model was found for the XML 
element
+         */
+        Condition newInstance(ModelWidget modelWidget, Element 
conditionElement);
+    }
+
+    public static class DefaultConditionFactory implements ConditionFactory {
+        public static final Condition TRUE = new Condition() {
+            @Override
+            public boolean eval(Map<String, Object> context) {
+                return true;
+            }
+        };
+        public static final Condition FALSE = new Condition() {
+            @Override
+            public boolean eval(Map<String, Object> context) {
+                return false;
+            }
+        };
+
+        public Condition newInstance(ModelWidget modelWidget, Element 
conditionElement) {
+            if (conditionElement == null) {
+                return TRUE;
+            }
+            if ("and".equals(conditionElement.getNodeName())) {
+                return new And(this, modelWidget, conditionElement);
+            } else if ("xor".equals(conditionElement.getNodeName())) {
+                return new Xor(this, modelWidget, conditionElement);
+            } else if ("or".equals(conditionElement.getNodeName())) {
+                return new Or(this, modelWidget, conditionElement);
+            } else if ("not".equals(conditionElement.getNodeName())) {
+                return new Not(this, modelWidget, conditionElement);
+            } else if 
("if-service-permission".equals(conditionElement.getNodeName())) {
+                return new IfServicePermission(this, modelWidget, 
conditionElement);
+            } else if 
("if-has-permission".equals(conditionElement.getNodeName())) {
+                return new IfHasPermission(this, modelWidget, 
conditionElement);
+            } else if 
("if-validate-method".equals(conditionElement.getNodeName())) {
+                return new IfValidateMethod(this, modelWidget, 
conditionElement);
+            } else if ("if-compare".equals(conditionElement.getNodeName())) {
+                return new IfCompare(this, modelWidget, conditionElement);
+            } else if 
("if-compare-field".equals(conditionElement.getNodeName())) {
+                return new IfCompareField(this, modelWidget, conditionElement);
+            } else if ("if-regexp".equals(conditionElement.getNodeName())) {
+                return new IfRegexp(this, modelWidget, conditionElement);
+            } else if ("if-empty".equals(conditionElement.getNodeName())) {
+                return new IfEmpty(this, modelWidget, conditionElement);
+            } else if 
("if-entity-permission".equals(conditionElement.getNodeName())) {
+                return new IfEntityPermission(this, modelWidget, 
conditionElement);
+            } else {
+                throw new IllegalArgumentException("Condition element not 
supported with name: " + conditionElement.getNodeName());
+            }
+        }
+    }
+
+    /**
+     * Models the &lt;if-compare&gt; element.
+     * 
+     * @see <code>widget-common.xsd</code>
+     */
+    public static class IfCompare extends ModelWidgetCondition implements 
Condition {
+        private final FlexibleMapAccessor<Object> fieldAcsr;
+        private final FlexibleStringExpander formatExdr;
+        private final String operator;
+        private final String type;
+        private final FlexibleStringExpander valueExdr;
+
+        private IfCompare(ConditionFactory factory, ModelWidget modelWidget, 
Element condElement) {
+            super(factory, modelWidget, condElement);
+            String fieldAcsr = condElement.getAttribute("field");
+            if (fieldAcsr.isEmpty())
+                fieldAcsr = condElement.getAttribute("field-name");
+            this.fieldAcsr = FlexibleMapAccessor.getInstance(fieldAcsr);
+            this.valueExdr = 
FlexibleStringExpander.getInstance(condElement.getAttribute("value"));
+            this.operator = condElement.getAttribute("operator");
+            this.type = condElement.getAttribute("type");
+            this.formatExdr = 
FlexibleStringExpander.getInstance(condElement.getAttribute("format"));
+        }
+
+        @Override
+        public boolean eval(Map<String, Object> context) {
+            String value = this.valueExdr.expandString(context);
+            String format = this.formatExdr.expandString(context);
+            Object fieldVal = this.fieldAcsr.get(context);
+            // always use an empty string by default
+            if (fieldVal == null) {
+                fieldVal = "";
+            }
+            List<Object> messages = new LinkedList<Object>();
+            Boolean resultBool = BaseCompare.doRealCompare(fieldVal, value, 
operator, type, format, messages, null, null, true);
+            if (messages.size() > 0) {
+                messages.add(0, "Error with comparison in if-compare between 
field [" + fieldAcsr.toString() + "] with value ["
+                        + fieldVal + "] and value [" + value + "] with 
operator [" + operator + "] and type [" + type + "]: ");
+
+                StringBuilder fullString = new StringBuilder();
+                for (Object item : messages) {
+                    fullString.append(item.toString());
+                }
+                Debug.logWarning(fullString.toString(), module);
+                throw new IllegalArgumentException(fullString.toString());
+            }
+            return resultBool.booleanValue();
+        }
+    }
+
+    /**
+     * Models the &lt;if-compare-field&gt; element.
+     * 
+     * @see <code>widget-common.xsd</code>
+     */
+    public static class IfCompareField extends ModelWidgetCondition implements 
Condition {
+        private final FlexibleMapAccessor<Object> fieldAcsr;
+        private final FlexibleStringExpander formatExdr;
+        private final String operator;
+        private final FlexibleMapAccessor<Object> toFieldAcsr;
+        private final String type;
+
+        private IfCompareField(ConditionFactory factory, ModelWidget 
modelWidget, Element condElement) {
+            super(factory, modelWidget, condElement);
+            String fieldAcsr = condElement.getAttribute("field");
+            if (fieldAcsr.isEmpty())
+                fieldAcsr = condElement.getAttribute("field-name");
+            this.fieldAcsr = FlexibleMapAccessor.getInstance(fieldAcsr);
+            String toFieldAcsr = condElement.getAttribute("to-field");
+            if (toFieldAcsr.isEmpty())
+                toFieldAcsr = condElement.getAttribute("to-field-name");
+            this.toFieldAcsr = FlexibleMapAccessor.getInstance(toFieldAcsr);
+            this.operator = condElement.getAttribute("operator");
+            this.type = condElement.getAttribute("type");
+            this.formatExdr = 
FlexibleStringExpander.getInstance(condElement.getAttribute("format"));
+        }
+
+        @Override
+        public boolean eval(Map<String, Object> context) {
+            String format = this.formatExdr.expandString(context);
+            Object fieldVal = this.fieldAcsr.get(context);
+            Object toFieldVal = this.toFieldAcsr.get(context);
+            // always use an empty string by default
+            if (fieldVal == null) {
+                fieldVal = "";
+            }
+            List<Object> messages = new LinkedList<Object>();
+            Boolean resultBool = BaseCompare.doRealCompare(fieldVal, 
toFieldVal, operator, type, format, messages, null, null,
+                    false);
+            if (messages.size() > 0) {
+                messages.add(0, "Error with comparison in if-compare-field 
between field [" + fieldAcsr.toString()
+                        + "] with value [" + fieldVal + "] and to-field [" + 
toFieldAcsr.toString() + "] with value ["
+                        + toFieldVal + "] with operator [" + operator + "] and 
type [" + type + "]: ");
+
+                StringBuilder fullString = new StringBuilder();
+                for (Object item : messages) {
+                    fullString.append(item.toString());
+                }
+                Debug.logWarning(fullString.toString(), module);
+                throw new IllegalArgumentException(fullString.toString());
+            }
+            return resultBool.booleanValue();
+        }
+    }
+
+    /**
+     * Models the &lt;if-empty&gt; element.
+     * 
+     * @see <code>widget-common.xsd</code>
+     */
+    public static class IfEmpty extends ModelWidgetCondition implements 
Condition {
+        private final FlexibleMapAccessor<Object> fieldAcsr;
+
+        private IfEmpty(ConditionFactory factory, ModelWidget modelWidget, 
Element condElement) {
+            super(factory, modelWidget, condElement);
+            String fieldAcsr = condElement.getAttribute("field");
+            if (fieldAcsr.isEmpty())
+                fieldAcsr = condElement.getAttribute("field-name");
+            this.fieldAcsr = FlexibleMapAccessor.getInstance(fieldAcsr);
+        }
+
+        @Override
+        public boolean eval(Map<String, Object> context) {
+            Object fieldVal = this.fieldAcsr.get(context);
+            return ObjectType.isEmpty(fieldVal);
+        }
+    }
+
+    /**
+     * Models the &lt;if-entity-permission&gt; element.
+     * 
+     * @see <code>widget-common.xsd</code>
+     */
+    public static class IfEntityPermission extends ModelWidgetCondition 
implements Condition {
+        private final EntityPermissionChecker permissionChecker;
+
+        private IfEntityPermission(ConditionFactory factory, ModelWidget 
modelWidget, Element condElement) {
+            super(factory, modelWidget, condElement);
+            this.permissionChecker = new EntityPermissionChecker(condElement);
+        }
+
+        @Override
+        public boolean eval(Map<String, Object> context) {
+            return permissionChecker.runPermissionCheck(context);
+        }
+    }
+
+    /**
+     * Models the &lt;if-has-permission&gt; element.
+     * 
+     * @see <code>widget-common.xsd</code>
+     */
+    public static class IfHasPermission extends ModelWidgetCondition 
implements Condition {
+        private final FlexibleStringExpander actionExdr;
+        private final FlexibleStringExpander permissionExdr;
+
+        private IfHasPermission(ConditionFactory factory, ModelWidget 
modelWidget, Element condElement) {
+            super(factory, modelWidget, condElement);
+            this.permissionExdr = 
FlexibleStringExpander.getInstance(condElement.getAttribute("permission"));
+            this.actionExdr = 
FlexibleStringExpander.getInstance(condElement.getAttribute("action"));
+        }
+
+        @Override
+        public boolean eval(Map<String, Object> context) {
+            // if no user is logged in, treat as if the user does not have 
permission
+            GenericValue userLogin = (GenericValue) context.get("userLogin");
+            if (userLogin != null) {
+                String permission = permissionExdr.expandString(context);
+                String action = actionExdr.expandString(context);
+                Security security = (Security) context.get("security");
+                if (UtilValidate.isNotEmpty(action)) {
+                    // run hasEntityPermission
+                    if (security.hasEntityPermission(permission, action, 
userLogin)) {
+                        return true;
+                    }
+                } else {
+                    // run hasPermission
+                    if (security.hasPermission(permission, userLogin)) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Models the &lt;if-regexp&gt; element.
+     * 
+     * @see <code>widget-common.xsd</code>
+     */
+    public static class IfRegexp extends ModelWidgetCondition implements 
Condition {
+        private final FlexibleStringExpander exprExdr;
+        private final FlexibleMapAccessor<Object> fieldAcsr;
+
+        private IfRegexp(ConditionFactory factory, ModelWidget modelWidget, 
Element condElement) {
+            super(factory, modelWidget, condElement);
+            String fieldAcsr = condElement.getAttribute("field");
+            if (fieldAcsr.isEmpty())
+                fieldAcsr = condElement.getAttribute("field-name");
+            this.fieldAcsr = FlexibleMapAccessor.getInstance(fieldAcsr);
+            this.exprExdr = 
FlexibleStringExpander.getInstance(condElement.getAttribute("expr"));
+        }
+
+        @Override
+        public boolean eval(Map<String, Object> context) {
+            Object fieldVal = this.fieldAcsr.get(context);
+            String expr = this.exprExdr.expandString(context);
+            Pattern pattern;
+            try {
+                pattern = PatternFactory.createOrGetPerl5CompiledPattern(expr, 
true);
+            } catch (MalformedPatternException e) {
+                String errMsg = "Error in evaluation in if-regexp in screen: " 
+ e.toString();
+                Debug.logError(e, errMsg, module);
+                throw new IllegalArgumentException(errMsg);
+            }
+            String fieldString = null;
+            try {
+                fieldString = (String) ObjectType.simpleTypeConvert(fieldVal, 
"String", null, (TimeZone) context.get("timeZone"),
+                        (Locale) context.get("locale"), true);
+            } catch (GeneralException e) {
+                Debug.logError(e, "Could not convert object to String, using 
empty String", module);
+            }
+            // always use an empty string by default
+            if (fieldString == null)
+                fieldString = "";
+            PatternMatcher matcher = new Perl5Matcher();
+            return matcher.matches(fieldString, pattern);
+        }
+    }
+
+    /**
+     * Models the &lt;if-service-permission&gt; element.
+     * 
+     * @see <code>widget-common.xsd</code>
+     */
+    public static class IfServicePermission extends ModelWidgetCondition 
implements Condition {
+        private final FlexibleStringExpander actionExdr;
+        private final FlexibleStringExpander ctxMapExdr;
+        private final FlexibleStringExpander resExdr;
+        private final FlexibleStringExpander serviceExdr;
+
+        private IfServicePermission(ConditionFactory factory, ModelWidget 
modelWidget, Element condElement) {
+            super(factory, modelWidget, condElement);
+            this.serviceExdr = 
FlexibleStringExpander.getInstance(condElement.getAttribute("service-name"));
+            this.actionExdr = 
FlexibleStringExpander.getInstance(condElement.getAttribute("main-action"));
+            this.ctxMapExdr = 
FlexibleStringExpander.getInstance(condElement.getAttribute("context-map"));
+            this.resExdr = 
FlexibleStringExpander.getInstance(condElement.getAttribute("resource-description"));
+        }
+
+        @Override
+        public boolean eval(Map<String, Object> context) {
+            // if no user is logged in, treat as if the user does not have 
permission
+            GenericValue userLogin = (GenericValue) context.get("userLogin");
+            if (userLogin != null) {
+                String serviceName = serviceExdr.expandString(context);
+                String mainAction = actionExdr.expandString(context);
+                String contextMap = ctxMapExdr.expandString(context);
+                String resource = resExdr.expandString(context);
+                if (UtilValidate.isEmpty(resource)) {
+                    resource = serviceName;
+                }
+                if (UtilValidate.isEmpty(serviceName)) {
+                    Debug.logWarning("No permission service-name specified!", 
module);
+                    return false;
+                }
+                Map<String, Object> serviceContext = 
UtilGenerics.toMap(context.get(contextMap));
+                if (serviceContext != null) {
+                    // copy the required internal fields
+                    serviceContext.put("userLogin", context.get("userLogin"));
+                    serviceContext.put("locale", context.get("locale"));
+                } else {
+                    serviceContext = context;
+                }
+                // get the service engine objects
+                LocalDispatcher dispatcher = (LocalDispatcher) 
context.get("dispatcher");
+                DispatchContext dctx = dispatcher.getDispatchContext();
+                // get the service
+                ModelService permService;
+                try {
+                    permService = dctx.getModelService(serviceName);
+                } catch (GenericServiceException e) {
+                    Debug.logError(e, module);
+                    return false;
+                }
+                if (permService != null) {
+                    // build the context
+                    Map<String, Object> svcCtx = 
permService.makeValid(serviceContext, ModelService.IN_PARAM);
+                    svcCtx.put("resourceDescription", resource);
+                    if (UtilValidate.isNotEmpty(mainAction)) {
+                        svcCtx.put("mainAction", mainAction);
+                    }
+                    // invoke the service
+                    Map<String, Object> resp;
+                    try {
+                        resp = dispatcher.runSync(permService.name, svcCtx, 
300, true);
+                    } catch (GenericServiceException e) {
+                        Debug.logError(e, module);
+                        return false;
+                    }
+                    if (ServiceUtil.isError(resp) || 
ServiceUtil.isFailure(resp)) {
+                        Debug.logError(ServiceUtil.getErrorMessage(resp), 
module);
+                        return false;
+                    }
+                    Boolean hasPermission = (Boolean) 
resp.get("hasPermission");
+                    if (hasPermission != null) {
+                        return hasPermission.booleanValue();
+                    }
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Models the &lt;if-validate-method&gt; element.
+     * 
+     * @see <code>widget-common.xsd</code>
+     */
+    public static class IfValidateMethod extends ModelWidgetCondition 
implements Condition {
+        private final FlexibleStringExpander classExdr;
+        private final FlexibleMapAccessor<Object> fieldAcsr;
+        private final FlexibleStringExpander methodExdr;
+
+        private IfValidateMethod(ConditionFactory factory, ModelWidget 
modelWidget, Element condElement) {
+            super(factory, modelWidget, condElement);
+            String fieldAcsr = condElement.getAttribute("field");
+            if (fieldAcsr.isEmpty())
+                fieldAcsr = condElement.getAttribute("field-name");
+            this.fieldAcsr = FlexibleMapAccessor.getInstance(fieldAcsr);
+            this.methodExdr = 
FlexibleStringExpander.getInstance(condElement.getAttribute("method"));
+            this.classExdr = 
FlexibleStringExpander.getInstance(condElement.getAttribute("class"));
+        }
+
+        @Override
+        public boolean eval(Map<String, Object> context) {
+            String methodName = this.methodExdr.expandString(context);
+            String className = this.classExdr.expandString(context);
+            Object fieldVal = this.fieldAcsr.get(context);
+            String fieldString = null;
+            if (fieldVal != null) {
+                try {
+                    fieldString = (String) 
ObjectType.simpleTypeConvert(fieldVal, "String", null,
+                            (TimeZone) context.get("timeZone"), (Locale) 
context.get("locale"), true);
+                } catch (GeneralException e) {
+                    Debug.logError(e, "Could not convert object to String, 
using empty String", module);
+                }
+            }
+            // always use an empty string by default
+            if (fieldString == null)
+                fieldString = "";
+            Class<?>[] paramTypes = new Class[] { String.class };
+            Object[] params = new Object[] { fieldString };
+            Class<?> valClass;
+            try {
+                valClass = ObjectType.loadClass(className);
+            } catch (ClassNotFoundException cnfe) {
+                Debug.logError("Could not find validation class: " + 
className, module);
+                return false;
+            }
+            Method valMethod;
+            try {
+                valMethod = valClass.getMethod(methodName, paramTypes);
+            } catch (NoSuchMethodException cnfe) {
+                Debug.logError("Could not find validation method: " + 
methodName + " of class " + className, module);
+                return false;
+            }
+            Boolean resultBool = Boolean.FALSE;
+            try {
+                resultBool = (Boolean) valMethod.invoke(null, params);
+            } catch (Exception e) {
+                Debug.logError(e, "Error in IfValidationMethod " + methodName 
+ " of class " + className
+                        + ", defaulting to false ", module);
+            }
+            return resultBool.booleanValue();
+        }
+    }
+
+    /**
+     * Models the &lt;not&gt; element.
+     * 
+     * @see <code>widget-common.xsd</code>
+     */
+    public static class Not extends ModelWidgetCondition implements Condition {
+        private final Condition subCondition;
+
+        private Not(ConditionFactory factory, ModelWidget modelWidget, Element 
condElement) {
+            super(factory, modelWidget, condElement);
+            Element firstChildElement = UtilXml.firstChildElement(condElement);
+            this.subCondition = factory.newInstance(modelWidget, 
firstChildElement);
+        }
+
+        @Override
+        public boolean eval(Map<String, Object> context) {
+            return !this.subCondition.eval(context);
+        }
+    }
+
+    /**
+     * Models the &lt;or&gt; element.
+     * 
+     * @see <code>widget-common.xsd</code>
+     */
+    public static class Or extends ModelWidgetCondition implements Condition {
+        private final List<Condition> subConditions;
+
+        private Or(ConditionFactory factory, ModelWidget modelWidget, Element 
condElement) {
+            super(factory, modelWidget, condElement);
+            this.subConditions = readSubConditions(factory, modelWidget, 
condElement);
+        }
+
+        @Override
+        public boolean eval(Map<String, Object> context) {
+            // return true for the first one in the list that is true, basic 
or algo
+            for (Condition subCondition : this.subConditions) {
+                if (subCondition.eval(context)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Models the &lt;xor&gt; element.
+     * 
+     * @see <code>widget-common.xsd</code>
+     */
+    public static class Xor extends ModelWidgetCondition implements Condition {
+        private final List<Condition> subConditions;
+
+        private Xor(ConditionFactory factory, ModelWidget modelWidget, Element 
condElement) {
+            super(factory, modelWidget, condElement);
+            this.subConditions = readSubConditions(factory, modelWidget, 
condElement);
+        }
+
+        @Override
+        public boolean eval(Map<String, Object> context) {
+            // if more than one is true stop immediately and return false; if 
all are false return false; if only one is true return true
+            boolean foundOneTrue = false;
+            for (Condition subCondition : this.subConditions) {
+                if (subCondition.eval(context)) {
+                    if (foundOneTrue) {
+                        // now found two true, so return false
+                        return false;
+                    } else {
+                        foundOneTrue = true;
+                    }
+                }
+            }
+            return foundOneTrue;
+        }
+    }
+}

Added: 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelWidgetVisitor.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelWidgetVisitor.java?rev=1652852&view=auto
==============================================================================
--- 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelWidgetVisitor.java 
(added)
+++ 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelWidgetVisitor.java 
Sun Jan 18 21:03:40 2015
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * 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 org.ofbiz.widget.model.HtmlWidget;
+
+/**
+ *  A <code>ModelWidget</code> visitor.
+ */
+public interface ModelWidgetVisitor {
+
+    void visit(HtmlWidget htmlWidget) throws Exception;
+
+    void visit(HtmlWidget.HtmlTemplate htmlTemplate) throws Exception;
+
+    void visit(HtmlWidget.HtmlTemplateDecorator htmlTemplateDecorator) throws 
Exception;
+
+    void visit(HtmlWidget.HtmlTemplateDecoratorSection 
htmlTemplateDecoratorSection) throws Exception;
+
+    void visit(IterateSectionWidget iterateSectionWidget) throws Exception;
+
+    void visit(ModelForm modelForm) throws Exception;
+
+    void visit(ModelMenu modelMenu) throws Exception;
+
+    void visit(ModelMenuItem modelMenuItem) throws Exception;
+
+    void visit(ModelScreen modelScreen) throws Exception;
+
+    void visit(ModelScreenWidget.ColumnContainer columnContainer) throws 
Exception;
+
+    void visit(ModelScreenWidget.Container container) throws Exception;
+
+    void visit(ModelScreenWidget.Content content) throws Exception;
+
+    void visit(ModelScreenWidget.DecoratorScreen decoratorScreen) throws 
Exception;
+
+    void visit(ModelScreenWidget.DecoratorSection decoratorSection) throws 
Exception;
+
+    void visit(ModelScreenWidget.DecoratorSectionInclude 
decoratorSectionInclude) throws Exception;
+
+    void visit(ModelScreenWidget.Form form) throws Exception;
+
+    void visit(ModelScreenWidget.HorizontalSeparator horizontalSeparator) 
throws Exception;
+
+    void visit(ModelScreenWidget.ScreenImage image) throws Exception;
+
+    void visit(ModelScreenWidget.IncludeScreen includeScreen) throws Exception;
+
+    void visit(ModelScreenWidget.Label label) throws Exception;
+
+    void visit(ModelScreenWidget.ScreenLink link) throws Exception;
+
+    void visit(ModelScreenWidget.Menu menu) throws Exception;
+
+    void visit(ModelScreenWidget.PlatformSpecific platformSpecific) throws 
Exception;
+
+    void visit(ModelScreenWidget.PortalPage portalPage) throws Exception;
+
+    void visit(ModelScreenWidget.Screenlet screenlet) throws Exception;
+
+    void visit(ModelScreenWidget.Section section) throws Exception;
+
+    void visit(ModelScreenWidget.Tree tree) throws Exception;
+
+    void visit(ModelTree modelTree) throws Exception;
+
+    void visit(ModelTree.ModelNode modelNode) throws Exception;
+
+    void visit(ModelTree.ModelNode.ModelSubNode modelSubNode) throws Exception;
+
+    void visit(ModelScreenWidget.Column column) throws Exception;
+}

Added: 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ScreenFactory.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ScreenFactory.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ScreenFactory.java 
(added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ScreenFactory.java 
Sun Jan 18 21:03:40 2015
@@ -0,0 +1,213 @@
+/*******************************************************************************
+ * 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.Debug;
+import org.ofbiz.base.util.GeneralException;
+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.ofbiz.widget.renderer.ScreenStringRenderer;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+
+/**
+ * Widget Library - Screen factory class
+ */
+public class ScreenFactory {
+
+    public static final String module = ScreenFactory.class.getName();
+
+    public static final UtilCache<String, Map<String, ModelScreen>> 
screenLocationCache = 
UtilCache.createUtilCache("widget.screen.locationResource", 0, 0, false);
+    public static final UtilCache<String, Map<String, ModelScreen>> 
screenWebappCache = UtilCache.createUtilCache("widget.screen.webappResource", 
0, 0, false);
+
+    public static boolean isCombinedName(String combinedName) {
+        int numSignIndex = combinedName.lastIndexOf("#");
+        if (numSignIndex == -1) {
+            return false;
+        }
+        if (numSignIndex + 1 >= combinedName.length()) {
+            return false;
+        }
+        return true;
+    }
+
+    public static String getResourceNameFromCombined(String combinedName) {
+        // split out the name on the last "#"
+        int numSignIndex = combinedName.lastIndexOf("#");
+        if (numSignIndex == -1) {
+            throw new IllegalArgumentException("Error in screen location/name: 
no \"#\" found to separate the location from the name; correct example: 
component://product/screen/product/ProductScreens.xml#EditProduct");
+        }
+        if (numSignIndex + 1 >= combinedName.length()) {
+            throw new IllegalArgumentException("Error in screen location/name: 
the \"#\" was at the end with no screen name after it; correct example: 
component://product/screen/product/ProductScreens.xml#EditProduct");
+        }
+        String resourceName = combinedName.substring(0, numSignIndex);
+        return resourceName;
+    }
+
+    public static String getScreenNameFromCombined(String combinedName) {
+        // split out the name on the last "#"
+        int numSignIndex = combinedName.lastIndexOf("#");
+        if (numSignIndex == -1) {
+            throw new IllegalArgumentException("Error in screen location/name: 
no \"#\" found to separate the location from the name; correct example: 
component://product/screen/product/ProductScreens.xml#EditProduct");
+        }
+        if (numSignIndex + 1 >= combinedName.length()) {
+            throw new IllegalArgumentException("Error in screen location/name: 
the \"#\" was at the end with no screen name after it; correct example: 
component://product/screen/product/ProductScreens.xml#EditProduct");
+        }
+        String screenName = combinedName.substring(numSignIndex + 1);
+        return screenName;
+    }
+
+    public static ModelScreen getScreenFromLocation(String combinedName)
+            throws IOException, SAXException, ParserConfigurationException {
+        String resourceName = getResourceNameFromCombined(combinedName);
+        String screenName = getScreenNameFromCombined(combinedName);
+        return getScreenFromLocation(resourceName, screenName);
+    }
+
+    public static ModelScreen getScreenFromLocation(String resourceName, 
String screenName)
+            throws IOException, SAXException, ParserConfigurationException {
+        Map<String, ModelScreen> modelScreenMap = 
getScreensFromLocation(resourceName);
+        ModelScreen modelScreen = modelScreenMap.get(screenName);
+        if (modelScreen == null) {
+            throw new IllegalArgumentException("Could not find screen with 
name [" + screenName + "] in class resource [" + resourceName + "]");
+        }
+        return modelScreen;
+    }
+
+    public static Map<String, ModelScreen> getScreensFromLocation(String 
resourceName)
+            throws IOException, SAXException, ParserConfigurationException {
+        Map<String, ModelScreen> modelScreenMap = 
screenLocationCache.get(resourceName);
+        if (modelScreenMap == null) {
+            synchronized (ScreenFactory.class) {
+                modelScreenMap = screenLocationCache.get(resourceName);
+                if (modelScreenMap == null) {
+                    long startTime = System.currentTimeMillis();
+                    URL screenFileUrl = null;
+                    screenFileUrl = 
FlexibleLocation.resolveLocation(resourceName);
+                    if (screenFileUrl == null) {
+                        throw new IllegalArgumentException("Could not resolve 
location to URL: " + resourceName);
+                    }
+                    Document screenFileDoc = 
UtilXml.readXmlDocument(screenFileUrl, true, true);
+                    modelScreenMap = readScreenDocument(screenFileDoc, 
resourceName);
+                    screenLocationCache.put(resourceName, modelScreenMap);
+                    double totalSeconds = (System.currentTimeMillis() - 
startTime)/1000.0;
+                    Debug.logInfo("Got " + modelScreenMap.size() + " screens 
in " + totalSeconds + "s from: " + screenFileUrl.toExternalForm(), module);
+                }
+            }
+        }
+
+        if (modelScreenMap.isEmpty()) {
+            throw new IllegalArgumentException("Could not find screen file 
with name [" + resourceName + "]");
+        }
+        return modelScreenMap;
+    }
+
+    public static ModelScreen getScreenFromWebappContext(String resourceName, 
String screenName, HttpServletRequest request)
+            throws IOException, SAXException, ParserConfigurationException {
+        String webappName = UtilHttp.getApplicationName(request);
+        String cacheKey = webappName + "::" + resourceName;
+
+
+        Map<String, ModelScreen> modelScreenMap = 
screenWebappCache.get(cacheKey);
+        if (modelScreenMap == null) {
+            synchronized (ScreenFactory.class) {
+                modelScreenMap = screenWebappCache.get(cacheKey);
+                if (modelScreenMap == null) {
+                    ServletContext servletContext = (ServletContext) 
request.getAttribute("servletContext");
+
+                    URL screenFileUrl = 
servletContext.getResource(resourceName);
+                    Document screenFileDoc = 
UtilXml.readXmlDocument(screenFileUrl, true, true);
+                    modelScreenMap = readScreenDocument(screenFileDoc, 
resourceName);
+                    screenWebappCache.put(cacheKey, modelScreenMap);
+                }
+            }
+        }
+
+        ModelScreen modelScreen = modelScreenMap.get(screenName);
+        if (modelScreen == null) {
+            throw new IllegalArgumentException("Could not find screen with 
name [" + screenName + "] in webapp resource [" + resourceName + "] in the 
webapp [" + webappName + "]");
+        }
+        return modelScreen;
+    }
+
+    public static Map<String, ModelScreen> readScreenDocument(Document 
screenFileDoc, String sourceLocation) {
+        Map<String, ModelScreen> modelScreenMap = new HashMap<String, 
ModelScreen>();
+        if (screenFileDoc != null) {
+            // read document and construct ModelScreen for each screen element
+            Element rootElement = screenFileDoc.getDocumentElement();
+            List<? extends Element> screenElements = 
UtilXml.childElementList(rootElement, "screen");
+            for (Element screenElement: screenElements) {
+                ModelScreen modelScreen = new ModelScreen(screenElement, 
modelScreenMap, sourceLocation);
+                //Debug.logInfo("Read Screen with name: " + 
modelScreen.getName(), module);
+                modelScreenMap.put(modelScreen.getName(), modelScreen);
+            }
+        }
+        return modelScreenMap;
+    }
+
+    public static void renderReferencedScreen(String name, String location, 
ModelScreenWidget parentWidget, Appendable writer, Map<String, Object> context, 
ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException 
{
+        // check to see if the name is a composite name separated by a #, if 
so split it up and get it by the full loc#name
+        if (ScreenFactory.isCombinedName(name)) {
+            String combinedName = name;
+            location = ScreenFactory.getResourceNameFromCombined(combinedName);
+            name = ScreenFactory.getScreenNameFromCombined(combinedName);
+        }
+
+        ModelScreen modelScreen = null;
+        if (UtilValidate.isNotEmpty(location)) {
+            try {
+                modelScreen = ScreenFactory.getScreenFromLocation(location, 
name);
+            } catch (IOException e) {
+                String errMsg = "Error rendering included screen named [" + 
name + "] at location [" + location + "]: " + e.toString();
+                Debug.logError(e, errMsg, module);
+                throw new RuntimeException(errMsg);
+            } catch (SAXException e) {
+                String errMsg = "Error rendering included screen named [" + 
name + "] at location [" + location + "]: " + e.toString();
+                Debug.logError(e, errMsg, module);
+                throw new RuntimeException(errMsg);
+            } catch (ParserConfigurationException e) {
+                String errMsg = "Error rendering included screen named [" + 
name + "] at location [" + location + "]: " + e.toString();
+                Debug.logError(e, errMsg, module);
+                throw new RuntimeException(errMsg);
+            }
+        } else {
+            modelScreen = 
parentWidget.getModelScreen().getModelScreenMap().get(name);
+            if (modelScreen == null) {
+                throw new IllegalArgumentException("Could not find screen with 
name [" + name + "] in the same file as the screen with name [" + 
parentWidget.getModelScreen().getName() + "]");
+            }
+        }
+        //Debug.logInfo("parent(" + parentWidget + ") rendering(" + 
modelScreen + ")", module);
+        modelScreen.renderScreenString(writer, context, screenStringRenderer);
+    }
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/TreeFactory.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/TreeFactory.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/TreeFactory.java 
(added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/TreeFactory.java 
Sun Jan 18 21:03:40 2015
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * 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.xml.parsers.ParserConfigurationException;
+
+import org.ofbiz.base.location.FlexibleLocation;
+import org.ofbiz.base.util.UtilXml;
+import org.ofbiz.base.util.cache.UtilCache;
+import org.ofbiz.entity.Delegator;
+import org.ofbiz.service.LocalDispatcher;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+
+/**
+ * Widget Library - Tree factory class
+ */
+public class TreeFactory {
+
+    public static final String module = TreeFactory.class.getName();
+
+    public static final UtilCache<String, Map<String, ModelTree>> 
treeLocationCache = UtilCache.createUtilCache("widget.tree.locationResource", 
0, 0, false);
+
+    public static ModelTree getTreeFromLocation(String resourceName, String 
treeName, Delegator delegator, LocalDispatcher dispatcher)
+            throws IOException, SAXException, ParserConfigurationException {
+        Map<String, ModelTree> modelTreeMap = 
treeLocationCache.get(resourceName);
+        if (modelTreeMap == null) {
+            synchronized (TreeFactory.class) {
+                modelTreeMap = treeLocationCache.get(resourceName);
+                if (modelTreeMap == null) {
+                    ClassLoader loader = 
Thread.currentThread().getContextClassLoader();
+                    if (loader == null) {
+                        loader = TreeFactory.class.getClassLoader();
+                    }
+
+                    URL treeFileUrl = null;
+                    treeFileUrl = 
FlexibleLocation.resolveLocation(resourceName); //, loader);
+                    Document treeFileDoc = 
UtilXml.readXmlDocument(treeFileUrl, true, true);
+                    modelTreeMap = readTreeDocument(treeFileDoc, delegator, 
dispatcher, resourceName);
+                    treeLocationCache.put(resourceName, modelTreeMap);
+                }
+            }
+        }
+
+        ModelTree modelTree = modelTreeMap.get(treeName);
+        if (modelTree == null) {
+            throw new IllegalArgumentException("Could not find tree with name 
[" + treeName + "] in class resource [" + resourceName + "]");
+        }
+        return modelTree;
+    }
+
+    public static Map<String, ModelTree> readTreeDocument(Document 
treeFileDoc, Delegator delegator, LocalDispatcher dispatcher, String 
treeLocation) {
+        Map<String, ModelTree> modelTreeMap = new HashMap<String, ModelTree>();
+        if (treeFileDoc != null) {
+            // read document and construct ModelTree for each tree element
+            Element rootElement = treeFileDoc.getDocumentElement();
+            for (Element treeElement: UtilXml.childElementList(rootElement, 
"tree")) {
+                ModelTree modelTree = new ModelTree(treeElement, treeLocation);
+                modelTreeMap.put(modelTree.getName(), modelTree);
+            }
+        }
+        return modelTreeMap;
+    }
+}

Added: 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlAbstractWidgetVisitor.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlAbstractWidgetVisitor.java?rev=1652852&view=auto
==============================================================================
--- 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlAbstractWidgetVisitor.java
 (added)
+++ 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlAbstractWidgetVisitor.java
 Sun Jan 18 21:03:40 2015
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * 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.Collection;
+
+import org.ofbiz.base.util.Assert;
+import org.ofbiz.base.util.collections.FlexibleMapAccessor;
+import org.ofbiz.base.util.string.FlexibleStringExpander;
+import org.ofbiz.widget.model.CommonWidgetModels.AutoEntityParameters;
+import org.ofbiz.widget.model.CommonWidgetModels.AutoServiceParameters;
+import org.ofbiz.widget.model.CommonWidgetModels.Image;
+import org.ofbiz.widget.model.CommonWidgetModels.Link;
+import org.ofbiz.widget.model.CommonWidgetModels.Parameter;
+
+/**
+ * Abstract XML widget visitor.
+ *
+ */
+public abstract class XmlAbstractWidgetVisitor {
+
+    protected final Appendable writer;
+
+    public XmlAbstractWidgetVisitor(Appendable writer) {
+        Assert.notNull("writer", writer);
+        this.writer = writer;
+    }
+
+    protected void visitAttribute(String attributeName, Boolean 
attributeValue) throws Exception {
+        if (attributeValue != null) {
+            writer.append(" ").append(attributeName).append("=\"");
+            writer.append(attributeValue.toString());
+            writer.append("\"");
+        }
+    }
+
+    protected void visitAttribute(String attributeName, FlexibleMapAccessor<?> 
attributeValue) throws Exception {
+        if (attributeValue != null && !attributeValue.isEmpty()) {
+            writer.append(" ").append(attributeName).append("=\"");
+            writer.append(attributeValue.getOriginalName());
+            writer.append("\"");
+        }
+    }
+
+    protected void visitAttribute(String attributeName, FlexibleStringExpander 
attributeValue) throws Exception {
+        if (attributeValue != null && !attributeValue.isEmpty()) {
+            writer.append(" ").append(attributeName).append("=\"");
+            writer.append(attributeValue.getOriginal());
+            writer.append("\"");
+        }
+    }
+
+    protected void visitAttribute(String attributeName, Integer 
attributeValue) throws Exception {
+        if (attributeValue != null) {
+            writer.append(" ").append(attributeName).append("=\"");
+            writer.append(attributeValue.toString());
+            writer.append("\"");
+        }
+    }
+
+    protected void visitAttribute(String attributeName, String attributeValue) 
throws Exception {
+        if (attributeValue != null && !attributeValue.isEmpty()) {
+            writer.append(" ").append(attributeName).append("=\"");
+            writer.append(attributeValue);
+            writer.append("\"");
+        }
+    }
+
+    protected void visitAutoEntityParameters(AutoEntityParameters 
autoEntityParameters) throws Exception {
+
+    }
+
+    protected void visitAutoServiceParameters(AutoServiceParameters 
autoServiceParameters) throws Exception {
+
+    }
+
+    protected void visitImage(Image image) throws Exception {
+        if (image != null) {
+            writer.append("<image");
+            visitAttribute("name", image.getName());
+            visitAttribute("alt", image.getAlt());
+            visitAttribute("border", image.getBorderExdr());
+            visitAttribute("height", image.getHeightExdr());
+            visitAttribute("id", image.getIdExdr());
+            visitAttribute("src", image.getSrcExdr());
+            visitAttribute("style", image.getStyleExdr());
+            visitAttribute("title", image.getTitleExdr());
+            visitAttribute("url-mode", image.getUrlMode());
+            visitAttribute("width", image.getWidthExdr());
+            writer.append("/>");
+        }
+    }
+
+    protected void visitLink(Link link) throws Exception {
+        if (link != null) {
+            writer.append("<link");
+            visitLinkAttributes(link);
+            if (link.getImage() != null || link.getAutoEntityParameters() != 
null || link.getAutoServiceParameters() != null) {
+                writer.append(">");
+                visitImage(link.getImage());
+                visitAutoEntityParameters(link.getAutoEntityParameters());
+                visitAutoServiceParameters(link.getAutoServiceParameters());
+                writer.append("</link>");
+            } else {
+                writer.append("/>");
+            }
+        }
+    }
+
+    protected void visitLinkAttributes(Link link) throws Exception {
+        if (link != null) {
+            visitAttribute("name", link.getName());
+            visitAttribute("encode", link.getEncode());
+            visitAttribute("full-path", link.getFullPath());
+            visitAttribute("id", link.getIdExdr());
+            visitAttribute("height", link.getHeight());
+            visitAttribute("link-type", link.getLinkType());
+            visitAttribute("prefix", link.getPrefixExdr());
+            visitAttribute("secure", link.getSecure());
+            visitAttribute("style", link.getStyleExdr());
+            visitAttribute("target", link.getTargetExdr());
+            visitAttribute("target-window", link.getTargetWindowExdr());
+            visitAttribute("text", link.getTextExdr());
+            visitAttribute("size", link.getSize());
+            visitAttribute("url-mode", link.getUrlMode());
+            visitAttribute("width", link.getWidth());
+        }
+    }
+
+    protected void visitModelWidget(ModelWidget widget) throws Exception {
+        if (widget.getName() != null && !widget.getName().isEmpty()) {
+            writer.append(" name=\"");
+            writer.append(widget.getName());
+            writer.append("\"");
+        }
+    }
+
+    protected void visitParameters(Collection<Parameter> parameters) throws 
Exception {
+        if (parameters != null) {
+            for (Parameter parameter : parameters) {
+                writer.append("<parameter");
+                visitAttribute("param-name", parameter.getName());
+                visitAttribute("from-field", parameter.getFromField());
+                visitAttribute("value", parameter.getValue());
+                writer.append("/>");
+            }
+        }
+    }
+}

Added: 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlWidgetActionVisitor.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlWidgetActionVisitor.java?rev=1652852&view=auto
==============================================================================
--- 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlWidgetActionVisitor.java
 (added)
+++ 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlWidgetActionVisitor.java
 Sun Jan 18 21:03:40 2015
@@ -0,0 +1,210 @@
+/*******************************************************************************
+ * 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 org.ofbiz.widget.model.AbstractModelAction.EntityAnd;
+import org.ofbiz.widget.model.AbstractModelAction.EntityCondition;
+import org.ofbiz.widget.model.AbstractModelAction.EntityOne;
+import org.ofbiz.widget.model.AbstractModelAction.GetRelated;
+import org.ofbiz.widget.model.AbstractModelAction.GetRelatedOne;
+import org.ofbiz.widget.model.AbstractModelAction.PropertyMap;
+import org.ofbiz.widget.model.AbstractModelAction.PropertyToField;
+import org.ofbiz.widget.model.AbstractModelAction.Script;
+import org.ofbiz.widget.model.AbstractModelAction.Service;
+import org.ofbiz.widget.model.AbstractModelAction.SetField;
+import org.ofbiz.widget.model.ModelFormAction.CallParentActions;
+
+/**
+ * An object that generates XML from widget models.
+ * The generated XML is unformatted - if you want to
+ * "pretty print" the XML, then use a transformer.
+ *
+ */
+public class XmlWidgetActionVisitor extends XmlAbstractWidgetVisitor 
implements ModelActionVisitor {
+
+    public static final String module = XmlWidgetActionVisitor.class.getName();
+
+    public XmlWidgetActionVisitor(Appendable writer) {
+        super(writer);
+    }
+
+    @Override
+    public void visit(CallParentActions callParentActions) throws Exception {
+        writer.append("<call-parent-actions/>");
+    }
+
+    @Override
+    public void visit(EntityAnd entityAnd) throws Exception {
+        writer.append("<entity-and/>");
+        // TODO: Create ByAndFinder visitor
+    }
+
+    @Override
+    public void visit(org.ofbiz.widget.model.ModelTreeAction.EntityAnd 
entityAnd) throws Exception {
+        writer.append("<entity-and/>");
+        // TODO: Create ByAndFinder visitor
+    }
+
+    @Override
+    public void visit(EntityCondition entityCondition) throws Exception {
+        writer.append("<entity-condition/>");
+        // TODO: Create ByConditionFinder visitor
+    }
+
+    @Override
+    public void visit(org.ofbiz.widget.model.ModelTreeAction.EntityCondition 
entityCondition) throws Exception {
+        writer.append("<entity-condition/>");
+        // TODO: Create ByConditionFinder visitor
+    }
+
+    @Override
+    public void visit(EntityOne entityOne) throws Exception {
+        writer.append("<entity-one/>");
+        // TODO: Create PrimaryKeyFinder visitor
+    }
+
+    @Override
+    public void visit(GetRelated getRelated) throws Exception {
+        writer.append("<get-related");
+        visitAttribute("value-field", getRelated.getValueNameAcsr());
+        visitAttribute("list", getRelated.getListNameAcsr());
+        visitAttribute("relation-name", getRelated.getRelationName());
+        visitAttribute("map", getRelated.getMapAcsr());
+        visitAttribute("order-by-list", getRelated.getOrderByListAcsr());
+        visitAttribute("use-cache", getRelated.getUseCache());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(GetRelatedOne getRelatedOne) throws Exception {
+        writer.append("<get-related-one");
+        visitAttribute("value-field", getRelatedOne.getValueNameAcsr());
+        visitAttribute("to-value-field", getRelatedOne.getToValueNameAcsr());
+        visitAttribute("relation-name", getRelatedOne.getRelationName());
+        visitAttribute("use-cache", getRelatedOne.getUseCache());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(PropertyMap propertyMap) throws Exception {
+        writer.append("<property-map");
+        visitAttribute("resource", propertyMap.getResourceExdr());
+        visitAttribute("map-name", propertyMap.getMapNameAcsr());
+        visitAttribute("global", propertyMap.getGlobalExdr());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(PropertyToField propertyToField) throws Exception {
+        writer.append("<property-map");
+        visitAttribute("resource", propertyToField.getResourceExdr());
+        visitAttribute("property", propertyToField.getPropertyExdr());
+        visitAttribute("field", propertyToField.getFieldAcsr());
+        visitAttribute("default", propertyToField.getDefaultExdr());
+        visitAttribute("no-locale", propertyToField.getNoLocale());
+        visitAttribute("arg-list-name", propertyToField.getArgListAcsr());
+        visitAttribute("global", propertyToField.getGlobalExdr());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(Script script) throws Exception {
+        writer.append("<script");
+        visitAttribute("location", script.getLocation());
+        visitAttribute("method", script.getMethod());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(org.ofbiz.widget.model.ModelTreeAction.Script script) 
throws Exception {
+        writer.append("<script");
+        visitAttribute("location", script.getLocation());
+        visitAttribute("method", script.getMethod());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(Service service) throws Exception {
+        writer.append("<service");
+        visitAttribute("service-name", service.getServiceNameExdr());
+        visitAttribute("result-map", service.getResultMapNameAcsr());
+        visitAttribute("auto-field-map", service.getAutoFieldMapExdr());
+        writer.append(">");
+        // TODO: Create Field Map visitor
+        writer.append("<field-map/>");
+        writer.append("</service>");
+    }
+
+    @Override
+    public void visit(org.ofbiz.widget.model.ModelFormAction.Service service) 
throws Exception {
+        writer.append("<service");
+        visitAttribute("service-name", service.getServiceNameExdr());
+        visitAttribute("result-map", service.getResultMapNameAcsr());
+        visitAttribute("auto-field-map", service.getAutoFieldMapExdr());
+        visitAttribute("result-map-list", service.getResultMapListNameExdr());
+        visitAttribute("ignore-error", service.getIgnoreError());
+        writer.append(">");
+        // TODO: Create Field Map visitor
+        writer.append("<field-map/>");
+        writer.append("</service>");
+    }
+
+    @Override
+    public void visit(org.ofbiz.widget.model.ModelTreeAction.Service service) 
throws Exception {
+        writer.append("<service");
+        visitAttribute("service-name", service.getServiceNameExdr());
+        visitAttribute("result-map", service.getResultMapNameAcsr());
+        visitAttribute("auto-field-map", service.getAutoFieldMapExdr());
+        visitAttribute("result-map-list", service.getResultMapListNameExdr());
+        visitAttribute("result-map-value", 
service.getResultMapValueNameExdr());
+        visitAttribute("value", service.getValueNameExdr());
+        writer.append(">");
+        // TODO: Create Field Map visitor
+        writer.append("<field-map/>");
+        writer.append("</service>");
+    }
+
+    @Override
+    public void visit(SetField setField) throws Exception {
+        writer.append("<set");
+        visitAttribute("field", setField.getField());
+        visitAttribute("from-field", setField.getFromField());
+        visitAttribute("value", setField.getValueExdr());
+        visitAttribute("default-value", setField.getDefaultExdr());
+        visitAttribute("global", setField.getGlobalExdr());
+        visitAttribute("type", setField.getType());
+        visitAttribute("to-scope", setField.getToScope());
+        visitAttribute("from-scope", setField.getFromScope());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(org.ofbiz.widget.model.ModelMenuAction.SetField 
setField) throws Exception {
+        writer.append("<set");
+        visitAttribute("field", setField.getField());
+        visitAttribute("from-field", setField.getFromField());
+        visitAttribute("value", setField.getValueExdr());
+        visitAttribute("default-value", setField.getDefaultExdr());
+        visitAttribute("global", setField.getGlobalExdr());
+        visitAttribute("type", setField.getType());
+        visitAttribute("to-scope", setField.getToScope());
+        visitAttribute("from-scope", setField.getFromScope());
+        writer.append("/>");
+    }
+}

Added: 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlWidgetConditionVisitor.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlWidgetConditionVisitor.java?rev=1652852&view=auto
==============================================================================
--- 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlWidgetConditionVisitor.java
 (added)
+++ 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlWidgetConditionVisitor.java
 Sun Jan 18 21:03:40 2015
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * 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.Collection;
+
+import org.ofbiz.widget.model.AbstractModelCondition.And;
+import org.ofbiz.widget.model.AbstractModelCondition.IfCompare;
+import org.ofbiz.widget.model.AbstractModelCondition.IfCompareField;
+import org.ofbiz.widget.model.AbstractModelCondition.IfEmpty;
+import org.ofbiz.widget.model.AbstractModelCondition.IfEntityPermission;
+import org.ofbiz.widget.model.AbstractModelCondition.IfHasPermission;
+import org.ofbiz.widget.model.AbstractModelCondition.IfRegexp;
+import org.ofbiz.widget.model.AbstractModelCondition.IfServicePermission;
+import org.ofbiz.widget.model.AbstractModelCondition.IfValidateMethod;
+import org.ofbiz.widget.model.AbstractModelCondition.Not;
+import org.ofbiz.widget.model.AbstractModelCondition.Or;
+import org.ofbiz.widget.model.AbstractModelCondition.Xor;
+import org.ofbiz.widget.model.ModelScreenCondition.IfEmptySection;
+
+/**
+ * An object that generates XML from widget models.
+ * The generated XML is unformatted - if you want to
+ * "pretty print" the XML, then use a transformer.
+ *
+ */
+public class XmlWidgetConditionVisitor extends XmlAbstractWidgetVisitor 
implements ModelConditionVisitor {
+
+    public XmlWidgetConditionVisitor(Appendable writer) {
+        super(writer);
+    }
+
+    @Override
+    public void visit(And and) throws Exception {
+        writer.append("<and>");
+        visitSubConditions(and.getSubConditions());
+        writer.append("</and>");
+    }
+
+    @Override
+    public void visit(IfCompare ifCompare) throws Exception {
+        writer.append("<if-compare");
+        visitAttribute("field", ifCompare.getFieldAcsr());
+        visitAttribute("operator", ifCompare.getOperator());
+        visitAttribute("value", ifCompare.getValueExdr());
+        visitAttribute("type", ifCompare.getType());
+        visitAttribute("format", ifCompare.getFormatExdr());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(IfCompareField ifCompareField) throws Exception {
+        writer.append("<if-compare-field");
+        visitAttribute("field", ifCompareField.getFieldAcsr());
+        visitAttribute("operator", ifCompareField.getOperator());
+        visitAttribute("to-field", ifCompareField.getToFieldAcsr());
+        visitAttribute("type", ifCompareField.getType());
+        visitAttribute("format", ifCompareField.getFormatExdr());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(IfEmpty ifEmpty) throws Exception {
+        writer.append("<if-empty");
+        visitAttribute("field", ifEmpty.getFieldAcsr());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(IfEmptySection ifEmptySection) throws Exception {
+        writer.append("<if-empty-section");
+        visitAttribute("section-name", ifEmptySection.getSectionExdr());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(IfEntityPermission ifEntityPermission) throws Exception {
+        writer.append("<if-entity-permission");
+        // TODO: Create EntityPermissionChecker visitor
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(IfHasPermission ifHasPermission) throws Exception {
+        writer.append("<if-has-permission");
+        visitAttribute("permission", ifHasPermission.getPermissionExdr());
+        visitAttribute("action", ifHasPermission.getActionExdr());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(IfRegexp ifRegexp) throws Exception {
+        writer.append("<if-regexp");
+        visitAttribute("field", ifRegexp.getFieldAcsr());
+        visitAttribute("expr", ifRegexp.getExprExdr());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(IfServicePermission ifServicePermission) throws 
Exception {
+        writer.append("<if-service-permission");
+        visitAttribute("service-name", ifServicePermission.getServiceExdr());
+        visitAttribute("main-action", ifServicePermission.getActionExdr());
+        visitAttribute("context-map", ifServicePermission.getCtxMapExdr());
+        visitAttribute("resource-description", 
ifServicePermission.getResExdr());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(IfValidateMethod ifValidateMethod) throws Exception {
+        writer.append("<if-validate-method");
+        visitAttribute("field", ifValidateMethod.getFieldAcsr());
+        visitAttribute("method", ifValidateMethod.getMethodExdr());
+        visitAttribute("class", ifValidateMethod.getClassExdr());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(ModelMenuCondition modelMenuCondition) throws Exception {
+        writer.append("<condition");
+        visitAttribute("pass-style", modelMenuCondition.getPassStyleExdr());
+        visitAttribute("disabled-style", 
modelMenuCondition.getFailStyleExdr());
+        writer.append("/>");
+        modelMenuCondition.getCondition().accept(this);
+        ;
+        writer.append("</condition>");
+    }
+
+    @Override
+    public void visit(ModelTreeCondition modelTreeCondition) throws Exception {
+        writer.append("<condition>");
+        modelTreeCondition.getCondition().accept(this);
+        writer.append("</condition>");
+    }
+
+    @Override
+    public void visit(Not not) throws Exception {
+        writer.append("<not>");
+        not.getSubCondition().accept(this);
+        writer.append("</not>");
+    }
+
+    @Override
+    public void visit(Or or) throws Exception {
+        writer.append("<or>");
+        visitSubConditions(or.getSubConditions());
+        writer.append("</or>");
+    }
+
+    @Override
+    public void visit(Xor xor) throws Exception {
+        writer.append("<xor>");
+        visitSubConditions(xor.getSubConditions());
+        writer.append("</xor>");
+    }
+
+    private void visitSubConditions(Collection<ModelCondition> subConditions) 
throws Exception {
+        for (ModelCondition subCondition : subConditions) {
+            subCondition.accept(this);
+        }
+    }
+}


Reply via email to