| Author |
Message |
|
|
Gostaria de pedir ao Sérgio e amigos commiters do nosso querido Mentawai para que pudessem dar uma olhada em algumas classes no estilo de JSONGenericRenderer e outras que possam ser extendidas, para que tivessem um suporte melhor para extensão.
Por exemplo, tive que adicionar algumas características a essa classe e existiam alguns métodos que se encontravam private e não pude reutilizá-los na minha classe filha, sendo assim tive que baixar o fonte e copiar praticamente ela inteira para que pudesse fazer funcionar em meu projeto.
Os métodos que estão "private" e que poderiam estar "protected" ou "public" são:
convertListData, convertBean, convertCollection, convertListBean, convertListBean.
Aqui vai o código:
Code:
package br.com.equus.cinesnack.renderer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import net.sf.json.JSONArray;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import org.mentawai.ajax.AjaxConsequence;
import org.mentawai.ajax.renderer.JSONGenericRenderer;
import org.mentawai.core.MapOutput;
import org.mentawai.i18n.LocaleManager;
import org.mentawai.list.ListData;
import org.mentawai.list.ListItem;
import org.mentawai.util.InjectionUtils;
import org.mentawai.util.MentaJson;
public class JSONExtjsRenderer extends JSONGenericRenderer {
String nameRoot = "results";
String totalLabel = "total";
String dateFormat = null;
private int levels = 0;
private int currentLevel = 0;
/**
* List de propriedades excluidas.
* Ex: hibernateLazyInitializer
*/
private static List<String> excludedProperties = new ArrayList<String>();
static {
excludedProperties.add("hibernateLazyInitializer");
}
public JSONExtjsRenderer() {
}
public JSONExtjsRenderer(String dateFormat) {
this.dateFormat = dateFormat;
}
public JSONExtjsRenderer(String dateFormat, String nameRoot) {
this(dateFormat);
this.nameRoot = nameRoot;
}
public JSONExtjsRenderer(int levels) {
this.levels = levels;
}
public JSONExtjsRenderer(String dateFormat, int levels) {
this(dateFormat);
this.levels = levels;
}
public String encode(Object object, Locale loc, boolean pretty) throws Exception {
if(object instanceof String){
return object.toString();
}
return buildJSON(object, loc).toString();
}
public String getContentType() {
return APP_URLENCODED; // better from binary objects!
}
public String getCharset() {
return AjaxConsequence.DEFAULT_CHARSET;
}
@SuppressWarnings("unchecked")
protected JSONObject buildJSON(Object obj, Locale loc) {
try {
JSONObject jsonBean = MentaJson.getJSONObject();
if (obj instanceof Map) {
jsonBean.put(totalLabel, ((Map)obj).size());
return jsonBean.put(nameRoot, convertMap((Map) obj, loc));
} else if (obj instanceof Collection) {
jsonBean.put(totalLabel, ((Collection)obj).size());
return jsonBean.put(nameRoot, convertListBean((Collection) obj, loc));
} else if(obj instanceof ListData) {
jsonBean.put(totalLabel, ((ListData)obj).size());
return jsonBean.put(nameRoot, convertListData((ListData) obj, loc));
} else { // Every Bean Must implement Serializable
jsonBean.put(totalLabel, 1);
return jsonBean.put(nameRoot, MentaJson.getJSONArray().put(convertBean(obj, loc)));
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
private JSONArray convertListData(ListData listData, Locale loc) {
List<ListItem> itens = listData.getValues(loc);
JSONArray jsa = MentaJson.getJSONArray();
JSONObject jso;
for (ListItem listItem : itens) {
try {
jso = MentaJson.getJSONObject().put("key", listItem.getKey()).put("value", listItem.getValue());
jsa.put(jso);
} catch (JSONException e) {
e.printStackTrace();
}
}
return jsa;
}
@SuppressWarnings("unchecked")
private JSONObject convertBean(Object bean, Locale loc){
MapOutput om = new MapOutput();
InjectionUtils.setObject(bean, om, null, false);
Iterator<String> interator = om.keys();
JSONObject jsonObj = MentaJson.getJSONObject();
String propertyName;
Object value;
while(interator.hasNext()){
propertyName = interator.next();
if(excludedProperties.contains(propertyName))
continue;
value = om.getValue(propertyName);
if(value instanceof Date) {
if(value != null) {
if(dateFormat == null){
SimpleDateFormat sdf = LocaleManager.getSimpleDateFormat(loc);
if (sdf != null) { value = sdf.format(value); }
} else {
value = new SimpleDateFormat(dateFormat).format(value);
}
}
}
if (value == null) value = "";
try {
if(isValidBean(value) && !value.equals("") && (levels > currentLevel)){ // Probably is JavaBean
currentLevel++;
jsonObj.put(propertyName, convertBean(value, loc)); // Recursive call
} else {
if(isWrapper(value) && !isValidBean(value)) {
jsonObj.put(propertyName, value.toString());
} else {
if (value instanceof Collection && (levels == 1) && (levels > currentLevel)) {
Collection list = (Collection) value;
jsonObj.put(propertyName, convertListBean(new ArrayList(list), loc));
} else {
jsonObj.put(propertyName, "");
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
currentLevel = 0;
return jsonObj;
}
@SuppressWarnings("unchecked")
private JSONArray convertCollection(Collection col){
JSONArray array = MentaJson.getJSONArray();
for (Object object : col) {
array.put(object.toString());
}
return array;
}
@SuppressWarnings("unchecked")
private JSONArray convertListBean(Collection list, Locale loc) {
JSONArray jsonArray = MentaJson.getJSONArray();
for (Object object : list) {
if(isValidBean(object)) { // if is bean
jsonArray.put(convertBean(object, loc));
} else {
jsonArray = convertCollection(list);
break;
}
}
return jsonArray;
}
@SuppressWarnings("unchecked")
private JSONArray convertMap(Map obj, Locale loc) {
Map map = (Map) obj;
Entry entry = null;
Object value;
JSONArray jsonArray = MentaJson.getJSONArray();
for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
entry = (Entry) iter.next();
try {
value = entry.getValue();
if(value instanceof Map){ // Recursive call
jsonArray.put( MentaJson.getJSONObject()
.put("key", entry.getKey().toString())
.put("value", convertMap( (Map) value, loc)) );
} else if (value instanceof Collection){
jsonArray.put( MentaJson.getJSONObject()
.put("key", entry.getKey().toString())
.put("value", convertCollection( (Collection) value) ));
} else if(value instanceof ListData) {
jsonArray.put( MentaJson.getJSONObject()
.put("key", entry.getKey().toString())
.put("value", convertListData( (ListData) value, loc))
);
} else {
jsonArray.put( MentaJson.getJSONObject()
.put("key", entry.getKey().toString())
.put("value", entry.getValue()) );
}
} catch (JSONException e) {
e.printStackTrace();
}
}
return jsonArray;
}
}
Muito Obrigado...
|
 |
|
|
Olá Andre,
Você conseguiu resolver esse problema?
|
 |
|
|
|
Sim, mas é o servlet do proprio ZK e eu gostaria de saber como fazer para mapear as urls do mentawai configuradas no appManager.
|
 |
|
|
|
Iae pessoal, eu sei que estou desenterrando esse tópico, mas alguém descobriu como fazer a integração do Zk com o Mentawai?
|
 |
|
|
Olá saoj e pessoal,
To postando minha versao de BeanCollectionAjaxRenderer, detalhe que se os métodos, printCR, printTab fossem publicos eu poderia ter usado herança, mesmo assim seria legal vcs deixarem essa classe de rederização de Collection com opção de formatação dinâmica, eu gostei bastante da solução que criei e espero que ajude outras pessoas, Abraços pessoal... esse framework é o melhor!!!! regulo em suas entranhas com muita facilidade. Só acho q algumas classes poderiam ser reescritas de alguma forma mais favorável para sua extensao de funcionalidade.
Code:
package org.extjsmentawai.utils.renderer;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import org.mentawai.ajax.AjaxRenderer;
import org.mentawai.formatter.Formatter;
import org.mentawai.formatter.FormatterManager;
import org.mentawai.util.InjectionUtils;
@SuppressWarnings("unchecked")
public abstract class BeanCollectionFormatAjaxRenderer implements AjaxRenderer {
private String CHARSET;
private String root;
private String child;
private String[] subTagsAttrs;
private String[] attrsAttrs;
private boolean isLoaded = false;
private Map<String, Object> formatters = new HashMap<String, Object>();
private void printCR(StringBuilder sb, boolean pretty) {
if (!pretty) return;
sb.append('\n');
}
private void printTab(StringBuilder sb, boolean pretty, int x) {
if (!pretty) return;
for(int i=0;i<x;i++) sb.append(" ");
}
private Map<String, Object> getFormatters() {
if (isLoaded) return formatters;
synchronized(this) {
if (!isLoaded) {
initFormatters();
isLoaded = true;
}
}
return formatters;
}
public abstract void initFormatters();
public void add(String field, Formatter formatter) {
formatters.put(field, formatter);
}
private Object getFormattedValue(String field, Object value, Locale loc) throws Exception {
Map<String, Object> formatters = getFormatters();
Iterator<String> iter = formatters.keySet().iterator();
while(iter.hasNext()) {
String nameFormatter = iter.next();
if (nameFormatter.equals(field)) {
Object o = formatters.get(nameFormatter);
Formatter f = null;
if (o instanceof String) {
String s = (String) o;
f = FormatterManager.getFormatter(s);
if (f == null) throw new Exception("Cannot find a formatter with this name: " + s);
} else if (o instanceof Formatter) {
f = (Formatter) o;
}
value = f.format(value, loc);
}
}
return value;
}
public String encode(Object obj, Locale loc, boolean pretty) throws Exception {
if (CHARSET.equals("") || CHARSET == null) CHARSET = "UTF-8";
if (!(obj instanceof Collection)) throw new IllegalArgumentException("Object is not a Collection: " + obj);
if (!(obj instanceof Collection)) throw new IllegalArgumentException("Object is not a Collection: " + obj);
Collection coll = (Collection) obj;
StringBuilder sb = new StringBuilder();
sb.append("<?xml version='1.0' encoding='").append(CHARSET).append("' ?>").append((char)13);
sb.append('<').append(root).append('>');
printCR(sb, pretty);
for(Iterator iter = coll.iterator(); iter.hasNext();) {
Object bean = iter.next();
Class<? extends Object> klass = bean.getClass();
printTab(sb, pretty, 1);
sb.append('<').append(child);
if (attrsAttrs != null) {
for (int i = 0; i < attrsAttrs.length; i++) {
String attrName = attrsAttrs[i];
Method method = InjectionUtils.findMethodToGet(klass, attrName);
if (method == null) throw new Exception("Cannot find method to get: " + klass + " / " + attrName);
Object value = getFormattedValue(attrName, method.invoke(bean, (Object[]) null),loc);
sb.append(' ').append(attrName).append("=\"").append(value).append("\"");
}
} else {
sb.append(' ');
}
sb.append('>');
printCR(sb, pretty);
if (subTagsAttrs != null) {
for (int i = 0; i < subTagsAttrs.length; i++) {
String attrName = subTagsAttrs[i];
Method method = InjectionUtils.findMethodToGet(klass, attrName);
if (method == null) throw new Exception("Cannot find method to get: " + klass + " / " + attrName);
printTab(sb, pretty, 2);
Object value = getFormattedValue(attrName, method.invoke(bean, (Object[]) null),loc);
sb.append('<').append(attrName).append('>').append(value).append("</").append(attrName).append('>');
printCR(sb, pretty);
}
}
printTab(sb, pretty, 1);
sb.append("</").append(child).append('>');
printCR(sb, pretty);
}
sb.append("</").append(root).append('>');
printCR(sb, pretty);
return sb.toString();
}
public BeanCollectionFormatAjaxRenderer(String rootTag, String childTag, String[] subTagsAttrs, String[] attrsAttrs, String CHARSET) {
this.root = rootTag;
this.child = childTag;
this.attrsAttrs = attrsAttrs;
this.subTagsAttrs = subTagsAttrs;
this.CHARSET = CHARSET;
}
public String getCharset() {
return CHARSET;
}
public String getContentType() {
return TEXT_XML;
}
}
|
 |
|
|
Bom, eu dei uma estudada no pacote reflection e vi que é realmente muito fácil trabalhar com ele, mas infelizmente percebi que minha empreitada não tinha sentido, pois eu teria que transformar atributos que naum eram string em strings, logo teria que criar uma classe especifica para isso e acho q o java naum da essa flexibilidade toda... terei que fazer a formatacao no meu renderer mesmo, como se estivesse formatando em um jsp mesmo.... Valews pessoal....
Se eu estiver enganado em algum ponto, por favor me digam... ateh mais...
|
 |
|
|
Olá Sergio e equipe Mentawai,
Resolvi implementar um filtro para formatar atributos especificos da minha Collection no ouput dela. Preciso disso pois estou trabalhando somente com ajax.
Eu consegui implementar ateh metade da solução, o resto eu ainda naum consegui por falta de conhecimento nas reflections... talvez exista uma forma mais facil de resolver isso, por isso estou postando logo abaixo meu filtro... se alguem tiver alguma opniao... me falem por favor.
Code:
package org.extjsmentawai.utils.formatter;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.mentawai.core.Filter;
import org.mentawai.core.FilterException;
import org.mentawai.core.InvocationChain;
import org.mentawai.core.Output;
import org.mentawai.formatter.Formatter;
import org.mentawai.formatter.FormatterManager;
import org.mentawai.util.InjectionUtils;
public abstract class FormatCollectionFilter implements Filter {
private boolean isLoaded = false;
private String key;
private Map<String, Object> formatters = new HashMap<String, Object>();
public FormatCollectionFilter(String key) {
this.key = key;
}
private Map<String, Object> getFormatters() {
if (isLoaded) return formatters;
synchronized(this) {
if (!isLoaded) {
initFormatters();
isLoaded = true;
}
}
return formatters;
}
public abstract void initFormatters();
public void add(String field, Formatter formatter) {
formatters.put(field, formatter);
}
private Object getFieldValue(Class<? extends Object> klass, String field, Object bean) throws Exception {
Method method = InjectionUtils.findMethodToGet(klass, field);
if (method == null) throw new Exception("Cannot find method to get: " + klass + " / " + field);
return method.invoke(bean, (Object[]) null);
}
@SuppressWarnings("unchecked")
public String filter(InvocationChain chain) throws Exception {
String result = chain.invoke();
Output output = chain.getAction().getOutput();
Object obj = output.getValue(key);
if (obj instanceof Collection) {
Collection coll = (Collection) obj;
for(Iterator iter = coll.iterator(); iter.hasNext();) {
Object bean = iter.next();
Class<? extends Object> klass = bean.getClass();
Map<String, Object> formatters = getFormatters();
Iterator<String> iterFormat = formatters.keySet().iterator();
while(iterFormat.hasNext()) {
String field = iterFormat.next();
Object toFormat = getFieldValue(klass, field, bean);
if (toFormat == null) continue;
Object o = formatters.get(field);
Formatter f = null;
if (o instanceof String) {
String s = (String) o;
f = FormatterManager.getFormatter(s);
if (f == null) throw new FilterException("Cannot find a formatter with this name: " + s);
} else if (o instanceof Formatter) {
f = (Formatter) o;
}
String formatted = f.format(toFormat, chain.getAction().getLocale());
System.out.println(formatted);
}
}
/**
* Proximo passo criar o objeto lista com os atributos formatados
*/
//output.setValue(key, coll);
}
return result;
}
}
Eu tinha pensado em extender a classe FormatFilter, mas estava tudo private intaum tive que reescrever tudo novamente... Abraço.
|
 |
|
|
|
Ae pessoal, descobri pq naum tava funcionando. O filtro de formatacao naum funcionam para Collections eu teria que implementar um renderer que usasse os Formatters do FormatterManager.... acho q é isso.
|
 |
|
|
Segue meus codigos:
PessoaAction:
Code:
public String lista() throws Exception {
output.setValue(AjaxConsequence.KEY, pessoaDAO.lista());
return SUCCESS;
}
ApplicationManager:
Code:
action("pessoa", PessoaAction.class, "lista")
.on(SUCCESS, new AjaxConsequence(new BeanCollectionAjaxRenderer("raiz", "pessoa", pessoa, null, "ISO-8859-1")))
.filter(new AuthorizationFilter(new Permission("read"), new Permission("write"), new Permission("delete")))
.filter(new PessoaFormatFilter("dd/MM/yyyy"));
Filtro:
Code:
package org.extjsmentawai.utils.formatter;
import org.mentawai.formatter.DateFormatter;
public class PessoaFormatFilter extends FormatFilter {
private String style;
public PessoaFormatFilter(String style) {
this.style = style;
}
@Override
public void initFormatters() {
add("dataNascimento", new DateFormatter(style));
}
}
|
 |
|
|
Ae galera, eu debuguei o codigo aki e constatei que a seguinte linha dentro da classe org.mentawai.filter.FormatFilter não está funcionando:
Code:
Object toFormat = output.getValue(field);
e antes que alguem pergunte, a String 'field' está preenchida com o nome do campo de data da minha classe bean 'Pessoa' sim
E devido a validação abaixo, ela naum da prosseguimento na formatacao:
Code:
if (toFormat == null) continue;
Eu soh naum entendi o por que disto... se alguem souber, ficarei agradecido se puder me explicar, muito obrigado.
Obs.: Estou estudando o mentawai por completo para o meu TCC na fatec e logo após meu estudo estar completo partirei para o JSF, meu objetivo é mostrar quais os beneficios de se utilizar uma framework action-based em certos casos e outra Component-based em outros casos.
|
 |
|
|
O meu DateFormatterFilter esta certo intaum?
Preciso colocar o OVFilter no ApplicationManager pra ele jogar o campo data no output? se sim, antes ou depois do filtro?
Eu ja tinha olhado esses posts antes, mas como agora naum esclareceram minha duvida ja que as coisas naum estao funcionando como funcionaram para o ConverterFilter
|
 |
|
|
|
Ou eu teria que usar ioc de alguma forma? se sim, por favor, como? muito obrigado.
|
 |
|
|
|
Preciso usar o OVFilter pra fazer funcionar o codigo postado acima?
|
 |
|
|
seria algo assim?
Code:
class DateFormatterFilter extends FormatFilter {
@Override
public void initFormatters() {
add("campo", new DateFormatter("dd/MM/yyyy"));
}
}
|
 |
|
|
Galera, to com um probleminha aki. Ja tentei de tudo aki mas nada funciona.
To implementando filtros, ja tentei usar o FormatFilter soh naum tentei o Formattable por motivos de desacoplamento e gostaria muito se alguém pudesse me dizer quais sao todos os passos que devo tomar para fazer funcionar uma conversao(formatacao) no output da minha action. To gerando xml pro ajax e gostaria que o valor da data ja viesse certinho.
Pode ser algo q estou eskecendo de colocar no ApplicationManager tb.. eu realmente naum faço idéia, por isso venho recorrer a vcs... muito obrigado.
|
 |
|
|
|
|