diff options
Diffstat (limited to 'config-model/src/main/java/com/yahoo/config/model/builder/xml/ConfigModelBuilder.java')
-rw-r--r-- | config-model/src/main/java/com/yahoo/config/model/builder/xml/ConfigModelBuilder.java | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/config-model/src/main/java/com/yahoo/config/model/builder/xml/ConfigModelBuilder.java b/config-model/src/main/java/com/yahoo/config/model/builder/xml/ConfigModelBuilder.java new file mode 100644 index 00000000000..a0b1be20df6 --- /dev/null +++ b/config-model/src/main/java/com/yahoo/config/model/builder/xml/ConfigModelBuilder.java @@ -0,0 +1,119 @@ +// Copyright 2016 Yahoo Inc. 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.AbstractConfigProducer; +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 + * @since 5.1.10 + */ +public abstract class ConfigModelBuilder<MODEL extends ConfigModel> extends AbstractComponent implements ConfigModelPlugin { + + private Class<MODEL> configModelClass; + + public ConfigModelBuilder(Class<MODEL> 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<ConfigModelId> 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, ConfigModelRepo configModelRepo, AbstractConfigProducer parent, Element spec) { + ConfigModelContext context = ConfigModelContext.create(deployState, 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<MODEL> factory, Element spec, ConfigModelContext context) { + MODEL model = factory.createModel(context); + doBuild(model, spec, context); + return model; + } + + public Class<MODEL> getModelClass() { + return configModelClass; + } + + private static String getIdString(Element spec) { + String idString = XmlHelper.getIdString(spec); + if (idString == null || idString.isEmpty()) { + idString = spec.getTagName(); + } + return idString; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof ConfigModelBuilder)) { + return false; + } + ConfigModelBuilder otherBuilder = (ConfigModelBuilder) other; + List<ConfigModelId> thisIds = this.handlesElements(); + List<ConfigModelId> 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<MODEL> { + @Override + public MODEL createModel(ConfigModelContext context) { + try { + Constructor<MODEL> constructor = configModelClass.getConstructor(ConfigModelContext.class); + return constructor.newInstance(context); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) { + throw new RuntimeException("Error constructing model '" + configModelClass.getName() + "'", e); + } + } + } +} |