package de.escalon.hypermedia.spring.hydra;
import de.escalon.hypermedia.AnnotationUtils;
import de.escalon.hypermedia.affordance.ActionInputParameter;
import de.escalon.hypermedia.hydra.mapping.Expose;
import de.escalon.hypermedia.hydra.serialize.LdContextFactory;
import de.escalon.hypermedia.hydra.serialize.MixinSource;
import de.escalon.hypermedia.spring.DocumentationProvider;
import de.escalon.hypermedia.spring.SpringActionInputParameter;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
/**
* Created by Dietrich on 05.04.2015.
*/
public class JsonLdDocumentationProvider implements DocumentationProvider {
private LdContextFactory ldContextFactory = new LdContextFactory();
private MixinSource mixinSource = new MixinSource() {
@Override
public Class<?> findMixInClassFor(Class<?> clazz) {
return null;
}
};
@Override
public String getDocumentationUrl(ActionInputParameter parameter, Object content) {
final Expose expose = parameter.getAnnotation(Expose.class);
String ret;
if (content == null) {
if (parameter instanceof SpringActionInputParameter) {
Class<?> clazz = ((SpringActionInputParameter) parameter).getDeclaringClass();
ret = getExposedUrl(parameter.getParameterName(), vocabFromClass(clazz), termsFromClazz(clazz), expose);
} else {
ret = null;
}
} else {
ret = getExposedUrl(parameter.getParameterName(), vocabFromBean(content), termsFromBean(content), expose);
}
return ret;
}
@Override
public String getDocumentationUrl(Field field, Object content) {
final Expose expose = AnnotationUtils.findAnnotation(field, Expose.class);
// TODO can we support Mixins from here?
// final Class<?> mixin = provider.getConfig()
// .findMixInClassFor(bean.getClass());
// final Expose mixinExpose = findAnnotation(mixin, Expose.class);
return getExposedUrl(field.getName(), vocabFromBean(content), termsFromBean(content), expose);
}
@Override
public String getDocumentationUrl(Method method, Object content) {
final Expose expose = AnnotationUtils.findAnnotation(method, Expose.class);
// TODO can we support Mixins from here?
// final Class<?> mixin = provider.getConfig()
// .findMixInClassFor(bean.getClass());
// final Expose mixinExpose = findAnnotation(mixin, Expose.class);
String methodName = method.getName();
String propertyName;
if (methodName.startsWith("get")) {
propertyName = StringUtils.uncapitalize(StringUtils.removeStart(methodName, "get"));
} else {
propertyName = StringUtils.uncapitalize(StringUtils.removeStart(methodName, "is"));
}
return getExposedUrl(propertyName, vocabFromBean(content), termsFromBean(content), expose);
}
@Override
public String getDocumentationUrl(Class clazz, Object content) {
final Expose expose = AnnotationUtils.findAnnotation(clazz, Expose.class);
// TODO can we support Mixins from here?
// final Class<?> mixin = provider.getConfig()
// .findMixInClassFor(bean.getClass());
// final Expose mixinExpose = findAnnotation(mixin, Expose.class);
return getExposedUrl(clazz.getSimpleName(), vocabFromBean(content), termsFromBean(content), expose);
}
@Nullable
private String getExposedUrl(String plainName, String vocab, Map<String, Object> terms, Expose expose) {
final String name;
if (expose != null) {
name = expose.value(); // expose is better than Java name
} else {
name = plainName;
}
String url;
if (name.matches("http(s)?://.+")) {
url = name;
} else if (name.contains(":")) {
url = resolveCurie(terms, name);
} else {
url = makeVocabUrl(vocab, name);
}
return url;
}
@Nullable
private String resolveCurie(Map<String, Object> terms, String name) {
String url;
String[] curie = name.split(":");
Object termDef = terms.get(curie[0]);
if (termDef != null) {
if (termDef instanceof Map) {
// TODO handle @name:@vocab etc.
url = null;
} else {
url = termDef.toString() + curie[1];
}
} else {
url = null;
}
return url;
}
@Override
public String getDocumentationUrl(String name, Object content) {
String ret;
if (content == null) {
ret = null;
} else {
ret = getExposedUrl(name, vocabFromBean(content), termsFromBean(content), null);
}
return ret;
}
@Nullable
private String makeVocabUrl(String vocab, String name) {
String url;
if (vocab != null) {
url = vocab + name;
} else {
url = null;
}
return url;
}
@Nullable
private String vocabFromBean(Object content) {
return ldContextFactory.getVocab(mixinSource, content, null);
}
private Map<String, Object> termsFromBean(Object content) {
return ldContextFactory.getTerms(mixinSource, content, null);
}
private Map<String, Object> termsFromClazz(Class<?> clazz) {
return ldContextFactory.termsFromClass(clazz);
}
private String vocabFromClass(Class<?> clazz) {
String vocabFromClassOrPackage = ldContextFactory.vocabFromClassOrPackage(clazz);
return vocabFromClassOrPackage == null ? LdContextFactory.HTTP_SCHEMA_ORG : vocabFromClassOrPackage;
}
}