
de.beyondjava.angularFaces.components.puiModelSync.PuiModelSync Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of angularFaces-core Show documentation
Show all versions of angularFaces-core Show documentation
AngularFaces makes JSF programming simpler. In particular, it adds AngularJS to JSF.
/**
* (C) 2013-2014 Stephan Rauh http://www.beyondjava.net
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package de.beyondjava.angularFaces.components.puiModelSync;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Logger;
import javax.el.PropertyNotFoundException;
import javax.faces.application.ProjectStage;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.FacesComponent;
import javax.faces.component.StateHelper;
import javax.faces.component.UIComponent;
import javax.faces.component.ValueHolder;
import javax.faces.component.html.HtmlBody;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import com.google.gson.Gson;
import de.beyondjava.angularFaces.core.ELTools;
import de.beyondjava.angularFaces.core.transformation.AttributeUtilities;
/**
* PuiBody is an HtmlBody that activates the AngularJS/AngularDart framework.
*/
@FacesComponent("de.beyondjava.kendoFaces.puiBody.PuiBody")
public class PuiModelSync extends HtmlBody {
private static final String JSF_ATTRIBUTES_SESSION_PARAMETER = "de.beyondjava.angularFaces.jsfAttributes";
private static final Logger LOGGER = Logger.getLogger("de.beyondjava.kendoFaces.puiBody.PuiBody");
private final Gson gson = new Gson();
/**
* This method is not as superfluous as it seems. We need it to be able to call getStateHelper() in defender methods.
*/
@Override
public StateHelper getStateHelper() {
return super.getStateHelper();
}
public static boolean isJSFAttributesTableEmpty() {
Map sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
Map jsfAttributes = (Map) sessionMap.get(JSF_ATTRIBUTES_SESSION_PARAMETER);
return (null == jsfAttributes || jsfAttributes.isEmpty());
}
public static void initJSFAttributesTable() {
Map sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
if (!sessionMap.containsKey(JSF_ATTRIBUTES_SESSION_PARAMETER)) {
sessionMap.put(JSF_ATTRIBUTES_SESSION_PARAMETER, new HashMap());
} else {
Map jsfAttributes = (Map) sessionMap.get(JSF_ATTRIBUTES_SESSION_PARAMETER);
jsfAttributes.clear();
}
}
public static void addJSFAttrbitute(String key, UIComponent component) {
Map sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
Map jsfAttributes = (Map) sessionMap.get(JSF_ATTRIBUTES_SESSION_PARAMETER);
jsfAttributes.put(key, component);
}
/** Builds basically a JSON structure from the JSF model. */
public void addJSFAttrbituteToAngularModel(Map model, String key, Object value) {
String[] keys = key.split("\\.");
Map currentMap = model;
for (int i = 0; i < keys.length - 1; i++) {
if (!currentMap.containsKey(keys[i])) {
currentMap.put(keys[i], new HashMap());
}
currentMap = (Map) currentMap.get(keys[i]);
}
currentMap.put(keys[keys.length - 1], value);
}
public List getFacesModel() {
Map model = new HashMap();
Map sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
Map jsfAttributes = (Map) sessionMap.get(JSF_ATTRIBUTES_SESSION_PARAMETER);
// sessionMap.remove(JSF_ATTRIBUTES_SESSION_PARAMETER);
for (Entry entry : jsfAttributes.entrySet()) {
try {
String attribute = entry.getKey();
UIComponent comp = entry.getValue();
if (null != comp && comp instanceof EditableValueHolder) {
Object value = ELTools.evalAsObject("#{" + attribute + "}");
Object valueToRender = getValueToRender(FacesContext.getCurrentInstance(), comp);
if (value!=null && valueToRender!=null && valueToRender instanceof String) {
valueToRender=convertToDatatype((String) valueToRender, value.getClass());
}
addJSFAttrbituteToAngularModel(model, attribute, valueToRender);
} else {
Object value = ELTools.evalAsObject("#{" + attribute + "}");
// vex.getValue(FacesContext.getCurrentInstance().getELContext())
addJSFAttrbituteToAngularModel(model, attribute, value);
}
}
catch (PropertyNotFoundException pureAngularAttribute) {
// probably it's an AngularJS attribute that doesn't have a JSF counterpart, so we don't consider this an error
}
}
List beans = new ArrayList();
for (Entry bean: model.entrySet()) {
String assignment = "\"" + bean.getKey() + "\",'" + gson.toJson(bean.getValue())+"'";
beans.add(assignment);
}
return beans;
}
private Object convertToDatatype(String valueToRender, Class targetClass) {
if ("".equals(valueToRender)) return null;
if (null==valueToRender) return null;
if (valueToRender.getClass()==targetClass) return valueToRender;
if (targetClass==int.class) return new Integer((String)valueToRender).intValue();
if (targetClass==long.class) return new Long((String)valueToRender).longValue();
if (targetClass==short.class) return new Short((String)valueToRender).shortValue();
if (targetClass==float.class) return new Float((String)valueToRender).floatValue();
if (targetClass==double.class) return new Double((String)valueToRender).doubleValue();
if (targetClass==byte.class) return new Byte((String)valueToRender).byteValue();
if (targetClass==Integer.class) return new Integer((String)valueToRender);
if (targetClass==Long.class) return new Long((String)valueToRender);
if (targetClass==Short.class) return new Short((String)valueToRender);
if (targetClass==Float.class) return new Float((String)valueToRender);
if (targetClass==Double.class) return new Double((String)valueToRender);
if (targetClass==Byte.class) return new Byte((String)valueToRender);
return null;
}
/**
* This method has been copied from the PrimeFaces 5 project (and been adapted after).
*
* Algorithm works as follows; - If it's an input component, submitted value is checked first since it'd be the value to be used in case
* validation errors terminates jsf lifecycle - Finally the value of the component is retrieved from backing bean and if there's a
* converter, converted value is returned
*
* @param context
* FacesContext instance
* @param component
* UIComponent instance whose value will be returned
* @return End text
*/
public static Object getValueToRender(FacesContext context, UIComponent component) {
if (component instanceof ValueHolder) {
if (component instanceof EditableValueHolder) {
EditableValueHolder input = (EditableValueHolder) component;
Object submittedValue = input.getSubmittedValue();
if (submittedValue == null && context.isValidationFailed() && !input.isValid()) {
return null;
} else if (submittedValue != null) {
return submittedValue;
}
}
ValueHolder valueHolder = (ValueHolder) component;
Object value = valueHolder.getValue();
return value;
}
// component it not a value holder
return null;
}
@Override
public void encodeAll(FacesContext arg0) throws IOException {
encodeBegin(arg0);
}
@Override
public void encodeBegin(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
boolean debugMode = context.isProjectStage(ProjectStage.Development);
if (debugMode) {writer.append("\r\n");}
writer.startElement("script", this);
if (debugMode) {writer.append("\r\n");}
writer.writeText("window.jsfScope=null;", null);
if (debugMode) {writer.append("\r\n");}
writer.writeText("function initJSFScope($scope){", null);
if (debugMode) {writer.append("\r\n ");}
writer.writeText("window.jsfScope=$scope;", null);
if (debugMode) {writer.append("\r\n ");}
if (debugMode) {writer.append("\r\n ");}
List beansAsJSon = getFacesModel();
for (String bean:beansAsJSon){
writer.writeText("injectJSonIntoScope(" +bean +",$scope);", null);
}
if (debugMode) {writer.append("\r\n");}
writer.writeText("}", null);
if (debugMode) {writer.append("\r\n");}
writer.endElement("script");
if (debugMode) {writer.append("\r\n");}
String main = AttributeUtilities.getAttributeAsString(this, "angularJSFile");
if (main == null) {
main = "main.js";
}
if (!main.endsWith(".js")) {
main = main + ".js";
}
writer.append("");
PuiScriptRenderer r = new PuiScriptRenderer();
// Locale locale = context.getViewRoot().getLocale();
Locale locale = context.getExternalContext().getRequestLocale();
String language = locale.getLanguage();
r.encodeScript(context, this, "messages_" + language +".js", "AngularFaces");
r.encodeScript(context, this, "components.js", "AngularFaces");
r.encodeScript(context, this, "glue.js", "AngularFaces");
r.encodeMessageBundle(context);
}
@Override
public void encodeChildren(FacesContext arg0) throws IOException {
}
@Override
public void encodeEnd(FacesContext arg0) throws IOException {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy