private JSONArray enrichProperties(String operatorClass, JSONArray properties)
      throws JSONException {
    JSONArray result = new JSONArray();
    for (int i = 0; i < properties.length(); i++) {
      JSONObject propJ = properties.getJSONObject(i);
      String propName = WordUtils.capitalize(propJ.getString("name"));
      String getPrefix =
          (propJ.getString("type").equals("boolean")
                  || propJ.getString("type").equals("java.lang.Boolean"))
              ? "is"
              : "get";
      String setPrefix = "set";
      OperatorClassInfo oci =
          getOperatorClassWithGetterSetter(
              operatorClass, setPrefix + propName, getPrefix + propName);
      if (oci == null) {
        result.put(propJ);
        continue;
      }
      MethodInfo setterInfo = oci.setMethods.get(setPrefix + propName);
      MethodInfo getterInfo = oci.getMethods.get(getPrefix + propName);

      if ((getterInfo != null && getterInfo.omitFromUI)
          || (setterInfo != null && setterInfo.omitFromUI)) {
        continue;
      }
      if (setterInfo != null) {
        addTagsToProperties(setterInfo, propJ);
      } else if (getterInfo != null) {
        addTagsToProperties(getterInfo, propJ);
      }
      result.put(propJ);
    }
    return result;
  }
  /**
   * Enrich portClassHier with class/interface names that map to a list of parent
   * classes/interfaces. For any class encountered, find its parents too.<br>
   * Also find the port types which have assignable schema classes.
   *
   * @param oper Operator to work on
   * @param portClassHierarchy In-Out param that contains a mapping of class/interface to its
   *     parents
   * @param portTypesWithSchemaClasses Json that will contain all the ports which have any schema
   *     classes.
   */
  public void buildAdditionalPortInfo(
      JSONObject oper, JSONObject portClassHierarchy, JSONObject portTypesWithSchemaClasses) {
    try {
      JSONArray ports = oper.getJSONArray(OperatorDiscoverer.PORT_TYPE_INFO_KEY);
      for (int i = 0; i < ports.length(); i++) {
        JSONObject port = ports.getJSONObject(i);

        String portType = port.optString("type");
        if (portType == null) {
          // skipping if port type is null
          continue;
        }

        if (typeGraph.size() == 0) {
          buildTypeGraph();
        }

        try {
          // building port class hierarchy
          LinkedList<String> queue = Lists.newLinkedList();
          queue.add(portType);
          while (!queue.isEmpty()) {
            String currentType = queue.remove();
            if (portClassHierarchy.has(currentType)) {
              // already present in the json so we skip.
              continue;
            }
            List<String> immediateParents = typeGraph.getParents(currentType);
            if (immediateParents == null) {
              portClassHierarchy.put(currentType, Lists.<String>newArrayList());
              continue;
            }
            portClassHierarchy.put(currentType, immediateParents);
            queue.addAll(immediateParents);
          }
        } catch (JSONException e) {
          LOG.warn("building port type hierarchy {}", portType, e);
        }

        // finding port types with schema classes
        if (portTypesWithSchemaClasses.has(portType)) {
          // already present in the json so skipping
          continue;
        }
        if (portType.equals("byte")
            || portType.equals("short")
            || portType.equals("char")
            || portType.equals("int")
            || portType.equals("long")
            || portType.equals("float")
            || portType.equals("double")
            || portType.equals("java.lang.String")
            || portType.equals("java.lang.Object")) {
          // ignoring primitives, strings and object types as this information is needed only for
          // complex types.
          continue;
        }
        if (port.has("typeArgs")) {
          // ignoring any type with generics
          continue;
        }
        boolean hasSchemaClasses = false;
        List<String> instantiableDescendants = typeGraph.getInstantiableDescendants(portType);
        if (instantiableDescendants != null) {
          for (String descendant : instantiableDescendants) {
            try {
              if (typeGraph.isInstantiableBean(descendant)) {
                hasSchemaClasses = true;
                break;
              }
            } catch (JSONException ex) {
              LOG.warn("checking descendant is instantiable {}", descendant);
            }
          }
        }
        portTypesWithSchemaClasses.put(portType, hasSchemaClasses);
      }
    } catch (JSONException e) {
      // should not reach this
      LOG.error("JSON Exception {}", e);
      throw new RuntimeException(e);
    }
  }
      @Override
      public void onComplete(String response, Object state) {
        try {
          Log.i(TAG, response);
          json = Util.parseJson(response);

          // photos are in the form of a json array
          child = json.getJSONArray("data");

          int total = child.length();

          // contains links to photos
          links = new ArrayList<String>(total);

          // adds link to each photo to our list after replacing the "https" from url
          // DownloadManager does not support https in gingerbread
          for (int i = 0; i < total; i++) {
            photo_json = child.getJSONObject(i);

            if (dl_high_res_pics) {
              JSONArray image_set = photo_json.getJSONArray("images");

              // highest resolution picture has the index zero in the images jsonarray
              JSONObject highest_res_pic = image_set.getJSONObject(0);
              String http_replaced =
                  highest_res_pic.getString("source").replaceFirst("https", "http");
              links.add(i, http_replaced);
            } else {
              // source property of the json object points to the photo's link
              String http_replaced = photo_json.getString("source").replaceFirst("https", "http");
              links.add(i, http_replaced);
            }
          }

          download_photos.this.runOnUiThread(
              new Runnable() {
                public void run() {
                  //	mytask = new DownloadImageTask();
                  //	mytask.execute(links);
                  // start downloading using asynctask
                  // new DownloadImageTask().execute(links);
                  // downloadThread.setPath(path);
                  // downloadThread.setWholeTasks(links.size());
                  if (resume_file.exists()) {

                    initial_value = readProgress()[0];
                    final_value = links.size();
                    // case if the task is already completed
                    if (initial_value == final_value) {
                      completed = true;
                      resume_pause.setVisibility(View.GONE);

                      progress_download.setMax(final_value);
                      progress_download.setProgress(0); // bug in progress bar
                      progress_download.setProgress(initial_value);

                      progress_text.setText("Completed.");
                      mtext.setText(
                          getText(R.string.download_textview_message_1)
                              + " "
                              + path.toString()
                              + ". ");

                    }

                    // case if some of the photos are already downloaded
                    else {
                      progress_download.setMax(links.size());
                      // progress_download.setProgress(0);	//bug in progress bar
                      progress_download.setProgress(initial_value);

                      // N.B if i= initial_value -1, then one image will be downloaded again. so to
                      // save cost we start with i = initial_value
                      for (int i = initial_value; i < links.size(); i++) {
                        mtext.setText(
                            getText(R.string.download_textview_message_1)
                                + " "
                                + path.toString()
                                + ". ");
                        // downloadThread.setRunningTask(i + 1);
                        downloadThread.enqueueDownload(
                            new DownloadTask(
                                links.get(i), path, i + 1, final_value, download_photos.this));
                      }
                    }
                  }

                  // case if the task is entirely new task
                  else {
                    for (int i = 0; i < links.size(); i++) {
                      mtext.setText(
                          getText(R.string.download_textview_message_1)
                              + " "
                              + path.toString()
                              + ". ");
                      // downloadThread.setRunningTask(i + 1);
                      downloadThread.enqueueDownload(
                          new DownloadTask(
                              links.get(i), path, i + 1, links.size(), download_photos.this));
                    }
                  }
                }
              });
        } catch (JSONException ex) {
          Log.e(TAG, "JSONEXception : " + ex.getMessage());
        }
      }