package com.braintreegateway;
import com.braintreegateway.util.QueryString;
import com.braintreegateway.util.StringUtils;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
public class RequestBuilder {
private String parent;
private Map<String, String> topLevelElements;
private Map<String, Object> elements;
public RequestBuilder(String parent) {
this.parent = parent;
this.topLevelElements = new HashMap<String, String>();
this.elements = new HashMap<String, Object>();
}
public RequestBuilder addTopLevelElement(String name, String value) {
topLevelElements.put(name, value);
return this;
}
public RequestBuilder addElement(String name, Object value) {
elements.put(name, value);
return this;
}
public String toQueryString() {
QueryString queryString = new QueryString();
for (Map.Entry<String, String> entry : topLevelElements.entrySet()) {
queryString.append(StringUtils.underscore(entry.getKey()), entry.getValue());
}
for (Map.Entry<String, Object> entry : elements.entrySet()) {
queryString.append(parentBracketChildString(StringUtils.underscore(parent), StringUtils.underscore(entry.getKey())), entry.getValue());
}
return queryString.toString();
}
public String toXML() {
StringBuilder builder = new StringBuilder();
builder.append(String.format("<%s>", parent));
for (Map.Entry<String, Object> entry : elements.entrySet()) {
builder.append(buildXMLElement(entry.getKey(), entry.getValue()));
}
builder.append(String.format("</%s>", parent));
return builder.toString();
}
protected static String buildXMLElement(Object element) {
return buildXMLElement("", element);
}
@SuppressWarnings("unchecked")
protected static String buildXMLElement(String name, Object element) {
if (element == null) {
return "";
} else if (element instanceof Request) {
return ((Request) element).toXML();
} else if (element instanceof Calendar) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
return String.format("<%s type=\"datetime\">%s</%s>", name, dateFormat.format(((Calendar) element).getTime()), name);
} else if (element instanceof Map<?, ?>) {
return formatAsXML(name, (Map<String, Object>) element);
} else if (element instanceof List<?>) {
StringBuilder xml = new StringBuilder();
for (Object item : (List<Object>) element) {
xml.append(buildXMLElement("item", item));
}
return wrapInXMLTag(name, xml.toString(), "array");
} else {
return String.format("<%s>%s</%s>", xmlEscape(name), element == null ? "" : xmlEscape(element.toString()), xmlEscape(name));
}
}
protected static String formatAsXML(String name, Map<String, Object> map) {
if (map == null)
return "";
StringBuilder xml = new StringBuilder();
xml.append(String.format("<%s>", name));
for (Map.Entry<String, Object> entry : map.entrySet()) {
xml.append(buildXMLElement(entry.getKey(), entry.getValue()));
}
xml.append(String.format("</%s>", name));
return xml.toString();
}
protected static Object buildQueryStringElement(String name, String value) {
if (value != null) {
try {
return String.format("%s=%s&", URLEncoder.encode(name, "UTF-8"), URLEncoder.encode(value, "UTF-8"));
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
return "";
}
}
protected static String parentBracketChildString(String parent, String child) {
return String.format("%s[%s]", parent, child);
}
protected static String wrapInXMLTag(String tagName, String xml) {
return String.format("<%s>%s</%s>", tagName, xml, tagName);
}
protected static String wrapInXMLTag(String tagName, String xml, String type) {
return String.format("<%s type=\"%s\">%s</%s>", tagName, type, xml, tagName);
}
protected static String xmlEscape(String input) {
return input.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("'", "'").replaceAll("\"", """);
}
}