Adapted to comply with JSR API. Signed-off-by: Anatole Tresch <[email protected]>
Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/commit/54b627b9 Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/tree/54b627b9 Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/diff/54b627b9 Branch: refs/heads/configjsr Commit: 54b627b951ea201fe82f7765de1713cccea8d373 Parents: 117c0a9 Author: Anatole Tresch <[email protected]> Authored: Sun Jan 14 22:20:55 2018 +0100 Committer: Anatole Tresch <[email protected]> Committed: Sun Jan 14 22:20:55 2018 +0100 ---------------------------------------------------------------------- .../apache/tamaya/validation/ConfigModel.java | 78 ----- .../tamaya/validation/ConfigModelManager.java | 298 ------------------- .../apache/tamaya/validation/ModelTarget.java | 37 --- .../apache/tamaya/validation/Validation.java | 50 ++-- .../tamaya/validation/ValidationManager.java | 294 ++++++++++++++++++ .../tamaya/validation/ValidationModel.java | 78 +++++ .../tamaya/validation/ValidationResult.java | 59 ---- .../tamaya/validation/ValidationTarget.java | 37 +++ .../tamaya/validation/ValidationType.java | 59 ++++ .../internal/ConfigDocumentationBean.java | 197 ------------ .../internal/ConfigValidationBean.java | 197 ++++++++++++ .../ConfiguredInlineModelProviderSpi.java | 40 ++- .../ConfiguredPropertiesModelProviderSpi.java | 38 +-- .../ConfiguredResourcesModelProviderSpi.java | 21 +- .../ConfiguredTypeEventsModelPopulator.java | 17 +- .../ConfiguredTypeEventsModelProvider.java | 14 +- .../validation/spi/AbstractConfigModel.java | 6 +- .../spi/ConfigDocumentationMBean.java | 53 ---- .../validation/spi/ConfigModelReader.java | 142 --------- .../validation/spi/ConfigValidationMBean.java | 53 ++++ .../validation/spi/ConfigValidationReader.java | 131 ++++++++ .../tamaya/validation/spi/GroupModel.java | 110 ------- .../tamaya/validation/spi/ModelProviderSpi.java | 39 --- .../tamaya/validation/spi/ParameterModel.java | 242 --------------- .../tamaya/validation/spi/SectionModel.java | 202 ------------- .../tamaya/validation/spi/ValidateGroup.java | 110 +++++++ .../validation/spi/ValidateParameter.java | 242 +++++++++++++++ .../tamaya/validation/spi/ValidateSection.java | 201 +++++++++++++ .../spi/ValidationModelProviderSpi.java | 39 +++ .../resources/META-INF/configmodel.properties | 35 --- .../META-INF/configvalidation.properties | 35 +++ ...org.apache.tamaya.events.ConfigEventListener | 2 +- ...maya.validation.spi.ConfigDocumentationMBean | 38 --- ....tamaya.validation.spi.ConfigValidationMBean | 19 ++ ...pache.tamaya.validation.spi.ModelProviderSpi | 41 --- ...ya.validation.spi.ValidationModelProviderSpi | 22 ++ .../validation/ConfigModelProviderTest.java | 32 +- .../tamaya/validation/ValidationTests.java | 13 +- .../internal/ConfigDocumentationBeanTest.java | 8 +- .../java/test/model/TestConfigAccessor.java | 16 +- .../resources/META-INF/configmodel.properties | 96 ------ .../META-INF/configvalidation.properties | 96 ++++++ .../resources/META-INF/javaconfig.properties | 22 ++ .../META-INF/javaconfiguration.properties | 22 -- ...org.apache.tamaya.model.spi.ModelProviderSpi | 2 +- .../src/test/resources/examples/configmodel.ini | 76 ----- .../test/resources/examples/configmodel.json | 108 ------- .../resources/examples/configmodel.properties | 96 ------ .../src/test/resources/examples/configmodel.xml | 97 ------ .../test/resources/examples/configmodel.yaml | 106 ------- .../resources/examples/configvalidation.ini | 76 +++++ .../resources/examples/configvalidation.json | 108 +++++++ .../examples/configvalidation.properties | 96 ++++++ .../resources/examples/configvalidation.xml | 97 ++++++ .../resources/examples/configvalidation.yaml | 106 +++++++ 55 files changed, 2248 insertions(+), 2301 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/ConfigModel.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/ConfigModel.java b/validation/src/main/java/org/apache/tamaya/validation/ConfigModel.java deleted file mode 100644 index a9c58f0..0000000 --- a/validation/src/main/java/org/apache/tamaya/validation/ConfigModel.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.validation; - -import org.apache.tamaya.Configuration; - -import java.util.Collection; - -/** - * Base structure describing a validated item, by default a parameter or a section. - */ -public interface ConfigModel { - - /** - * Access the owner. - * @return the owner of this model, never null. - */ - String getOwner(); - - /** - * Get the type of item that is modelled. - * @return the modelled type, never null. - */ - ModelTarget getType(); - - /** - * Get the item's name, it should minimally describe the validation. Examples are: - * <pre> - * Sections: a.b.c - * Params: a.b.c.paramName - * Filter: a.b.c.FilterImplClass - * Dependency: mydepClassname - * CombinationPolicy: a.b.c.MyCombinationPolicyClass - * </pre> - * @return the item's name. - */ - String getName(); - - /** - * Check if this validation is a required one. - * @return true, if this validation is required. - */ - boolean isRequired(); - - /** - * Get an description of the item, using the default locale. The description is basically optional - * though it is higly recommended to provide a description, so the validation issues is well - * resolvable. - * - * @return the description required, or null. - */ - String getDescription(); - - /** - * Validates the item and all its children against the given configuration. - * - * @param config the configuration to be validated against, not null. - * @return the validation result, or null, if not applicable. - */ - Collection<Validation> validate(Configuration config); - -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/ConfigModelManager.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/ConfigModelManager.java b/validation/src/main/java/org/apache/tamaya/validation/ConfigModelManager.java deleted file mode 100644 index 0f3cce5..0000000 --- a/validation/src/main/java/org/apache/tamaya/validation/ConfigModelManager.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.validation; - -import org.apache.tamaya.Configuration; -import org.apache.tamaya.ConfigurationProvider; -import org.apache.tamaya.validation.spi.ConfigDocumentationMBean; -import org.apache.tamaya.validation.spi.ModelProviderSpi; -import org.apache.tamaya.spi.ServiceContextManager; - -import javax.management.InstanceNotFoundException; -import javax.management.MBeanServer; -import javax.management.ObjectName; -import java.lang.management.ManagementFactory; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Validator accessor to validate the current configuration. - */ -public final class ConfigModelManager { - - /** The logger used. */ - private static final Logger LOG = Logger.getLogger(ConfigModelManager.class.getName()); - - /** - * Singleton constructor. - */ - private ConfigModelManager() { - } - - /** - * Access the usage statistics for the recorded uses of configuration. - * @return usage statistics - */ - public static String getConfigInfoText(){ - StringBuilder b = new StringBuilder(); - List<ConfigModel> models = new ArrayList<>(getModels()); - Collections.sort(models, new Comparator<ConfigModel>() { - @Override - public int compare(ConfigModel k1, ConfigModel k2) { - return k2.getName().compareTo(k2.getName()); - } - }); - b.append("TYPE OWNER NAME MANDATORY DESCRIPTION\n"); - b.append("-----------------------------------------------------------------------------------------------------\n"); - for(ConfigModel model:models){ - switch(model.getType()){ - case Parameter: - b.append("PARAM "); - break; - case Section: - b.append("SECTION "); - break; - case Group: - b.append("GROUP "); - break; - default: - break; - } - b.append(formatWithFixedLength(model.getOwner(), 10)).append(' '); - b.append(formatWithFixedLength(model.getName(), 50)); - if(model.isRequired()){ - b.append(formatWithFixedLength("yes", 12)); - }else{ - b.append(formatWithFixedLength("no", 12)); - } - if(model.getDescription()!=null){ - b.append(model.getDescription().replace("\n", "\\\n").replace("\"", "'")).append("\""); - } - b.append("\n"); - } - return b.toString(); - } - - private static String formatWithFixedLength(String name, int targetLength) { - targetLength = targetLength-1; - StringBuilder b = new StringBuilder(); - if(name.length() > targetLength){ - name = name.substring(0, targetLength); - } - b.append(name); - for(int i=0;i<(targetLength-name.length());i++){ - b.append(' '); - } - b.append(' '); - return b.toString(); - } - - /** - * Get the validations defined. - * - * @return the sections defined, never null. - */ - public static Collection<ConfigModel> getModels() { - List<ConfigModel> result = new ArrayList<>(); - for (ModelProviderSpi model : ServiceContextManager.getServiceContext().getServices(ModelProviderSpi.class)) { - result.addAll(model.getConfigModels()); - } - return result; - } - - - /** - * Find the validations by matching the validation's name against the given model type. - * - * @param name the name to use, not null. - * @param modelType classname of the target model type. - * @param <T> type of the model to filter for. - * @return the sections defined, never null. - */ - public static <T extends ConfigModel> T getModel(String name, Class<T> modelType) { - for (ModelProviderSpi model : ServiceContextManager.getServiceContext().getServices(ModelProviderSpi.class)) { - for(ConfigModel configModel : model.getConfigModels()) { - if(configModel.getName().equals(name) && configModel.getClass().equals(modelType)) { - return modelType.cast(configModel); - } - } - } - return null; - } - - /** - * Find the validations by checking the validation's name using the given regular expression. - * @param namePattern the regular expression to use, not null. - * @param targets the target types only to be returned (optional). - * @return the sections defined, never null. - */ - public static Collection<ConfigModel> findModels(String namePattern, ModelTarget... targets) { - List<ConfigModel> result = new ArrayList<>(); - for (ModelProviderSpi model : ServiceContextManager.getServiceContext().getServices(ModelProviderSpi.class)) { - for(ConfigModel configModel : model.getConfigModels()) { - if(configModel.getName().matches(namePattern)) { - if(targets.length>0){ - for(ModelTarget tgt:targets){ - if(configModel.getType().equals(tgt)){ - result.add(configModel); - break; - } - } - }else { - result.add(configModel); - } - } - } - } - return result; - } - - /** - * Validates the current configuration. - * - * @return the validation results, never null. - */ - public static Collection<Validation> validate() { - return validate(false); - } - - /** - * Validates the current configuration. - * @param showUndefined show any unknown parameters. - * @return the validation results, never null. - */ - public static Collection<Validation> validate(boolean showUndefined) { - return validate(ConfigurationProvider.getConfiguration(), showUndefined); - } - - /** - * Validates the given configuration. - * - * @param config the configuration to be validated against, not null. - * @return the validation results, never null. - */ - public static Collection<Validation> validate(Configuration config) { - return validate(config, false); - } - - /** - * Validates the given configuration. - * - * @param config the configuration to be validated against, not null. - * @param showUndefined allows filtering for undefined configuration elements. - * @return the validation results, never null. - */ - public static Collection<Validation> validate(Configuration config, boolean showUndefined) { - List<Validation> result = new ArrayList<>(); - for (ConfigModel defConf : getModels()) { - result.addAll(defConf.validate(config)); - } - if(showUndefined){ - Map<String,String> map = new HashMap<>(config.getProperties()); - Set<String> areas = extractTransitiveAreas(map.keySet()); - for (ConfigModel defConf : getModels()) { - if(ModelTarget.Section.equals(defConf.getType())){ - for (Iterator<String> iter = areas.iterator();iter.hasNext();){ - String area = iter.next(); - if(area.matches(defConf.getName())){ - iter.remove(); - } - } - } - if(ModelTarget.Parameter.equals(defConf.getType())){ - map.remove(defConf.getName()); - } - } - outer:for(Map.Entry<String,String> entry:map.entrySet()){ - for (ConfigModel defConf : getModels()) { - if(ModelTarget.Section.equals(defConf.getType())){ - if(defConf.getName().endsWith(".*") && entry.getKey().matches(defConf.getName())){ - // Ignore parameters that are part of transitive section. - continue outer; - } - } - } - result.add(Validation.ofUndefined("<auto>", entry.getKey(), ModelTarget.Parameter)); - } - for(String area:areas){ - result.add(Validation.ofUndefined("<auto>", area, ModelTarget.Section)); - } - } - return result; - } - - private static java.util.Set<java.lang.String> extractTransitiveAreas(Set<String> keys) { - Set<String> transitiveClosure = new HashSet<>(); - for(String key:keys){ - int index = key.lastIndexOf('.'); - while(index>0){ - String areaKey = key.substring(0,index); - transitiveClosure.add(areaKey); - index = areaKey.lastIndexOf('.'); - } - } - return transitiveClosure; - } - - - /** - * Registers the {@link ConfigDocumentationMBean} mbean for accessing config documentation into the local platform - * mbean server. - */ - public static void registerMBean() { - registerMBean(null); - } - - /** - * Registers the {@link ConfigDocumentationMBean} mbean for accessing config documentation into the local platform - * mbean server. - * - * @param context allows to specify an additional MBean context, maybe {@code null}. - */ - public static void registerMBean(String context) { - try{ - ConfigDocumentationMBean configMbean = ServiceContextManager.getServiceContext() - .getService(ConfigDocumentationMBean.class); - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - ObjectName on = context==null?new ObjectName("org.apache.tamaya.model:type=ConfigDocumentationMBean"): - new ObjectName("org.apache.tamaya.model:type=ConfigDocumentationMBean,context="+context); - try{ - mbs.getMBeanInfo(on); - LOG.warning("Cannot register mbean " + on + ": already existing."); - } catch(InstanceNotFoundException e) { - LOG.info("Registering mbean " + on + "..."); - mbs.registerMBean(configMbean, on); - } - } catch(Exception e){ - LOG.log(Level.WARNING, - "Failed to register ConfigDocumentationMBean.", e); - } - } - -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/ModelTarget.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/ModelTarget.java b/validation/src/main/java/org/apache/tamaya/validation/ModelTarget.java deleted file mode 100644 index e087c66..0000000 --- a/validation/src/main/java/org/apache/tamaya/validation/ModelTarget.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.validation; - -/** - * This enumeration defines the types of supported validations. - */ -public enum ModelTarget { - /** - * A configuration section. - */ - Section, - /** - * A configuration paramter. - */ - Parameter, - /** - * ConfigModel that is a container of other validations. - */ - Group, -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/Validation.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/Validation.java b/validation/src/main/java/org/apache/tamaya/validation/Validation.java index 81a0118..d9c4ba1 100644 --- a/validation/src/main/java/org/apache/tamaya/validation/Validation.java +++ b/validation/src/main/java/org/apache/tamaya/validation/Validation.java @@ -18,9 +18,9 @@ */ package org.apache.tamaya.validation; -import org.apache.tamaya.Configuration; import org.apache.tamaya.validation.spi.AbstractConfigModel; +import javax.config.Config; import java.util.Collection; import java.util.Collections; import java.util.Objects; @@ -32,11 +32,11 @@ public final class Validation { /** * the config section. */ - private final ConfigModel configModel; + private final ValidationModel configModel; /** * The configModel result. */ - private final ValidationResult result; + private final ValidationType result; /** * The configModel message. */ @@ -48,8 +48,8 @@ public final class Validation { * @param configModel the configModel item, not null. * @return a new validation result containing valid parts of the given model. */ - public static Validation ofValid(ConfigModel configModel) { - return new Validation(configModel, ValidationResult.VALID, null); + public static Validation checkValid(ValidationModel configModel) { + return new Validation(configModel, ValidationType.VALID, null); } /** @@ -58,8 +58,8 @@ public final class Validation { * @param configModel the configModel item, not null. * @return a new validation result containing missing parts of the given model. */ - public static Validation ofMissing(ConfigModel configModel) { - return new Validation(configModel, ValidationResult.MISSING, null); + public static Validation checkMissing(ValidationModel configModel) { + return new Validation(configModel, ValidationType.MISSING, null); } /** @@ -69,8 +69,8 @@ public final class Validation { * @param message Additional message to be shown (optional). * @return a new validation result containing missing parts of the given model with a message. */ - public static Validation ofMissing(ConfigModel configModel, String message) { - return new Validation(configModel, ValidationResult.MISSING, message); + public static Validation checkMissing(ValidationModel configModel, String message) { + return new Validation(configModel, ValidationType.MISSING, message); } /** @@ -80,8 +80,8 @@ public final class Validation { * @param error error message to add. * @return a new validation result containing erroneous parts of the given model with the given error message. */ - public static Validation ofError(ConfigModel configModel, String error) { - return new Validation(configModel, ValidationResult.ERROR, error); + public static Validation checkError(ValidationModel configModel, String error) { + return new Validation(configModel, ValidationType.ERROR, error); } /** @@ -91,8 +91,8 @@ public final class Validation { * @param warning warning message to add. * @return a new validation result containing warning parts of the given model with the given warning message. */ - public static Validation ofWarning(ConfigModel configModel, String warning) { - return new Validation(configModel, ValidationResult.WARNING, warning); + public static Validation checkWarning(ValidationModel configModel, String warning) { + return new Validation(configModel, ValidationType.WARNING, warning); } /** @@ -102,8 +102,8 @@ public final class Validation { * @param alternativeUsage allows setting a message to indicate non-deprecated replacement, maybe null. * @return a new validation result containing deprecated parts of the given model with an optional message. */ - public static Validation ofDeprecated(ConfigModel configModel, String alternativeUsage) { - return new Validation(configModel, ValidationResult.DEPRECATED, alternativeUsage != null ? "Use instead: " + alternativeUsage : null); + public static Validation checkDeprecation(ValidationModel configModel, String alternativeUsage) { + return new Validation(configModel, ValidationType.DEPRECATED, alternativeUsage != null ? "Use instead: " + alternativeUsage : null); } /** @@ -112,8 +112,8 @@ public final class Validation { * @param configModel the configModel item, not null. * @return a new validation result containing deprecated parts of the given model. */ - public static Validation ofDeprecated(ConfigModel configModel) { - return new Validation(configModel, ValidationResult.DEPRECATED, null); + public static Validation checkDeprecation(ValidationModel configModel) { + return new Validation(configModel, ValidationType.DEPRECATED, null); } /** @@ -124,19 +124,19 @@ public final class Validation { * @param type model type * @return a corresponding configModel item */ - public static Validation ofUndefined(final String owner, final String key, final ModelTarget type) { + public static Validation checkUndefined(final String owner, final String key, final ValidationTarget type) { return new Validation(new AbstractConfigModel(owner, key, false, "Undefined key: " + key) { @Override - public ModelTarget getType() { + public ValidationTarget getType() { return type; } @Override - public Collection<Validation> validate(Configuration config) { + public Collection<Validation> validate(Config config) { return Collections.emptyList(); } - }, ValidationResult.UNDEFINED, null); + }, ValidationType.UNDEFINED, null); } @@ -148,7 +148,7 @@ public final class Validation { * @param message the detail message. * @return new validation result. */ - public static Validation of(ConfigModel configModel, ValidationResult result, String message) { + public static Validation of(ValidationModel configModel, ValidationType result, String message) { return new Validation(configModel, result, message); } @@ -160,7 +160,7 @@ public final class Validation { * @param result the configModel result, not null. * @param message the detail message. */ - private Validation(ConfigModel configModel, ValidationResult result, String message) { + private Validation(ValidationModel configModel, ValidationType result, String message) { this.message = message; this.configModel = Objects.requireNonNull(configModel); this.result = Objects.requireNonNull(result); @@ -171,7 +171,7 @@ public final class Validation { * * @return the section, never null. */ - public ConfigModel getConfigModel() { + public ValidationModel getConfigModel() { return configModel; } @@ -180,7 +180,7 @@ public final class Validation { * * @return the result, never null. */ - public ValidationResult getResult() { + public ValidationType getResult() { return result; } http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/ValidationManager.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/ValidationManager.java b/validation/src/main/java/org/apache/tamaya/validation/ValidationManager.java new file mode 100644 index 0000000..565dd32 --- /dev/null +++ b/validation/src/main/java/org/apache/tamaya/validation/ValidationManager.java @@ -0,0 +1,294 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tamaya.validation; + +import org.apache.tamaya.validation.spi.ConfigValidationMBean; +import org.apache.tamaya.validation.spi.ValidationModelProviderSpi; +import org.apache.tamaya.spi.ServiceContextManager; + +import javax.config.Config; +import javax.management.InstanceNotFoundException; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import java.lang.management.ManagementFactory; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Validator accessor to validate the current configuration. + */ +public final class ValidationManager { + + /** The logger used. */ + private static final Logger LOG = Logger.getLogger(ValidationManager.class.getName()); + + private static final ValidationManager INSTANCE = new ValidationManager(); + + private List<ValidationModel> models = new ArrayList<>(); + + /** + * Get the singleton instance. + * @return the instance, never null. + */ + public static ValidationManager getInstance(){ + return INSTANCE; + } + + /** + * Singleton constructor. + */ + private ValidationManager() { + for (ValidationModelProviderSpi model : ServiceContextManager.getServiceContext().getServices(ValidationModelProviderSpi.class)) { + models.addAll(model.getConfigModels()); + } + Collections.sort(models, new Comparator<ValidationModel>() { + @Override + public int compare(ValidationModel k1, ValidationModel k2) { + return k2.getName().compareTo(k2.getName()); + } + }); + } + + /** + * Access the usage statistics for the recorded uses of configuration. + * @return usage statistics + */ + public String getConfigInfoText(){ + StringBuilder b = new StringBuilder(); + b.append("TYPE OWNER NAME MANDATORY DESCRIPTION\n"); + b.append("-----------------------------------------------------------------------------------------------------\n"); + for(ValidationModel model:models){ + switch(model.getType()){ + case Parameter: + b.append("PARAM "); + break; + case Section: + b.append("SECTION "); + break; + case Group: + b.append("GROUP "); + break; + default: + break; + } + b.append(formatWithFixedLength(model.getOwner(), 10)).append(' '); + b.append(formatWithFixedLength(model.getName(), 50)); + if(model.isRequired()){ + b.append(formatWithFixedLength("yes", 12)); + }else{ + b.append(formatWithFixedLength("no", 12)); + } + if(model.getDescription()!=null){ + b.append(model.getDescription().replace("\n", "\\\n").replace("\"", "'")).append("\""); + } + b.append("\n"); + } + return b.toString(); + } + + private String formatWithFixedLength(String name, int targetLength) { + targetLength = targetLength-1; + StringBuilder b = new StringBuilder(); + if(name.length() > targetLength){ + name = name.substring(0, targetLength); + } + b.append(name); + for(int i=0;i<(targetLength-name.length());i++){ + b.append(' '); + } + b.append(' '); + return b.toString(); + } + + /** + * Get the validations defined. + * + * @return the sections defined, never null. + */ + public Collection<ValidationModel> getModels() { + return Collections.unmodifiableCollection(models); + } + + + /** + * Find the validations by matching the validation's name against the given model type. + * + * @param name the name to use, not null. + * @param modelType classname of the target model type. + * @param <T> type of the model to filter for. + * @return the sections defined, never null. + */ + public <T extends ValidationModel> T getModel(String name, Class<T> modelType) { + for (ValidationModelProviderSpi model : ServiceContextManager.getServiceContext().getServices(ValidationModelProviderSpi.class)) { + for(ValidationModel configModel : model.getConfigModels()) { + if(configModel.getName().equals(name) && configModel.getClass().equals(modelType)) { + return modelType.cast(configModel); + } + } + } + return null; + } + + /** + * Find the validations by checking the validation's name using the given regular expression. + * @param namePattern the regular expression to use, not null. + * @param targets the target types only to be returned (optional). + * @return the sections defined, never null. + */ + public Collection<ValidationModel> findModels(String namePattern, ValidationTarget... targets) { + List<ValidationModel> result = new ArrayList<>(); + for (ValidationModelProviderSpi model : ServiceContextManager.getServiceContext().getServices(ValidationModelProviderSpi.class)) { + for(ValidationModel configModel : model.getConfigModels()) { + if(configModel.getName().matches(namePattern)) { + if(targets.length>0){ + for(ValidationTarget tgt:targets){ + if(configModel.getType().equals(tgt)){ + result.add(configModel); + break; + } + } + }else { + result.add(configModel); + } + } + } + } + return result; + } + + /** + * Validates the given configuration. + * + * @param config the configuration to be validated against, not null. + * @return the validation results, never null. + */ + public Collection<Validation> validate(Config config) { + return validate(config, false); + } + + /** + * Validates the given configuration. + * + * @param config the configuration to be validated against, not null. + * @param showUndefined allows filtering for undefined configuration elements. + * @return the validation results, never null. + */ + public Collection<Validation> validate(Config config, boolean showUndefined) { + List<Validation> result = new ArrayList<>(); + for (ValidationModel defConf : getModels()) { + result.addAll(defConf.validate(config)); + } + if(showUndefined){ + Iterable<String> map = config.getPropertyNames(); + Set<String> keys = new HashSet<>(); + map.forEach(keys::add); + Set<String> areas = extractTransitiveAreas(keys); + for (ValidationModel defConf : getModels()) { + if(ValidationTarget.Section.equals(defConf.getType())){ + for (Iterator<String> iter = areas.iterator();iter.hasNext();){ + String area = iter.next(); + if(area.matches(defConf.getName())){ + iter.remove(); + } + } + } + if(ValidationTarget.Parameter.equals(defConf.getType())){ + keys.remove(defConf.getName()); + } + } + outer:for(String key:keys){ + for (ValidationModel defConf : getModels()) { + if(ValidationTarget.Section.equals(defConf.getType())){ + if(defConf.getName().endsWith(".*") && key.matches(defConf.getName())){ + // Ignore parameters that are part of transitive section. + continue outer; + } + } + } + result.add(Validation.checkUndefined("<auto>", key, ValidationTarget.Parameter)); + } + for(String area:areas){ + result.add(Validation.checkUndefined("<auto>", area, ValidationTarget.Section)); + } + } + return result; + } + + private java.util.Set<java.lang.String> extractTransitiveAreas(Set<String> keys) { + Set<String> transitiveClosure = new HashSet<>(); + for(String key:keys){ + int index = key.lastIndexOf('.'); + while(index>0){ + String areaKey = key.substring(0,index); + transitiveClosure.add(areaKey); + index = areaKey.lastIndexOf('.'); + } + } + return transitiveClosure; + } + + + /** + * Registers the {@link ConfigValidationMBean} mbean for accessing config documentation into the local platform + * mbean server. + */ + public void registerMBean() { + registerMBean(null); + } + + /** + * Registers the {@link ConfigValidationMBean} mbean for accessing config documentation into the local platform + * mbean server. + * + * @param context allows to specify an additional MBean context, maybe {@code null}. + */ + public void registerMBean(String context) { + try{ + ConfigValidationMBean configMbean = ServiceContextManager.getServiceContext() + .getService(ConfigValidationMBean.class); + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + ObjectName on = context==null?new ObjectName("org.apache.tamaya.model:type=ConfigDocumentationMBean"): + new ObjectName("org.apache.tamaya.model:type=ConfigDocumentationMBean,context="+context); + try{ + mbs.getMBeanInfo(on); + LOG.warning("Cannot register mbean " + on + ": already existing."); + } catch(InstanceNotFoundException e) { + LOG.info("Registering mbean " + on + "..."); + mbs.registerMBean(configMbean, on); + } + } catch(Exception e){ + LOG.log(Level.WARNING, + "Failed to register ConfigDocumentationMBean.", e); + } + } + + @Override + public String toString(){ + return "ValidationManager\n "+getConfigInfoText(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/ValidationModel.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/ValidationModel.java b/validation/src/main/java/org/apache/tamaya/validation/ValidationModel.java new file mode 100644 index 0000000..01c8cb6 --- /dev/null +++ b/validation/src/main/java/org/apache/tamaya/validation/ValidationModel.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tamaya.validation; + + +import javax.config.Config; +import java.util.Collection; + +/** + * Base structure describing a validated item, by default a parameter or a section. + */ +public interface ValidationModel { + + /** + * Access the owner. + * @return the owner of this model, never null. + */ + String getOwner(); + + /** + * Get the type of item that is modelled. + * @return the modelled type, never null. + */ + ValidationTarget getType(); + + /** + * Get the item's name, it should minimally describe the validation. Examples are: + * <pre> + * Sections: a.b.c + * Params: a.b.c.paramName + * Filter: a.b.c.FilterImplClass + * Dependency: mydepClassname + * CombinationPolicy: a.b.c.MyCombinationPolicyClass + * </pre> + * @return the item's name. + */ + String getName(); + + /** + * Check if this validation is a required one. + * @return true, if this validation is required. + */ + boolean isRequired(); + + /** + * Get an description of the item, using the default locale. The description is basically optional + * though it is higly recommended to provide a description, so the validation issues is well + * resolvable. + * + * @return the description required, or null. + */ + String getDescription(); + + /** + * Validates the item and all its children against the given configuration. + * + * @param config the configuration to be validated against, not null. + * @return the validation result, or null, if not applicable. + */ + Collection<Validation> validate(Config config); + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/ValidationResult.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/ValidationResult.java b/validation/src/main/java/org/apache/tamaya/validation/ValidationResult.java deleted file mode 100644 index f368985..0000000 --- a/validation/src/main/java/org/apache/tamaya/validation/ValidationResult.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.validation; - -/** - * Enum type describing the different validation results supported. - */ -public enum ValidationResult { - /** - * The validated item is valid - */ - VALID, - /** - * The validated item is deprecated. - */ - DEPRECATED, - /** - * The validated item is correct, but the value is worth a warning. - */ - WARNING, - /** - * The given section or parameter is not a defined/validated item. It may be still valid, but typically, - * when validation is fully implemented, such a parameter or section should be removed. - */ - UNDEFINED, - /** - * A required parameter or section is missing. - */ - MISSING, - /** - * The validated item has an invalid value. - */ - ERROR; - - /** - * Method to quickly evaluate if the current state is an error state. - * - * @return true, if the state is not ERROR or MISSING. - */ - boolean isError() { - return this.ordinal() == MISSING.ordinal() || this.ordinal() == ERROR.ordinal(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/ValidationTarget.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/ValidationTarget.java b/validation/src/main/java/org/apache/tamaya/validation/ValidationTarget.java new file mode 100644 index 0000000..5a501e5 --- /dev/null +++ b/validation/src/main/java/org/apache/tamaya/validation/ValidationTarget.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tamaya.validation; + +/** + * This enumeration defines the types of supported validations. + */ +public enum ValidationTarget { + /** + * A configuration section. + */ + Section, + /** + * A configuration paramter. + */ + Parameter, + /** + * ConfigModel that is a container of other validations. + */ + Group, +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/ValidationType.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/ValidationType.java b/validation/src/main/java/org/apache/tamaya/validation/ValidationType.java new file mode 100644 index 0000000..f7a2158 --- /dev/null +++ b/validation/src/main/java/org/apache/tamaya/validation/ValidationType.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tamaya.validation; + +/** + * Enum type describing the different validation results supported. + */ +public enum ValidationType { + /** + * The validated item is valid + */ + VALID, + /** + * The validated item is deprecated. + */ + DEPRECATED, + /** + * The validated item is correct, but the value is worth a warning. + */ + WARNING, + /** + * The given section or parameter is not a defined/validated item. It may be still valid, but typically, + * when validation is fully implemented, such a parameter or section should be removed. + */ + UNDEFINED, + /** + * A required parameter or section is missing. + */ + MISSING, + /** + * The validated item has an invalid value. + */ + ERROR; + + /** + * Method to quickly evaluate if the current state is an error state. + * + * @return true, if the state is not ERROR or MISSING. + */ + boolean isError() { + return this.ordinal() == MISSING.ordinal() || this.ordinal() == ERROR.ordinal(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/internal/ConfigDocumentationBean.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/internal/ConfigDocumentationBean.java b/validation/src/main/java/org/apache/tamaya/validation/internal/ConfigDocumentationBean.java deleted file mode 100644 index 59c5c22..0000000 --- a/validation/src/main/java/org/apache/tamaya/validation/internal/ConfigDocumentationBean.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.validation.internal; - -import org.apache.tamaya.Configuration; -import org.apache.tamaya.ConfigurationProvider; -import org.apache.tamaya.validation.ConfigModel; -import org.apache.tamaya.validation.ConfigModelManager; -import org.apache.tamaya.validation.ModelTarget; -import org.apache.tamaya.validation.Validation; -import org.apache.tamaya.validation.spi.ConfigDocumentationMBean; - -import javax.json.Json; -import javax.json.JsonArray; -import javax.json.JsonArrayBuilder; -import javax.json.JsonObject; -import javax.json.JsonObjectBuilder; -import javax.json.JsonWriter; -import javax.json.JsonWriterFactory; -import javax.json.stream.JsonGenerator; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * MBean implementation of {@link ConfigDocumentationMBean}. - */ -public class ConfigDocumentationBean implements ConfigDocumentationMBean{ - - private final JsonWriterFactory writerFactory; - - private static final Comparator<Validation> COMPARATOR = new Comparator<Validation>() { - @Override - public int compare(Validation v1, Validation v2) { - int compare = VAL_COMPARATOR.compare(v1.getConfigModel(), v2.getConfigModel()); - if(compare==0){ - compare = v1.getResult().compareTo(v2.getResult()); - } - if(compare==0){ - return v1.getMessage().compareTo(v2.getMessage()); - } - return compare; - } - }; - private static final Comparator<ConfigModel> VAL_COMPARATOR = new Comparator<ConfigModel>() { - @Override - public int compare(ConfigModel v1, ConfigModel v2) { - int compare = v1.getType().compareTo(v2.getType()); - if(compare==0){ - compare = v1.getName().compareTo(v2.getName()); - } - return compare; - } - }; - - private Configuration config; - - /** - * Default constructor, using the current configuration being available. - */ - public ConfigDocumentationBean(){ - this(null); - } - - - /** - * Creates an mbean bound to the given configuration. This is useful, when multiple mbeans for each - * context should be used, e.g. one mbean per ear, app deployment. - * @param config the configuration to be used. - */ - public ConfigDocumentationBean(Configuration config){ - this.config = config; - Map<String, Object> writerProperties = new HashMap<>(1); - writerProperties.put(JsonGenerator.PRETTY_PRINTING, true); - writerFactory = Json.createWriterFactory(writerProperties); - } - - /** - * Access the configuration. - * @return either the configuration bound to this bean, or the current configuration. - */ - private Configuration getConfig(){ - return config!=null?config: ConfigurationProvider.getConfiguration(); - } - - @Override - public String validate(boolean showUndefined) { - List<Validation> validations = new ArrayList<>(ConfigModelManager.validate(getConfig(), showUndefined)); - Collections.sort(validations, COMPARATOR); - JsonArrayBuilder builder = Json.createArrayBuilder(); - for(Validation val:validations){ - builder.add(toJsonObject(val)); - } - return formatJson(builder.build()); - } - - - - @Override - public String getConfigurationModel() { - List<ConfigModel> configModels = new ArrayList<>(ConfigModelManager.getModels()); - Collections.sort(configModels, VAL_COMPARATOR); - JsonArrayBuilder result = Json.createArrayBuilder(); - for(ConfigModel val: configModels){ - result.add(toJsonObject(val)); - } - return formatJson(result.build()); - } - - @Override - public String getConfigurationModel(ModelTarget type) { - return findValidationModels(".*", type); - } - - @Override - public String findConfigurationModels(String namePattern) { - List<ConfigModel> configModels = new ArrayList<>(ConfigModelManager.findModels(namePattern)); - Collections.sort(configModels, VAL_COMPARATOR); - JsonArrayBuilder result = Json.createArrayBuilder(); - for(ConfigModel val: configModels){ - result.add(toJsonObject(val)); - } - return formatJson(result.build()); - } - - @Override - public String findValidationModels(String namePattern, ModelTarget... type) { - List<ConfigModel> configModels = new ArrayList<>(ConfigModelManager.findModels(namePattern, type)); - Collections.sort(configModels, VAL_COMPARATOR); - JsonArrayBuilder result = Json.createArrayBuilder(); - for(ConfigModel val: configModels){ - result.add(toJsonObject(val)); - } - return formatJson(result.build()); - } - - @Override - public String toString(){ - return "ConfigDocumentationBean, config: " + (this.config!=null?this.config.toString():"<current>"); - } - - - private JsonObject toJsonObject(ConfigModel val) { - JsonObjectBuilder valJson = Json.createObjectBuilder().add("target", val.getType().toString()) - .add("name", val.getName()); - if(val.getDescription()!=null) { - valJson.add("description", val.getDescription()); - } - if(val.isRequired()){ - valJson.add("required",true); - } - return valJson.build(); - } - - private JsonObject toJsonObject(Validation val) { - JsonObjectBuilder valJson = Json.createObjectBuilder().add("target", val.getConfigModel().getType().toString()) - .add("name", val.getConfigModel().getName()); - if(val.getConfigModel().isRequired()){ - valJson.add("required",true); - } - if(val.getConfigModel().getDescription() != null){ - valJson.add("description", val.getConfigModel().getDescription()); - } - valJson.add("result", val.getResult().toString()); - if( val.getMessage() != null) { - valJson.add("message", val.getMessage()); - } - return valJson.build(); - } - - private String formatJson(JsonArray data) { - StringWriter writer = new StringWriter(); - JsonWriter gen = writerFactory.createWriter(writer); - gen.writeArray(data); - return writer.toString(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/internal/ConfigValidationBean.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/internal/ConfigValidationBean.java b/validation/src/main/java/org/apache/tamaya/validation/internal/ConfigValidationBean.java new file mode 100644 index 0000000..fc75a26 --- /dev/null +++ b/validation/src/main/java/org/apache/tamaya/validation/internal/ConfigValidationBean.java @@ -0,0 +1,197 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tamaya.validation.internal; + +import org.apache.tamaya.validation.ValidationModel; +import org.apache.tamaya.validation.ValidationManager; +import org.apache.tamaya.validation.ValidationTarget; +import org.apache.tamaya.validation.Validation; +import org.apache.tamaya.validation.spi.ConfigValidationMBean; + +import javax.config.Config; +import javax.config.ConfigProvider; +import javax.json.Json; +import javax.json.JsonArray; +import javax.json.JsonArrayBuilder; +import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; +import javax.json.JsonWriter; +import javax.json.JsonWriterFactory; +import javax.json.stream.JsonGenerator; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * MBean implementation of {@link ConfigValidationMBean}. + */ +public class ConfigValidationBean implements ConfigValidationMBean { + + private final JsonWriterFactory writerFactory; + + private static final Comparator<Validation> COMPARATOR = new Comparator<Validation>() { + @Override + public int compare(Validation v1, Validation v2) { + int compare = VAL_COMPARATOR.compare(v1.getConfigModel(), v2.getConfigModel()); + if(compare==0){ + compare = v1.getResult().compareTo(v2.getResult()); + } + if(compare==0){ + return v1.getMessage().compareTo(v2.getMessage()); + } + return compare; + } + }; + private static final Comparator<ValidationModel> VAL_COMPARATOR = new Comparator<ValidationModel>() { + @Override + public int compare(ValidationModel v1, ValidationModel v2) { + int compare = v1.getType().compareTo(v2.getType()); + if(compare==0){ + compare = v1.getName().compareTo(v2.getName()); + } + return compare; + } + }; + + private Config config; + + /** + * Default constructor, using the current configuration being available. + */ + public ConfigValidationBean(){ + this(null); + } + + + /** + * Creates an mbean bound to the given configuration. This is useful, when multiple mbeans for each + * context should be used, e.g. one mbean per ear, app deployment. + * @param config the configuration to be used. + */ + public ConfigValidationBean(Config config){ + this.config = config; + Map<String, Object> writerProperties = new HashMap<>(1); + writerProperties.put(JsonGenerator.PRETTY_PRINTING, true); + writerFactory = Json.createWriterFactory(writerProperties); + } + + /** + * Access the configuration. + * @return either the configuration bound to this bean, or the current configuration. + */ + private Config getConfig(){ + return config!=null?config: ConfigProvider.getConfig(); + } + + @Override + public String validate(boolean showUndefined) { + List<Validation> validations = new ArrayList<>(ValidationManager.getInstance().validate(getConfig(), showUndefined)); + Collections.sort(validations, COMPARATOR); + JsonArrayBuilder builder = Json.createArrayBuilder(); + for(Validation val:validations){ + builder.add(toJsonObject(val)); + } + return formatJson(builder.build()); + } + + + + @Override + public String getConfigurationModel() { + List<ValidationModel> configModels = new ArrayList<>(ValidationManager.getInstance().getModels()); + Collections.sort(configModels, VAL_COMPARATOR); + JsonArrayBuilder result = Json.createArrayBuilder(); + for(ValidationModel val: configModels){ + result.add(toJsonObject(val)); + } + return formatJson(result.build()); + } + + @Override + public String getConfigurationModel(ValidationTarget type) { + return findValidationModels(".*", type); + } + + @Override + public String findConfigurationModels(String namePattern) { + List<ValidationModel> configModels = new ArrayList<>(ValidationManager.getInstance().findModels(namePattern)); + Collections.sort(configModels, VAL_COMPARATOR); + JsonArrayBuilder result = Json.createArrayBuilder(); + for(ValidationModel val: configModels){ + result.add(toJsonObject(val)); + } + return formatJson(result.build()); + } + + @Override + public String findValidationModels(String namePattern, ValidationTarget... type) { + List<ValidationModel> configModels = new ArrayList<>(ValidationManager.getInstance().findModels(namePattern, type)); + Collections.sort(configModels, VAL_COMPARATOR); + JsonArrayBuilder result = Json.createArrayBuilder(); + for(ValidationModel val: configModels){ + result.add(toJsonObject(val)); + } + return formatJson(result.build()); + } + + @Override + public String toString(){ + return "ConfigDocumentationBean, config: " + (this.config!=null?this.config.toString():"<current>"); + } + + + private JsonObject toJsonObject(ValidationModel val) { + JsonObjectBuilder valJson = Json.createObjectBuilder().add("target", val.getType().toString()) + .add("name", val.getName()); + if(val.getDescription()!=null) { + valJson.add("description", val.getDescription()); + } + if(val.isRequired()){ + valJson.add("required",true); + } + return valJson.build(); + } + + private JsonObject toJsonObject(Validation val) { + JsonObjectBuilder valJson = Json.createObjectBuilder().add("target", val.getConfigModel().getType().toString()) + .add("name", val.getConfigModel().getName()); + if(val.getConfigModel().isRequired()){ + valJson.add("required",true); + } + if(val.getConfigModel().getDescription() != null){ + valJson.add("description", val.getConfigModel().getDescription()); + } + valJson.add("result", val.getResult().toString()); + if( val.getMessage() != null) { + valJson.add("message", val.getMessage()); + } + return valJson.build(); + } + + private String formatJson(JsonArray data) { + StringWriter writer = new StringWriter(); + JsonWriter gen = writerFactory.createWriter(writer); + gen.writeArray(data); + return writer.toString(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredInlineModelProviderSpi.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredInlineModelProviderSpi.java b/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredInlineModelProviderSpi.java index 6658bb5..097030b 100644 --- a/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredInlineModelProviderSpi.java +++ b/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredInlineModelProviderSpi.java @@ -18,52 +18,48 @@ */ package org.apache.tamaya.validation.internal; -import org.apache.tamaya.ConfigurationProvider; -import org.apache.tamaya.validation.ConfigModel; -import org.apache.tamaya.validation.spi.ConfigModelReader; -import org.apache.tamaya.validation.spi.ModelProviderSpi; +import org.apache.tamaya.functions.ConfigurationFunctions; +import org.apache.tamaya.validation.ValidationModel; +import org.apache.tamaya.validation.spi.ConfigValidationReader; +import org.apache.tamaya.validation.spi.ValidationModelProviderSpi; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import javax.config.Config; +import javax.config.ConfigProvider; +import java.util.*; import java.util.logging.Logger; /** - * ConfigModel provider that reads model metadata from the current {@link org.apache.tamaya.Configuration}. + * ConfigModel provider that reads model metadata from the current {@link Config}. */ -public class ConfiguredInlineModelProviderSpi implements ModelProviderSpi { +public class ConfiguredInlineModelProviderSpi implements ValidationModelProviderSpi { /** The logger. */ private static final Logger LOG = Logger.getLogger(ConfiguredInlineModelProviderSpi.class.getName()); /** parameter to disable this provider. By default the provider is active. */ - private static final String MODEL_EANABLED_PARAM = "org.apache.tamaya.model.integrated.enabled"; + private static final String MODEL_EANABLED_PARAM = "org.apache.tamaya.validation.integrated.enabled"; /** The configModels read. */ - private List<ConfigModel> configModels = new ArrayList<>(); + private List<ValidationModel> configModels = new ArrayList<>(); /** * Constructor, typically called by the {@link java.util.ServiceLoader}. */ public ConfiguredInlineModelProviderSpi() { - String enabledVal = ConfigurationProvider.getConfiguration().get(MODEL_EANABLED_PARAM); - boolean enabled = enabledVal == null || "true".equalsIgnoreCase(enabledVal); + Config config = ConfigProvider.getConfig(); + Optional<String> enabledVal = config.getOptionalValue(MODEL_EANABLED_PARAM, String.class); + boolean enabled = Boolean.parseBoolean(enabledVal.orElse("true")); if (enabled) { LOG.info("Reading model configuration from config..."); - Map<String,String> config = ConfigurationProvider.getConfiguration().getProperties(); - String owner = config.get("_model.provider"); - if(owner==null){ - owner = config.toString(); - } - configModels.addAll(ConfigModelReader.loadValidations(owner, config)); + Optional<String> owner = config.getOptionalValue("_model.provider", String.class); + configModels.addAll(ConfigValidationReader.loadValidations(owner.orElse(config.toString()), + ConfigurationFunctions.toMap(config))); } configModels = Collections.unmodifiableList(configModels); } - public Collection<ConfigModel> getConfigModels() { + public Collection<ValidationModel> getConfigModels() { return configModels; } } http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredPropertiesModelProviderSpi.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredPropertiesModelProviderSpi.java b/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredPropertiesModelProviderSpi.java index eeeeea4..0b7df20 100644 --- a/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredPropertiesModelProviderSpi.java +++ b/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredPropertiesModelProviderSpi.java @@ -18,12 +18,12 @@ */ package org.apache.tamaya.validation.internal; -import org.apache.tamaya.ConfigurationProvider; -import org.apache.tamaya.validation.ConfigModel; -import org.apache.tamaya.validation.spi.ConfigModelReader; -import org.apache.tamaya.validation.spi.ModelProviderSpi; -import org.apache.tamaya.spisupport.propertysource.MapPropertySource; +import org.apache.tamaya.base.configsource.MapConfigSource; +import org.apache.tamaya.validation.ValidationModel; +import org.apache.tamaya.validation.spi.ConfigValidationReader; +import org.apache.tamaya.validation.spi.ValidationModelProviderSpi; +import javax.config.ConfigProvider; import java.io.InputStream; import java.net.URL; import java.util.*; @@ -32,7 +32,7 @@ import java.util.logging.Logger; /** * ConfigModel provider that reads model metadata from property files from - * {@code classpath*:META-INF/configmodel.properties} in the following format: + * {@code classpath*:META-INF/configvalidation.properties} in the following format: * <pre> * ################################################################################### * # Example of a configuration metamodel expressed via properties. @@ -104,36 +104,36 @@ import java.util.logging.Logger; * {model}a.b.c.aValidatedSection.configModels=org.apache.tamaya.model.TestValidator * </pre> */ -public class ConfiguredPropertiesModelProviderSpi implements ModelProviderSpi { +public class ConfiguredPropertiesModelProviderSpi implements ValidationModelProviderSpi { /** The logger. */ private static final Logger LOG = Logger.getLogger(ConfiguredPropertiesModelProviderSpi.class.getName()); /** parameter to disable this provider. By default the provider is active. */ - private static final String MODEL_EANABLED_PARAM = "org.apache.tamaya.model.default.enabled"; + private static final String MODEL_EANABLED_PARAM = "org.apache.tamaya.validation.default.enabled"; /** The configModels read. */ - private List<ConfigModel> configModels = new ArrayList<>(); + private List<ValidationModel> configModels = new ArrayList<>(); public ConfiguredPropertiesModelProviderSpi() { - String enabledVal = ConfigurationProvider.getConfiguration().get(MODEL_EANABLED_PARAM); - boolean enabled = enabledVal == null || "true".equalsIgnoreCase(enabledVal); + Optional<String> enabledVal = ConfigProvider.getConfig().getOptionalValue(MODEL_EANABLED_PARAM, String.class); + boolean enabled = Boolean.parseBoolean(enabledVal.orElse("true")); if(!enabled){ - LOG.info("Reading model data from META-INF/configmodel.properties has been disabled."); + LOG.info("Reading model data from META-INF/configvalidation.properties has been disabled."); return; } try { - LOG.info("Reading model data from META-INF/configmodel.properties..."); - Enumeration<URL> configs = getClass().getClassLoader().getResources("META-INF/configmodel.properties"); + LOG.info("Reading model data from META-INF/configvalidation.properties..."); + Enumeration<URL> configs = getClass().getClassLoader().getResources("META-INF/configvalidation.properties"); while (configs.hasMoreElements()) { URL config = configs.nextElement(); try (InputStream is = config.openStream()) { Properties props = new Properties(); props.load(is); - Map<String,String> data = MapPropertySource.getMap(props); - String owner = data.get("_model.owner"); + Map<String,String> data = MapConfigSource.getMap(props); + String owner = data.get("_model.provider"); if(owner==null){ owner = config.toString(); } - configModels.addAll(ConfigModelReader.loadValidations(owner, + configModels.addAll(ConfigValidationReader.loadValidations(owner, data)); } catch (Exception e) { Logger.getLogger(getClass().getName()).log(Level.SEVERE, @@ -142,13 +142,13 @@ public class ConfiguredPropertiesModelProviderSpi implements ModelProviderSpi { } } catch (Exception e) { LOG.log(Level.SEVERE, - "Error loading config metadata from META-INF/configmodel.properties", e); + "Error loading config metadata from META-INF/configvalidation.properties", e); } configModels = Collections.unmodifiableList(configModels); } - public Collection<ConfigModel> getConfigModels() { + public Collection<ValidationModel> getConfigModels() { return configModels; } } http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredResourcesModelProviderSpi.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredResourcesModelProviderSpi.java b/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredResourcesModelProviderSpi.java index 1894570..9d871d0 100644 --- a/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredResourcesModelProviderSpi.java +++ b/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredResourcesModelProviderSpi.java @@ -25,14 +25,15 @@ import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; -import org.apache.tamaya.ConfigurationProvider; import org.apache.tamaya.format.ConfigurationData; import org.apache.tamaya.format.ConfigurationFormats; -import org.apache.tamaya.validation.ConfigModel; -import org.apache.tamaya.validation.spi.ConfigModelReader; -import org.apache.tamaya.validation.spi.ModelProviderSpi; +import org.apache.tamaya.validation.ValidationModel; +import org.apache.tamaya.validation.spi.ConfigValidationReader; +import org.apache.tamaya.validation.spi.ValidationModelProviderSpi; import org.apache.tamaya.resource.ConfigResources; +import javax.config.ConfigProvider; + /** * ConfigModel provider that reads model metadata from property files from * {@code classpath*:META-INF/configmodel.json} in the following format: @@ -43,7 +44,7 @@ import org.apache.tamaya.resource.ConfigResources; * key value pairs within a map are separated by a colon. * </pre> */ -public class ConfiguredResourcesModelProviderSpi implements ModelProviderSpi { +public class ConfiguredResourcesModelProviderSpi implements ValidationModelProviderSpi { /** * The logger. @@ -52,7 +53,7 @@ public class ConfiguredResourcesModelProviderSpi implements ModelProviderSpi { /** * The parameter that can be used to configure the location of the configuration model resources. */ - private static final String MODEL_RESOURCE_PARAM = "org.apache.tamaya.model.resources"; + private static final String MODEL_RESOURCE_PARAM = "org.apache.tamaya.validation.resources"; /** * The resource class to checked for testing the availability of the resources extension module. */ @@ -73,7 +74,7 @@ public class ConfiguredResourcesModelProviderSpi implements ModelProviderSpi { /** * The configModels read. */ - private List<ConfigModel> configModels = new ArrayList<>(); + private List<ValidationModel> configModels = new ArrayList<>(); /** * Initializes the flag showing if the formats module is present (required). @@ -106,7 +107,7 @@ public class ConfiguredResourcesModelProviderSpi implements ModelProviderSpi { if (!AVAILABLE) { LOG.info("tamaya-format extension is required to read model configuration, No extended model support AVAILABLE."); } else { - final String resources = ConfigurationProvider.getConfiguration().get(MODEL_RESOURCE_PARAM); + final String resources = ConfigProvider.getConfig().getValue(MODEL_RESOURCE_PARAM, String.class); if (resources == null || resources.trim().isEmpty()) { LOG.info("Mo model resources location configured in " + MODEL_RESOURCE_PARAM + "."); return; @@ -142,7 +143,7 @@ public class ConfiguredResourcesModelProviderSpi implements ModelProviderSpi { if(owner==null){ owner = config.toString(); } - configModels.addAll(ConfigModelReader.loadValidations(owner, props)); + configModels.addAll(ConfigValidationReader.loadValidations(owner, props)); } catch (final Exception e) { Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Error loading config model data from " + config, e); @@ -154,7 +155,7 @@ public class ConfiguredResourcesModelProviderSpi implements ModelProviderSpi { @Override - public Collection<ConfigModel> getConfigModels() { + public Collection<ValidationModel> getConfigModels() { return configModels; } } http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredTypeEventsModelPopulator.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredTypeEventsModelPopulator.java b/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredTypeEventsModelPopulator.java index a89986a..74afcc9 100644 --- a/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredTypeEventsModelPopulator.java +++ b/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredTypeEventsModelPopulator.java @@ -23,14 +23,15 @@ import org.apache.tamaya.events.ConfigEventListener; import org.apache.tamaya.inject.spi.ConfiguredField; import org.apache.tamaya.inject.spi.ConfiguredMethod; import org.apache.tamaya.inject.spi.ConfiguredType; -import org.apache.tamaya.validation.ConfigModelManager; -import org.apache.tamaya.validation.spi.ParameterModel; +import org.apache.tamaya.validation.ValidationManager; +import org.apache.tamaya.validation.ValidationModel; +import org.apache.tamaya.validation.spi.ValidateParameter; import java.util.Collection; import java.util.logging.Logger; /** - * Internal facade that registers all kind of injected fields as {@link org.apache.tamaya.validation.ConfigModel} entries, + * Internal facade that registers all kind of injected fields as {@link ValidationModel} entries, * so all configured injection points are visible as documented configuration hooks. */ public final class ConfiguredTypeEventsModelPopulator implements ConfigEventListener { @@ -43,7 +44,7 @@ public final class ConfiguredTypeEventsModelPopulator implements ConfigEventList /** System property to be set to deactivate auto documentation of configured classes published thorugh * ConfiguredType events. */ - private static final String ENABLE_EVENT_DOC = "org.apache.tamaya.model.autoModelEvents"; + private static final String ENABLE_EVENT_DOC = "org.apache.tamaya.validation.autoValidationEvents"; @Override public void onConfigEvent(ConfigEvent event) { @@ -56,10 +57,10 @@ public final class ConfiguredTypeEventsModelPopulator implements ConfigEventList for (ConfiguredField field : confType.getConfiguredFields()) { Collection<String> keys = field.getConfiguredKeys(); for (String key : keys) { - ParameterModel val = ConfigModelManager.getModel(key, ParameterModel.class); + ValidateParameter val = ValidationManager.getInstance().getModel(key, ValidateParameter.class); if (val == null) { ConfiguredTypeEventsModelProvider.addConfigModel( - new ParameterModel.Builder(confType.getName(), key) + new ValidateParameter.Builder(confType.getName(), key) .setType(field.getType().getName()) .setDescription("Injected field: " + field.getAnnotatedField().getDeclaringClass().getName() + '.' + field.toString() + @@ -71,10 +72,10 @@ public final class ConfiguredTypeEventsModelPopulator implements ConfigEventList for (ConfiguredMethod method : confType.getConfiguredMethods()) { Collection<String> keys = method.getConfiguredKeys(); for (String key : keys) { - ParameterModel val = ConfigModelManager.getModel(key, ParameterModel.class); + ValidateParameter val = ValidationManager.getInstance().getModel(key, ValidateParameter.class); if (val == null) { ConfiguredTypeEventsModelProvider.addConfigModel( - new ParameterModel.Builder(confType.getName(), key) + new ValidateParameter.Builder(confType.getName(), key) .setType(method.getParameterTypes()[0].getName()) .setDescription("Injected field: " + method.getAnnotatedMethod().getDeclaringClass().getName() + '.' + method.toString() + http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredTypeEventsModelProvider.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredTypeEventsModelProvider.java b/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredTypeEventsModelProvider.java index 82bd925..e11e97a 100644 --- a/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredTypeEventsModelProvider.java +++ b/validation/src/main/java/org/apache/tamaya/validation/internal/ConfiguredTypeEventsModelProvider.java @@ -18,8 +18,8 @@ */ package org.apache.tamaya.validation.internal; -import org.apache.tamaya.validation.ConfigModel; -import org.apache.tamaya.validation.spi.ModelProviderSpi; +import org.apache.tamaya.validation.ValidationModel; +import org.apache.tamaya.validation.spi.ValidationModelProviderSpi; import java.util.ArrayList; import java.util.Collection; @@ -30,22 +30,22 @@ import java.util.List; * Model provider that adds model definitions for the items published as * {@link org.apache.tamaya.inject.spi.ConfiguredType} events. */ -public class ConfiguredTypeEventsModelProvider implements ModelProviderSpi { +public class ConfiguredTypeEventsModelProvider implements ValidationModelProviderSpi { /** The collected models. */ - private static Collection<ConfigModel> configModels = new ArrayList<>(); + private static Collection<ValidationModel> configModels = new ArrayList<>(); /** * Adds a model, called from the registered listener class. * @param configModel adds the config model. */ - static void addConfigModel(ConfigModel configModel){ - List<ConfigModel> newList = new ArrayList<>(configModels); + static void addConfigModel(ValidationModel configModel){ + List<ValidationModel> newList = new ArrayList<>(configModels); newList.add(configModel); ConfiguredTypeEventsModelProvider.configModels = newList; } @Override - public Collection<ConfigModel> getConfigModels() { + public Collection<ValidationModel> getConfigModels() { return Collections.unmodifiableCollection(configModels); } } http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/54b627b9/validation/src/main/java/org/apache/tamaya/validation/spi/AbstractConfigModel.java ---------------------------------------------------------------------- diff --git a/validation/src/main/java/org/apache/tamaya/validation/spi/AbstractConfigModel.java b/validation/src/main/java/org/apache/tamaya/validation/spi/AbstractConfigModel.java index 31c2395..7f12753 100644 --- a/validation/src/main/java/org/apache/tamaya/validation/spi/AbstractConfigModel.java +++ b/validation/src/main/java/org/apache/tamaya/validation/spi/AbstractConfigModel.java @@ -18,14 +18,14 @@ */ package org.apache.tamaya.validation.spi; -import org.apache.tamaya.validation.ConfigModel; +import org.apache.tamaya.validation.ValidationModel; import java.util.Objects; /** * Default configuration Model for a configuration area. */ -public abstract class AbstractConfigModel implements ConfigModel, Comparable<ConfigModel> { +public abstract class AbstractConfigModel implements ValidationModel, Comparable<ValidationModel> { private final String owner; private final String name; private final String description; @@ -60,7 +60,7 @@ public abstract class AbstractConfigModel implements ConfigModel, Comparable<Con } @Override - public int compareTo(ConfigModel configModel) { + public int compareTo(ValidationModel configModel) { int compare = getType().compareTo(configModel.getType()); if (compare != 0) { return compare;
