package io.cattle.platform.api.utils;
import io.cattle.platform.api.auth.Policy;
import io.cattle.platform.api.auth.impl.DefaultPolicy;
import io.cattle.platform.object.meta.ObjectMetaDataManager;
import io.cattle.platform.object.util.DataUtils;
import io.cattle.platform.object.util.ObjectUtils;
import io.github.ibuildthecloud.gdapi.context.ApiContext;
import io.github.ibuildthecloud.gdapi.factory.SchemaFactory;
import io.github.ibuildthecloud.gdapi.id.IdFormatter;
import io.github.ibuildthecloud.gdapi.model.Collection;
import io.github.ibuildthecloud.gdapi.model.Resource;
import io.github.ibuildthecloud.gdapi.model.Schema;
import io.github.ibuildthecloud.gdapi.model.impl.WrappedResource;
import io.github.ibuildthecloud.gdapi.request.ApiRequest;
import io.github.ibuildthecloud.gdapi.request.resource.ResourceManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.cloudstack.managed.threadlocal.ManagedThreadLocal;
import org.apache.commons.collections.Transformer;
public class ApiUtils {
public static final String SINGLE_ATTACHMENT_PREFIX = "s__";
private static final Policy DEFAULT_POLICY = new DefaultPolicy();
private static final Set<String> PRIORITY_FIELDS = new LinkedHashSet<>(Arrays.asList(ObjectMetaDataManager.NAME_FIELD, ObjectMetaDataManager.STATE_FIELD));
private static final ManagedThreadLocal<Integer> DEPTH = new ManagedThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};
public static Object getFirstFromList(Object obj) {
if (obj instanceof Collection) {
return getFirstFromList(((Collection) obj).getData());
}
if (obj instanceof List) {
List<?> list = (List<?>) obj;
return list.size() > 0 ? list.get(0) : null;
}
return null;
}
public static Policy getPolicy() {
Object policy = ApiContext.getContext().getPolicy();
if (policy instanceof Policy) {
return (Policy) policy;
} else {
return DEFAULT_POLICY;
}
}
public static <T> List<T> authorize(List<T> list) {
return getPolicy().authorizeList(list);
}
@SuppressWarnings("unchecked")
public static <T> T authorize(T obj) {
if (obj instanceof List) {
return (T) authorize((List<T>) obj);
}
return getPolicy().authorizeObject(obj);
}
public static String getAttachementKey(Object obj) {
return getAttachementKey(obj, ObjectUtils.getId(obj));
}
public static String getAttachementKey(Object obj, Object id) {
if (obj == null) {
return null;
}
if (id == null) {
return null;
}
return obj.getClass().getName() + ":" + id;
}
public static void addAttachement(Object key, String name, Object obj) {
ApiRequest request = ApiContext.getContext().getApiRequest();
@SuppressWarnings("unchecked")
Map<String, Map<Object, Object>> attachments = (Map<String, Map<Object, Object>>) request.getAttribute(key);
Object id = ObjectUtils.getId(obj);
if (id == null) {
return;
}
if (attachments == null) {
attachments = new HashMap<String, Map<Object, Object>>();
request.setAttribute(key, attachments);
}
Map<Object, Object> attachment = attachments.get(name);
if (attachment == null) {
attachment = new LinkedHashMap<Object, Object>();
attachments.put(name, attachment);
}
attachment.put(id, obj);
}
public static Map<String, Object> getAttachements(Object obj, Transformer transformer) {
Map<String, Object> result = new LinkedHashMap<String, Object>();
Object key = getAttachementKey(obj);
ApiRequest request = ApiContext.getContext().getApiRequest();
@SuppressWarnings("unchecked")
Map<String, Map<Object, Object>> attachments = (Map<String, Map<Object, Object>>) request.getAttribute(key);
if (attachments == null) {
return result;
}
for (Map.Entry<String, Map<Object, Object>> entry : attachments.entrySet()) {
String keyName = entry.getKey();
List<Object> objects = new ArrayList<Object>();
for (Object attachment : entry.getValue().values()) {
attachment = transformer.transform(attachment);
if (attachment != null) {
objects.add(attachment);
}
}
if (keyName.startsWith(SINGLE_ATTACHMENT_PREFIX)) {
Object attachedObj = objects.size() > 0 ? objects.get(0) : null;
result.put(keyName.substring(SINGLE_ATTACHMENT_PREFIX.length()), attachedObj);
} else {
result.put(keyName, objects);
}
}
return result;
}
public static Resource createResourceWithAttachments(final ResourceManager resourceManager, final ApiRequest request, final IdFormatter idFormatter,
final SchemaFactory schemaFactory, final Schema schema, Object obj, Map<String, Object> inputAdditionalFields) {
Integer depth = DEPTH.get();
try {
DEPTH.set(depth + 1);
Map<String, Object> additionalFields = new LinkedHashMap<String, Object>();
additionalFields.putAll(DataUtils.getFields(obj));
if (inputAdditionalFields != null && inputAdditionalFields.size() > 0) {
additionalFields.putAll(inputAdditionalFields);
}
if (depth == 0) {
Map<String, Object> attachments = ApiUtils.getAttachements(obj, new Transformer() {
@Override
public Object transform(Object input) {
input = ApiUtils.authorize(input);
if (input == null)
return null;
return resourceManager.convertResponse(input, request);
}
});
additionalFields.putAll(attachments);
}
String method = request == null ? null : request.getMethod();
return new WrappedResource(idFormatter, schemaFactory, schema, obj, additionalFields, PRIORITY_FIELDS, method);
} finally {
DEPTH.set(depth);
}
}
public static String getSchemaIdForDisplay(SchemaFactory factory, Object obj) {
Schema schema = factory.getSchema(obj.getClass());
if (schema == null) {
return null;
}
String kind = ObjectUtils.getKind(obj);
Schema kindSchema = factory.getSchema(kind);
if (kindSchema != null && schema.getId().equals(factory.getBaseType(kindSchema.getParent()))) {
return kindSchema.getId();
}
return schema.getId();
}
}