	public static String format(Object o, String format) {
		if (o == null) { return ""; }
		if (o instanceof Date) {
			DateFormat df = decode(format, Context.getDateFormat(), new SimpleDateFormat(format));
			return df.format((Date)o);
		}
		if (o instanceof Map) {
			return toString((Map)o, nvl(format, ","));
		}
		if (o instanceof Collection) {
			return OpenmrsUtil.join((Collection)o, nvl(format, ","));
		}
		if (o instanceof Object[]) {
			return toString(nvl(format, ","), (Object[])o);
		}
		if (o instanceof Number) {
			if (notNull(format)) {
				NumberFormat nf = NumberFormat.getInstance();
				nf.setGroupingUsed(false);
				return nf.format((Number)o);
			}
		}
		if (o instanceof OpenmrsMetadata) {
			String name = ((OpenmrsMetadata) o).getName();
			if (name == null) {
				if (o instanceof ProgramWorkflow) {
					name = ((ProgramWorkflow)o).getConcept().getDisplayString();
				}
				else if (o instanceof ProgramWorkflowState) {
					name = ((ProgramWorkflowState)o).getConcept().getDisplayString();
				}
			}
			return name;
		}
		if (o instanceof OpenmrsData) {
			if (ObjectUtil.notNull(format)) {
				String[] formatSplit = format.split("\\|");
				String ret = formatSplit[0];
				try {
					int startIndex = ret.indexOf("{");
					int endIndex = ret.indexOf("}", startIndex+1);
					while (startIndex != -1 && endIndex != -1) {
						String propertyName = format.substring(startIndex+1, endIndex);
						Object replacement = ReflectionUtil.getPropertyValue(o, propertyName);
						String newFormat = (replacement != null && formatSplit.length > 1 ? formatSplit[1] : null);
						replacement = ObjectUtil.format(replacement, newFormat);
						ret = ret.replace("{"+propertyName+"}", nvlStr(replacement, ""));
						startIndex = ret.indexOf("{");
						endIndex = ret.indexOf("}", startIndex+1);
					}
					return ret;
				}
				catch (Exception e) {
					log.warn("Unable to get property using converter with format: " + format, e);
				}
			}
		}
		return o.toString();
	}

	public static String format(Object o, String format) {
		if (o == null) { return ""; }
		if (o instanceof Date) {
			DateFormat df = decode(format, Context.getDateFormat(), new SimpleDateFormat(format));
			return df.format((Date)o);
		}
		if (o instanceof Map) {
			return toString((Map)o, nvl(format, ","));
		}
		if (o instanceof Collection) {
			return OpenmrsUtil.join((Collection)o, nvl(format, ","));
		}
		if (o instanceof Object[]) {
			return toString(nvl(format, ","), (Object[])o);
		}
		if (o instanceof Number) {
			if (notNull(format)) {
				NumberFormat nf = NumberFormat.getInstance();
				nf.setGroupingUsed(false);
				return nf.format((Number)o);
			}
		}
		if (o instanceof OpenmrsMetadata) {
			String name = ((OpenmrsMetadata) o).getName();
			if (name == null) {
				if (o instanceof ProgramWorkflow) {
					name = ((ProgramWorkflow)o).getConcept().getDisplayString();
				}
				else if (o instanceof ProgramWorkflowState) {
					name = ((ProgramWorkflowState)o).getConcept().getDisplayString();
				}
			}
			return name;
		}
		if (o instanceof OpenmrsData) {
			if (ObjectUtil.notNull(format)) {
				String[] formatSplit = format.split("\\|");
				String ret = formatSplit[0];
				try {
					int startIndex = ret.indexOf("{");
					int endIndex = ret.indexOf("}", startIndex+1);
					while (startIndex != -1 && endIndex != -1) {
						String propertyName = ret.substring(startIndex+1, endIndex);
						Object replacement = ReflectionUtil.getPropertyValue(o, propertyName);
						String newFormat = (replacement != null && formatSplit.length > 1 ? formatSplit[1] : null);
						replacement = ObjectUtil.format(replacement, newFormat);
						ret = ret.replace("{"+propertyName+"}", nvlStr(replacement, ""));
						startIndex = ret.indexOf("{");
						endIndex = ret.indexOf("}", startIndex+1);
					}
					return ret;
				}
				catch (Exception e) {
					log.warn("Unable to get property using converter with format: " + format, e);
				}
			}
		}
		return o.toString();
	}
