com.yahoo.config.model.builder.xml.ConfigModelBuilder Maven / Gradle / Ivy
// 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