blob: 718b9a3998383fe43a64b33d6d7413b0d1cbee6d [file] [log] [blame]
/**
* 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.camel.catalog;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.apache.camel.catalog.URISupport.isEmpty;
/**
* Details result of validating endpoint uri.
*/
public class EndpointValidationResult implements Serializable {
private final String uri;
private int errors;
// general
private String syntaxError;
private String unknownComponent;
private String incapable;
// options
private Set<String> unknown;
private Map<String, String[]> unknownSuggestions;
private Set<String> lenient;
private Set<String> notConsumerOnly;
private Set<String> notProducerOnly;
private Set<String> required;
private Set<String> deprecated;
private Map<String, String> invalidEnum;
private Map<String, String[]> invalidEnumChoices;
private Map<String, String[]> invalidEnumSuggestions;
private Map<String, String> invalidReference;
private Map<String, String> invalidBoolean;
private Map<String, String> invalidInteger;
private Map<String, String> invalidNumber;
private Map<String, String> defaultValues;
public EndpointValidationResult() {
this(null);
}
public EndpointValidationResult(String uri) {
this.uri = uri;
}
public String getUri() {
return uri;
}
public boolean hasErrors() {
return errors > 0;
}
public int getNumberOfErrors() {
return errors;
}
public boolean isSuccess() {
boolean ok = syntaxError == null && unknownComponent == null && incapable == null
&& unknown == null && required == null;
if (ok) {
ok = notConsumerOnly == null && notProducerOnly == null;
}
if (ok) {
ok = invalidEnum == null && invalidEnumChoices == null && invalidReference == null
&& invalidBoolean == null && invalidInteger == null && invalidNumber == null;
}
return ok;
}
public void addSyntaxError(String syntaxError) {
this.syntaxError = syntaxError;
errors++;
}
public void addIncapable(String uri) {
this.incapable = uri;
errors++;
}
public void addUnknownComponent(String name) {
this.unknownComponent = name;
errors++;
}
public void addUnknown(String name) {
if (unknown == null) {
unknown = new LinkedHashSet<>();
}
if (!unknown.contains(name)) {
unknown.add(name);
errors++;
}
}
public void addUnknownSuggestions(String name, String[] suggestions) {
if (unknownSuggestions == null) {
unknownSuggestions = new LinkedHashMap<>();
}
unknownSuggestions.put(name, suggestions);
}
public void addLenient(String name) {
if (lenient == null) {
lenient = new LinkedHashSet<>();
}
if (!lenient.contains(name)) {
lenient.add(name);
}
}
public void addRequired(String name) {
if (required == null) {
required = new LinkedHashSet<>();
}
if (!required.contains(name)) {
required.add(name);
errors++;
}
}
public void addDeprecated(String name) {
if (deprecated == null) {
deprecated = new LinkedHashSet<>();
}
if (!deprecated.contains(name)) {
deprecated.add(name);
}
}
public void addInvalidEnum(String name, String value) {
if (invalidEnum == null) {
invalidEnum = new LinkedHashMap<>();
}
if (!invalidEnum.containsKey(name)) {
invalidEnum.put(name, value);
errors++;
}
}
public void addInvalidEnumChoices(String name, String[] choices) {
if (invalidEnumChoices == null) {
invalidEnumChoices = new LinkedHashMap<>();
}
invalidEnumChoices.put(name, choices);
}
public void addInvalidEnumSuggestions(String name, String[] suggestions) {
if (invalidEnumSuggestions == null) {
invalidEnumSuggestions = new LinkedHashMap<>();
}
invalidEnumSuggestions.put(name, suggestions);
}
public void addInvalidReference(String name, String value) {
if (invalidReference == null) {
invalidReference = new LinkedHashMap<>();
}
if (!invalidReference.containsKey(name)) {
invalidReference.put(name, value);
errors++;
}
}
public void addInvalidBoolean(String name, String value) {
if (invalidBoolean == null) {
invalidBoolean = new LinkedHashMap<>();
}
if (!invalidBoolean.containsKey(name)) {
invalidBoolean.put(name, value);
errors++;
}
}
public void addInvalidInteger(String name, String value) {
if (invalidInteger == null) {
invalidInteger = new LinkedHashMap<>();
}
if (!invalidInteger.containsKey(name)) {
invalidInteger.put(name, value);
errors++;
}
}
public void addInvalidNumber(String name, String value) {
if (invalidNumber == null) {
invalidNumber = new LinkedHashMap<>();
}
if (!invalidNumber.containsKey(name)) {
invalidNumber.put(name, value);
errors++;
}
}
public void addDefaultValue(String name, String value) {
if (defaultValues == null) {
defaultValues = new LinkedHashMap<>();
}
defaultValues.put(name, value);
}
public void addNotConsumerOnly(String name) {
if (notConsumerOnly == null) {
notConsumerOnly = new LinkedHashSet<>();
}
if (!notConsumerOnly.contains(name)) {
notConsumerOnly.add(name);
errors++;
}
}
public void addNotProducerOnly(String name) {
if (notProducerOnly == null) {
notProducerOnly = new LinkedHashSet<>();
}
if (!notProducerOnly.contains(name)) {
notProducerOnly.add(name);
errors++;
}
}
public String getSyntaxError() {
return syntaxError;
}
public String getIncapable() {
return incapable;
}
public Set<String> getUnknown() {
return unknown;
}
public Set<String> getLenient() {
return lenient;
}
public Map<String, String[]> getUnknownSuggestions() {
return unknownSuggestions;
}
public String getUnknownComponent() {
return unknownComponent;
}
public Set<String> getRequired() {
return required;
}
public Set<String> getDeprecated() {
return deprecated;
}
public Map<String, String> getInvalidEnum() {
return invalidEnum;
}
public Map<String, String[]> getInvalidEnumChoices() {
return invalidEnumChoices;
}
public List<String> getEnumChoices(String optionName) {
if (invalidEnumChoices != null) {
String[] enums = invalidEnumChoices.get(optionName);
if (enums != null) {
return Arrays.asList(enums);
}
}
return Collections.emptyList();
}
public Map<String, String> getInvalidReference() {
return invalidReference;
}
public Map<String, String> getInvalidBoolean() {
return invalidBoolean;
}
public Map<String, String> getInvalidInteger() {
return invalidInteger;
}
public Map<String, String> getInvalidNumber() {
return invalidNumber;
}
public Map<String, String> getDefaultValues() {
return defaultValues;
}
public Set<String> getNotConsumerOnly() {
return notConsumerOnly;
}
public Set<String> getNotProducerOnly() {
return notProducerOnly;
}
/**
* A human readable summary of the validation errors.
*
* @param includeHeader whether to include a header
* @return the summary, or <tt>null</tt> if no validation errors
*/
public String summaryErrorMessage(boolean includeHeader) {
return summaryErrorMessage(includeHeader, true);
}
/**
* A human readable summary of the validation errors.
*
* @param includeHeader whether to include a header
* @param ignoreDeprecated whether to ignore deprecated options in use as an error or not
* @return the summary, or <tt>null</tt> if no validation errors
*/
public String summaryErrorMessage(boolean includeHeader, boolean ignoreDeprecated) {
boolean ok = isSuccess();
// special check if we should ignore deprecated options being used
if (ok && !ignoreDeprecated) {
ok = deprecated == null;
}
if (ok) {
return null;
}
if (incapable != null) {
return "\tIncapable of parsing uri: " + incapable;
} else if (syntaxError != null) {
return "\tSyntax error: " + syntaxError;
} else if (unknownComponent != null) {
return "\tUnknown component: " + unknownComponent;
}
// for each invalid option build a reason message
Map<String, String> options = new LinkedHashMap<>();
if (unknown != null) {
for (String name : unknown) {
if (unknownSuggestions != null && unknownSuggestions.containsKey(name)) {
String[] suggestions = unknownSuggestions.get(name);
if (suggestions != null && suggestions.length > 0) {
String str = Arrays.asList(suggestions).toString();
options.put(name, "Unknown option. Did you mean: " + str);
} else {
options.put(name, "Unknown option");
}
} else {
options.put(name, "Unknown option");
}
}
}
if (notConsumerOnly != null) {
for (String name : notConsumerOnly) {
options.put(name, "Option not applicable in consumer only mode");
}
}
if (notProducerOnly != null) {
for (String name : notProducerOnly) {
options.put(name, "Option not applicable in producer only mode");
}
}
if (required != null) {
for (String name : required) {
options.put(name, "Missing required option");
}
}
if (deprecated != null) {
for (String name : deprecated) {
options.put(name, "Deprecated option");
}
}
if (invalidEnum != null) {
for (Map.Entry<String, String> entry : invalidEnum.entrySet()) {
String name = entry.getKey();
String[] choices = invalidEnumChoices.get(name);
String defaultValue = defaultValues != null ? defaultValues.get(entry.getKey()) : null;
String str = Arrays.asList(choices).toString();
String msg = "Invalid enum value: " + entry.getValue() + ". Possible values: " + str;
if (invalidEnumSuggestions != null) {
String[] suggestions = invalidEnumSuggestions.get(name);
if (suggestions != null && suggestions.length > 0) {
str = Arrays.asList(suggestions).toString();
msg += ". Did you mean: " + str;
}
}
if (defaultValue != null) {
msg += ". Default value: " + defaultValue;
}
options.put(entry.getKey(), msg);
}
}
if (invalidReference != null) {
for (Map.Entry<String, String> entry : invalidReference.entrySet()) {
boolean empty = isEmpty(entry.getValue());
if (empty) {
options.put(entry.getKey(), "Empty reference value");
} else if (!entry.getValue().startsWith("#")) {
options.put(entry.getKey(), "Invalid reference value: " + entry.getValue() + " must start with #");
} else {
options.put(entry.getKey(), "Invalid reference value: " + entry.getValue());
}
}
}
if (invalidBoolean != null) {
for (Map.Entry<String, String> entry : invalidBoolean.entrySet()) {
boolean empty = isEmpty(entry.getValue());
if (empty) {
options.put(entry.getKey(), "Empty boolean value");
} else {
options.put(entry.getKey(), "Invalid boolean value: " + entry.getValue());
}
}
}
if (invalidInteger != null) {
for (Map.Entry<String, String> entry : invalidInteger.entrySet()) {
boolean empty = isEmpty(entry.getValue());
if (empty) {
options.put(entry.getKey(), "Empty integer value");
} else {
options.put(entry.getKey(), "Invalid integer value: " + entry.getValue());
}
}
}
if (invalidNumber != null) {
for (Map.Entry<String, String> entry : invalidNumber.entrySet()) {
boolean empty = isEmpty(entry.getValue());
if (empty) {
options.put(entry.getKey(), "Empty number value");
} else {
options.put(entry.getKey(), "Invalid number value: " + entry.getValue());
}
}
}
// build a table with the error summary nicely formatted
// lets use 24 as min length
int maxLen = 24;
for (String key : options.keySet()) {
maxLen = Math.max(maxLen, key.length());
}
String format = "%" + maxLen + "s %s";
// build the human error summary
StringBuilder sb = new StringBuilder();
if (includeHeader) {
sb.append("Endpoint validator error\n");
sb.append("---------------------------------------------------------------------------------------------------------------------------------------\n");
sb.append("\n");
}
if (uri != null) {
sb.append("\t").append(uri).append("\n");
} else {
sb.append("\n");
}
for (Map.Entry<String, String> option : options.entrySet()) {
String out = String.format(format, option.getKey(), option.getValue());
sb.append("\n\t").append(out);
}
return sb.toString();
}
}