private JSONObject setFieldAttributes(String clazz, CompactFieldNode field) throws JSONException {
    JSONObject port = new JSONObject();
    port.put("name", field.getName());

    TypeGraphVertex tgv = typeGraph.getTypeGraphVertex(clazz);
    putFieldDescription(field, port, tgv);

    List<CompactAnnotationNode> annotations = field.getVisibleAnnotations();
    CompactAnnotationNode firstAnnotation;
    if (annotations != null
        && !annotations.isEmpty()
        && (firstAnnotation = field.getVisibleAnnotations().get(0)) != null) {
      for (Map.Entry<String, Object> entry : firstAnnotation.getAnnotations().entrySet()) {
        port.put(entry.getKey(), entry.getValue());
      }
    }

    return port;
  }
 private OperatorClassInfo getOperatorClassWithGetterSetter(
     String operatorClass, String setterName, String getterName) {
   TypeGraphVertex tgv = typeGraph.getTypeGraphVertex(operatorClass);
   return getOperatorClassWithGetterSetter(tgv, setterName, getterName);
 }
  public JSONObject describeOperator(String clazz) throws Exception {
    TypeGraphVertex tgv = typeGraph.getTypeGraphVertex(clazz);
    if (tgv.isInstantiable()) {
      JSONObject response = new JSONObject();
      JSONArray inputPorts = new JSONArray();
      JSONArray outputPorts = new JSONArray();
      // Get properties from ASM

      JSONObject operatorDescriptor = describeClassByASM(clazz);
      JSONArray properties = operatorDescriptor.getJSONArray("properties");

      properties = enrichProperties(clazz, properties);

      JSONArray portTypeInfo = operatorDescriptor.getJSONArray("portTypeInfo");

      List<CompactFieldNode> inputPortfields = typeGraph.getAllInputPorts(clazz);
      List<CompactFieldNode> outputPortfields = typeGraph.getAllOutputPorts(clazz);

      try {
        for (CompactFieldNode field : inputPortfields) {
          JSONObject inputPort = setFieldAttributes(clazz, field);
          if (!inputPort.has("optional")) {
            inputPort.put(
                "optional",
                false); // input port that is not annotated is default to be not optional
          }
          if (!inputPort.has(SCHEMA_REQUIRED_KEY)) {
            inputPort.put(SCHEMA_REQUIRED_KEY, false);
          }
          inputPorts.put(inputPort);
        }

        for (CompactFieldNode field : outputPortfields) {
          JSONObject outputPort = setFieldAttributes(clazz, field);

          if (!outputPort.has("optional")) {
            outputPort.put(
                "optional", true); // output port that is not annotated is default to be optional
          }
          if (!outputPort.has("error")) {
            outputPort.put("error", false);
          }
          if (!outputPort.has(SCHEMA_REQUIRED_KEY)) {
            outputPort.put(SCHEMA_REQUIRED_KEY, false);
          }
          outputPorts.put(outputPort);
        }

        response.put("name", clazz);
        response.put("properties", properties);
        response.put(PORT_TYPE_INFO_KEY, portTypeInfo);
        response.put("inputPorts", inputPorts);
        response.put("outputPorts", outputPorts);

        OperatorClassInfo oci = classInfo.get(clazz);

        if (oci != null) {
          if (oci.comment != null) {
            String[] descriptions;
            // first look for a <p> tag
            String keptPrefix = "<p>";
            descriptions = oci.comment.split("<p>", 2);
            if (descriptions.length == 0) {
              keptPrefix = "";
              // if no <p> tag, then look for a blank line
              descriptions = oci.comment.split("\n\n", 2);
            }
            if (descriptions.length > 0) {
              response.put("shortDesc", descriptions[0]);
            }
            if (descriptions.length > 1) {
              response.put("longDesc", keptPrefix + descriptions[1]);
            }
          }
          response.put("category", oci.tags.get("@category"));
          String displayName = oci.tags.get("@displayName");
          if (displayName == null) {
            displayName = decamelizeClassName(ClassUtils.getShortClassName(clazz));
          }
          response.put("displayName", displayName);
          String tags = oci.tags.get("@tags");
          if (tags != null) {
            JSONArray tagArray = new JSONArray();
            for (String tag : StringUtils.split(tags, ',')) {
              tagArray.put(tag.trim().toLowerCase());
            }
            response.put("tags", tagArray);
          }
          String doclink = oci.tags.get("@doclink");
          if (doclink != null) {
            response.put("doclink", doclink + "?" + getDocName(clazz));
          } else if (clazz.startsWith("com.datatorrent.lib.")
              || clazz.startsWith("com.datatorrent.contrib.")) {
            response.put("doclink", DT_OPERATOR_DOCLINK_PREFIX + "?" + getDocName(clazz));
          }
        }
      } catch (JSONException ex) {
        throw new RuntimeException(ex);
      }
      return response;
    } else {
      throw new UnsupportedOperationException();
    }
  }