protected function processFilter($filter)
    {
        if (!is_string($filter) && is_callable($filter)) {
            $expr   = $this->createFilter();
            /**
             * @param  FilterInterface           $expr The new filter expression object.
             * @param  FilterCollectionInterface $this The context of the collection.
             * @return string|array|FilterInterface The prepared filter expression
             *     string, structure, object.
             */
            $filter = $filter($expr, $this);
        }

        if (is_string($filter)) {
            $expr   = $this->createFilter()->setCondition($filter);
            $filter = $expr;
        } elseif (is_array($filter)) {
            $expr   = $this->createFilter()->setData($filter);
            $filter = $expr;
        }

        /** Append the filter to the expression's stack. */
        if ($filter instanceof FilterInterface) {
            return $filter;
        }

        throw new InvalidArgumentException(sprintf(
            'Filter must be a string, structure, or Expression object; received %s',
            is_object($filter) ? get_class($filter) : gettype($filter)
        ));
    }