boolean containsProperty(ExecutionContext context, String name, int numArgs,
      boolean mustBeMethod) {
    // first handle structs
    if ((elementType instanceof StructType) && !mustBeMethod) {
      // check field names
      String[] fieldName = ((StructType) elementType).getFieldNames();
      for (String s : fieldName) {
        if (name.equals(s)) {
          return true;
        }
      }
    }
    Class<?> clazz = elementType.resolveClass();
    if (numArgs > 0 || mustBeMethod) {
      // if numArgs==0, then just look up method directly
      // instead of sifting through all methods
      if (numArgs == 0) {
        try {
          clazz.getMethod(name, (Class[]) null);
          return true;
        } catch (NoSuchMethodException e) {
          return false;
        }
      }
      // enumerate methods and match with name
      // here, only check for a method with the same number of arguments.
      // we'll check for ambiguous method invocation when the method is
      // actually fully resolved and invoked
      Method[] methods = clazz.getMethods();
      for (Method m : methods) {
        if (m.getName().equals(name) && m.getParameterTypes().length == numArgs) {
          return true;
        }
      }
      return false;
    }
    // if there are zero arguments and it's an attribute, then defer to
    // AttributeDescriptor to see if there's a match
    return new AttributeDescriptor(context.getCache().getPdxRegistry(), name)
        .validateReadType(clazz);
  }
(Re)evaluate in the context of the current iterations through the cross-product. If this
iterator is not dependent on the current iteration, then just return the previously evaluated
collection. Otherwise, re-evaluate. Returns null if the collection itself is null or UNDEFINED
geode-core/src/main/java/org/apache/geode/cache/query/internal/RuntimeIterator.java