private boolean generateReceiveImpl()

in json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java [1240:1443]


    private boolean generateReceiveImpl(
        Element clazz, StringWriter body, String className,
        List<? extends Element> enclosedElements, StringBuilder inType, Set<String> propertyFqns
    ) {
        inType.append("  @Override public void onMessage(").append(className).append(" model, int index, int type, Object data, Object[] params) {\n");
        inType.append("    switch (index) {\n");
        int index = 0;
        boolean ok = true;
        boolean instance = clazz.getAnnotation(Model.class).instance();
        for (Element m : enclosedElements) {
            if (m.getKind() != ElementKind.METHOD) {
                continue;
            }
            ExecutableElement e = (ExecutableElement)m;
            OnReceive onR = e.getAnnotation(OnReceive.class);
            if (onR == null) {
                continue;
            }
            if (!instance && !e.getModifiers().contains(Modifier.STATIC)) {
                error("@OnReceive method needs to be static", e);
                return false;
            }
            if (e.getModifiers().contains(Modifier.PRIVATE)) {
                error("@OnReceive method cannot be private", e);
                return false;
            }
            if (e.getReturnType().getKind() != TypeKind.VOID) {
                error("@OnReceive method should return void", e);
                return false;
            }
            if (!onR.jsonp().isEmpty() && !"GET".equals(onR.method())) {
                error("JSONP works only with GET transport method", e);
            }
            String dataMirror = findDataSpecified(e, onR);
            if ("PUT".equals(onR.method()) && dataMirror == null) {
                error("PUT method needs to specify a data() class", e);
                return false;
            }
            if ("POST".equals(onR.method()) && dataMirror == null) {
                error("POST method needs to specify a data() class", e);
                return false;
            }
            if (e.getParameters().size() < 2) {
                error("@OnReceive method needs at least two parameters", e);
            }
            final boolean isWebSocket = "WebSocket".equals(onR.method());
            if (isWebSocket && dataMirror == null) {
                error("WebSocket method needs to specify a data() class", e);
            }
            int expectsList = 0;
            List<String> args = new ArrayList<String>();
            List<String> params = new ArrayList<String>();
            // first argument is model class
            {
                TypeMirror type = e.getParameters().get(0).asType();
                CharSequence simpleName;
                if (type.getKind() == TypeKind.DECLARED) {
                    simpleName = ((DeclaredType) type).asElement().getSimpleName();
                } else {
                    simpleName = type.toString();
                }
                if (simpleName.toString().equals(className)) {
                    args.add("model");
                } else {
                    error("First parameter needs to be " + className, e);
                    return false;
                }
            }

            String modelClass;
            {
                final Types tu = processingEnv.getTypeUtils();
                TypeMirror type = e.getParameters().get(1).asType();
                TypeMirror modelType = null;
                TypeMirror ert = tu.erasure(type);

                if (isModel(type)) {
                    modelType = type;
                } else if (type.getKind() == TypeKind.ARRAY) {
                    modelType = ((ArrayType)type).getComponentType();
                    expectsList = 1;
                } else if ("java.util.List".equals(fqn(ert, e))) {
                    List<? extends TypeMirror> typeArgs = ((DeclaredType)type).getTypeArguments();
                    if (typeArgs.size() == 1) {
                        modelType = typeArgs.get(0);
                        expectsList = 2;
                    }
                } else if (type.toString().equals("java.lang.String")) {
                    modelType = type;
                }
                if (modelType == null) {
                    error("Second arguments needs to be a model, String or array or List of models", e);
                    return false;
                }
                modelClass = modelType.toString();           
                final String simpleName = modelClass;
                List<String> knownPackages = packages.get(simpleName);
                if (knownPackages != null && !knownPackages.isEmpty()) {
                    for (String pkg : knownPackages) {
                        propertyFqns.add(pkg+"."+simpleName);
                    }
                }
                if (expectsList == 1) {
                    args.add("arr");
                } else if (expectsList == 2) {
                    args.add("net.java.html.json.Models.asList(arr)");
                } else {
                    args.add("arr[0]");
                }
            }
            String n = e.getSimpleName().toString();
            String c = inPckName(clazz, false);
            if (isWebSocket) {
                body.append("  /** Performs WebSocket communication and then calls {@link ");
                body.append(c).append("#").append(n).append("}.\n");
                body.append("  * Call with <code>null</code> data parameter\n");
                body.append("  * to open the connection (even if not required). Call with non-null data to\n");
                body.append("  * send messages to server. Call again with <code>null</code> data to close the socket.\n");
                body.append("  */\n");
                if (onR.headers().length > 0) {
                    error("WebSocket spec does not support headers", e);
                }
            } else {
                body.append("  /** Performs network communication and then calls {@link ");
                body.append(c).append("#").append(n).append("}.\n");
                body.append("  */\n");
            }
            body.append("  public void ").append(n).append("(");
            StringBuilder urlBefore = new StringBuilder();
            StringBuilder urlAfter = new StringBuilder();
            StringBuilder headers = new StringBuilder();
            String jsonpVarName = null;
            {
                String sep = "";
                boolean skipJSONP = onR.jsonp().isEmpty();
                Set<String> receiveParams = new LinkedHashSet<String>();
                findParamNames(receiveParams, e, onR.url(), onR.jsonp(), urlBefore, urlAfter);
                for (String headerLine : onR.headers()) {
                    if (headerLine.contains("\r") || headerLine.contains("\n")) {
                        error("Header line cannot contain line separator", e);
                    }
                    findParamNames(receiveParams, e, headerLine, null, headers);
                    headers.append("+ \"\\r\\n\" +\n");
                }
                if (headers.length() > 0) {
                    headers.append("\"\"");
                }
                for (String p : receiveParams) {
                    if (!skipJSONP && p.equals(onR.jsonp())) {
                        skipJSONP = true;
                        jsonpVarName = p;
                        continue;
                    }
                    body.append(sep);
                    body.append("String ").append(p);
                    sep = ", ";
                }
                if (!skipJSONP) {
                    error(
                        "Name of jsonp attribute ('" + onR.jsonp() +
                        "') is not used in url attribute '" + onR.url() + "'", e
                    );
                }
                if (dataMirror != null) {
                    body.append(sep).append(dataMirror.toString()).append(" data");
                }
                for (int i = 2; i < e.getParameters().size(); i++) {
                    if (isWebSocket) {
                        error("@OnReceive(method=\"WebSocket\") can only have two arguments", e);
                        ok = false;
                    }

                    VariableElement ve = e.getParameters().get(i);
                    body.append(sep).append(ve.asType().toString()).append(" ").append(ve.getSimpleName());
                    final String tp = ve.asType().toString();
                    String btn = findBoxedType(tp);
                    if (btn == null) {
                        btn = tp;
                    }
                    args.add("(" + btn + ")params[" + (i - 2) + "]");
                    params.add(ve.getSimpleName().toString());
                    sep = ", ";
                }
            }
            body.append(") {\n");
            boolean webSocket = onR.method().equals("WebSocket");
            if (webSocket) {
                if (generateWSReceiveBody(index++, body, inType, onR, e, clazz, className, expectsList != 0, modelClass, n, args, params, urlBefore, jsonpVarName, urlAfter, dataMirror, headers)) {
                    return false;
                }
                body.append("  }\n");
                body.append("  private Object ws_" + e.getSimpleName() + ";\n");
            } else {
                if (generateJSONReceiveBody(index++, body, inType, onR, e, clazz, className, expectsList != 0, modelClass, n, args, params, urlBefore, jsonpVarName, urlAfter, dataMirror, headers)) {
                    ok = false;
                }
                body.append("  }\n");
            }
        }
        inType.append("    }\n");
        inType.append("    throw new UnsupportedOperationException(\"index: \" + index + \" type: \" + type);\n");
        inType.append("  }\n");
        return ok;
    }