summaryrefslogtreecommitdiffstats
path: root/config-lib/src/main/java/com/yahoo/config/ConfigInstance.java
blob: 5f06bc27decabb7c55011bb7ee0b35a81d617c97 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.config;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Represents an instance of an application config with a specific configId.
 * <p>
 * An instance of this class contains all values (represented by Nodes) for the config object as it
 * is the superclass of the generated config class used by the client.
 */
public abstract class ConfigInstance extends InnerNode {

    public interface Builder extends ConfigBuilder {

        /**
         * Dispatches a getConfig() call if this instance's producer is of the right type
         *
         * @param producer a config producer
         * @return true if this instance's producer was the correct type, and hence a getConfig call was dispatched
         */
        boolean dispatchGetConfig(Producer producer);

        String getDefName();
        String getDefNamespace();
        String getDefMd5();

        /** Returns true if this instance should be applied on restart, false if it should be applied immediately */
        default boolean getApplyOnRestart() { return false; }

        default void setApplyOnRestart(boolean applyOnRestart) { throw new java.lang.UnsupportedOperationException(); }

    }

    public interface Producer {}

    private String configMd5 = "";

    @SuppressWarnings("unused") // Used by reflection from ConfigInstanceUtil
    String configId;

    /**
     * Gets the name of the given config instance
     */
    public static String getDefName(Class<?> type) {
        return getStaticStringField(type, "CONFIG_DEF_NAME");
    }

    /**
     * Gets the namespace of the given config instance
     */
    public static String getDefNamespace(Class<?> type) {
        return getStaticStringField(type, "CONFIG_DEF_NAMESPACE");
    }

    /**
     * Returns the serialized representation of the given node.
     * <p>
     * Declared static, instead of InnerNode member, to avoid a public 0-arg method with a commonly used name.
     *
     * @param node The inner node
     * @return a list of strings, containing the serialized representation of this config
     */
    public static List<String> serialize(InnerNode node) {
        List<String> ret = new ArrayList<>();
        for (Map.Entry<String, LeafNode<?>> entry : getAllDescendantLeafNodes(node).entrySet()) {
            ret.add(entry.getKey() + " " + entry.getValue().toString());
        }
        return ret;
    }

    public static void serialize(InnerNode node, Serializer serializer) {
        serializeMap(node.getChildren(), serializer);
    }

    @SuppressWarnings("unchecked")
    private static void serializeObject(String name, Object child, Serializer serializer) {
        if (child instanceof InnerNode) {
            Serializer childSerializer = serializer.createInner(name);
            serialize((InnerNode) child, childSerializer);
        } else if (child instanceof Map) {
            Serializer mapSerializer = serializer.createMap(name);
            serializeMap((Map<String, Object>)child, mapSerializer);
        } else if (child instanceof NodeVector) {
            Serializer arraySerializer = serializer.createArray(name);
            serializeArray((NodeVector) child, arraySerializer);
        } else if (child instanceof LeafNode) {
            ((LeafNode) child).serialize(name, serializer);
        }
    }

    private static void serializeMap(Map<String, Object> childMap, Serializer serializer) {
        for (Map.Entry<String, Object> entry : childMap.entrySet()) {
            String name = entry.getKey();
            Object child = entry.getValue();
            serializeObject(name, child, serializer);
        }
    }

    private static void serializeArray(NodeVector<?> nodeVector, Serializer arraySerializer) {
        for (Object child : nodeVector.vector) {
            if (child instanceof InnerNode) {
                Serializer childSerializer = arraySerializer.createInner();
                serialize((InnerNode) child, childSerializer);
            } else if (child instanceof LeafNode) {
                ((LeafNode) child).serialize(arraySerializer);
            }
        }
    }

    /**
     * @deprecated do not use
     */
    @Deprecated
    // TODO: Remove in Vespa 8
    public String getConfigMd5() {
        return configMd5;
    }

    /**
     * @deprecated do not use
     */
    @Deprecated
    // TODO: Remove in Vespa 8
    public void setConfigMd5(String configMd5) {
        this.configMd5 = configMd5;
    }

    private static String getStaticStringField(Class<?> type, String fieldName) {
        try {
            return (String) type.getField(fieldName).get(null);
        } catch (Exception e) {
            throw new RuntimeException
                    (e.getMessage() + ": Static field " + fieldName + " not " + "accessible in " + type.getName());
        }
    }

}