/**
  * Returns the attribute datatype based on the attribute code
  *
  * <p>If it cannot determine the datatype, it returns "string" as the default
  *
  * @param code
  * @return String
  */
 public String getAttributeDatatype(String code) {
   String type = Open311.STRING;
   try {
     JSONObject a = getAttribute(code);
     type = a.optString(Open311.DATATYPE, Open311.STRING);
   } catch (JSONException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
   }
   return type;
 }
 /**
  * @param code
  * @return boolean
  */
 public boolean isAttributeRequired(String code) {
   try {
     JSONObject a = getAttribute(code);
     if (a.opt(Open311.REQUIRED).equals(Open311.TRUE)) {
       return true;
     }
   } catch (JSONException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
   }
   return false;
 }
  /**
   * Returns the values for an attribute
   *
   * <p>If it cannot determine the attribute, it returns an empty JSONArray
   *
   * @param code
   * @return JSONArray
   */
  public JSONArray getAttributeValues(String code) {
    JSONArray values = new JSONArray();
    try {
      JSONObject a = getAttribute(code);
      values = a.getJSONArray(Open311.VALUES);
    } catch (JSONException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    return values;
  }
  /**
   * Returns the attribute description based on the attribute code
   *
   * <p>Returns an empty string if it cannot find the requested attribute
   *
   * @param code
   * @return String
   */
  public String getAttributeDescription(String code) {
    String description = "";
    try {
      JSONObject a = getAttribute(code);
      description = a.optString(Open311.DESCRIPTION);
    } catch (JSONException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    return description;
  }
  /**
   * @param code
   * @throws JSONException
   * @return JSONObject
   */
  public JSONObject getAttribute(String code) throws JSONException {
    JSONObject attribute = null;

    JSONArray attributes = service_definition.optJSONArray(Open311.ATTRIBUTES);
    int len = attributes.length();
    for (int i = 0; i < len; i++) {
      JSONObject a = attributes.getJSONObject(i);
      if (a.optString(Open311.CODE).equals(code)) {
        attribute = a;
        break;
      }
    }
    return attribute;
  }
 /**
  * Returns the name from a single value in an attribute
  *
  * @param code The attribute code
  * @param key The value key
  * @return String
  */
 public String getAttributeValueName(String code, String key) {
   JSONArray values = getAttributeValues(code);
   int len = values.length();
   try {
     for (int i = 0; i < len; i++) {
       JSONObject v = values.getJSONObject(i);
       String k = v.getString(Open311.KEY);
       if (k.equals(key)) {
         return v.getString(Open311.NAME);
       }
     }
   } catch (JSONException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
   }
   return null;
 }
 /**
  * @param parser
  * @return
  * @throws XmlPullParserException
  * @throws IOException
  * @throws JSONException
  */
 private JSONObject parseError(XmlPullParser parser)
     throws XmlPullParserException, IOException, JSONException {
   parser.require(XmlPullParser.START_TAG, ns, ERROR);
   JSONObject jo = new JSONObject();
   while (parser.next() != XmlPullParser.END_TAG) {
     if (parser.getEventType() != XmlPullParser.START_TAG) {
       continue;
     }
     String name = parser.getName();
     if (name.equals(Open311.CODE)) {
       jo.put(Open311.CODE, readElement(parser, Open311.CODE));
     } else if (name.equals(Open311.DESCRIPTION)) {
       jo.put(Open311.DESCRIPTION, readElement(parser, Open311.DESCRIPTION));
     } else {
       skip(parser);
     }
   }
   return jo;
 }
 /**
  * Returns a bitmap of the user's attached media
  *
  * <p>It seems we cannot use Uri's directly, without running out of memory. This will safely
  * generate a small bitmap ready to attach to an ImageView
  *
  * @param width
  * @param height
  * @param context
  * @return Bitmap
  */
 public Bitmap getMediaBitmap(int width, int height, Context context) {
   String m = post_data.optString(Open311.MEDIA);
   if (!m.equals("")) {
     Uri imageUri = Uri.parse(m);
     if (imageUri != null) {
       String path = Media.getRealPathFromUri(imageUri, context);
       return Media.decodeSampledBitmap(path, width, height, context);
     }
   }
   return null;
 }
  /**
   * Creates a new, empty ServiceRequest
   *
   * <p>This does not load any user-submitted data and should only be used for initial startup.
   * Subsequent loads should be done using the JSON String version
   *
   * @param s A single service from GET Service List
   */
  public ServiceRequest(JSONObject s, Context c) {
    service = s;
    post_data = new JSONObject();

    if (service.optBoolean(Open311.METADATA)) {
      try {
        service_definition =
            Open311.getServiceDefinition(service.getString(Open311.SERVICE_CODE), c);
      } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }

    // Read in the personal info fields from Preferences
    JSONObject personalInfo = Preferences.getPersonalInfo(c);
    Iterator<?> keys = personalInfo.keys();
    while (keys.hasNext()) {
      try {
        String key = (String) keys.next();
        String value = personalInfo.getString(key);
        if (value != "") {
          post_data.put(key, value);
        }
      } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
 /** Serializes all the data as a single JSON string */
 @Override
 public String toString() {
   JSONObject sr = new JSONObject();
   try {
     sr.put(SERVICE, service);
     if (endpoint != null) sr.put(ENDPOINT, endpoint);
     if (service_definition != null) sr.put(SERVICE_DEFINITION, service_definition);
     if (post_data != null) sr.put(POST_DATA, post_data);
     if (service_request != null) sr.put(SERVICE_REQUEST, service_request);
   } catch (JSONException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
   }
   return sr.toString();
 }
  /**
   * Adds a new server JSONObject to Preferences
   *
   * <p>This only updates the Preferences data. You still need make sure that the screen actually
   * reflects this change.
   *
   * @param dialog
   */
  private void saveNewServer(View dialog) {
    final EditText name = (EditText) dialog.findViewById(R.id.name);
    final EditText url = (EditText) dialog.findViewById(R.id.url);
    final EditText jurisdiction = (EditText) dialog.findViewById(R.id.jurisdiction);
    final EditText api_key = (EditText) dialog.findViewById(R.id.api_key);
    final ToggleButton supports_media = (ToggleButton) dialog.findViewById(R.id.supports_media);
    final Spinner format = (Spinner) dialog.findViewById(R.id.format);

    JSONObject server = new JSONObject();
    try {
      server.put(Open311.NAME, name.getText().toString());
      server.put(Open311.URL, url.getText().toString());
      server.put(Open311.JURISDICTION, jurisdiction.getText().toString());
      server.put(Open311.API_KEY, api_key.getText().toString());
      server.put(Open311.SUPPORTS_MEDIA, supports_media.isChecked());
      server.put(Open311.FORMAT, format.getSelectedItem());

      mCustomServers.put(server);
      Preferences.setCustomServers(mCustomServers, getActivity());
    } catch (JSONException e) {
      e.printStackTrace();
    }
  }
 /**
  * Returns the URL for getting a service_request_id from a token
  *
  * @param token
  * @return String
  * @throws JSONException
  */
 public String getServiceRequestIdFromTokenUrl(String token) throws JSONException {
   String baseUrl = endpoint.getString(Open311.URL);
   String jurisdiction = endpoint.optString(Open311.JURISDICTION);
   return String.format(
       "%s/tokens/%s.json?%s=%s", baseUrl, token, Open311.JURISDICTION, jurisdiction);
 }
 /**
  * Returns the URL for getting fresh information from the endpoint
  *
  * @param request_id
  * @return String
  * @throws JSONException
  */
 public String getServiceRequestUrl(String request_id) throws JSONException {
   String baseUrl = endpoint.getString(Open311.URL);
   String jurisdiction = endpoint.optString(Open311.JURISDICTION);
   return String.format(
       "%s/requests/%s.json?%s=%s", baseUrl, request_id, Open311.JURISDICTION, jurisdiction);
 }
 /** @return boolean */
 public boolean hasAttributes() {
   return service.optBoolean(Open311.METADATA);
 }
 /**
  * Loads an existing ServiceRequest from a JSON String
  *
  * <p>We will be serializing to a file as JSON Strings. This will include any data a user has
  * already entered and any new information from the endpoint. All createView() methods should use
  * this constructor, since they might be restoring from saveInstanceState()
  *
  * @param json
  */
 public ServiceRequest(String json) {
   try {
     JSONObject sr = new JSONObject(json);
     if (sr.has(ENDPOINT)) endpoint = sr.getJSONObject(ENDPOINT);
     if (sr.has(SERVICE)) service = sr.getJSONObject(SERVICE);
     if (sr.has(SERVICE_DEFINITION)) service_definition = sr.getJSONObject(SERVICE_DEFINITION);
     if (sr.has(POST_DATA)) post_data = sr.getJSONObject(POST_DATA);
     if (sr.has(SERVICE_REQUEST)) service_request = sr.getJSONObject(SERVICE_REQUEST);
   } catch (JSONException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
   }
 }