/** * Copyright (c) 2000-2017 Liferay, Inc. All rights reserved. * * Licensed 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 com.liferay.faces.util.render; import java.io.IOException; import javax.faces.component.UIComponent; import javax.faces.component.UINamingContainer; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.render.Renderer; import com.liferay.faces.util.client.Script; import com.liferay.faces.util.client.ScriptFactory; import com.liferay.faces.util.component.ClientComponent; import com.liferay.faces.util.component.ComponentUtil; import com.liferay.faces.util.context.FacesRequestContext; /** * This is an abstract class that provides base rendering functionality. It extends normal rendering with methods such * as {@link #encodeMarkupBegin(FacesContext, UIComponent)} and {@link #encodeMarkupEnd(FacesContext, UIComponent)} that * provide a more fine-grained rendering sequence. * * @author Neil Griffin */ public abstract class ClientComponentRendererBase extends Renderer implements ClientComponentRenderer { /** * @see {@link ClientComponentRenderer#encodeJavaScript(javax.faces.context.FacesContext, * javax.faces.component.UIComponent)} */ @Override public abstract void encodeJavaScript(FacesContext facesContext, UIComponent uiComponent) throws IOException; /** * @see {@link ClientComponentRenderer#encodeMarkupBegin(javax.faces.context.FacesContext, * javax.faces.component.UIComponent)} */ @Override public abstract void encodeMarkupBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException; /** * @see {@link ClientComponentRenderer#encodeMarkupEnd(javax.faces.context.FacesContext, * javax.faces.component.UIComponent)} */ @Override public abstract void encodeMarkupEnd(FacesContext facesContext, UIComponent uiComponent) throws IOException; @Override public void decode(FacesContext facesContext, UIComponent uiComponent) { decodeClientState(facesContext, uiComponent); super.decode(facesContext, uiComponent); } /** * @see {@link ClientComponentRenderer#decodeClientState(javax.faces.context.FacesContext, * javax.faces.component.UIComponent)} */ @Override public void decodeClientState(FacesContext facesContext, UIComponent uiComponent) { // no-op } @Override public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException { super.encodeBegin(facesContext, uiComponent); encodeMarkupBegin(facesContext, uiComponent); } /** * @see {@link ClientComponentRenderer#encodeClientState(javax.faces.context.FacesContext, * javax.faces.context.ResponseWriter, javax.faces.component.UIComponent)} */ @Override public void encodeClientState(FacesContext facesContext, ResponseWriter responseWriter, UIComponent uiComponent) throws IOException { // no-op } @Override public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) throws IOException { super.encodeEnd(facesContext, uiComponent); ResponseWriter responseWriter = facesContext.getResponseWriter(); encodeClientState(facesContext, responseWriter, uiComponent); encodeMarkupEnd(facesContext, uiComponent); encodeJavaScript(facesContext, uiComponent); } protected void encodeBooleanProperty(ResponseWriter responseWriter, String propertyName, Boolean propertyValue, boolean first) throws IOException { if (!first) { responseWriter.write(","); } responseWriter.write(propertyName); responseWriter.write(":"); responseWriter.write(propertyValue.toString()); } protected void encodeClientIdProperty(ResponseWriter responseWriter, String propertyName, String clientId, boolean first) throws IOException { String escapedClientId = "'#" + ComponentUtil.escapeClientId(clientId) + "'"; encodeNonEscapedObjectProperty(responseWriter, propertyName, escapedClientId, first); } protected void encodeClientIdProperty(ResponseWriter responseWriter, String propertyName, String clientId, UIComponent uiComponent, boolean first) throws IOException { UIComponent forComponent = uiComponent.findComponent(clientId); String escapedClientId = clientId; if (forComponent != null) { escapedClientId = forComponent.getClientId(); } encodeClientIdProperty(responseWriter, propertyName, escapedClientId, first); } protected void encodeFunctionCall(ResponseWriter responseWriter, String functionName, Object... parameters) throws IOException { responseWriter.write(functionName); responseWriter.write("("); boolean first = true; for (Object parameter : parameters) { if (first) { first = false; } else { responseWriter.write(","); } encodeFunctionParameter(responseWriter, parameter); } responseWriter.write(");"); } protected void encodeIntegerProperty(ResponseWriter responseWriter, String propertyName, Integer propertyValue, boolean first) throws IOException { if (!first) { responseWriter.write(","); } responseWriter.write(propertyName); responseWriter.write(":"); responseWriter.write(propertyValue.toString()); } protected void encodeNonEscapedObjectProperty(ResponseWriter responseWriter, String propertyName, Object propertyValue, boolean first) throws IOException { if (!first) { responseWriter.write(","); } responseWriter.write(propertyName); responseWriter.write(":"); responseWriter.write(propertyValue.toString()); } protected void encodeStringProperty(ResponseWriter responseWriter, String propertyName, Object propertyValue, boolean first) throws IOException { String escapedAttributeValue = RendererUtil.escapeJavaScript(propertyValue.toString()); if (!first) { responseWriter.write(","); } responseWriter.write(propertyName); responseWriter.write(":'"); responseWriter.write(escapedAttributeValue); responseWriter.write("'"); } protected String getClientVarName(FacesContext facesContext, ClientComponent clientComponent) { char separatorChar = UINamingContainer.getSeparatorChar(facesContext); String clientId = clientComponent.getClientId(); String regex = "[" + separatorChar + "]"; String clientVarName = clientId.replaceAll(regex, "_"); return clientVarName; } protected void renderScript(FacesContext facesContext, String bufferedScriptString, String[] modules, Script.ModulesType modulesType) { Script script; if (modules != null) { script = ScriptFactory.getScriptInstance(facesContext.getExternalContext(), bufferedScriptString, modules, modulesType); } else { script = ScriptFactory.getScriptInstance(facesContext.getExternalContext(), bufferedScriptString); } FacesRequestContext facesRequestContext = FacesRequestContext.getCurrentInstance(); facesRequestContext.addScript(script); } private void encodeFunctionParameter(ResponseWriter responseWriter, Object parameter) throws IOException { if (parameter == null) { responseWriter.write("null"); } else { if (parameter instanceof Object[]) { Object[] parameterItems = (Object[]) parameter; if (parameterItems.length == 0) { responseWriter.write("[]"); } else { responseWriter.write("["); boolean firstIndex = true; for (Object parameterItem : parameterItems) { if (firstIndex) { firstIndex = false; } else { responseWriter.write(","); } encodeFunctionParameter(responseWriter, parameterItem); } responseWriter.write("]"); } } else if (parameter instanceof String) { responseWriter.write("'" + parameter.toString() + "'"); } else { responseWriter.write(parameter.toString()); } } } }