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

com.yahoo.config.model.builder.xml.ConfigModelBuilder Maven / Gradle / Ivy

There is a newer version: 8.409.18
Show newest version
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.config.model.builder.xml;

import com.yahoo.component.AbstractComponent;
import com.yahoo.config.model.ConfigModel;
import com.yahoo.config.model.ConfigModelContext;
import com.yahoo.config.model.ConfigModelInstanceFactory;
import com.yahoo.config.model.ConfigModelRepo;
import com.yahoo.config.model.api.ConfigModelPlugin;
import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.config.model.producer.AnyConfigProducer;
import com.yahoo.config.model.producer.TreeConfigProducer;
import com.yahoo.vespa.model.VespaModel;
import org.w3c.dom.Element;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

/**
 * Builds a config model using DOM parsers
 *
 * @author vegardh
 */
public abstract class ConfigModelBuilder extends AbstractComponent implements ConfigModelPlugin {

    private final Class configModelClass;

    public ConfigModelBuilder(Class configModelClass) {
        this.configModelClass = configModelClass;
    }

    /**
     * Method that must return the XML elements this builder handles. Subclasses must implement this in order to
     * get called when one of the elements have been encountered when parsing.
     *
     * @return a list of elements that this builder handles
     */
    public abstract List handlesElements();

    /**
     * Convenience hook called from {@link #build}. Implement this method to build a config model.
     *
     * @param spec the XML element that this builder should handle
     * @param modelContext a model context that contains the application package and other data needed by the
     *                     config model constructor
     */
    public abstract void doBuild(MODEL model, Element spec, ConfigModelContext modelContext);

    /**
     * Builds an instance of this component model.
     * This calls instantiate(...), instance.setUp(...), doBuild(instance, ...).
     *
     * @param deployState a global deployment state used for this model.
     * @param parent the root config producer this should be added to
     * @param spec the XML element this is constructed from
     */
    public final MODEL build(DeployState deployState, VespaModel vespaModel, ConfigModelRepo configModelRepo,
                             TreeConfigProducer parent, Element spec) {
        ConfigModelContext context = ConfigModelContext.create(deployState, vespaModel, configModelRepo, parent, getIdString(spec));
        return build(new DefaultModelInstanceFactory(), spec, context);
    }

    /**
     * Builds an instance of this component model.
     * This calls instantiate(...), instance.setUp(...), doBuild(instance, ...).
     *
     * @param factory A factory capable of creating models.
     * @param spec the XML element this is constructed from
     * @param context A context object containing various data used by builders.
     */
    public MODEL build(ConfigModelInstanceFactory factory, Element spec, ConfigModelContext context) {
        MODEL model = factory.createModel(context);
        doBuild(model, spec, context);
        return model;
    }

    public Class getModelClass() {
        return configModelClass;
    }

    private static String getIdString(Element spec) {
        String idString = XmlHelper.getIdString(spec);
        if (idString.isEmpty())
            idString = spec.getTagName();
        return idString;
    }

    @Override
    public boolean equals(Object other) {
        if (!(other instanceof ConfigModelBuilder otherBuilder)) {
            return false;
        }
        List thisIds = this.handlesElements();
        List otherIds = otherBuilder.handlesElements();
        if (thisIds.size() != otherIds.size()) {
            return false;
        }
        for (int i = 0; i < thisIds.size(); i++) {
            if (!thisIds.get(i).equals(otherIds.get(i))) {
                return false;
            }
        }
        return true;
    }


    private class DefaultModelInstanceFactory implements ConfigModelInstanceFactory {
        @Override
        public MODEL createModel(ConfigModelContext context) {
            try {
                Constructor constructor = configModelClass.getConstructor(ConfigModelContext.class);
                return constructor.newInstance(context);
            } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
                throw new RuntimeException("Error constructing model '" + configModelClass.getName() + "'", e);
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy