ReadInvocationHandler(
        final Node node,
        final Method method,
        final String annotationValue,
        final XBProjector projector,
        final boolean absentIsEmpty) {
      super(node, method, annotationValue, projector);
      wrappedInOptional = ReflectionHelper.isOptional(method.getGenericReturnType());
      returnType =
          wrappedInOptional
              ? ReflectionHelper.getParameterType(method.getGenericReturnType())
              : method.getReturnType();
      Class<?>[] exceptionTypes = method.getExceptionTypes();
      exceptionType = exceptionTypes.length > 0 ? exceptionTypes[0] : null;
      this.isConvertable = projector.config().getTypeConverter().isConvertable(returnType);
      this.isReturnAsNode = Node.class.isAssignableFrom(returnType);
      this.isEvaluateAsList =
          List.class.equals(returnType) || ReflectionHelper.isStreamClass(returnType);
      this.isReturnAsStream = ReflectionHelper.isStreamClass(returnType);
      this.isEvaluateAsArray = returnType.isArray();
      if (wrappedInOptional && (isEvaluateAsArray || isEvaluateAsList)) {
        throw new IllegalArgumentException(
            "Method "
                + method
                + " must not declare an optional return type of list or array. Lists and arrays may be empty but will never be null.");
      }
      this.isEvaluateAsSubProjection = returnType.isInterface();
      this.isThrowIfAbsent = exceptionType != null;

      // Throwing exception overrides empty default value.
      this.absentIsEmpty = absentIsEmpty && (!isThrowIfAbsent);
    }
 protected Node getNodeForMethod(final Method method, final Object[] args)
     throws SAXException, IOException, ParserConfigurationException {
   if (docAnnotationValue != null) {
     String uri =
         projector.config().getExternalizer().resolveURL(docAnnotationValue, method, args);
     final Map<String, String> requestParams =
         ((IOBuilder) projector.io()).filterRequestParamsFromParams(uri, args);
     uri = Preprocessor.applyParams(uri, methodParameterIndexes, args);
     Class<?> callerClass = null;
     if (IOHelper.isResourceProtocol(uri)) {
       callerClass = ReflectionHelper.getCallerClass(8);
     }
     return IOHelper.getDocumentFromURL(
         projector.config().createDocumentBuilder(),
         uri,
         requestParams,
         method.getDeclaringClass(),
         callerClass);
   }
   return node;
 }
 protected String resolveXPath(final Object[] args) {
   return Preprocessor.applyParams(
       projector.config().getExternalizer().resolveXPath(annotationValue, method, args),
       methodParameterIndexes,
       args);
 }