/******************************************************************************* * 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.apache.ofbiz.widget.renderer.html; import java.io.IOException; import java.util.List; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.ofbiz.base.util.StringUtil; import org.apache.ofbiz.base.util.UtilGenerics; import org.apache.ofbiz.base.util.UtilProperties; import org.apache.ofbiz.base.util.UtilValidate; import org.apache.ofbiz.webapp.control.RequestHandler; import org.apache.ofbiz.webapp.taglib.ContentUrlTag; import org.apache.ofbiz.widget.WidgetWorker; import org.apache.ofbiz.widget.model.ModelTree; import org.apache.ofbiz.widget.model.ModelWidget; import org.apache.ofbiz.widget.renderer.ScreenRenderer; import org.apache.ofbiz.widget.renderer.ScreenStringRenderer; import org.apache.ofbiz.widget.renderer.TreeStringRenderer; import org.apache.ofbiz.widget.renderer.macro.MacroScreenRenderer; import freemarker.template.TemplateException; /** * Widget Library - HTML Tree Renderer implementation */ public class HtmlTreeRenderer extends HtmlWidgetRenderer implements TreeStringRenderer { ScreenStringRenderer screenStringRenderer = null; public static final String module = HtmlTreeRenderer.class.getName(); public HtmlTreeRenderer() {} public void renderNodeBegin(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node, int depth) throws IOException { String currentNodeTrailPiped = null; List<String> currentNodeTrail = UtilGenerics.toList(context.get("currentNodeTrail")); if (node.isRootNode()) { appendWhitespace(writer); this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context); renderBeginningBoundaryComment(writer, "Tree Widget", node.getModelTree()); writer.append("<ul class=\"basic-tree\">"); } appendWhitespace(writer); writer.append("<li>"); String pkName = node.getPkName(context); String entityId = null; String entryName = node.getEntryName(); if (UtilValidate.isNotEmpty(entryName)) { entityId = UtilGenerics.<Map<String, String>>cast(context.get(entryName)).get(pkName); } else { entityId = (String) context.get(pkName); } boolean hasChildren = node.hasChildren(context); // check to see if this node needs to be expanded. if (hasChildren && node.isExpandCollapse()) { String targetEntityId = null; List<String> targetNodeTrail = UtilGenerics.toList(context.get("targetNodeTrail")); if (depth < targetNodeTrail.size()) { targetEntityId = targetNodeTrail.get(depth); } // FIXME: Using a widget model in this way is an ugly hack. ModelTree.ModelNode.Link expandCollapseLink = null; int openDepth = node.getModelTree().getOpenDepth(); if (depth >= openDepth && (targetEntityId == null || !targetEntityId.equals(entityId))) { // Not on the trail if (node.showPeers(depth, context)) { context.put("processChildren", Boolean.FALSE); //expandCollapseLink.setText(" + "); currentNodeTrailPiped = StringUtil.join(currentNodeTrail, "|"); StringBuilder target = new StringBuilder(node.getModelTree().getExpandCollapseRequest(context)); String trailName = node.getModelTree().getTrailName(context); if (target.indexOf("?") < 0) { target.append("?"); } else { target.append("&"); } target.append(trailName).append("=").append(currentNodeTrailPiped); expandCollapseLink = new ModelTree.ModelNode.Link("collapsed", target.toString(), " "); } } else { context.put("processChildren", Boolean.TRUE); //expandCollapseLink.setText(" - "); String lastContentId = currentNodeTrail.remove(currentNodeTrail.size() - 1); currentNodeTrailPiped = StringUtil.join(currentNodeTrail, "|"); if (currentNodeTrailPiped == null) { currentNodeTrailPiped = ""; } StringBuilder target = new StringBuilder(node.getModelTree().getExpandCollapseRequest(context)); String trailName = node.getModelTree().getTrailName(context); if (target.indexOf("?") < 0) { target.append("?"); } else { target.append("&"); } target.append(trailName).append("=").append(currentNodeTrailPiped); expandCollapseLink = new ModelTree.ModelNode.Link("expanded", target.toString(), " "); // add it so it can be remove in renderNodeEnd currentNodeTrail.add(lastContentId); } if (expandCollapseLink != null) { renderLink(writer, context, expandCollapseLink); } } else if (!hasChildren) { context.put("processChildren", Boolean.FALSE); ModelTree.ModelNode.Link expandCollapseLink = new ModelTree.ModelNode.Link("leafnode", "", " "); renderLink(writer, context, expandCollapseLink); } } public void renderNodeEnd(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node) throws IOException { Boolean processChildren = (Boolean) context.get("processChildren"); if (processChildren.booleanValue()) { appendWhitespace(writer); writer.append("</ul>"); } appendWhitespace(writer); writer.append("</li>"); if (node.isRootNode()) { appendWhitespace(writer); writer.append("</ul>"); appendWhitespace(writer); renderEndingBoundaryComment(writer, "Tree Widget", node.getModelTree()); } } public void renderLastElement(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node) throws IOException { Boolean processChildren = (Boolean) context.get("processChildren"); if (processChildren.booleanValue()) { appendWhitespace(writer); writer.append("<ul class=\"basic-tree\">"); } } public void renderLabel(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Label label) throws IOException { // open tag writer.append("<span"); String id = label.getId(context); if (UtilValidate.isNotEmpty(id)) { writer.append(" id=\""); writer.append(id); writer.append("\""); } String style = label.getStyle(context); if (UtilValidate.isNotEmpty(style)) { writer.append(" class=\""); writer.append(style); writer.append("\""); } writer.append(">"); // the text writer.append(label.getText(context)); // close tag writer.append("</span>"); appendWhitespace(writer); } public void renderLink(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Link link) throws IOException { // open tag writer.append("<a"); String id = link.getId(context); if (UtilValidate.isNotEmpty(id)) { writer.append(" id=\""); writer.append(id); writer.append("\""); } String style = link.getStyle(context); if (UtilValidate.isNotEmpty(style)) { writer.append(" class=\""); writer.append(style); writer.append("\""); } String name = link.getName(context); if (UtilValidate.isNotEmpty(name)) { writer.append(" name=\""); writer.append(name); writer.append("\""); } String title = link.getTitle(context); if (UtilValidate.isNotEmpty(title)) { writer.append(" title=\""); writer.append(title); writer.append("\""); } String targetWindow = link.getTargetWindow(context); if (UtilValidate.isNotEmpty(targetWindow)) { writer.append(" target=\""); writer.append(targetWindow); writer.append("\""); } String target = link.getTarget(context); if (UtilValidate.isNotEmpty(target)) { writer.append(" href=\""); String urlMode = link.getUrlMode(); String prefix = link.getPrefix(context); HttpServletResponse res = (HttpServletResponse) context.get("response"); HttpServletRequest req = (HttpServletRequest) context.get("request"); if (urlMode != null && urlMode.equalsIgnoreCase("intra-app")) { if (req != null && res != null) { WidgetWorker.buildHyperlinkUrl(writer, target, link.getUrlMode(), link.getParameterMap(context), link.getPrefix(context), link.getFullPath(), link.getSecure(), link.getEncode(), req, res, context); } else if (prefix != null) { writer.append(prefix).append(target); } else { writer.append(target); } } else if (urlMode != null && urlMode.equalsIgnoreCase("content")) { StringBuilder newURL = new StringBuilder(); ContentUrlTag.appendContentPrefix(req, newURL); newURL.append(target); writer.append(newURL.toString()); } else if ("inter-app".equalsIgnoreCase(urlMode) && req != null) { String externalLoginKey = (String) req.getAttribute("externalLoginKey"); if (UtilValidate.isNotEmpty(externalLoginKey)) { writer.append(target); if (target.contains("?")) { writer.append("&externalLoginKey="); } else { writer.append("?externalLoginKey="); } writer.append(externalLoginKey); } } else { writer.append(target); } writer.append("\""); } writer.append(">"); // the text ModelTree.ModelNode.Image img = link.getImage(); if (img == null) { writer.append(link.getText(context)); } else { renderImage(writer, context, img); } // close tag writer.append("</a>"); } public void renderImage(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Image image) throws IOException { // open tag writer.append("<img "); String id = image.getId(context); if (UtilValidate.isNotEmpty(id)) { writer.append(" id=\""); writer.append(id); writer.append("\""); } String style = image.getStyle(context); if (UtilValidate.isNotEmpty(style)) { writer.append(" class=\""); writer.append(style); writer.append("\""); } String wid = image.getWidth(context); if (UtilValidate.isNotEmpty(wid)) { writer.append(" width=\""); writer.append(wid); writer.append("\""); } String hgt = image.getHeight(context); if (UtilValidate.isNotEmpty(hgt)) { writer.append(" height=\""); writer.append(hgt); writer.append("\""); } String border = image.getBorder(context); if (UtilValidate.isNotEmpty(border)) { writer.append(" border=\""); writer.append(border); writer.append("\""); } String src = image.getSrc(context); if (UtilValidate.isNotEmpty(src)) { writer.append(" src=\""); String urlMode = image.getUrlMode(); boolean fullPath = false; boolean secure = false; boolean encode = false; HttpServletResponse response = (HttpServletResponse) context.get("response"); HttpServletRequest request = (HttpServletRequest) context.get("request"); if (urlMode != null && urlMode.equalsIgnoreCase("intra-app")) { if (request != null && response != null) { ServletContext ctx = (ServletContext) request.getAttribute("servletContext"); RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_"); String urlString = rh.makeLink(request, response, src, fullPath, secure, encode); writer.append(urlString); } else { writer.append(src); } } else if (urlMode != null && urlMode.equalsIgnoreCase("content")) { if (request != null && response != null) { StringBuilder newURL = new StringBuilder(); ContentUrlTag.appendContentPrefix(request, newURL); newURL.append(src); writer.append(newURL.toString()); } } else { writer.append(src); } writer.append("\""); } writer.append("/>"); } public ScreenStringRenderer getScreenStringRenderer(Map<String, Object> context) { ScreenRenderer screenRenderer = (ScreenRenderer)context.get("screens"); if (screenRenderer != null) { screenStringRenderer = screenRenderer.getScreenStringRenderer(); } else { if (screenStringRenderer == null) { try { screenStringRenderer = new MacroScreenRenderer(UtilProperties.getPropertyValue("widget", "screen.name"), UtilProperties.getPropertyValue("widget", "screen.screenrenderer")); } catch (TemplateException | IOException e) { e.printStackTrace(); } } } return screenStringRenderer; } }