Skip to content

Instantly share code, notes, and snippets.

@rponte
Last active October 24, 2021 01:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rponte/f579f0731898e7df4cab02f2b991182d to your computer and use it in GitHub Desktop.
Save rponte/f579f0731898e7df4cab02f2b991182d to your computer and use it in GitHub Desktop.
ADF 11G: extracting all fields from a query panel (af:query)
@ManagedBean
public class ProductBean {
private FacesUtils facesUtils = new FacesUtils();
/**
* Listens to af:query event
*/
public void onQuery(QueryEvent event) {
QueryEventWrapper filter = QueryEventWrapper.of(event); // creates a wrapper from a QueryEvent instance
/*
* Extracts a field value and converts it to a specific type
*/
String name = filter.field("Name").asString();
Integer code = filter.field("Code").asInteger();
BigDecimal price = filter.field("Price").asBigDecimal();
/*
* You can deal with field manually (non type-safe) and convert it to some basic types
* (this approach may be necessary because ADF returns different types sometimes)
*/
FilterField<?> codeField = filter.field("Code");
Object codeAsObject = codeField.asObject(); // or codeField.value();
String codeAsString = codeField.asString();
Long codeAsLong = codeField.asLong();
BigDecimal codeAsBigDecimal = codeField.asBigDecimal();
/*
* Or you may deal with a field in a type-safe manner
*/
String category = "all";
FilterField<String> categoryField = filter.field("Category", String.class); // you must know the field type in advance
if (categoryField.isFilled()) { // verifies if the field is not blank
category = categoryField.value(); // now you extract the value
}
/*
* How about dealing with Date Range fields?
*/
FilterField<Date> createdAt = filter.field("CreatedAt", Date.class);
Date begin = filter.indexed(0).value(); // first field
Date end = filter.indexed(1).value(); // second field
// process the original query
facesUtils.invokeEL("#{bindings.ProductViewObject.processQuery}",
new Class[] { QueryEvent.class },
new Object[] { queryEvent });
}
}
package br.com.rponte.view.utils.query;
import java.io.Serializable;
import java.math.BigDecimal;
import oracle.adf.view.rich.model.AttributeCriterion;
/**
* Representa um campo de filtro do componente af:query
*/
public class FilterField<T extends Serializable> {
private final String name;
private final Class<T> type;
private final AttributeCriterion attribute;
private final int index;
public FilterField(String name, Class<T> type, AttributeCriterion attribute) {
this(name, type, attribute, 0);
}
public FilterField(String name, Class<T> type, AttributeCriterion attribute, int index) {
this.name = name;
this.type = type;
this.attribute = attribute;
this.index = index;
}
/**
* Retorna cópia do <code>FilterField</code> posicionado em determinado <code>index</code>.
* Seu uso será necessário em filtros de múltiplos inputs, como datas com predicado <code>between</code>.
*/
public FilterField<T> indexed(int index) {
return new FilterField<T>(name, type, attribute, index);
}
/**
* Faz casting e retorna valor do campo
*/
public T value() {
Object value = attribute.getValues().get(index);
return type.cast(value);
}
/**
* Verifica se o campo foi preenchido
*/
public boolean isFilled() {
String value = this.asString();
return (value != null && !value.isEmpty());
}
/**
* Retorna valor "RAW" do campo como <code>Object</code>
*/
public Object asObject() {
Object value = attribute.getValues().get(index);
return value;
}
/**
* Retorna valor do campo como <code>String</code>
*/
public String asString() {
Object value = this.asObject();
if (value == null)
return null;
if (value instanceof String) {
return (String) value;
}
return value.toString();
}
/**
* Retorna valor do campo como <code>Integer</code>
*/
public Integer asInteger() {
Object value = this.asObject();
if (value == null)
return null;
if (value instanceof Integer) {
return (Integer) value;
}
String strValue = value.toString().trim();
if (strValue.isEmpty())
return null;
return new Integer(strValue);
}
/**
* Retorna valor do campo como <code>Long</code>
*/
public Long asLong() {
Object value = this.asObject();
if (value == null)
return null;
if (value instanceof Long) {
return (Long) value;
}
String strValue = value.toString().trim();
if (strValue.isEmpty())
return null;
return new Long(strValue);
}
/**
* Retorna valor do campo como <code>Double</code>
*/
public Double asDouble() {
Object value = this.asObject();
if (value == null)
return null;
if (value instanceof Double) {
return (Double) value;
}
String strValue = value.toString().trim();
if (strValue.isEmpty())
return null;
return new Double(strValue);
}
/**
* Retorna valor do campo como <code>BigDecimal</code>
*/
public BigDecimal asBigDecimal() {
Object value = this.asObject();
if (value == null)
return null;
if (value instanceof BigDecimal) {
return (BigDecimal) value;
}
String strValue = value.toString().trim();
if (strValue.isEmpty())
return null;
return new BigDecimal(strValue);
}
}
package br.com.rponte.view.utils.query;
public class FilterFieldNotFoundException extends RuntimeException {
private static final long serialVersionUID = 1L;
public FilterFieldNotFoundException(String fieldName) {
super("Campo '" + fieldName + "' não encontrado no componente af:query");
}
}
package br.com.rponte.view.utils.query;
import java.io.Serializable;
import java.util.List;
import oracle.adf.view.rich.event.QueryEvent;
import oracle.adf.view.rich.model.AttributeCriterion;
import oracle.adf.view.rich.model.AttributeDescriptor;
import oracle.adf.view.rich.model.ConjunctionCriterion;
import oracle.adf.view.rich.model.Criterion;
import oracle.adf.view.rich.model.QueryDescriptor;
/**
* Wrapper para <code>QueryEvent</code> com o objetivo de simplificar
* a extração dos campos gerados pelo componente af:query
*/
public class QueryEventWrapper {
private final QueryEvent event;
public QueryEventWrapper(QueryEvent event) {
this.event = event;
}
/**
* Metodo de fabrica
*/
public static QueryEventWrapper of(QueryEvent event) {
return new QueryEventWrapper(event);
}
/**
* Extrai campo pelo <code>name</code> ou
* lança exceção <code>FilterFieldNotFondException</code>
*/
public FilterField<?> field(String name) {
FilterField<?> ff = this.field(name, Serializable.class);
return ff;
}
/**
* Extrai campo pelo <code>name</code> de forma <b>type-safety</b> ou
* lança exceção <code>FilterFieldNotFondException</code>
*/
public <T extends Serializable> FilterField<T> field(String name, Class<T> fieldType) {
AttributeCriterion attribute = this.findFieldByName(name);
FilterField<T> ff = new FilterField<T>(name, fieldType, attribute);
return ff;
}
private AttributeCriterion findFieldByName(String fieldName) {
QueryDescriptor descriptor = event.getDescriptor();
ConjunctionCriterion filters = descriptor.getConjunctionCriterion();
List<Criterion> criterionList = filters.getCriterionList();
for (Criterion criterion : criterionList) {
AttributeDescriptor ad = ((AttributeCriterion) criterion).getAttribute();
if (ad.getName().equalsIgnoreCase(fieldName)) {
return ((AttributeCriterion) criterion);
}
}
throw new FilterFieldNotFoundException(fieldName);
}
}
@rponte
Copy link
Author

rponte commented Oct 24, 2021

with Java 8 we can use Optional to deal with fields not filled by user instead of invoking isFilled()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment