Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Coherence: Collections Filter

DZone's Guide to

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.

· Java Zone
Free Resource

Learn how to troubleshoot and diagnose some of the most common performance issues in Java today. Brought to you in partnership with AppDynamics.

Recently, 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.

Understand the needs and benefits around implementing the right monitoring solution for a growing containerized market. Brought to you in partnership with AppDynamics.

Topics:
coherence ,java ,collections

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}