svn commit: r1652638 [6/6] - in /ofbiz/trunk/framework/widget: dtd/ src/org/ofbiz/widget/ src/org/ofbiz/widget/artifact/ src/org/ofbiz/widget/fo/ src/org/ofbiz/widget/form/ src/org/ofbiz/widget/html/ src/org/ofbiz/widget/menu/ src/org/ofbiz/widget/scre...

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

svn commit: r1652638 [6/6] - in /ofbiz/trunk/framework/widget: dtd/ src/org/ofbiz/widget/ src/org/ofbiz/widget/artifact/ src/org/ofbiz/widget/fo/ src/org/ofbiz/widget/form/ src/org/ofbiz/widget/html/ src/org/ofbiz/widget/menu/ src/org/ofbiz/widget/scre...

adrianc
Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/AbstractWidgetVisitor.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/AbstractWidgetVisitor.java?rev=1652638&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/AbstractWidgetVisitor.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/AbstractWidgetVisitor.java Sat Jan 17 16:47:23 2015
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * 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.xml;
+
+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.ModelWidget;
+import org.ofbiz.widget.CommonWidgetModels.AutoEntityParameters;
+import org.ofbiz.widget.CommonWidgetModels.AutoServiceParameters;
+import org.ofbiz.widget.CommonWidgetModels.Image;
+import org.ofbiz.widget.CommonWidgetModels.Link;
+import org.ofbiz.widget.CommonWidgetModels.Parameter;
+
+/**
+ * Abstract XML widget visitor.
+ *
+ */
+public abstract class AbstractWidgetVisitor {
+
+    protected final Appendable writer;
+
+    public AbstractWidgetVisitor(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/xml/XmlWidgetActionVisitor.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetActionVisitor.java?rev=1652638&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetActionVisitor.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetActionVisitor.java Sat Jan 17 16:47:23 2015
@@ -0,0 +1,211 @@
+/*******************************************************************************
+ * 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.xml;
+
+import org.ofbiz.widget.AbstractModelAction.EntityAnd;
+import org.ofbiz.widget.AbstractModelAction.EntityCondition;
+import org.ofbiz.widget.AbstractModelAction.EntityOne;
+import org.ofbiz.widget.AbstractModelAction.GetRelated;
+import org.ofbiz.widget.AbstractModelAction.GetRelatedOne;
+import org.ofbiz.widget.AbstractModelAction.PropertyMap;
+import org.ofbiz.widget.AbstractModelAction.PropertyToField;
+import org.ofbiz.widget.AbstractModelAction.Script;
+import org.ofbiz.widget.AbstractModelAction.Service;
+import org.ofbiz.widget.AbstractModelAction.SetField;
+import org.ofbiz.widget.ModelActionVisitor;
+import org.ofbiz.widget.form.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 AbstractWidgetVisitor 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.tree.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.tree.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.tree.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.form.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.tree.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.menu.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/xml/XmlWidgetConditionVisitor.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetConditionVisitor.java?rev=1652638&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetConditionVisitor.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetConditionVisitor.java Sat Jan 17 16:47:23 2015
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * 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.xml;
+
+import java.util.Collection;
+
+import org.ofbiz.widget.AbstractModelCondition.And;
+import org.ofbiz.widget.AbstractModelCondition.IfCompare;
+import org.ofbiz.widget.AbstractModelCondition.IfCompareField;
+import org.ofbiz.widget.AbstractModelCondition.IfEmpty;
+import org.ofbiz.widget.AbstractModelCondition.IfEntityPermission;
+import org.ofbiz.widget.AbstractModelCondition.IfHasPermission;
+import org.ofbiz.widget.AbstractModelCondition.IfRegexp;
+import org.ofbiz.widget.AbstractModelCondition.IfServicePermission;
+import org.ofbiz.widget.AbstractModelCondition.IfValidateMethod;
+import org.ofbiz.widget.AbstractModelCondition.Not;
+import org.ofbiz.widget.AbstractModelCondition.Or;
+import org.ofbiz.widget.AbstractModelCondition.Xor;
+import org.ofbiz.widget.ModelCondition;
+import org.ofbiz.widget.ModelConditionVisitor;
+import org.ofbiz.widget.menu.ModelMenuCondition;
+import org.ofbiz.widget.screen.ModelScreenCondition.IfEmptySection;
+import org.ofbiz.widget.tree.ModelTreeCondition;
+
+/**
+ * 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 AbstractWidgetVisitor 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);
+        }
+    }
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetFieldVisitor.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetFieldVisitor.java?rev=1652638&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetFieldVisitor.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetFieldVisitor.java Sat Jan 17 16:47:23 2015
@@ -0,0 +1,333 @@
+/*******************************************************************************
+ * 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.xml;
+
+import java.util.Collection;
+
+import org.ofbiz.widget.ModelFieldVisitor;
+import org.ofbiz.widget.CommonWidgetModels.Link;
+import org.ofbiz.widget.form.ModelFormField.*;
+import org.ofbiz.widget.form.*;
+
+/**
+ * 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 XmlWidgetFieldVisitor extends AbstractWidgetVisitor implements ModelFieldVisitor {
+
+    public XmlWidgetFieldVisitor(Appendable writer) {
+        super(writer);
+    }
+
+    @Override
+    public void visit(CheckField checkField) throws Exception {
+        visitModelField(checkField.getModelFormField());
+        writer.append("<check");
+        visitAttribute("all-checked", checkField.getAllChecked());
+        visitFieldInfoWithOptions(checkField);
+        writer.append("</check></field>");
+    }
+
+    @Override
+    public void visit(ContainerField containerField) throws Exception {
+        visitModelField(containerField.getModelFormField());
+        writer.append("<container/></field>");
+    }
+
+    @Override
+    public void visit(DateFindField dateTimeField) throws Exception {
+        visitModelField(dateTimeField.getModelFormField());
+        writer.append("<date-find");
+        visitDateTimeFieldAttrs(dateTimeField);
+        visitAttribute("default-option-from", dateTimeField.getDefaultOptionFrom());
+        visitAttribute("default-option-thru", dateTimeField.getDefaultOptionThru());
+        writer.append("/></field>");
+    }
+
+    @Override
+    public void visit(DateTimeField dateTimeField) throws Exception {
+        visitModelField(dateTimeField.getModelFormField());
+        writer.append("<date-time");
+        visitDateTimeFieldAttrs(dateTimeField);
+        writer.append("/></field>");
+    }
+
+    @Override
+    public void visit(DisplayEntityField displayField) throws Exception {
+        visitModelField(displayField.getModelFormField());
+        writer.append("<display-entity");
+        visitDisplayFieldAttrs(displayField);
+        visitAttribute("cache", displayField.getCache());
+        visitAttribute("entity-name", displayField.getEntityName());
+        visitAttribute("key-field-name", displayField.getKeyFieldName());
+        writer.append(">");
+        visitInPlaceEditor(displayField.getInPlaceEditor());
+        visitSubHyperlink(displayField.getSubHyperlink());
+        writer.append("</display-entity></field>");
+    }
+
+    @Override
+    public void visit(DisplayField displayField) throws Exception {
+        visitModelField(displayField.getModelFormField());
+        writer.append("<display");
+        visitDisplayFieldAttrs(displayField);
+        writer.append(">");
+        visitInPlaceEditor(displayField.getInPlaceEditor());
+        writer.append("</display></field>");
+    }
+
+    @Override
+    public void visit(DropDownField dropDownField) throws Exception {
+        visitModelField(dropDownField.getModelFormField());
+        writer.append("<drop-down");
+        visitAttribute("allow-empty", dropDownField.getAllowEmpty());
+        visitAttribute("allow-multiple", dropDownField.getAllowMultiple());
+        visitAttribute("current", dropDownField.getCurrent());
+        visitAttribute("current-description", dropDownField.getCurrentDescription());
+        visitAttribute("other-field-size", dropDownField.getOtherFieldSize());
+        visitAttribute("size", dropDownField.getSize());
+        visitAttribute("text-size", dropDownField.getTextSize());
+        visitFieldInfoWithOptions(dropDownField);
+        visitAutoComplete(dropDownField.getAutoComplete());
+        visitSubHyperlink(dropDownField.getSubHyperlink());
+        writer.append("</drop-down></field>");
+    }
+
+    @Override
+    public void visit(FileField textField) throws Exception {
+        visitModelField(textField.getModelFormField());
+        writer.append("<file");
+        visitTextFieldAttrs(textField);
+        writer.append(">");
+        visitSubHyperlink(textField.getSubHyperlink());
+        writer.append("</file></field>");
+    }
+
+    @Override
+    public void visit(HiddenField hiddenField) throws Exception {
+        visitModelField(hiddenField.getModelFormField());
+        writer.append("<hidden");
+        visitAttribute("value", hiddenField.getValue());
+        writer.append("/></field>");
+    }
+
+    @Override
+    public void visit(HyperlinkField hyperlinkField) throws Exception {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void visit(IgnoredField ignoredField) throws Exception {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void visit(ImageField imageField) throws Exception {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void visit(LookupField textField) throws Exception {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void visit(PasswordField textField) throws Exception {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void visit(RadioField radioField) throws Exception {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void visit(RangeFindField textField) throws Exception {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void visit(ResetField resetField) throws Exception {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void visit(SubmitField submitField) throws Exception {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void visit(TextareaField textareaField) throws Exception {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void visit(TextField textField) throws Exception {
+        visitModelField(textField.getModelFormField());
+        writer.append("<text");
+        visitTextFieldAttrs(textField);
+        writer.append(">");
+        visitSubHyperlink(textField.getSubHyperlink());
+        writer.append("</text></field>");
+    }
+
+    @Override
+    public void visit(TextFindField textField) throws Exception {
+        visitModelField(textField.getModelFormField());
+        writer.append("<text-find");
+        visitTextFieldAttrs(textField);
+        visitAttribute("default-option", textField.getDefaultOption());
+        visitAttribute("hide-options", textField.getHideOptions());
+        visitAttribute("ignore-case", textField.getIgnoreCase());
+        writer.append(">");
+        visitSubHyperlink(textField.getSubHyperlink());
+        writer.append("</text-find></field>");
+    }
+
+    private void visitTextFieldAttrs(TextField field) throws Exception {
+        visitAttribute("client-autocomplete-field", field.getClientAutocompleteField());
+        visitAttribute("default-value", field.getDefaultValue());
+        visitAttribute("disabled", field.getDisabled());
+        visitAttribute("mask", field.getMask());
+        visitAttribute("maxlength", field.getMaxlength());
+        visitAttribute("placeholder", field.getPlaceholder());
+        visitAttribute("read-only", field.getReadonly());
+        visitAttribute("size", field.getSize());
+    }
+
+    private void visitDisplayFieldAttrs(DisplayField field) throws Exception {
+        visitAttribute("also-hidden", field.getAlsoHidden());
+        visitAttribute("currency", field.getCurrency());
+        visitAttribute("date", field.getDate());
+        visitAttribute("default-value", field.getDefaultValue());
+        visitAttribute("description", field.getDescription());
+        visitAttribute("image-location", field.getImageLocation());
+        visitAttribute("size", field.getSize());
+        visitAttribute("type", field.getType());
+    }
+
+    private void visitDateTimeFieldAttrs(DateTimeField field) throws Exception {
+        visitAttribute("default-value", field.getDefaultValue());
+        visitAttribute("type", field.getType());
+        visitAttribute("input-method", field.getInputMethod());
+        visitAttribute("clock", field.getClock());
+        visitAttribute("mask", field.getMask());
+        visitAttribute("step", field.getStep());
+    }
+
+    private void visitFieldInfoWithOptions(FieldInfoWithOptions fieldInfo) throws Exception {
+        visitAttribute("no-current-selected-key", fieldInfo.getNoCurrentSelectedKey());
+        writer.append(">");
+        // TODO: Options
+    }
+
+    private void visitModelField(ModelFormField modelField) throws Exception {
+        writer.append("<field");
+        visitAttribute("name", modelField.getName());
+        visitAttribute("action", modelField.getAction());
+        visitAttribute("attribute-name", modelField.getAttributeName());
+        visitAttribute("encode-output", modelField.getEncodeOutput());
+        visitAttribute("entity-name", modelField.getEntityName());
+        visitAttribute("entry-name", modelField.getEntryName());
+        visitAttribute("event", modelField.getEvent());
+        visitAttribute("field-name", modelField.getFieldName());
+        visitAttribute("header-link", modelField.getHeaderLink());
+        visitAttribute("header-link-style", modelField.getHeaderLinkStyle());
+        visitAttribute("id-name", modelField.getIdName());
+        visitAttribute("map-name", modelField.getMapName());
+        visitAttribute("parameter-name", modelField.getParameterName());
+        visitAttribute("position", modelField.getPosition());
+        visitAttribute("red-when", modelField.getRedWhen());
+        visitAttribute("required-field", modelField.getRequiredField());
+        visitAttribute("required-field-style", modelField.getRequiredFieldStyle());
+        visitAttribute("separate-column", modelField.getSeparateColumn());
+        visitAttribute("service-name", modelField.getServiceName());
+        visitAttribute("sort-field", modelField.getSortField());
+        visitAttribute("sort-field-asc-style", modelField.getSortFieldAscStyle());
+        visitAttribute("sort-field-desc-style", modelField.getSortFieldDescStyle());
+        visitAttribute("sort-field-help-text", modelField.getSortFieldHelpText());
+        visitAttribute("sort-field-style", modelField.getSortFieldStyle());
+        visitAttribute("title", modelField.getTitle());
+        visitAttribute("title-area-style", modelField.getTitleAreaStyle());
+        visitAttribute("title-style", modelField.getTitleStyle());
+        visitAttribute("tooltip", modelField.getTooltip());
+        visitAttribute("tooltip-style", modelField.getTooltipStyle());
+        visitAttribute("use-when", modelField.getUseWhen());
+        visitAttribute("widget-area-style", modelField.getWidgetAreaStyle());
+        visitAttribute("widget-style", modelField.getWidgetStyle());
+        writer.append(">");
+        visitUpdateAreas(modelField.getOnChangeUpdateAreas());
+        visitUpdateAreas(modelField.getOnClickUpdateAreas());
+    }
+
+    private void visitSubHyperlink(SubHyperlink hyperlink) throws Exception {
+        if (hyperlink != null) {
+            writer.append("<sub-hyperlink");
+            Link link = hyperlink.getLink();
+            visitLinkAttributes(link);
+            visitAttribute("description", hyperlink.getDescription());
+            visitAttribute("use-when", hyperlink.getUseWhen());
+            if (link.getImage() != null || link.getAutoEntityParameters() != null || link.getAutoServiceParameters() != null) {
+                writer.append(">");
+                visitImage(link.getImage());
+                visitAutoEntityParameters(link.getAutoEntityParameters());
+                visitAutoServiceParameters(link.getAutoServiceParameters());
+                writer.append("</sub-hyperlink>");
+            } else {
+                writer.append("/>");
+            }
+        }
+    }
+
+    private void visitAutoComplete(AutoComplete autoComplete) throws Exception {
+        // TODO: Finish implementation
+        
+    }
+
+    private void visitInPlaceEditor(InPlaceEditor editor) throws Exception {
+        // TODO: Finish implementation
+        
+    }
+
+    private void visitUpdateAreas(Collection<ModelForm.UpdateArea> updateAreas) throws Exception {
+        for (ModelForm.UpdateArea updateArea : updateAreas) {
+            writer.append("<on-field-event-update-area");
+            visitAttribute("event-type", updateArea.getEventType());
+            visitAttribute("area-id", updateArea.getAreaId());
+            visitAttribute("area-target", updateArea.getAreaTarget());
+            writer.append(">");
+            visitAutoEntityParameters(updateArea.getAutoEntityParameters());
+            visitAutoServiceParameters(updateArea.getAutoServiceParameters());
+            visitParameters(updateArea.getParameterList());
+            writer.append("</on-field-event-update-area>");
+        }
+    }
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetVisitor.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetVisitor.java?rev=1652638&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetVisitor.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetVisitor.java Sat Jan 17 16:47:23 2015
@@ -0,0 +1,657 @@
+/*******************************************************************************
+ * 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.xml;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.ofbiz.widget.ModelAction;
+import org.ofbiz.widget.ModelActionVisitor;
+import org.ofbiz.widget.ModelConditionVisitor;
+import org.ofbiz.widget.ModelFieldVisitor;
+import org.ofbiz.widget.ModelWidget;
+import org.ofbiz.widget.ModelWidgetVisitor;
+import org.ofbiz.widget.form.ModelForm;
+import org.ofbiz.widget.form.ModelFormField;
+import org.ofbiz.widget.menu.ModelMenu;
+import org.ofbiz.widget.menu.ModelMenuItem;
+import org.ofbiz.widget.screen.HtmlWidget;
+import org.ofbiz.widget.screen.HtmlWidget.HtmlTemplate;
+import org.ofbiz.widget.screen.HtmlWidget.HtmlTemplateDecorator;
+import org.ofbiz.widget.screen.HtmlWidget.HtmlTemplateDecoratorSection;
+import org.ofbiz.widget.screen.IterateSectionWidget;
+import org.ofbiz.widget.screen.ModelScreen;
+import org.ofbiz.widget.screen.ModelScreenWidget;
+import org.ofbiz.widget.screen.ModelScreenWidget.Column;
+import org.ofbiz.widget.screen.ModelScreenWidget.ColumnContainer;
+import org.ofbiz.widget.screen.ModelScreenWidget.Container;
+import org.ofbiz.widget.screen.ModelScreenWidget.Content;
+import org.ofbiz.widget.screen.ModelScreenWidget.DecoratorScreen;
+import org.ofbiz.widget.screen.ModelScreenWidget.DecoratorSection;
+import org.ofbiz.widget.screen.ModelScreenWidget.DecoratorSectionInclude;
+import org.ofbiz.widget.screen.ModelScreenWidget.Form;
+import org.ofbiz.widget.screen.ModelScreenWidget.HorizontalSeparator;
+import org.ofbiz.widget.screen.ModelScreenWidget.IncludeScreen;
+import org.ofbiz.widget.screen.ModelScreenWidget.Label;
+import org.ofbiz.widget.screen.ModelScreenWidget.Menu;
+import org.ofbiz.widget.screen.ModelScreenWidget.PlatformSpecific;
+import org.ofbiz.widget.screen.ModelScreenWidget.PortalPage;
+import org.ofbiz.widget.screen.ModelScreenWidget.ScreenImage;
+import org.ofbiz.widget.screen.ModelScreenWidget.ScreenLink;
+import org.ofbiz.widget.screen.ModelScreenWidget.Screenlet;
+import org.ofbiz.widget.screen.ModelScreenWidget.Section;
+import org.ofbiz.widget.screen.ModelScreenWidget.Tree;
+import org.ofbiz.widget.tree.ModelTree;
+import org.ofbiz.widget.tree.ModelTree.ModelNode;
+import org.ofbiz.widget.tree.ModelTree.ModelNode.ModelSubNode;
+
+/**
+ * An object that generates an XML representation from widget models.
+ * The generated XML is unformatted - if you want to
+ * "pretty print" the XML, then use a transformer.
+ *
+ */
+public class XmlWidgetVisitor extends AbstractWidgetVisitor implements ModelWidgetVisitor {
+
+    private final ModelFieldVisitor fieldVisitor;
+    private final ModelActionVisitor actionVisitor;
+    private final ModelConditionVisitor conditionVisitor;
+
+    public XmlWidgetVisitor(Appendable writer) {
+        super(writer);
+        this.fieldVisitor = new XmlWidgetFieldVisitor(writer);
+        this.actionVisitor = new XmlWidgetActionVisitor(writer);
+        this.conditionVisitor = new XmlWidgetConditionVisitor(writer);
+    }
+
+    @Override
+    public void visit(Column column) throws Exception {
+        writer.append("<column");
+        visitModelWidget(column);
+        visitAttribute("id", column.getIdExdr());
+        visitAttribute("style", column.getStyleExdr());
+        writer.append(">");
+        visitSubWidgets(column.getSubWidgets());
+        writer.append("</column>");
+    }
+
+    @Override
+    public void visit(ColumnContainer columnContainer) throws Exception {
+        writer.append("<column-container");
+        visitModelWidget(columnContainer);
+        visitAttribute("id", columnContainer.getIdExdr());
+        visitAttribute("style", columnContainer.getStyleExdr());
+        writer.append(">");
+        visitSubWidgets(columnContainer.getColumns());
+        writer.append("</column-container>");
+    }
+
+    @Override
+    public void visit(Container container) throws Exception {
+        writer.append("<container");
+        visitModelWidget(container);
+        visitAttribute("auto-update-interval", container.getAutoUpdateInterval());
+        visitAttribute("auto-update-target", container.getAutoUpdateTargetExdr());
+        visitAttribute("id", container.getIdExdr());
+        visitAttribute("style", container.getStyleExdr());
+        writer.append(">");
+        visitSubWidgets(container.getSubWidgets());
+        writer.append("</container>");
+    }
+
+    @Override
+    public void visit(Content content) throws Exception {
+        writer.append("<content");
+        visitModelWidget(content);
+        visitAttribute("border", content.getBorder());
+        visitAttribute("content-id", content.getContentId());
+        visitAttribute("dataresource-id", content.getDataResourceId());
+        visitAttribute("edit-container-style", content.getEditContainerStyle());
+        visitAttribute("edit-request", content.getEditRequest());
+        visitAttribute("enable-edit-name", content.getEnableEditName());
+        visitAttribute("height", content.getHeight());
+        visitAttribute("width", content.getWidth());
+        visitAttribute("xml-escape", content.xmlEscape());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(DecoratorScreen decoratorScreen) throws Exception {
+        writer.append("<decorator-screen");
+        visitModelWidget(decoratorScreen);
+        visitAttribute("location", decoratorScreen.getLocationExdr());
+        writer.append(">");
+        visitSubWidgets(decoratorScreen.getSectionMap().values());
+        writer.append("</decorator-screen>");
+    }
+
+    @Override
+    public void visit(DecoratorSection decoratorSection) throws Exception {
+        writer.append("<decorator-section");
+        visitModelWidget(decoratorSection);
+        writer.append(">");
+        visitSubWidgets(decoratorSection.getSubWidgets());
+        writer.append("</decorator-screen>");
+    }
+
+    @Override
+    public void visit(DecoratorSectionInclude decoratorSectionInclude) throws Exception {
+        writer.append("<decorator-section-include");
+        visitModelWidget(decoratorSectionInclude);
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(Form form) throws Exception {
+        writer.append("<include-form");
+        visitModelWidget(form);
+        visitAttribute("location", form.getLocationExdr());
+        visitAttribute("share-scope", form.getShareScopeExdr());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(HorizontalSeparator horizontalSeparator) throws Exception {
+        writer.append("<horizontal-separator");
+        visitModelWidget(horizontalSeparator);
+        visitAttribute("id", horizontalSeparator.getIdExdr());
+        visitAttribute("style", horizontalSeparator.getStyleExdr());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(HtmlTemplate htmlTemplate) throws Exception {
+        writer.append("<html-template");
+        visitModelWidget(htmlTemplate);
+        visitAttribute("location", htmlTemplate.getLocationExdr());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(HtmlTemplateDecorator htmlTemplateDecorator) throws Exception {
+        writer.append("<html-template-decorator");
+        visitModelWidget(htmlTemplateDecorator);
+        visitAttribute("location", htmlTemplateDecorator.getLocationExdr());
+        writer.append(">");
+        visitSubWidgets(htmlTemplateDecorator.getSectionMap().values());
+        writer.append("</html-template-decorator>");
+    }
+
+    @Override
+    public void visit(HtmlTemplateDecoratorSection htmlTemplateDecoratorSection) throws Exception {
+        writer.append("<html-template-decorator-section");
+        visitModelWidget(htmlTemplateDecoratorSection);
+        writer.append(">");
+        visitSubWidgets(htmlTemplateDecoratorSection.getSubWidgets());
+        writer.append("</html-template-decorator-section>");
+    }
+
+    @Override
+    public void visit(HtmlWidget htmlWidget) throws Exception {
+        visitSubWidgets(htmlWidget.getSubWidgets());
+    }
+
+    @Override
+    public void visit(IncludeScreen includeScreen) throws Exception {
+        writer.append("<include-screen");
+        visitModelWidget(includeScreen);
+        visitAttribute("location", includeScreen.getLocationExdr());
+        visitAttribute("share-scope", includeScreen.getShareScopeExdr());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(IterateSectionWidget iterateSectionWidget) throws Exception {
+        writer.append("<iterate-section");
+        visitModelWidget(iterateSectionWidget);
+        visitAttribute("entry", iterateSectionWidget.getEntryNameExdr());
+        visitAttribute("key", iterateSectionWidget.getKeyNameExdr());
+        visitAttribute("list", iterateSectionWidget.getListNameExdr());
+        visitAttribute("paginate", iterateSectionWidget.getPaginate());
+        visitAttribute("paginate-target", iterateSectionWidget.getPaginateTarget());
+        visitAttribute("view-size", iterateSectionWidget.getViewSize());
+        writer.append(">");
+        visitSubWidgets(iterateSectionWidget.getSectionList());
+        writer.append("</iterate-section>");
+    }
+
+    @Override
+    public void visit(Label label) throws Exception {
+        writer.append("<label");
+        visitModelWidget(label);
+        visitAttribute("id", label.getIdExdr());
+        visitAttribute("style", label.getStyleExdr());
+        writer.append(">");
+        writer.append(label.getTextExdr().getOriginal());
+        writer.append("</label>");
+    }
+
+    @Override
+    public void visit(Menu menu) throws Exception {
+        writer.append("<include-menu");
+        visitModelWidget(menu);
+        visitAttribute("location", menu.getLocationExdr());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(ModelForm modelForm) throws Exception {
+        writer.append("<form");
+        visitModelWidget(modelForm);
+        if (modelForm.getParentModelForm() != null) {
+            visitAttribute("extends", modelForm.getParentModelForm().getName());
+            visitAttribute("extends-resource", modelForm.getParentModelForm().getFormLocation());
+        }
+        visitAttribute("view-size", modelForm.getDefaultViewSize());
+        visitAttribute("type", modelForm.getType());
+        visitAttribute("target", modelForm.getTarget());
+        visitAttribute("id", modelForm.getContainerId());
+        visitAttribute("style", modelForm.getContainerStyle());
+        visitAttribute("title", modelForm.getTitle());
+        visitAttribute("tooltip", modelForm.getTooltip());
+        visitAttribute("list-name", modelForm.getListName());
+        visitAttribute("list-entry-name", modelForm.getListEntryName());
+        visitAttribute("default-entity-name", modelForm.getDefaultEntityName());
+        visitAttribute("default-service-name", modelForm.getDefaultServiceName());
+        visitAttribute("form-title-area-style", modelForm.getFormTitleAreaStyle());
+        visitAttribute("form-widget-area-style", modelForm.getFormWidgetAreaStyle());
+        visitAttribute("default-title-area-style", modelForm.getDefaultTitleAreaStyle());
+        visitAttribute("default-widget-area-style", modelForm.getDefaultWidgetAreaStyle());
+        visitAttribute("odd-row-style", modelForm.getOddRowStyle());
+        visitAttribute("even-row-style", modelForm.getEvenRowStyle());
+        visitAttribute("default-table-style", modelForm.getDefaultTableStyle());
+        visitAttribute("header-row-style", modelForm.getHeaderRowStyle());
+        visitAttribute("default-title-style", modelForm.getDefaultTitleStyle());
+        visitAttribute("default-widget-style", modelForm.getDefaultWidgetStyle());
+        visitAttribute("default-tooltip-style", modelForm.getDefaultTooltipStyle());
+        visitAttribute("item-index-separator", modelForm.getItemIndexSeparator());
+        visitAttribute("separate-columns", modelForm.getSeparateColumns());
+        visitAttribute("group-columns", modelForm.getGroupColumns());
+        visitAttribute("target-type", modelForm.getTargetType());
+        visitAttribute("default-map-name", modelForm.getDefaultMapName());
+        visitAttribute("target-window", modelForm.getTargetWindow());
+        visitAttribute("hide-header", modelForm.getHideHeader());
+        visitAttribute("client-autocomplete-fields", modelForm.getClientAutocompleteFields());
+        visitAttribute("paginate-target", modelForm.getPaginateTarget());
+        visitAttribute("sort-field-parameter-name", modelForm.getSortFieldParameterName());
+        visitAttribute("default-required-field-style", modelForm.getDefaultRequiredFieldStyle());
+        visitAttribute("default-sort-field-style", modelForm.getDefaultSortFieldStyle());
+        visitAttribute("default-sort-field-asc-style", modelForm.getDefaultSortFieldAscStyle());
+        visitAttribute("default-sort-field-desc-style", modelForm.getDefaultSortFieldDescStyle());
+        visitAttribute("paginate-target-anchor", modelForm.getPaginateTargetAnchor());
+        visitAttribute("paginate-index-field", modelForm.getPaginateIndexField());
+        visitAttribute("paginate-size-field", modelForm.getPaginateSizeField());
+        visitAttribute("override-list-size", modelForm.getOverrideListSize());
+        visitAttribute("paginate-first-label", modelForm.getPaginateFirstLabel());
+        visitAttribute("paginate-previous-label", modelForm.getPaginatePreviousLabel());
+        visitAttribute("paginate-next-label", modelForm.getPaginateNextLabel());
+        visitAttribute("paginate-last-label", modelForm.getPaginateLastLabel());
+        visitAttribute("paginate-viewsize-label", modelForm.getPaginateViewSizeLabel());
+        visitAttribute("paginate-style", modelForm.getPaginateStyle());
+        visitAttribute("paginate", modelForm.getPaginate());
+        visitAttribute("skip-start", modelForm.getSkipStart());
+        visitAttribute("skip-end", modelForm.getSkipEnd());
+        visitAttribute("use-row-submit", modelForm.getUseRowSubmit());
+        visitAttribute("row-count", modelForm.getRowCount());
+        visitAttribute("focus-field-name", modelForm.getFocusFieldName());
+        writer.append(">");
+        if (!modelForm.getActions().isEmpty()) {
+            writer.append("<actions>");
+            visitActions(modelForm.getActions());
+            writer.append("</actions>");
+        }
+        if (!modelForm.getRowActions().isEmpty()) {
+            writer.append("<row-actions>");
+            visitActions(modelForm.getRowActions());
+            writer.append("</row-actions>");
+        }
+        for (ModelForm.AltRowStyle rowStyle : modelForm.getAltRowStyles()) {
+            writer.append("<alt-row-style");
+            visitAttribute("use-when", rowStyle.useWhen);
+            visitAttribute("style", rowStyle.style);
+            writer.append("/>");
+        }
+        for (ModelForm.AltTarget target : modelForm.getAltTargets()) {
+            writer.append("<alt-target");
+            visitAttribute("use-when", target.useWhen);
+            visitAttribute("target", target.targetExdr);
+            writer.append("/>");
+        }
+        for (ModelForm.AutoFieldsService service : modelForm.getAutoFieldsServices()) {
+            writer.append("<auto-fields-service");
+            visitAttribute("service-name", service.serviceName);
+            visitAttribute("map-name", service.mapName);
+            visitAttribute("default-field-type", service.defaultFieldType);
+            visitAttribute("default-position", service.defaultPosition);
+            writer.append("/>");
+        }
+        for (ModelForm.AutoFieldsEntity entity : modelForm.getAutoFieldsEntities()) {
+            writer.append("<auto-fields-entity");
+            visitAttribute("entity-name", entity.entityName);
+            visitAttribute("map-name", entity.mapName);
+            visitAttribute("default-field-type", entity.defaultFieldType);
+            visitAttribute("default-position", entity.defaultPosition);
+            writer.append("/>");
+        }
+        for (ModelFormField field : modelForm.getFieldList()) {
+            field.getFieldInfo().accept(fieldVisitor);
+        }
+        visitUpdateAreas(modelForm.getOnPaginateUpdateAreas());
+        visitUpdateAreas(modelForm.getOnSortColumnUpdateAreas());
+        visitUpdateAreas(modelForm.getOnSubmitUpdateAreas());
+        writer.append("</form>");
+    }
+
+    @Override
+    public void visit(ModelMenu modelMenu) throws Exception {
+        writer.append("<menu");
+        visitModelWidget(modelMenu);
+        if (modelMenu.getParentMenu() != null) {
+            visitAttribute("extends", modelMenu.getParentMenu().getName());
+            visitAttribute("extends-resource", modelMenu.getParentMenu().getMenuLocation());
+        }
+        visitAttribute("type", modelMenu.getType());
+        visitAttribute("target", modelMenu.getTarget());
+        visitAttribute("id", modelMenu.getId());
+        visitAttribute("title", modelMenu.getTitle());
+        visitAttribute("tooltip", modelMenu.getTooltip());
+        visitAttribute("default-entity-name", modelMenu.getDefaultEntityName());
+        visitAttribute("default-title-style", modelMenu.getDefaultTitleStyle());
+        visitAttribute("default-selected-style", modelMenu.getDefaultSelectedStyle());
+        visitAttribute("default-widget-style", modelMenu.getDefaultWidgetStyle());
+        visitAttribute("default-tooltip-style", modelMenu.getDefaultTooltipStyle());
+        visitAttribute("default-menu-item-name", modelMenu.getDefaultMenuItemName());
+        visitAttribute("default-permission-operation", modelMenu.getDefaultPermissionOperation());
+        visitAttribute("default-permission-entity-action", modelMenu.getDefaultPermissionEntityAction());
+        visitAttribute("default-associated-content-id", modelMenu.getDefaultAssociatedContentId());
+        visitAttribute("orientation", modelMenu.getOrientation());
+        visitAttribute("menu-width", modelMenu.getMenuWidth());
+        visitAttribute("default-cell-width", modelMenu.getDefaultCellWidth());
+        visitAttribute("default-hide-if-selected", modelMenu.getDefaultHideIfSelected());
+        visitAttribute("default-disabled-title-style", modelMenu.getDefaultDisabledTitleStyle());
+        visitAttribute("selected-menuitem-context-field-name", modelMenu.getSelectedMenuItemContextFieldName());
+        visitAttribute("menu-container-style", modelMenu.getMenuContainerStyleExdr());
+        visitAttribute("default-align", modelMenu.getDefaultAlign());
+        visitAttribute("default-align-style", modelMenu.getDefaultAlignStyle());
+        visitAttribute("fill-style", modelMenu.getFillStyle());
+        visitAttribute("extra-index", modelMenu.getExtraIndex());
+        writer.append(">");
+        if (!modelMenu.getActions().isEmpty()) {
+            writer.append("<actions>");
+            visitActions(modelMenu.getActions());
+            writer.append("</actions>");
+        }
+        for (ModelMenuItem menuItem : modelMenu.getMenuItemList()) {
+            menuItem.accept(this);;
+        }
+        writer.append("</menu>");
+    }
+
+    @Override
+    public void visit(ModelMenuItem modelMenuItem) throws Exception {
+        writer.append("<menu-item");
+        visitModelWidget(modelMenuItem);
+        visitAttribute("entity-name", modelMenuItem.getEntityName());
+        visitAttribute("title", modelMenuItem.getTitle());
+        visitAttribute("tooltip", modelMenuItem.getTooltip());
+        visitAttribute("parent-portal-page-value", modelMenuItem.getParentPortalPageId());
+        visitAttribute("title-style", modelMenuItem.getTitleStyle());
+        visitAttribute("disabled-title-style", modelMenuItem.getDisabledTitleStyle());
+        visitAttribute("widget-style", modelMenuItem.getWidgetStyle());
+        visitAttribute("tooltip-style", modelMenuItem.getTooltipStyle());
+        visitAttribute("selected-style", modelMenuItem.getSelectedStyle());
+        visitAttribute("hide-if-selected", modelMenuItem.getHideIfSelected());
+        visitAttribute("disable-if-empty", modelMenuItem.getDisableIfEmpty());
+        visitAttribute("align", modelMenuItem.getAlign());
+        visitAttribute("align-style", modelMenuItem.getAlignStyle());
+        visitAttribute("position", modelMenuItem.getPosition());
+        visitAttribute("associated-content-id", modelMenuItem.getAssociatedContentId());
+        visitAttribute("cell-width", modelMenuItem.getCellWidth());
+        visitAttribute("sub-menu", modelMenuItem.getSubMenu());
+        writer.append(">");
+        if (modelMenuItem.getCondition() != null) {
+            modelMenuItem.getCondition().getCondition().accept(conditionVisitor);
+        }
+        if (!modelMenuItem.getActions().isEmpty()) {
+            writer.append("<actions>");
+            visitActions(modelMenuItem.getActions());
+            writer.append("</actions>");
+        }
+        visitLink(modelMenuItem.getLink().getLink());
+        for (ModelMenuItem menuItem : modelMenuItem.getMenuItemList()) {
+            menuItem.accept(this);;
+        }
+        writer.append("</menu-item>");
+    }
+
+    @Override
+    public void visit(ModelNode modelNode) throws Exception {
+        writer.append("<node");
+        visitModelWidget(modelNode);
+        visitAttribute("expand-collapse-style", modelNode.getExpandCollapseStyle());
+        visitAttribute("wrap-style", modelNode.getWrapStyleExdr());
+        visitAttribute("render-style", modelNode.getRenderStyle());
+        visitAttribute("entry-name", modelNode.getEntryName());
+        visitAttribute("entity-name", modelNode.getEntityName());
+        visitAttribute("join-field-name", modelNode.getPkName());
+        writer.append(">");
+        if (modelNode.getCondition() != null) {
+            modelNode.getCondition().getCondition().accept(conditionVisitor);
+        }
+        if (!modelNode.getActions().isEmpty()) {
+            writer.append("<actions>");
+            visitActions(modelNode.getActions());
+            writer.append("</actions>");
+        }
+        if (!modelNode.getScreenNameExdr().isEmpty()) {
+            writer.append("<include-screen");
+            visitAttribute("name", modelNode.getScreenNameExdr());
+            visitAttribute("location", modelNode.getScreenLocationExdr());
+            visitAttribute("share-scope", modelNode.getShareScope());
+            visitAttribute("name", modelNode.getScreenNameExdr());
+            writer.append("/>");
+        }
+        if (modelNode.getLabel() != null) {
+            ModelNode.Label label = modelNode.getLabel();
+            writer.append("<label");
+            visitAttribute("id", label.getIdExdr());
+            visitAttribute("style", label.getStyleExdr());
+            writer.append(">");
+            writer.append(label.getTextExdr().getOriginal());
+            writer.append("</label>");
+        }
+        if (modelNode.getLink() != null) {
+            ModelNode.Link link = modelNode.getLink();
+            writer.append("<link");
+            visitAttribute("encode", link.getEncode());
+            visitAttribute("full-path", link.getFullPath());
+            visitAttribute("id", link.getIdExdr());
+            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("url-mode", link.getUrlMode());
+            if (!link.getParameterList().isEmpty()) {
+                writer.append(">");
+                visitParameters(link.getParameterList());
+                writer.append("</link>");
+            } else {
+                writer.append("/>");
+            }
+        }
+        writer.append("</node>");
+    }
+
+    @Override
+    public void visit(ModelScreen modelScreen) throws Exception {
+        writer.append("<screen");
+        visitModelWidget(modelScreen);
+        visitAttribute("transaction-timeout", modelScreen.getTransactionTimeout());
+        visitAttribute("use-transaction", modelScreen.getUseTransaction());
+        visitAttribute("use-cache", modelScreen.getUseCache());
+        writer.append(">");
+        modelScreen.getSection().accept(this);
+        writer.append("</screen>");
+    }
+
+    @Override
+    public void visit(ModelSubNode modelSubNode) throws Exception {
+        writer.append("<sub-node");
+        visitModelWidget(modelSubNode);
+        visitAttribute("node-name", modelSubNode.getNodeNameExdr());
+        writer.append(">");
+        if (!modelSubNode.getActions().isEmpty()) {
+            writer.append("<actions>");
+            visitActions(modelSubNode.getActions());
+            writer.append("</actions>");
+        }
+        writer.append("</sub-node>");
+    }
+
+    @Override
+    public void visit(ModelTree modelTree) throws Exception {
+        writer.append("<tree");
+        visitModelWidget(modelTree);
+        visitAttribute("root-node-name", modelTree.getRootNodeName());
+        visitAttribute("default-render-style", modelTree.getDefaultRenderStyle());
+        visitAttribute("render-style", modelTree.getDefaultRenderStyle());
+        visitAttribute("default-wrap-style", modelTree.getDefaultWrapStyleExdr());
+        visitAttribute("expand-collapse-request", modelTree.getExpandCollapseRequestExdr());
+        visitAttribute("trail-name", modelTree.getTrailNameExdr());
+        visitAttribute("force-child-check", modelTree.getForceChildCheck());
+        visitAttribute("entity-name", modelTree.getDefaultEntityName());
+        visitAttribute("open-depth", modelTree.getOpenDepth());
+        visitAttribute("post-trail-open-depth", modelTree.getPostTrailOpenDepth());
+        writer.append(">");
+        visitSubWidgets(modelTree.getNodeMap().values());
+        writer.append("</tree>");
+    }
+
+    @Override
+    public void visit(PlatformSpecific platformSpecific) throws Exception {
+        writer.append("<platform-specific>");
+        for (Map.Entry<String, ModelScreenWidget> entry : platformSpecific.getSubWidgets().entrySet()) {
+            writer.append("<").append(entry.getKey()).append(">");
+            entry.getValue().accept(this);
+            writer.append("</").append(entry.getKey()).append(">");
+        }
+        writer.append("</platform-specific>");
+    }
+
+    @Override
+    public void visit(PortalPage portalPage) throws Exception {
+        writer.append("<include-portal-page");
+        visitModelWidget(portalPage);
+        visitAttribute("id", portalPage.getIdExdr());
+        visitAttribute("conf-mode", portalPage.getConfModeExdr());
+        visitAttribute("use-private", portalPage.getUsePrivate());
+        writer.append("/>");
+    }
+
+    @Override
+    public void visit(ScreenImage image) throws Exception {
+        visitImage(image.getImage());
+    }
+
+    @Override
+    public void visit(Screenlet screenlet) throws Exception {
+        writer.append("<screenlet");
+        visitModelWidget(screenlet);
+        visitAttribute("id", screenlet.getIdExdr());
+        visitAttribute("collapsible", screenlet.getCollapsible());
+        visitAttribute("initially-collapsed", screenlet.getInitiallyCollapsed());
+        visitAttribute("save-collapsed", screenlet.getSaveCollapsed());
+        visitAttribute("padded", screenlet.getPadded());
+        visitAttribute("title", screenlet.getTitleExdr());
+        writer.append(">");
+        visitSubWidgets(screenlet.getSubWidgets());
+        writer.append("</screenlet>");
+    }
+
+    @Override
+    public void visit(ScreenLink link) throws Exception {
+        visitLink(link.getLink());
+    }
+
+    @Override
+    public void visit(Section section) throws Exception {
+        writer.append("<section");
+        visitModelWidget(section);
+        writer.append(">");
+        if (section.getCondition() != null) {
+            writer.append("<condition>");
+            section.getCondition().accept(conditionVisitor);
+            writer.append("</condition>");
+        }
+        if (!section.getActions().isEmpty()) {
+            writer.append("<actions>");
+            visitActions(section.getActions());
+            writer.append("</actions>");
+        }
+        if (!section.getSubWidgets().isEmpty()) {
+            writer.append("<widgets>");
+            visitSubWidgets(section.getSubWidgets());
+            writer.append("</widgets>");
+        }
+        if (!section.getFailWidgets().isEmpty()) {
+            writer.append("<fail-widgets>");
+            visitSubWidgets(section.getFailWidgets());
+            writer.append("</fail-widgets>");
+        }
+        writer.append("</section>");
+    }
+
+    @Override
+    public void visit(Tree tree) throws Exception {
+        writer.append("<include-tree");
+        visitModelWidget(tree);
+        visitAttribute("location", tree.getLocationExdr());
+        visitAttribute("share-scope", tree.getShareScopeExdr());
+        writer.append("/>");
+    }
+
+    private void visitActions(Collection<? extends ModelAction> actions) throws Exception {
+        for (ModelAction action : actions) {
+            action.accept(actionVisitor);
+        }
+    }
+
+    private void visitSubWidgets(Collection<? extends ModelWidget> subWidgets) throws Exception {
+        for (ModelWidget subWidget : subWidgets) {
+            subWidget.accept(this);
+        }
+    }
+
+    private void visitUpdateAreas(Collection<ModelForm.UpdateArea> updateAreas) throws Exception {
+        for (ModelForm.UpdateArea updateArea : updateAreas) {
+            writer.append("<on-event-update-area");
+            visitAttribute("event-type", updateArea.getEventType());
+            visitAttribute("area-id", updateArea.getAreaId());
+            visitAttribute("area-target", updateArea.getAreaTarget());
+            writer.append(">");
+            visitAutoEntityParameters(updateArea.getAutoEntityParameters());
+            visitAutoServiceParameters(updateArea.getAutoServiceParameters());
+            visitParameters(updateArea.getParameterList());
+            writer.append("</on-event-update-area>");
+        }
+    }
+}