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

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

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

adrianc
Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlWidgetFieldVisitor.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlWidgetFieldVisitor.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlWidgetFieldVisitor.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlWidgetFieldVisitor.java Sun Jan 18 21:03:40 2015
@@ -0,0 +1,460 @@
+/*******************************************************************************
+ * 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.CommonWidgetModels.Link;
+import org.ofbiz.widget.model.ModelFormField.AutoComplete;
+import org.ofbiz.widget.model.ModelFormField.CheckField;
+import org.ofbiz.widget.model.ModelFormField.ContainerField;
+import org.ofbiz.widget.model.ModelFormField.DateFindField;
+import org.ofbiz.widget.model.ModelFormField.DateTimeField;
+import org.ofbiz.widget.model.ModelFormField.DisplayEntityField;
+import org.ofbiz.widget.model.ModelFormField.DisplayField;
+import org.ofbiz.widget.model.ModelFormField.DropDownField;
+import org.ofbiz.widget.model.ModelFormField.FieldInfoWithOptions;
+import org.ofbiz.widget.model.ModelFormField.FileField;
+import org.ofbiz.widget.model.ModelFormField.HiddenField;
+import org.ofbiz.widget.model.ModelFormField.HyperlinkField;
+import org.ofbiz.widget.model.ModelFormField.IgnoredField;
+import org.ofbiz.widget.model.ModelFormField.ImageField;
+import org.ofbiz.widget.model.ModelFormField.InPlaceEditor;
+import org.ofbiz.widget.model.ModelFormField.LookupField;
+import org.ofbiz.widget.model.ModelFormField.PasswordField;
+import org.ofbiz.widget.model.ModelFormField.RadioField;
+import org.ofbiz.widget.model.ModelFormField.RangeFindField;
+import org.ofbiz.widget.model.ModelFormField.ResetField;
+import org.ofbiz.widget.model.ModelFormField.SubHyperlink;
+import org.ofbiz.widget.model.ModelFormField.SubmitField;
+import org.ofbiz.widget.model.ModelFormField.TextField;
+import org.ofbiz.widget.model.ModelFormField.TextFindField;
+import org.ofbiz.widget.model.ModelFormField.TextareaField;
+
+/**
+ * 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 XmlAbstractWidgetVisitor 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 {
+        visitModelField(hyperlinkField.getModelFormField());
+        writer.append("<hyperlink");
+        visitAttribute("also-hidden", hyperlinkField.getAlsoHidden());
+        visitAttribute("confirmation-message", hyperlinkField.getConfirmationMsgExdr());
+        visitAttribute("description", hyperlinkField.getDescription());
+        visitAttribute("request-confirmation", hyperlinkField.getRequestConfirmation());
+        Link link = hyperlinkField.getLink();
+        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("</hyperlink>");
+        } else {
+            writer.append("/>");
+        }
+        writer.append("</field>");
+    }
+
+    @Override
+    public void visit(IgnoredField ignoredField) throws Exception {
+        visitModelField(ignoredField.getModelFormField());
+        writer.append("<ignored/></field>");
+    }
+
+    @Override
+    public void visit(ImageField imageField) throws Exception {
+        visitModelField(imageField.getModelFormField());
+        writer.append("<image");
+        visitAttribute("alternate", imageField.getAlternate());
+        visitAttribute("default-value", imageField.getDefaultValue());
+        visitAttribute("description", imageField.getDescription());
+        visitAttribute("style", imageField.getStyle());
+        visitAttribute("value", imageField.getValue());
+        writer.append(">");
+        visitSubHyperlink(imageField.getSubHyperlink());
+        writer.append("</image></field>");
+    }
+
+    @Override
+    public void visit(LookupField textField) throws Exception {
+        visitModelField(textField.getModelFormField());
+        writer.append("<lookup");
+        visitTextFieldAttrs(textField);
+        visitAttribute("description-field-name", textField.getDescriptionFieldName());
+        visitAttribute("fade-background", textField.getFadeBackground());
+        visitAttribute("target-form-name", textField.getFormName());
+        visitAttribute("initially-collapsed", textField.getInitiallyCollapsed());
+        visitAttribute("height", textField.getLookupHeight());
+        visitAttribute("position", textField.getLookupPosition());
+        visitAttribute("presentation", textField.getLookupPresentation());
+        visitAttribute("width", textField.getLookupWidth());
+        visitAttribute("show-description", textField.getShowDescription());
+        visitAttribute("target-parameter", textField.getTargetParameter());
+        writer.append(">");
+        visitSubHyperlink(textField.getSubHyperlink());
+        writer.append("</lookup></field>");
+    }
+
+    @Override
+    public void visit(PasswordField textField) throws Exception {
+        visitModelField(textField.getModelFormField());
+        writer.append("<password");
+        visitTextFieldAttrs(textField);
+        writer.append(">");
+        visitSubHyperlink(textField.getSubHyperlink());
+        writer.append("</password></field>");
+    }
+
+    @Override
+    public void visit(RadioField radioField) throws Exception {
+        visitModelField(radioField.getModelFormField());
+        writer.append("<radio");
+        visitFieldInfoWithOptions(radioField);
+        writer.append("</radio></field>");
+    }
+
+    @Override
+    public void visit(RangeFindField textField) throws Exception {
+        visitModelField(textField.getModelFormField());
+        writer.append("<range-find");
+        visitTextFieldAttrs(textField);
+        visitAttribute("default-option-from", textField.getDefaultOptionFrom());
+        visitAttribute("default-option-thru", textField.getDefaultOptionThru());
+        writer.append(">");
+        visitSubHyperlink(textField.getSubHyperlink());
+        writer.append("</range-find></field>");
+    }
+
+    @Override
+    public void visit(ResetField resetField) throws Exception {
+        visitModelField(resetField.getModelFormField());
+        writer.append("<reset/></field>");
+    }
+
+    @Override
+    public void visit(SubmitField submitField) throws Exception {
+        visitModelField(submitField.getModelFormField());
+        writer.append("<submit");
+        visitAttribute("background-submit-refresh-target", submitField.getBackgroundSubmitRefreshTargetExdr());
+        visitAttribute("button-type", submitField.getButtonType());
+        visitAttribute("confirmation-message", submitField.getConfirmationMsgExdr());
+        visitAttribute("image-location", submitField.getImageLocation());
+        visitAttribute("request-confirmation", submitField.getRequestConfirmation());
+        writer.append("/></field>");
+    }
+
+    @Override
+    public void visit(TextareaField textareaField) throws Exception {
+        visitModelField(textareaField.getModelFormField());
+        writer.append("<textarea");
+        visitAttribute("cols", textareaField.getCols());
+        visitAttribute("default-value", textareaField.getDefaultValue());
+        visitAttribute("read-only", textareaField.isReadOnly());
+        visitAttribute("rows", textareaField.getRows());
+        visitAttribute("visual-editor-buttons", textareaField.getVisualEditorButtons());
+        visitAttribute("visual-editor-enable", textareaField.getVisualEditorEnable());
+        writer.append("/></field>");
+    }
+
+    @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 {
+        if (autoComplete != null) {
+            writer.append("<auto-complete");
+            visitAttribute("auto-select", autoComplete.getAutoSelect());
+            visitAttribute("frequency", autoComplete.getFrequency());
+            visitAttribute("min-chars", autoComplete.getMinChars());
+            visitAttribute("choices", autoComplete.getChoices());
+            visitAttribute("partial-search", autoComplete.getPartialSearch());
+            visitAttribute("partial-chars", autoComplete.getPartialChars());
+            visitAttribute("ignore-case", autoComplete.getIgnoreCase());
+            visitAttribute("full-search", autoComplete.getFullSearch());
+            writer.append("/>");
+        }
+    }
+
+    private void visitInPlaceEditor(InPlaceEditor editor) throws Exception {
+        if (editor != null) {
+            writer.append("<in-place-editor");
+            visitAttribute("cancel-control", editor.getCancelControl());
+            visitAttribute("cancel-text", editor.getCancelText());
+            visitAttribute("click-to-edit-text", editor.getClickToEditText());
+            visitAttribute("field-post-creation", editor.getFieldPostCreation());
+            visitAttribute("form-class-name", editor.getFormClassName());
+            visitAttribute("highlight-color", editor.getHighlightColor());
+            visitAttribute("highlight-end-color", editor.getHighlightEndColor());
+            visitAttribute("hover-class-name", editor.getHoverClassName());
+            visitAttribute("html-response", editor.getHtmlResponse());
+            visitAttribute("loading-class-name", editor.getLoadingClassName());
+            visitAttribute("loading-text", editor.getLoadingText());
+            visitAttribute("ok-control", editor.getOkControl());
+            visitAttribute("ok-text", editor.getOkText());
+            visitAttribute("param-name", editor.getParamName());
+            visitAttribute("saving-class-name", editor.getSavingClassName());
+            visitAttribute("saving-text", editor.getSavingText());
+            visitAttribute("submit-on-blur", editor.getSubmitOnBlur());
+            visitAttribute("text-before-controls", editor.getTextBeforeControls());
+            visitAttribute("text-after-controls", editor.getTextAfterControls());
+            visitAttribute("text-between-controls", editor.getTextBetweenControls());
+            visitAttribute("update-after-request-call", editor.getUpdateAfterRequestCall());
+            visitAttribute("url", editor.getUrl());
+            if (!editor.getCols().isEmpty() || !editor.getRows().isEmpty()) {
+                writer.append(">");
+                writer.append("<simple-editor");
+                visitAttribute("cols", editor.getCols());
+                visitAttribute("rows", editor.getRows());
+                writer.append("/></in-place-editor>");
+            } else {
+                writer.append("/>");
+            }
+        }
+    }
+
+    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/model/XmlWidgetVisitor.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlWidgetVisitor.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlWidgetVisitor.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/XmlWidgetVisitor.java Sun Jan 18 21:03:40 2015
@@ -0,0 +1,645 @@
+/*******************************************************************************
+ * 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 java.util.Map;
+
+import org.ofbiz.widget.model.HtmlWidget.HtmlTemplate;
+import org.ofbiz.widget.model.HtmlWidget.HtmlTemplateDecorator;
+import org.ofbiz.widget.model.HtmlWidget.HtmlTemplateDecoratorSection;
+import org.ofbiz.widget.model.ModelScreenWidget.Column;
+import org.ofbiz.widget.model.ModelScreenWidget.ColumnContainer;
+import org.ofbiz.widget.model.ModelScreenWidget.Container;
+import org.ofbiz.widget.model.ModelScreenWidget.Content;
+import org.ofbiz.widget.model.ModelScreenWidget.DecoratorScreen;
+import org.ofbiz.widget.model.ModelScreenWidget.DecoratorSection;
+import org.ofbiz.widget.model.ModelScreenWidget.DecoratorSectionInclude;
+import org.ofbiz.widget.model.ModelScreenWidget.Form;
+import org.ofbiz.widget.model.ModelScreenWidget.HorizontalSeparator;
+import org.ofbiz.widget.model.ModelScreenWidget.IncludeScreen;
+import org.ofbiz.widget.model.ModelScreenWidget.Label;
+import org.ofbiz.widget.model.ModelScreenWidget.Menu;
+import org.ofbiz.widget.model.ModelScreenWidget.PlatformSpecific;
+import org.ofbiz.widget.model.ModelScreenWidget.PortalPage;
+import org.ofbiz.widget.model.ModelScreenWidget.ScreenImage;
+import org.ofbiz.widget.model.ModelScreenWidget.ScreenLink;
+import org.ofbiz.widget.model.ModelScreenWidget.Screenlet;
+import org.ofbiz.widget.model.ModelScreenWidget.Section;
+import org.ofbiz.widget.model.ModelScreenWidget.Tree;
+import org.ofbiz.widget.model.ModelTree.ModelNode;
+import org.ofbiz.widget.model.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 XmlAbstractWidgetVisitor 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>");
+        }
+        if (modelMenuItem.getLink() != null) {
+            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>");
+        }
+    }
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/portal/PortalPageWorker.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/portal/PortalPageWorker.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/portal/PortalPageWorker.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/portal/PortalPageWorker.java Sun Jan 18 21:03:40 2015
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * 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.portal;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.GeneralException;
+import org.ofbiz.base.util.UtilMisc;
+import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.entity.Delegator;
+import org.ofbiz.entity.GenericEntityException;
+import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.condition.EntityCondition;
+import org.ofbiz.entity.condition.EntityOperator;
+import org.ofbiz.entity.util.EntityQuery;
+import org.ofbiz.entity.util.EntityUtil;
+import org.ofbiz.security.Security;
+import org.ofbiz.widget.WidgetWorker;
+
+/**
+ * PortalPageWorker Class
+ */
+public class PortalPageWorker {
+
+    public static final String module = PortalPageWorker.class.getName();
+
+    public PortalPageWorker() { }
+
+    public String renderPortalPageAsTextExt(Delegator delegator, String portalPageId, Map<String, Object> templateContext,
+            boolean cache) throws GeneralException, IOException {
+        return "success";
+    }
+
+    /**
+    * Returns a list of PortalPages that have the specified parentPortalPageId as parent.
+    * If a specific PortalPage exists for the current userLogin it is returned instead of the original one.
+    */
+    public static List<GenericValue> getPortalPages(String parentPortalPageId, Map<String, Object> context) {
+        List<GenericValue> portalPages = null;
+        if (UtilValidate.isNotEmpty(parentPortalPageId)) {
+            Delegator delegator = WidgetWorker.getDelegator(context);
+            try {
+                // first get public pages
+                EntityCondition cond =
+                    EntityCondition.makeCondition(UtilMisc.toList(
+                        EntityCondition.makeCondition("ownerUserLoginId", EntityOperator.EQUALS, "_NA_"),
+                        EntityCondition.makeCondition(UtilMisc.toList(
+                                EntityCondition.makeCondition("portalPageId", EntityOperator.EQUALS, parentPortalPageId),
+                                EntityCondition.makeCondition("parentPortalPageId", EntityOperator.EQUALS, parentPortalPageId)),
+                                EntityOperator.OR)),
+                        EntityOperator.AND);
+                portalPages = EntityQuery.use(delegator).from("PortalPage").where(cond).queryList();
+                List<GenericValue> userPortalPages = new ArrayList<GenericValue>();
+                if (UtilValidate.isNotEmpty(context.get("userLogin"))) { // check if a user is logged in
+                    String userLoginId = ((GenericValue)context.get("userLogin")).getString("userLoginId");
+                    // replace with private pages
+                    for (GenericValue portalPage : portalPages) {
+                        List<GenericValue> privatePortalPages = EntityQuery.use(delegator)
+                                                                           .from("PortalPage")
+                                                                           .where("ownerUserLoginId", userLoginId, "originalPortalPageId", portalPage.getString("portalPageId"))
+                                                                           .queryList();
+                        if (UtilValidate.isNotEmpty(privatePortalPages)) {
+                            userPortalPages.add(privatePortalPages.get(0));
+                        } else {
+                            userPortalPages.add(portalPage);
+                        }
+                    }
+                    // add any other created private pages
+                    userPortalPages.addAll(EntityQuery.use(delegator)
+                                                      .from("PortalPage")
+                                                      .where("ownerUserLoginId", userLoginId, "originalPortalPageId", null, "parentPortalPageId", parentPortalPageId)
+                                                      .queryList());
+                }
+                portalPages = EntityUtil.orderBy(userPortalPages, UtilMisc.toList("sequenceNum"));
+            } catch (GenericEntityException e) {
+                Debug.logError("Could not retrieve portalpages:" + e.getMessage(), module);
+            }
+        }
+        return portalPages;
+    }
+
+    /**
+    * Returns the PortalPage with the specified portalPageId.
+    * If a specific PortalPage exists for the current userLogin it is returned instead of the original one.
+    */
+    public static GenericValue getPortalPage(String portalPageId, Map<String, Object> context) {
+        GenericValue portalPage = null;
+        if (UtilValidate.isNotEmpty(portalPageId)) {
+            Delegator delegator = WidgetWorker.getDelegator(context);
+            try {
+                // Get the current userLoginId
+                String userLoginId = "_NA_";
+                if (UtilValidate.isNotEmpty(context.get("userLogin"))) { // check if a user is logged in
+                    userLoginId = ((GenericValue)context.get("userLogin")).getString("userLoginId");
+                }
+                
+                // Get the PortalPage ensuring that it is either owned by the user or a system page
+                EntityCondition cond = EntityCondition.makeCondition(UtilMisc.toList(
+                    EntityCondition.makeCondition("portalPageId", EntityOperator.EQUALS, portalPageId),
+                    EntityCondition.makeCondition(UtilMisc.toList(
+                        EntityCondition.makeCondition("ownerUserLoginId", EntityOperator.EQUALS, "_NA_"),
+                        EntityCondition.makeCondition("ownerUserLoginId", EntityOperator.EQUALS, userLoginId)),
+                        EntityOperator.OR)),
+                    EntityOperator.AND);
+                List <GenericValue> portalPages = EntityQuery.use(delegator).from("PortalPage").where(cond).queryList();
+                if (UtilValidate.isNotEmpty(portalPages)) {
+                    portalPage = EntityUtil.getFirst(portalPages);
+                }
+                
+                // If a derived PortalPage private to the user exists, returns this instead of the system one
+                cond = EntityCondition.makeCondition(UtilMisc.toList(
+                        EntityCondition.makeCondition("originalPortalPageId", EntityOperator.EQUALS, portalPageId),
+                        EntityCondition.makeCondition("ownerUserLoginId", EntityOperator.EQUALS, userLoginId)),
+                        EntityOperator.AND);
+                List <GenericValue> privateDerivedPortalPages = EntityQuery.use(delegator).from("PortalPage").where(cond).queryList();
+                if (UtilValidate.isNotEmpty(privateDerivedPortalPages)) {
+                    portalPage = EntityUtil.getFirst(privateDerivedPortalPages);
+                }
+            } catch (GenericEntityException e) {
+                Debug.logError("Could not retrieve portalpage:" + e.getMessage(), module);
+            }
+        }
+        return portalPage;
+    }
+
+    /**
+    * Checks if the user is allowed to configure the PortalPage.
+    * PortalPage configuration is allowed if he is the PortalPage owner or he has got the PORTALPAGE_ADMIN permission
+    */  
+    public static Boolean userIsAllowedToConfigure(String portalPageId, Map<String, Object> context) {
+        Boolean userIsAllowed = false;
+
+        if (UtilValidate.isNotEmpty(portalPageId)) {
+            GenericValue userLogin = (GenericValue) context.get("userLogin");
+            if (UtilValidate.isNotEmpty(userLogin)) {
+                String userLoginId = (String) userLogin.get("userLoginId");
+                Security security = (Security) context.get("security");
+
+                Boolean hasPortalAdminPermission = security.hasPermission("PORTALPAGE_ADMIN", userLogin);
+                try {
+                    Delegator delegator = WidgetWorker.getDelegator(context);
+                    GenericValue portalPage = EntityQuery.use(delegator).from("PortalPage").where("portalPageId", portalPageId).queryOne();
+                    if (UtilValidate.isNotEmpty(portalPage)) {
+                        String ownerUserLoginId = (String) portalPage.get("ownerUserLoginId");
+                        // Users with PORTALPAGE_ADMIN permission can configure every Portal Page
+                        userIsAllowed = (ownerUserLoginId.equals(userLoginId) || hasPortalAdminPermission);
+                    }
+                } catch (GenericEntityException e) {
+                    return false;
+                }
+            }
+        }
+
+        return userIsAllowed;      
+    }
+    
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/portal/PortalPageWorkerInterface.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/portal/PortalPageWorkerInterface.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/portal/PortalPageWorkerInterface.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/portal/PortalPageWorkerInterface.java Sun Jan 18 21:03:40 2015
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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.portal;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.ofbiz.base.util.GeneralException;
+import org.ofbiz.entity.Delegator;
+
+/**
+ * PortalPageWorkerInterface
+ */
+public interface PortalPageWorkerInterface {
+    public String renderPortalPageAsTextExt(Delegator delegator, String portalPageId, Map<String, Object> templateContext,
+            boolean cache) throws GeneralException, IOException;
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/portal/WidgetPortalPageWorker.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/portal/WidgetPortalPageWorker.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/portal/WidgetPortalPageWorker.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/portal/WidgetPortalPageWorker.java Sun Jan 18 21:03:40 2015
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.portal;
+
+import org.ofbiz.base.util.Debug;
+
+/**
+ * PortalPageWorker Class
+ */
+public class WidgetPortalPageWorker {
+    public static final String module = WidgetPortalPageWorker.class.getName();
+    public static PortalPageWorkerInterface portalPageWorker = null;
+    static {
+        try {
+            ClassLoader loader = Thread.currentThread().getContextClassLoader();
+            // note: loadClass is necessary for these since this class doesn't know anything about them at compile time
+            portalPageWorker = (PortalPageWorkerInterface) loader.loadClass("org.ofbiz.widget.portal.PortalPageWorker").newInstance();
+        } catch (ClassNotFoundException e) {
+            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);
+        } catch (IllegalAccessException e) {
+            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);
+        } catch (InstantiationException e) {
+            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);
+        }
+    }
+}