code: static <S extends Storable> Filter<S> build(ChainedProperty<S> property,
                                                  Filter<?> subFilter,
                                                  boolean not)
      {
          if (property == null) {
              throw new IllegalArgumentException();
          }
  
          StorableProperty<?> joinProperty = property.getLastProperty();
  
          if (subFilter == null) {
              subFilter = Filter.getOpenFilter(joinProperty.getJoinedType());
          } else if (joinProperty.getJoinedType() != subFilter.getStorableType()) {
              throw new IllegalArgumentException
                  ("Filter not compatible with join property type: " +
                   property + " joins to a " + joinProperty.getJoinedType().getName() +
                   ", but filter is for a " + subFilter.getStorableType().getName());
          }
  
          if (subFilter.isClosed()) {
              // Exists filter reduces to a closed (or open) filter.
              Filter<S> f = Filter.getClosedFilter(property.getPrimeProperty().getEnclosingType());
              return not ? f.not() : f;
          } else if (joinProperty.isQuery() || subFilter.isOpen()) {
              return getCanonical(property, subFilter, not);
          } else {
              // Convert to normal join filter.
              return subFilter.asJoinedFrom(property);
          }
      }
docs: Returns a canonical instance, creating a new one if there isn't one
  already in the cache.