Paints the given definition list.

@param component the list to paint.
@param renderContext the RenderContext to paint to.
185669
@Override
	public void doRender(final WComponent component, final WebXmlRenderContext renderContext) {
		WDefinitionList list = (WDefinitionList) component;
		XmlStringBuilder xml = renderContext.getWriter();

		xml.appendTagOpen("ui:definitionlist");
		xml.appendAttribute("id", component.getId());
		xml.appendOptionalAttribute("class", component.getHtmlClass());
		xml.appendOptionalAttribute("track", component.isTracking(), "true");

		switch (list.getType()) {
			case FLAT:
				xml.appendAttribute("type", "flat");
				break;

			case COLUMN:
				xml.appendAttribute("type", "column");
				break;

			case STACKED:
				xml.appendAttribute("type", "stacked");
				break;

			case NORMAL:
				break;

			default:
				throw new SystemException("Unknown layout type: " + list.getType());
		}

		xml.appendClose();

		// Render margin
		MarginRendererUtil.renderMargin(list, renderContext);

		for (Duplet<String, ArrayList<WComponent>> term : list.getTerms()) {
			xml.appendTagOpen("ui:term");
			xml.appendAttribute("text", I18nUtilities.format(null, term.getFirst()));
			xml.appendClose();

			for (WComponent data : term.getSecond()) {
				xml.appendTag("ui:data");
				data.paint(renderContext);
				xml.appendEndTag("ui:data");
			}

			xml.appendEndTag("ui:term");
		}

		xml.appendEndTag("ui:definitionlist");
	}
1279775
@Override
	public void doRender(final WComponent component, final WebXmlRenderContext renderContext) {
		WTemplate template = (WTemplate) component;

		// Setup the context
		Map<String, Object> context = new HashMap<>();
		// Make the component available under the "wc" key.
		context.put("wc", template);
		// Load the parameters
		context.putAll(template.getParameters());

		// Get template renderer for the engine
		String engine = template.getEngineName();
		if (Util.empty(engine)) {
			engine = ConfigurationProperties.getDefaultRenderingEngine();
		}
		TemplateRenderer templateRenderer = TemplateRendererFactory.newInstance(engine);

		// Render
		if (!Util.empty(template.getTemplateName())) {
			// Render the template
			templateRenderer.renderTemplate(template.getTemplateName(), context, template.getTaggedComponents(), renderContext.getWriter(),
					template.getEngineOptions());
		} else if (!Util.empty(template.getInlineTemplate())) {
			// Render inline
			templateRenderer.renderInline(template.getInlineTemplate(), context, template.getTaggedComponents(), renderContext.getWriter(),
					template.getEngineOptions());
		}
	}
1026696
@Override
	public void doRender(final WComponent component, final WebXmlRenderContext renderContext) {
		WTextField textField = (WTextField) component;
		XmlStringBuilder xml = renderContext.getWriter();
		boolean readOnly = textField.isReadOnly();

		xml.appendTagOpen("ui:textfield");
		xml.appendAttribute("id", component.getId());
		xml.appendOptionalAttribute("class", component.getHtmlClass());
		xml.appendOptionalAttribute("track", component.isTracking(), "true");
		xml.appendOptionalAttribute("hidden", component.isHidden(), "true");
		if (readOnly) {
			xml.appendAttribute("readOnly", "true");
		} else {
			int cols = textField.getColumns();
			int minLength = textField.getMinLength();
			int maxLength = textField.getMaxLength();
			String pattern = textField.getPattern();

			WSuggestions suggestions = textField.getSuggestions();
			String suggestionsId = suggestions == null ? null : suggestions.getId();

			WComponent submitControl = textField.getDefaultSubmitButton();
			String submitControlId = submitControl == null ? null : submitControl.getId();

			xml.appendOptionalAttribute("disabled", textField.isDisabled(), "true");
			xml.appendOptionalAttribute("required", textField.isMandatory(), "true");
			xml.appendOptionalAttribute("minLength", minLength > 0, minLength);
			xml.appendOptionalAttribute("maxLength", maxLength > 0, maxLength);
			xml.appendOptionalAttribute("toolTip", textField.getToolTip());
			xml.appendOptionalAttribute("accessibleText", textField.getAccessibleText());
			xml.appendOptionalAttribute("size", cols > 0, cols);
			xml.appendOptionalAttribute("buttonId", submitControlId);
			xml.appendOptionalAttribute("pattern", !Util.empty(pattern), pattern);
			xml.appendOptionalAttribute("list", suggestionsId);
			String placeholder = textField.getPlaceholder();
			xml.appendOptionalAttribute("placeholder", !Util.empty(placeholder), placeholder);
			String autocomplete = textField.getAutocomplete();
			xml.appendOptionalAttribute("autocomplete", !Util.empty(autocomplete), autocomplete);
		}

		xml.appendClose();

		xml.appendEscaped(textField.getText());
		if (!readOnly) {
			DiagnosticRenderUtil.renderDiagnostics(textField, renderContext);
		}
		xml.appendEndTag("ui:textfield");
	}
1280747
@Override
	public void doRender(final WComponent component, final WebXmlRenderContext renderContext) {
		WCollapsibleToggle toggle = (WCollapsibleToggle) component;
		XmlStringBuilder xml = renderContext.getWriter();

		xml.appendTagOpen("ui:collapsibletoggle");
		xml.appendAttribute("id", component.getId());
		xml.appendOptionalAttribute("class", component.getHtmlClass());
		xml.appendOptionalAttribute("track", component.isTracking(), "true");
		xml.appendAttribute("groupName", toggle.getGroupName());
		xml.appendEnd();
	}
82326
@Override
	public void doRender(final WComponent component, final WebXmlRenderContext renderContext) {
		XmlStringBuilder xml = renderContext.getWriter();
		WButton button = (WButton) component;
		String text = button.getText();
		String imageUrl = button.getImageUrl();
		String accessibleText = button.getAccessibleText();
		String toolTip = button.getToolTip();

		if (Util.empty(text) && imageUrl == null && Util.empty(accessibleText) && Util.empty(toolTip)) {
			throw new SystemException("WButton text or imageUrl must be specified");
		}

		xml.appendTagOpen(getTagName(button));

		String buttonId = button.getId();
		ImagePosition pos = button.getImagePosition();
		if (Util.empty(text) && Util.empty(toolTip) && Util.empty(accessibleText)) {
			// If the button has an imageUrl but no text equivalent get the text equivalent off of the image
			WImage imgHolder = button.getImageHolder();
			if (null != imgHolder) {
				toolTip = imgHolder.getAlternativeText();
			}
		}

		xml.appendAttribute("id", buttonId);
		xml.appendAttribute("name", buttonId);
		xml.appendAttribute("value", "x");
		xml.appendAttribute("type", getButtonType(button));
		xml.appendAttribute("class", geHtmlClassName(button));
		xml.appendOptionalAttribute("disabled", button.isDisabled(), "disabled");
		xml.appendOptionalAttribute("hidden", button.isHidden(), "hidden");
		xml.appendOptionalAttribute("title", toolTip);
		xml.appendOptionalAttribute("aria-label", accessibleText);
		xml.appendOptionalAttribute("aria-haspopup", button.isPopupTrigger(), "true");
		xml.appendOptionalAttribute("accesskey", Util.upperCase(button.getAccessKeyAsString()));
		xml.appendOptionalAttribute("data-wc-btnmsg", button.getMessage());

		if (button.isCancel()) {
			xml.appendAttribute("formnovalidate", "formnovalidate");
		} else {
			Action action = button.getAction();
			if (action instanceof ValidatingAction) {
				WComponent validationTarget = ((ValidatingAction) action).getComponentToValidate();
				xml.appendAttribute("data-wc-validate", validationTarget.getId());
			}
		}

		xml.appendClose();

		if (imageUrl != null) {
			xml.appendTagOpen("span");
			String imageHolderClass =  "wc_nti";
			if (pos != null) {
				StringBuffer imageHolderClassBuffer = new StringBuffer("wc_btn_img wc_btn_img");
				switch (pos) {
					case NORTH:
						imageHolderClassBuffer.append("n");
						break;
					case EAST:
						imageHolderClassBuffer.append("e");
						break;
					case SOUTH:
						imageHolderClassBuffer.append("s");
						break;
					case WEST:
						imageHolderClassBuffer.append("w");
						break;
					default:
						throw new SystemException("Unknown image position: " + pos);
				}
				imageHolderClass = imageHolderClassBuffer.toString();
			}
			xml.appendAttribute("class", imageHolderClass);
			xml.appendClose();

			if (pos != null && text != null) {
				xml.appendTag("span");
				xml.appendEscaped(text);
				xml.appendEndTag("span");
			}

			xml.appendTagOpen("img");
			xml.appendUrlAttribute("src", imageUrl);
			String alternateText = pos == null ? text : "";
			xml.appendAttribute("alt", alternateText);
			xml.appendEnd();
			xml.appendEndTag("span");
		} else if (text != null) {
			xml.appendEscaped(text);
		}

		xml.appendEndTag(getTagName(button));

		if (button.isAjax()) {
			paintAjax(button, xml);
		}
	}
288977
@Override
	public void doRender(final WComponent component, final WebXmlRenderContext renderContext) {
		WSubMenu menu = (WSubMenu) component;
		XmlStringBuilder xml = renderContext.getWriter();

		xml.appendTagOpen("ui:submenu");
		xml.appendAttribute("id", component.getId());
		xml.appendOptionalAttribute("class", component.getHtmlClass());
		xml.appendOptionalAttribute("track", component.isTracking(), "true");
		if (isTree(menu)) {
			xml.appendAttribute("open", String.valueOf(isOpen(menu)));
		}
		xml.appendOptionalAttribute("disabled", menu.isDisabled(), "true");
		xml.appendOptionalAttribute("hidden", menu.isHidden(), "true");
		if (menu.isTopLevelMenu()) {
			xml.appendOptionalAttribute("accessKey", menu.getAccessKeyAsString());
		} else {
			xml.appendAttribute("nested", "true");
		}
		xml.appendOptionalAttribute("type", getMenuType(menu));

		switch (menu.getMode()) {
			case CLIENT:
				xml.appendAttribute("mode", "client");
				break;
			case LAZY:
				xml.appendAttribute("mode", "lazy");
				break;
			case EAGER:
				xml.appendAttribute("mode", "eager");
				break;
			case DYNAMIC:
			case SERVER:
				// mode server mapped to mode dynamic as per https://github.com/BorderTech/wcomponents/issues/687
				xml.appendAttribute("mode", "dynamic");
				break;
			default:
				throw new SystemException("Unknown menu mode: " + menu.getMode());
		}

		xml.appendClose();

		// Paint label
		menu.getDecoratedLabel().paint(renderContext);

		MenuMode mode = menu.getMode();

		// Paint submenu items
		xml.appendTagOpen("ui:content");
		xml.appendAttribute("id", component.getId() + "-content");
		xml.appendClose();

		// Render content if not EAGER Mode or is EAGER and is the current AJAX request
		if (mode != MenuMode.EAGER || AjaxHelper.isCurrentAjaxTrigger(menu)) {
			// Visibility of content set in prepare paint
			menu.paintMenuItems(renderContext);
		}

		xml.appendEndTag("ui:content");

		xml.appendEndTag("ui:submenu");
	}
513508
@Override
	public void render(final WComponent component, final RenderContext renderContext) {
		if (renderContext instanceof WebXmlRenderContext) {
			doRender(component, (WebXmlRenderContext) renderContext);
		} else {
			throw new SystemException("Unable to render web xml output to " + renderContext);
		}
	}
738963
@Override
	public void doRender(final WComponent component, final WebXmlRenderContext renderContext) {
		WMultiDropdown dropdown = (WMultiDropdown) component;
		XmlStringBuilder xml = renderContext.getWriter();
		String dataKey = dropdown.getListCacheKey();
		boolean readOnly = dropdown.isReadOnly();

		xml.appendTagOpen("ui:multidropdown");
		xml.appendAttribute("id", component.getId());
		xml.appendOptionalAttribute("class", component.getHtmlClass());
		xml.appendOptionalAttribute("track", component.isTracking(), "true");
		xml.appendOptionalAttribute("hidden", dropdown.isHidden(), "true");
		if (readOnly) {
			xml.appendAttribute("readOnly", "true");
		} else {
			xml.appendOptionalAttribute("data", dataKey != null && !readOnly, dataKey);
			xml.appendOptionalAttribute("disabled", dropdown.isDisabled(), "true");
			xml.appendOptionalAttribute("required", dropdown.isMandatory(), "true");
			xml.appendOptionalAttribute("submitOnChange", dropdown.isSubmitOnChange(), "true");
			xml.appendOptionalAttribute("toolTip", component.getToolTip());
			xml.appendOptionalAttribute("accessibleText", component.getAccessibleText());
			int min = dropdown.getMinSelect();
			int max = dropdown.getMaxSelect();
			xml.appendOptionalAttribute("min", min > 0, min);
			xml.appendOptionalAttribute("max", max > 0, max);
			xml.appendOptionalAttribute("title", I18nUtilities.format(null, InternalMessages.DEFAULT_MULTIDROPDOWN_TIP));
		}

		xml.appendClose();

		// Options
		List<?> options = dropdown.getOptions();
		boolean renderSelectionsOnly = dropdown.isReadOnly() || dataKey != null;

		if (options != null) {
			int optionIndex = 0;
			List<?> selections = dropdown.getSelected();

			for (Object option : options) {
				if (option instanceof OptionGroup) {
					xml.appendTagOpen("ui:optgroup");
					xml.appendAttribute("label", ((OptionGroup) option).getDesc());
					xml.appendClose();

					for (Object nestedOption : ((OptionGroup) option).getOptions()) {
						renderOption(dropdown, nestedOption, optionIndex++, xml, selections,
								renderSelectionsOnly);
					}

					xml.appendEndTag("ui:optgroup");
				} else {
					renderOption(dropdown, option, optionIndex++, xml, selections,
							renderSelectionsOnly);
				}
			}
		}

		if (!readOnly) {
			DiagnosticRenderUtil.renderDiagnostics(dropdown, renderContext);
		}
		// End tag
		xml.appendEndTag("ui:multidropdown");
	}
195629
@Override
	public void paint(final RenderContext renderContext) {
		boolean enabled = ConfigurationProperties.getDeveloperDumpUIContext();

		super.paint(renderContext);

		if (enabled) {
			UIContext uic = UIContextHolder.getCurrent();

			// We want to dump the shared WComponent tree (UIC) first, so that all the
			// references from the UI context are shown as such
			Object[] treeAndSession
					= new Object[]{
						uic.getUI(),
						uic
					};

			try {
				ObjectGraphNode root = ObjectGraphDump.dump(treeAndSession);

				// We only want to dump the tree once
				boolean treeDumped = "true".equalsIgnoreCase((String) uic.getFwkAttribute(
						UICONTEXT_TREE_DUMPED_KEY));

				if (!treeDumped) {
					uic.setFwkAttribute(UICONTEXT_TREE_DUMPED_KEY, "true");

					// The UI will be the 1st child
					LOG.info("UI dump follows:");
					LOG.info(((ObjectGraphNode) root.getChildAt(0)).toXml());
				}

				// The UI context will be the 2nd child
				LOG.info("UI Context dump follows:");
				LOG.info(((ObjectGraphNode) root.getChildAt(1)).toXml());
			} catch (Exception e) {
				LOG.error("Failed to dump context", e);
			}
		}
	}
1285790
@Override
	public void doRender(final WComponent component, final WebXmlRenderContext renderContext) {
		WRow row = (WRow) component;
		XmlStringBuilder xml = renderContext.getWriter();
		int cols = row.getChildCount();
		Size gap = row.getSpace();
		String gapString = gap != null ? gap.toString() : null;

		if (cols > 0) {
			xml.appendTagOpen("ui:row");
			xml.appendAttribute("id", component.getId());
			xml.appendOptionalAttribute("class", component.getHtmlClass());
			xml.appendOptionalAttribute("track", component.isTracking(), "true");
			xml.appendOptionalAttribute("gap", gapString);
			xml.appendClose();

			// Render margin
			MarginRendererUtil.renderMargin(row, renderContext);

			paintChildren(row, renderContext);

			xml.appendEndTag("ui:row");
		}
	}
103092
@Override
	protected void afterPaint(final RenderContext renderContext) {
		super.afterPaint(renderContext);

		if (this.isPressed() && renderContext instanceof WebXmlRenderContext) {
			PrintWriter writer = ((WebXmlRenderContext) renderContext).getWriter();

			StringBuffer temp = dumpAll();
			writer.println("<br/><br/>");
			writer.println(temp);
		}
	}
230358
@Override
	public void doRender(final WComponent component, final WebXmlRenderContext renderContext) {
		XmlStringBuilder xml = renderContext.getWriter();
		xml.appendTagOpen("hr");
		xml.appendOptionalAttribute("class", component.getHtmlClass());
		xml.appendEnd();
	}
1186865
@Override
	public void doRender(final WComponent component, final WebXmlRenderContext renderContext) {
		WAjaxControl ajaxControl = (WAjaxControl) component;
		XmlStringBuilder xml = renderContext.getWriter();
		WComponent trigger = ajaxControl.getTrigger() == null ? ajaxControl : ajaxControl.
				getTrigger();
		int delay = ajaxControl.getDelay();

		if (ajaxControl.getTargets() == null || ajaxControl.getTargets().isEmpty()) {
			return;
		}

		// Start tag
		xml.appendTagOpen("ui:ajaxtrigger");
		xml.appendAttribute("triggerId", trigger.getId());
		xml.appendOptionalAttribute("loadOnce", ajaxControl.isLoadOnce(), "true");
		xml.appendOptionalAttribute("delay", delay > 0, delay);
		xml.appendClose();

		// Targets
		for (AjaxTarget target : ajaxControl.getTargets()) {
			xml.appendTagOpen("ui:ajaxtargetid");
			xml.appendAttribute("targetId", target.getId());
			xml.appendEnd();
		}

		// End tag
		xml.appendEndTag("ui:ajaxtrigger");
	}
916254
@Override
	public void paint(final RenderContext renderContext) {
		// Check interceptor is enabled
		if (!DebugValidateXML.isEnabled()) {
			super.paint(renderContext);
			return;
		}

		if (!(renderContext instanceof WebXmlRenderContext)) {
			LOG.warn("Unable to validate against a " + renderContext);
			super.paint(renderContext);
			return;
		}

		LOG.debug("Validate XML Interceptor: Start");

		WebXmlRenderContext webRenderContext = (WebXmlRenderContext) renderContext;
		PrintWriter writer = webRenderContext.getWriter();

		// Generate XML
		StringWriter tempBuffer = new StringWriter();
		PrintWriter tempWriter = new PrintWriter(tempBuffer);
		WebXmlRenderContext tempContext = new WebXmlRenderContext(tempWriter, UIContextHolder.
				getCurrent().getLocale());

		super.paint(tempContext);
		String xml = tempBuffer.toString();

		// If no errors, check against the schema
		String error = DebugValidateXML.validateXMLAgainstSchema(xml);

		if (error != null) {
			// XML is NOT valid, so Report Errors and Wrap the original XML
			LOG.debug("Validate XML Interceptor: XML Has Errors");
			writer.println("<div>");

			writer.println("<div>");
			writer.println("Invalid XML");
			writer.println("<ul><li>" + WebUtilities.encode(error) + "</li></ul>");
			writer.println("<br/>");
			writer.println("</div>");

			// If a schema error detected, Wrap XML so line numbers reported in validation message are correct
			String testXML = DebugValidateXML.wrapXMLInRootElement(xml);
			paintOriginalXML(testXML, writer);

			writer.println("</div>");
		} else {
			// XML is valid
			writer.write(xml);
		}

		LOG.debug("Validate XML Interceptor: Finished");
	}
693978
@Override
	public void doRender(final WComponent component, final WebXmlRenderContext renderContext) {
		WMenuItemGroup group = (WMenuItemGroup) component;
		XmlStringBuilder xml = renderContext.getWriter();

		xml.appendTagOpen("ui:menugroup");
		xml.appendAttribute("id", component.getId());
		xml.appendOptionalAttribute("class", component.getHtmlClass());
		xml.appendOptionalAttribute("track", component.isTracking(), "true");
		xml.appendClose();

		paintChildren(group, renderContext);

		xml.appendEndTag("ui:menugroup");
	}
486177
@Override
	public void paint(final RenderContext renderContext) {
		super.paint(renderContext);
		UIContext uic = UIContextHolder.getCurrent();

		if (LOG.isDebugEnabled()) {
			UIContextDebugWrapper debugWrapper = new UIContextDebugWrapper(uic);
			LOG.debug("Session usage after paint:\n" + debugWrapper);
		}

		LOG.debug("Performing session tidy up of WComponents (any WComponents disconnected from the active top component will not be tidied up.");
		getUI().tidyUpUIContextForTree();

		LOG.debug("After paint - Clearing scratch maps.");
		uic.clearScratchMap();
		uic.clearRequestScratchMap();
	}
219044
@Override
	public void doRender(final WComponent component, final WebXmlRenderContext renderContext) {
		WCollapsible collapsible = (WCollapsible) component;
		XmlStringBuilder xml = renderContext.getWriter();
		WComponent content = collapsible.getContent();
		boolean collapsed = collapsible.isCollapsed();

		xml.appendTagOpen("ui:collapsible");
		xml.appendAttribute("id", component.getId());
		xml.appendOptionalAttribute("class", component.getHtmlClass());
		xml.appendOptionalAttribute("track", component.isTracking(), "true");
		xml.appendAttribute("groupName", collapsible.getGroupName());
		xml.appendOptionalAttribute("collapsed", collapsed, "true");
		xml.appendOptionalAttribute("hidden", collapsible.isHidden(), "true");

		switch (collapsible.getMode()) {
			case CLIENT:
				xml.appendAttribute("mode", "client");
				break;
			case LAZY:
				xml.appendAttribute("mode", "lazy");
				break;
			case EAGER:
				xml.appendAttribute("mode", "eager");
				break;
			case DYNAMIC:
				xml.appendAttribute("mode", "dynamic");
				break;
			case SERVER:
				xml.appendAttribute("mode", "server");
				break;
			default:
				throw new SystemException("Unknown collapsible mode: " + collapsible.getMode());
		}

		HeadingLevel level = collapsible.getHeadingLevel();
		if (level != null) {
			xml.appendAttribute("level", level.getLevel());
		}

		xml.appendClose();

		// Render margin
		MarginRendererUtil.renderMargin(collapsible, renderContext);

		// Label
		collapsible.getDecoratedLabel().paint(renderContext);

		// Content
		xml.appendTagOpen("ui:content");
		xml.appendAttribute("id", component.getId() + "-content");
		xml.appendClose();

		// Render content if not EAGER Mode or is EAGER and is the current AJAX trigger
		if (CollapsibleMode.EAGER != collapsible.getMode() || AjaxHelper.isCurrentAjaxTrigger(
				collapsible)) {
			// Visibility of content set in prepare paint
			content.paint(renderContext);
		}

		xml.appendEndTag("ui:content");

		xml.appendEndTag("ui:collapsible");
	}