All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.atlassian.bamboo.specs.util.Yamlizator Maven / Gradle / Ivy

package com.atlassian.bamboo.specs.util;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.BaseConstructor;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.introspector.BeanAccess;
import org.yaml.snakeyaml.introspector.FieldProperty;
import org.yaml.snakeyaml.introspector.Property;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;

import java.beans.IntrospectionException;
import java.lang.reflect.Field;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;

public final class Yamlizator {
    private static final DumperOptions BLOCK_STYLE_DUMPER;

    private static final Field FIELD_FIELD;

    static {
        BLOCK_STYLE_DUMPER = new DumperOptions();
        BLOCK_STYLE_DUMPER.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
        BLOCK_STYLE_DUMPER.setExplicitStart(true);
        BLOCK_STYLE_DUMPER.setExplicitEnd(true);
        BLOCK_STYLE_DUMPER.setAllowReadOnlyProperties(true);

        try {
            FIELD_FIELD = FieldProperty.class.getDeclaredField("field");
            FIELD_FIELD.setAccessible(true);

        } catch (final NoSuchFieldException | SecurityException e) {
            throw new RuntimeException(e);
        }
    }

    private Yamlizator() {
    }

    public static Yaml getYaml() {
        final Yaml yaml = new Yaml(getConstructor(), getRepresenter(), BLOCK_STYLE_DUMPER);
        yaml.setBeanAccess(BeanAccess.FIELD);
        return yaml;
    }

    private static BaseConstructor getConstructor() {
        return new Constructor() {
            {
                for (final CustomYamlers.CustomYamler customYamler : CustomYamlers.YAMLERS) {
                    this.yamlConstructors.put(new Tag(customYamler.getYamledClass()), customYamler.getConstructor());
                }
            }
        };
    }

    @NotNull
    private static Representer getRepresenter() {
        return new Representer() {
            {
                for (final CustomYamlers.CustomYamler customYamler : CustomYamlers.YAMLERS) {
                    this.representers.put(customYamler.getYamledClass(), customYamler.getRepresenter());
                }
            }

            @Override
            protected Set getProperties(final Class type)
                    throws IntrospectionException {
                final Set properties = getPropertyUtils().getProperties(type);

                return properties.stream()
                        .sorted(CLASS_SCOPED_ORDER)
                        .collect(Collectors.toCollection(LinkedHashSet::new));
            }
        };
    }

    private static final Comparator CLASS_SCOPED_ORDER = new Comparator() {
        @Override
        public int compare(final Property o1, final Property o2) {
            final FieldProperty fp1 = asFieldProperty(o1);
            final FieldProperty fp2 = asFieldProperty(o2);

            if (fp1 == null && fp2 != null) {
                return -1;
            }
            if (fp1 != null && fp2 == null) {
                return 1;
            }
            if (fp1 == null) {
                return 0;
            }

            final Class class1 = getDeclaringClass(fp1);
            final Class class2 = getDeclaringClass(fp2);

            if (!class1.equals(class2)) { //fields from parent class first
                if (class2.isAssignableFrom(class1)) {
                    return 1;
                } else if (class1.isAssignableFrom(class2)) {
                    return -1;
                }
            }

            final int classCompare = class1.getName().compareTo(class2.getName());
            if (classCompare != 0) {
                return classCompare;
            }
            return fp1.getName().compareTo(fp2.getName());
        }


    };

    @Nullable
    private static FieldProperty asFieldProperty(final Property property) {
        if (property instanceof FieldProperty) {
            return (FieldProperty) property;
        }
        return null;
    }

    @NotNull
    private static Class getDeclaringClass(final FieldProperty fieldProperty) {
        try {
            return ((Field) FIELD_FIELD.get(fieldProperty)).getDeclaringClass();
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy