public static String toJson(OdeAccess access) {
		StringBuffer sb = new StringBuffer(1024);
		sb.append("{ ");
		
		boolean first = true;
		
		sb.append("\"vertices\":[ ");
		for (Visode v : access.getVisodes()) {
			String type = "";
			if (v.getType() == Visode.TYPE_LINK) {
				type = "link";
			} else if (v.getType() == Visode.TYPE_NODE) {
				type = "node";
			} else if (v.getType() == Visode.TYPE_SPACER) {
				continue;
			}
			
			if (first) {
				first = false;
			} else {
				sb.append(", ");
			}
			
			sb.append("{ ");
			
			jsonPair(sb, "uid", v.getUID());
			sb.append(", ");

			jsonPair(sb, "name", v.getDisplayName());
			sb.append(", ");

			jsonPair(sb, "longname", v.getLongName());
			sb.append(", ");

			jsonPair(sb, "type", type);
			sb.append(", ");
			
			jsonPair(sb, "url", urlFor(v.getUID()));
			sb.append(", ");

			jsonPair(sb, "x", v.getCenter().x);
			sb.append(", ");
			
			jsonPair(sb, "y", v.getCenter().y);
			sb.append(", ");
			
			jsonPair(sb, "z", v.getCenter().z);
			sb.append(", ");
			
			jsonPair(sb, "r", v.getRadius());
			
			sb.append(" }");
		}
		sb.append(" ]");
		
		first = true;
		sb.append(", ");
		sb.append("\"edges\":[ ");
		for (String v : access.getOdes()) {
			for (String p : access.findParents(v)) {
				if (first) {
					first = false;
				} else {
					sb.append(", ");
				}
				
				sb.append("{ ");
				jsonPair(sb, "tail", v);
				sb.append(", ");
				jsonPair(sb, "head", p);
				sb.append(" }");
			}
		}
		sb.append(" ]");
		
		sb.append(" }");
		return sb.toString();
	}