Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.predic8.membrane.core.kubernetes.GenericYamlParser Maven / Gradle / Ivy
/* Copyright 2022 predic8 GmbH, www.predic8.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
package com.predic8.membrane.core.kubernetes;
import com.google.common.collect.ImmutableMap;
import com.predic8.membrane.annot.MCAttribute;
import com.predic8.membrane.annot.MCElement;
import com.predic8.membrane.annot.MCOtherAttributes;
import com.predic8.membrane.core.config.spring.K8sHelperGeneratorAutoGenerated;
import org.yaml.snakeyaml.events.*;
import java.lang.reflect.Method;
import java.util.*;
import static com.predic8.membrane.core.config.spring.k8s.YamlLoader.readString;
import static com.predic8.membrane.core.kubernetes.ParserHelper.*;
import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
public class GenericYamlParser {
@SuppressWarnings({"unchecked", "rawtypes"})
public static T parse(String context, Class clazz, Iterator events, BeanRegistry registry) {
T obj = null;
try {
obj = clazz.newInstance();
Event event = events.next();
if (!(event instanceof MappingStartEvent)) {
throw new IllegalStateException("Expected start-of-map in line " + event.getStartMark().getLine() + " column " + event.getStartMark().getColumn());
}
while(true) {
event = events.next();
String key;
if (event instanceof ScalarEvent) {
key = ((ScalarEvent)event).getValue();
} else if (event instanceof MappingEndEvent) {
break;
} else {
throw new IllegalStateException("Expected scalar or end-of-map in line " + event.getStartMark().getLine() + " column " + event.getStartMark().getColumn());
}
if ("$ref".equals(key)) {
event = events.next();
if (!(event instanceof ScalarEvent))
throw new IllegalStateException("Expected a string after the '$ref' key.");
Object o = registry.resolveReference(((ScalarEvent) event).getValue());
Method setter = getChildSetter(clazz, o.getClass());
setSetter(obj, setter, o);
continue;
}
Method setter = getSetter(clazz, key);
Class clazz2 = null;
if (setter == null) {
try {
clazz2 = K8sHelperGeneratorAutoGenerated.getLocal(context, key);
if (clazz2 == null)
clazz2 = K8sHelperGeneratorAutoGenerated.elementMapping.get(key);
if (clazz2 != null)
setter = getChildSetter(clazz, clazz2);
} catch (Exception e) {
throw new RuntimeException("Can't find method or bean for key: " + key + " in " + clazz.getName(), e);
}
if (setter == null)
setter = getAnySetter(clazz);
if (clazz2 == null && setter == null)
throw new RuntimeException("Can't find method or bean for key: " + key + " in " + clazz.getName());
}
Class wanted = setter.getParameterTypes()[0];
// TODO: handle enums
if (wanted.equals(List.class)) {
setSetter(obj, setter, parseList(context, events, registry));
} else if (wanted.equals(String.class)) {
setSetter(obj, setter, readString(events));
} else if (wanted.equals(Integer.TYPE)) {
setSetter(obj, setter, Integer.parseInt(readString(events)));
} else if (wanted.equals(Long.TYPE)) {
setSetter(obj, setter, Long.parseLong(readString(events)));
} else if (wanted.equals(Boolean.TYPE)) {
setSetter(obj, setter, Boolean.parseBoolean(readString(events)));
} else if (wanted.equals(Map.class) && findAnnotation(setter, MCOtherAttributes.class) != null) {
setSetter(obj, setter, ImmutableMap.of(key, readString(events)));
} else if (isStructured(setter)) {
if (clazz2 != null)
setSetter(obj, setter, parseMapToObj(context, events, event, registry));
else
setSetter(obj, setter, parse(context, wanted, events, registry));
} else if (findAnnotation(setter, MCAttribute.class) != null && findAnnotation(setter.getParameterTypes()[0], MCElement.class) != null) {
setSetter(obj, setter, registry.resolveReference(readString(events)));
} else {
throw new RuntimeException("Not implemented setter type " + wanted);
}
}
} catch (Throwable e) {
throw new RuntimeException(e);
}
return obj;
}
private static List parseList(String context, Iterator events, BeanRegistry registry) {
Event event = events.next();
if (!(event instanceof SequenceStartEvent)) {
throw new IllegalStateException("Expected start-of-sequence in line " + event.getStartMark().getLine() + " column " + event.getStartMark().getColumn());
}
ArrayList res = new ArrayList();
while (true) {
event = events.next();
if (event instanceof SequenceEndEvent)
break;
else if (!(event instanceof MappingStartEvent))
throw new IllegalStateException("Expected end-of-sequence or begin-of-map in line " + event.getStartMark().getLine() + " column " + event.getStartMark().getColumn());
Object o = parseMapToObj(context, events, registry);
res.add(o);
}
return res;
}
private static Object parseMapToObj(String context, Iterator events, BeanRegistry registry) {
Event event = events.next();
if (!(event instanceof ScalarEvent))
throw new IllegalStateException("Expected scalar in line " + event.getStartMark().getLine() + " column " + event.getStartMark().getColumn());
Object o = parseMapToObj(context, events, event, registry);
event = events.next();
if (!(event instanceof MappingEndEvent))
throw new IllegalStateException("Expected end-of-map or begin-of-map in line " + event.getStartMark().getLine() + " column " + event.getStartMark().getColumn());
return o;
}
private static Object parseMapToObj(String context, Iterator events, Event event, BeanRegistry registry) {
String key = ((ScalarEvent) event).getValue();
if ("$ref".equals(key)) {
event = events.next();
if (!(event instanceof ScalarEvent))
throw new IllegalStateException("Expected a string after the '$ref' key.");
return registry.resolveReference(((ScalarEvent)event).getValue());
}
Class clazz = K8sHelperGeneratorAutoGenerated.getLocal(context, key);
if (clazz == null)
clazz = K8sHelperGeneratorAutoGenerated.elementMapping.get(key);
if (clazz == null)
throw new RuntimeException("Did not find java class for key '" + key + "'.");
return GenericYamlParser.parse(key, clazz, events, registry);
}
private static Method getSetter(Class clazz, String key) {
return Arrays.stream(clazz.getMethods())
.filter(ParserHelper::isSetter)
.filter(method -> matchesJsonKey(method, key))
.findFirst()
.orElse(null);
}
private static Method getAnySetter(Class clazz) {
return Arrays.stream(clazz.getMethods())
.filter(ParserHelper::isSetter)
.filter(method -> findAnnotation(method, MCOtherAttributes.class) != null)
.findFirst()
.orElse(null);
}
private static Method getChildSetter(Class clazz, Class valueClass) {
return Arrays.stream(clazz.getMethods())
.filter(ParserHelper::isSetter)
.filter(method -> method.getParameterTypes().length == 1)
.filter(method -> method.getParameterTypes()[0].isAssignableFrom(valueClass))
.findFirst()
.orElseThrow(() -> new RuntimeException("Could not find child setter on " + clazz.getName() + " for value of type " + valueClass.getName()));
}
}