View Javadoc
1   /*
2    * Copyright (c) 2011-2024 PrimeFaces Extensions
3    *
4    *  Permission is hereby granted, free of charge, to any person obtaining a copy
5    *  of this software and associated documentation files (the "Software"), to deal
6    *  in the Software without restriction, including without limitation the rights
7    *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    *  copies of the Software, and to permit persons to whom the Software is
9    *  furnished to do so, subject to the following conditions:
10   *
11   *  The above copyright notice and this permission notice shall be included in
12   *  all copies or substantial portions of the Software.
13   *
14   *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20   *  THE SOFTWARE.
21   */
22  package org.primefaces.extensions.component.orgchart;
23  
24  import java.io.IOException;
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.Map;
28  
29  import javax.el.ValueExpression;
30  import javax.faces.FacesException;
31  import javax.faces.component.UIComponent;
32  import javax.faces.context.FacesContext;
33  import javax.faces.context.ResponseWriter;
34  
35  import org.primefaces.extensions.util.Attrs;
36  import org.primefaces.renderkit.CoreRenderer;
37  import org.primefaces.shaded.json.JSONArray;
38  import org.primefaces.shaded.json.JSONObject;
39  import org.primefaces.util.HTML;
40  import org.primefaces.util.WidgetBuilder;
41  
42  /**
43   * <code>orgchart</code> component.
44   *
45   * @author @jxmai / last modified by $Author$
46   * @version $Revision$
47   * @since 7.0
48   */
49  public class OrgChartRenderer extends CoreRenderer {
50  
51      private static final String JSON_CHILDREN = "children";
52  
53      @Override
54      public void encodeEnd(final FacesContext context, final UIComponent component) throws IOException {
55          final OrgChart orgChart = (OrgChart) component;
56          encodeMarkup(context, orgChart);
57          encodeScript(context, orgChart);
58      }
59  
60      @Override
61      public void decode(final FacesContext context, final UIComponent component) {
62  
63          final OrgChart orgChart = (OrgChart) component;
64  
65          decodeNodeStructure(context, orgChart);
66          decodeBehaviors(context, component);
67      }
68  
69      private static void decodeNodeStructure(final FacesContext context, final OrgChart orgChart) {
70          final Map<String, String> params = context.getExternalContext().getRequestParameterMap();
71  
72          final String hierarchyStr = params.get(orgChart.getClientId() + "_hierarchy");
73  
74          if (null != hierarchyStr && !hierarchyStr.isEmpty()) {
75              final JSONObject hierarchy = new JSONObject(hierarchyStr);
76  
77              final ValueExpression ve = orgChart.getValueExpression("value");
78              OrgChartNode root = (OrgChartNode) ve.getValue(context.getELContext());
79  
80              final List<OrgChartNode> orgChartNodes = OrgChartHelper.getAllNodesTraverseFromRoot(root);
81  
82              for (final OrgChartNode o : orgChartNodes) {
83                  o.clearChildren();
84              }
85  
86              final Map<String, OrgChartNode> hashMap = OrgChartHelper
87                          .parseOrgChartNodesIntoHashMap(orgChartNodes);
88  
89              root = buildNodesFromJSON(hashMap, hierarchy, null);
90  
91              ve.setValue(context.getELContext(), root);
92  
93          }
94      }
95  
96      public static OrgChartNode buildNodesFromJSON(final Map<String, OrgChartNode> orgChartNodes,
97                  final JSONObject hierarchy, OrgChartNode parentNode) {
98          final String id = (String) hierarchy.get("id");
99          final OrgChartNode node = orgChartNodes.get(id);
100 
101         if (parentNode == null) {
102             parentNode = node;
103         }
104 
105         if (hierarchy.has(JSON_CHILDREN)) {
106             final JSONArray array = (JSONArray) hierarchy.get(JSON_CHILDREN);
107 
108             for (int i = 0; i < array.length(); i++) {
109                 final JSONObject jsonObject = array.getJSONObject(i);
110                 buildNodesFromJSON(orgChartNodes, jsonObject,
111                             orgChartNodes.get(jsonObject.get("id")));
112 
113                 parentNode.addChild(orgChartNodes.get(jsonObject.get("id")));
114 
115             }
116         }
117 
118         return node;
119 
120     }
121 
122     private void encodeMarkup(final FacesContext context, final OrgChart orgChart) throws IOException {
123         final ResponseWriter writer = context.getResponseWriter();
124         final String clientId = orgChart.getClientId();
125         final String widgetVar = orgChart.resolveWidgetVar();
126         final String styleClass = getStyleClassBuilder(context)
127                     .add(OrgChart.STYLE_CLASS)
128                     .add(orgChart.getStyleClass())
129                     .build();
130 
131         writer.startElement("div", orgChart);
132         writer.writeAttribute("id", clientId, "id");
133         writer.writeAttribute(HTML.WIDGET_VAR, widgetVar, null);
134         writer.writeAttribute(Attrs.CLASS, styleClass, "styleClass");
135         if (orgChart.getStyle() != null) {
136             writer.writeAttribute(Attrs.STYLE, orgChart.getStyle(), Attrs.STYLE);
137         }
138         writer.endElement("div");
139     }
140 
141     private void encodeScript(final FacesContext context, final OrgChart orgChart)
142                 throws IOException {
143         final WidgetBuilder wb = getWidgetBuilder(context);
144 
145         final OrgChartNode orgChartNode;
146         if (orgChart.getValue() == null) {
147             throw new FacesException("The value attribute must be OrgChartNode");
148         }
149         else {
150             if (!(orgChart.getValue() instanceof OrgChartNode)) {
151                 throw new FacesException("The value attribute must be OrgChartNode");
152             }
153             else {
154                 orgChartNode = (OrgChartNode) orgChart.getValue();
155             }
156         }
157 
158         final String data = toJSON(orgChartNode, orgChartNode.getChildren()).toString();
159 
160         wb.init("ExtOrgChart", orgChart);
161         wb.attr("nodeId", orgChart.getNodeId());
162         wb.attr("nodeContent", orgChart.getNodeContent());
163         wb.attr("direction", orgChart.getDirection());
164         wb.attr("pan", orgChart.getPan());
165         wb.attr("toggleSiblingsResp", orgChart.getToggleSiblingsResp());
166         wb.attr("depth", orgChart.getDepth());
167         wb.attr("exportButton", orgChart.getExportButton());
168         wb.attr("exportFilename", orgChart.getExportFilename());
169         wb.attr("exportFileextension", orgChart.getExportFileextension());
170         wb.attr("parentNodeSymbol", orgChart.getParentNodeSymbol());
171         wb.attr("draggable", orgChart.getDraggable());
172         wb.attr("chartClass", orgChart.getChartClass());
173         wb.attr("zoom", orgChart.getZoom());
174         wb.attr("zoominLimit", orgChart.getZoominLimit());
175         wb.attr("zoomoutLimit", orgChart.getZoomoutLimit());
176         wb.attr("verticalDepth", orgChart.getVerticalDepth());
177         wb.attr("nodeTitle", orgChart.getNodeTitle());
178         wb.nativeAttr("extender", orgChart.getExtender());
179         wb.attr("data", data);
180 
181         encodeClientBehaviors(context, orgChart);
182         wb.finish();
183     }
184 
185     public static JSONObject toJSON(final OrgChartNode orgChartNode, final List<OrgChartNode> children) {
186 
187         final JSONObject json = new JSONObject();
188 
189         if (null != orgChartNode.getId() && !orgChartNode.getId().isEmpty()) {
190             json.put("id", orgChartNode.getId());
191         }
192 
193         json.put("name", orgChartNode.getName());
194         json.put("title", orgChartNode.getTitle());
195         if (null != orgChartNode.getClassName() && !orgChartNode.getClassName().isEmpty()) {
196             json.put("className", orgChartNode.getClassName());
197         }
198 
199         if (orgChartNode.getChildCount() > 0) {
200             final List<JSONObject> jsonChildren = new ArrayList<>();
201             for (int i = 0; i < orgChartNode.getChildCount(); i++) {
202                 jsonChildren.add(toJSON(orgChartNode.getChildren().get(i),
203                             orgChartNode.getChildren().get(i).getChildren()));
204             }
205             json.put(JSON_CHILDREN, jsonChildren);
206         }
207 
208         return json;
209     }
210 
211 }