Class CapabilitiesFilterSplitter

  • All Implemented Interfaces:
    ExpressionVisitor, FilterVisitor

    public class CapabilitiesFilterSplitter
    extends Object
    implements FilterVisitor, ExpressionVisitor
    Determines what queries can be processed server side and which can be processed client side.

    IMPLEMENTATION NOTE: This class is implemented as a stack processor. If you're curious how it works, compare it with the old SQLUnpacker class, which did the same thing using recursion in a more straightforward way.

    Here's a non-implementors best-guess at the algorithm: Starting at the top of the filter, split each filter into its constituent parts. If the given FilterCapabilities support the given operator, then keep checking downwards.

    The key is in knowing whether or not something "down the tree" from you wound up being supported or not. This is where the stacks come in. Right before handing off to accept() the sub- filters, we count how many things are currently on the "can be proccessed by the underlying datastore" stack (the preStack) and we count how many things are currently on the "need to be post- processed" stack.

    After the accept() call returns, we look again at the preStack.size() and postStack.size(). If the postStack has grown, that means that there was stuff down in the accept()-ed filter that wasn't supportable. Usually this means that our filter isn't supportable, but not always.

    In some cases a sub-filter being unsupported isn't necessarily bad, as we can 'unpack' OR statements into AND statements (DeMorgans rule/modus poens) and still see if we can handle the other side of the OR. Same with NOT and certain kinds of AND statements.

    In addition this class supports the case where we're doing an split in the middle of a client-side transaction. I.e. imagine doing a against a WFS-T where you have to filter against actions that happened previously in the transaction. That's what the ClientTransactionAccessor interface does, and this class splits filters while respecting the information about deletes and updates that have happened previously in the Transaction. I can't say with certainty exactly how the logic for that part of this works, but the test suite does seem to test it and the tests do pass.

    Since GeoTools 8.0, the ClientTransactionAccessor interface can also be used to instruct the splitter that a filter referencing a given PropertyName can't be encoded by the back-end, by returning Filter.EXCLUDE in getUpdateFilter(String). This is so because there may be the case where some attribute names are encodable to the back-end's query language, while others may not be, or may not be part of the stored data model. In such case, returning Filter.EXCLUDE makes the filter referencing the property name part of the post-processing filter instead of the pre-processing filter.

    dzwiers, commented and ported from gt to ogc filters by saul.farber, ported to work upon org.geotools.filter.Capabilities by Gabriel Roldan