* @param metadata Keys are entity's name, values are Java classes.
* @return A new Yaml instance.
*/
private static Yaml newYaml(final ApplicationContext applicationContext,
final Map<String, ClassMetadata> metadata) {
CompactConstructor constructor = new CompactConstructor() {
@Override
protected Class<?> getClassForName(final String name) throws ClassNotFoundException {
Collection<ClassMetadata> classes = metadata.values();
for (ClassMetadata classMetadata : classes) {
Class<?> mappedClass = classMetadata.getMappedClass();
if (name.equals(mappedClass.getSimpleName())) {
return mappedClass;
}
}
return super.getClassForName(name);
}
@Override
protected Object createInstance(final ScalarNode node, final CompactData data)
throws Exception {
Class<?> clazz = getClassForName(data.getPrefix());
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
ConversionService conversionService = applicationContext.getBean(ConversionService.class);
// find best matching constructor
for (Constructor<?> constructor : constructors) {
Class<?>[] parameterTypes = constructor.getParameterTypes();
if (parameterTypes.length == data.getArguments().size()) {
boolean found = true;
int p = 0;
Object[] args = new Object[parameterTypes.length];
while (found && p < parameterTypes.length) {
Class<?> parameterType = parameterTypes[p];
boolean canConvert = conversionService.canConvert(String.class, parameterType);
if (canConvert) {
args[p] = conversionService.convert(data.getArguments().get(p), parameterType);
}
found &= canConvert;
p++;
}
if (found) {
constructor.setAccessible(true);
return BeanUtils.instantiateClass(constructor, args);
}
}
}
throw new IllegalArgumentException("Constructor not found: " + clazz.getName()
+ "(" + join(data.getArguments(), ",") + ")");
}
};
// Add !tag
for (Entry<String, ClassMetadata> entry : metadata.entrySet()) {
ClassMetadata cmetadata = entry.getValue();
Class<?> mappedClass = cmetadata.getMappedClass();
String tag = "!!" + mappedClass.getSimpleName();
constructor.addTypeDescription(new TypeDescription(mappedClass, tag));
}
return new Yaml(constructor);
}