Coherence: Collections Filter
Recently, I came up with the CollectionsAwareFilter which allows one to filter the bean attributes lying inside of a list—or list of a list of a list... Read on and check out my solution.
Join the DZone community and get the full member experience.
Join For FreeRecently, I was working on an API where I needed to get the coherence cache values based on a filter which can filter the attributes in the collection. I verified coherence APIs and found ContainsFilter but it would only check whether the whole object(Like String, Integer) is in the collection or not, but wouldn't filter the user-defined beans.
So, I came up with the below CollectionsAwareFilter where we can filter the bean attributes lying inside of a list—or list of a list of a list...
I am posting the code here... please feel free to copy it if you'd like. And of course, any suggestions for improvement or alternate (easier) ways would be much appreciated.
package coh.collections.filter;
import com.tangosol.util.Filter;
import com.tangosol.util.ValueExtractor;
import com.tangosol.util.filter.ComparisonFilter;
import java.util.Collection;
/**
* <pre>
* Filter which tests a Collection or Object array value returned from a method invocation for evaluation of filters on attributes of Collection objects.
*
*
* @author Hemambara Vamsi Kotari
*/
public class CollectionsAwareFilter extends ComparisonFilter {
/**
* Created to support default constructor mechanism
*/
public CollectionsAwareFilter() {
}
/**
* Takes methodName and convert it to value extractor. Method name should be the name of the method that retrieves {@code Collection} from main object.
*
* @param sMethod - methodName
* @param filter - {@link Filter}
*/
public CollectionsAwareFilter(String sMethod, Filter filter) {
super(sMethod, filter);
this.init(filter);
}
/**
* {@code ValueExtractor} retrieves {@code Collection} from main object.
*
* @param extractor - {@link ValueExtractor}
* @param filter - {@link Filter}
*/
public CollectionsAwareFilter(ValueExtractor extractor, Filter filter) {
super(extractor, filter);
this.init(filter);
}
/**
* Make sure {@link Filter} is NOT NULL. It does not make any sense to parse through collection if filter is null.
*
* @param filter
*/
protected void init(Filter filter){
if (null == filter) {
throw new IllegalArgumentException("Filter argument must not be null");
}
}
/**
* Evaluate the collection, iterate through them and apply filters.
*
* @param oExtracted - Extracted collection from main object.
* @return - True - If any filter pass.
* - False - If none of the filter pass.
*/
@Override
protected boolean evaluateExtracted(Object oExtracted) {
Collection aoExtracted = (Collection)oExtracted;
Filter filter = (Filter) this.getValue();
for(Object object : aoExtracted){
if(filter.evaluate(object)){
return true;
}
}
return false;
}
}
Here is the usage:
a) First, create the userbean with a person name and list of addresses (like home, office).
b) Then, put the values in coherence cache at line 14.
UserBean userBean1 = new UserBean();
userBean1.setName("Name1");
Address address1 = new Address();
address1.setStreetName("Davidson Drive");
address1.setCity("Charlotte");
Address address2 = new Address();
address2.setStreetName("Bevard st");
address2.setCity("Charlotte");
userBean1.setAddressList(Arrays.asList(address1, address2));
coherenceNamedCache.put(1, userBean1);
c) Apply filters on bean attributes. Line 1-4. We can create N number of filters.
d) Use CollectionsAwareFilter by passing the filters created at #c) and use the bean attribute name of the list.
LikeFilter likeFilter = new LikeFilter("getStreetName","%Drive%", false);
EqualsFilter equalsFilter = new EqualsFilter("getCity","Charlotte");
//... pass N number of filters
AllFilter filter = new AllFilter(new Filter[]{likeFilter, equalsFilter});
// getter name of a list in UserBean
Filter filterCriteria = new CollectionsAwareFilter("getAddressList", filter);
evaluateExtracted() of CollectionsAwareFilter will get the collection object (AddressList). It loops through the collections object and applies the filters that we pass at step c above. If any of the filters returns true then it will send the UserBean with the collection (AddressList) back to the client. If you would like to have search criteria where all the objects in a list should pass the filter criteria, please change evaluateExtracted() accordingly. |
UserBean with a Name and Address as a list of objects:
public class UserBean {
private String name;
private List<Address> addressList;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Address> getAddressList() {
return addressList;
}
public void setAddressList(List<Address> addressList) {
this.addressList = addressList;
}
@Override
public boolean equals(Object o) {
// write your own way of equals()
}
@Override
public int hashCode() {
// write your own way of hashCode()
}
}
AddressBean:
public class Address{
private String streetName;
private String city;
private String country;
private String zipCode;
public String getStreetName() {
return streetName;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
@Override
public boolean equals(Object o) {
// write your own way of equals
}
@Override
public int hashCode() {
// write your own way of hashCode()
}
}
That's all! Hope you find this helpful.
Opinions expressed by DZone contributors are their own.
Comments