use of io.siddhi.annotation.ParameterOverload in project siddhi by wso2.
the class SiddhiAnnotationProcessor method process.
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
// Iterate over all @Extension annotated elements.
for (Element element : roundEnv.getElementsAnnotatedWith(Extension.class)) {
// Check if a class has been annotated with @Extension.
if (element.getKind() == ElementKind.CLASS) {
String superClass = getMatchingSuperClass(element, new String[] { AnnotationConstants.SINK_MAPPER_SUPER_CLASS, AnnotationConstants.SINK_SUPER_CLASS, AnnotationConstants.FUNCTION_EXECUTOR_SUPER_CLASS, AnnotationConstants.AGGREGATION_ATTRIBUTE_EXECUTOR_SUPER_CLASS, AnnotationConstants.DISTRIBUTION_STRATEGY_SUPER_CLASS, AnnotationConstants.STREAM_PROCESSOR_SUPER_CLASS, AnnotationConstants.STREAM_FUNCTION_PROCESSOR_SUPER_CLASS, AnnotationConstants.STORE_SUPER_CLASS, AnnotationConstants.SOURCE_SUPER_CLASS, AnnotationConstants.SOURCE_MAPPER_SUPER_CLASS, AnnotationConstants.WINDOW_PROCESSOR_CLASS, AnnotationConstants.SCRIPT_SUPER_CLASS, AnnotationConstants.INCREMENTAL_ATTRIBUTE_AGGREGATOR_SUPER_CLASS });
AbstractAnnotationProcessor abstractAnnotationProcessor = null;
Extension annotation = element.getAnnotation(Extension.class);
String name = annotation.name();
String description = annotation.description();
String namespace = annotation.namespace();
Parameter[] parameters = annotation.parameters();
ParameterOverload[] parameterOverloads = annotation.parameterOverloads();
ReturnAttribute[] returnAttributes = annotation.returnAttributes();
SystemParameter[] systemParameters = annotation.systemParameter();
Example[] examples = annotation.examples();
String extensionClassFullName = element.asType().toString();
if (superClass != null) {
switch(superClass) {
case AnnotationConstants.DISTRIBUTION_STRATEGY_SUPER_CLASS:
abstractAnnotationProcessor = new DistributionStrategyValidationAnnotationProcessor(extensionClassFullName);
break;
case AnnotationConstants.SINK_MAPPER_SUPER_CLASS:
abstractAnnotationProcessor = new SinkMapperValidationAnnotationProcessor(extensionClassFullName);
break;
case AnnotationConstants.SINK_SUPER_CLASS:
abstractAnnotationProcessor = new SinkValidationAnnotationProcessor(extensionClassFullName);
break;
case AnnotationConstants.FUNCTION_EXECUTOR_SUPER_CLASS:
abstractAnnotationProcessor = new FunctionExecutorValidationAnnotationProcessor(extensionClassFullName);
break;
case AnnotationConstants.AGGREGATION_ATTRIBUTE_EXECUTOR_SUPER_CLASS:
abstractAnnotationProcessor = new AggregationAttributeValidationAnnotationProcessor(extensionClassFullName);
break;
case AnnotationConstants.STREAM_PROCESSOR_SUPER_CLASS:
abstractAnnotationProcessor = new StreamProcessorValidationAnnotationProcessor(extensionClassFullName);
break;
case AnnotationConstants.SOURCE_SUPER_CLASS:
abstractAnnotationProcessor = new SourceValidationAnnotationProcessor(extensionClassFullName);
break;
case AnnotationConstants.SOURCE_MAPPER_SUPER_CLASS:
abstractAnnotationProcessor = new SourceMapperValidationAnnotationProcessor(extensionClassFullName);
break;
case AnnotationConstants.STORE_SUPER_CLASS:
abstractAnnotationProcessor = new StoreValidationAnnotationProcessor(extensionClassFullName);
break;
case AnnotationConstants.STREAM_FUNCTION_PROCESSOR_SUPER_CLASS:
abstractAnnotationProcessor = new StreamFunctionProcessorValidationAnnotationProcessor(extensionClassFullName);
break;
case AnnotationConstants.WINDOW_PROCESSOR_CLASS:
abstractAnnotationProcessor = new WindowProcessorValidationAnnotationProcessor(extensionClassFullName);
break;
case AnnotationConstants.SCRIPT_SUPER_CLASS:
abstractAnnotationProcessor = new ScriptValidationAnnotationProcessor(extensionClassFullName);
break;
case AnnotationConstants.INCREMENTAL_ATTRIBUTE_AGGREGATOR_SUPER_CLASS:
abstractAnnotationProcessor = new IncrementalAggregationAttributeValidationAnnotationProcessor(extensionClassFullName);
break;
default:
// Throw error if no matching super class.
showBuildError(MessageFormat.format("Default switch case executed as there is no " + "matching super class option for @{0}.", superClass), element);
break;
}
if (abstractAnnotationProcessor != null) {
try {
abstractAnnotationProcessor.basicParameterValidation(name, description, namespace);
abstractAnnotationProcessor.parameterValidation(parameters);
abstractAnnotationProcessor.parameterOverloadValidation(parameterOverloads, parameters);
abstractAnnotationProcessor.returnAttributesValidation(returnAttributes);
abstractAnnotationProcessor.systemParametersValidation(systemParameters);
abstractAnnotationProcessor.examplesValidation(examples);
} catch (AnnotationValidationException e) {
showBuildError(e.getMessage(), element);
}
} else {
showBuildError(MessageFormat.format("Error while validation, " + "abstractAnnotationProcessor cannot be null.", superClass), element);
}
} else {
// Throw error if no matching super class.
showBuildError("Class does not have a matching Siddhi Extension super class.", element);
}
} else {
// Throw error if the element returned is method or package.
showBuildError(MessageFormat.format("Only classes can be annotated with @{0}.", Extension.class.getCanonicalName()), element);
}
}
// Returning false since this processor only validates.
return false;
}
use of io.siddhi.annotation.ParameterOverload in project siddhi by wso2.
the class InputParameterValidator method validateExpressionExecutors.
/**
* The method which validates the extension specific parameters of siddhi App with the pattern specified in the
* {@link ParameterOverload} annotation in the extension class
*
* @param objectHavingAnnotation the object which has Extension annotation
* @param attributeExpressionExecutors the executors of each function parameters
* @throws SiddhiAppValidationException SiddhiAppValidation exception
*/
public static void validateExpressionExecutors(Object objectHavingAnnotation, ExpressionExecutor[] attributeExpressionExecutors) throws SiddhiAppValidationException {
Extension annotation = objectHavingAnnotation.getClass().getAnnotation(Extension.class);
if (annotation == null) {
return;
}
ParameterOverload[] parameterOverloads = annotation.parameterOverloads();
Parameter[] parameters = annotation.parameters();
String key = AnnotationHelper.createAnnotationKey(annotation);
// Count the mandatory number of parameters specified in @Extension
int mandatoryCount = 0;
Map<String, Parameter> parameterMap = new HashMap<>();
for (Parameter parameter : parameters) {
if (!parameter.optional()) {
mandatoryCount++;
}
parameterMap.put(parameter.name(), parameter);
}
// Find the parameterOverLoad
ParameterOverload parameterOverload = null;
for (ParameterOverload aParameterOverload : parameterOverloads) {
String[] overloadParameterNames = aParameterOverload.parameterNames();
if (overloadParameterNames.length == attributeExpressionExecutors.length && (overloadParameterNames.length == 0 || !overloadParameterNames[overloadParameterNames.length - 1].equals(REPETITIVE_PARAMETER_NOTATION))) {
boolean isExpectedParameterOverload = true;
for (int i = 0; i < overloadParameterNames.length; i++) {
String overloadParameterName = overloadParameterNames[i];
Parameter parameter = parameterMap.get(overloadParameterName);
boolean supportedReturnType = false;
for (DataType type : parameter.type()) {
if (attributeExpressionExecutors[i].getReturnType().toString().equalsIgnoreCase(type.toString())) {
supportedReturnType = true;
break;
}
}
if (!supportedReturnType) {
isExpectedParameterOverload = false;
break;
}
}
if (isExpectedParameterOverload) {
parameterOverload = aParameterOverload;
break;
}
} else if (overloadParameterNames.length - 1 <= attributeExpressionExecutors.length && overloadParameterNames.length > 0 && overloadParameterNames[overloadParameterNames.length - 1].equals(REPETITIVE_PARAMETER_NOTATION)) {
if (attributeExpressionExecutors.length > 0) {
boolean isExpectedParameterOverload = true;
for (int i = 0; i < attributeExpressionExecutors.length; i++) {
Parameter parameter = null;
String overloadParameterName = null;
if (i < overloadParameterNames.length - 1) {
overloadParameterName = overloadParameterNames[i];
} else {
overloadParameterName = overloadParameterNames[overloadParameterNames.length - 2];
}
parameter = parameterMap.get(overloadParameterName);
boolean supportedReturnType = false;
for (DataType type : parameter.type()) {
if (attributeExpressionExecutors[i].getReturnType().toString().equalsIgnoreCase(type.toString())) {
supportedReturnType = true;
break;
}
}
if (!supportedReturnType) {
isExpectedParameterOverload = false;
break;
}
}
if (isExpectedParameterOverload) {
parameterOverload = aParameterOverload;
break;
}
}
}
}
if (parameterOverload == null) {
if (parameterOverloads.length > 0) {
List<Attribute.Type> returnTypes = new ArrayList<>();
for (ExpressionExecutor expressionExecutor : attributeExpressionExecutors) {
returnTypes.add(expressionExecutor.getReturnType());
}
String formattedParamOverloadString = getSupportedParamOverloads(parameterMap, parameterOverloads);
throw new SiddhiAppValidationException("There is no parameterOverload for '" + key + "' that matches attribute types '" + returnTypes.stream().map(String::valueOf).collect(Collectors.joining(", ", "<", ">")) + "'. Supported parameter overloads are " + formattedParamOverloadString + ".");
} else {
if (mandatoryCount > attributeExpressionExecutors.length) {
throw new SiddhiAppValidationException("The '" + key + "' expects at least " + mandatoryCount + " parameters, but found only " + attributeExpressionExecutors.length + " input parameters.");
}
}
} else {
String[] overloadParameterNames = parameterOverload.parameterNames();
for (int i = 0; i < overloadParameterNames.length; i++) {
String overloadParameterName = overloadParameterNames[i];
Parameter parameter = parameterMap.get(overloadParameterName);
if (parameter != null && !parameter.dynamic() && !(attributeExpressionExecutors[i] instanceof ConstantExpressionExecutor)) {
throw new SiddhiAppValidationException("The '" + key + "' expects input parameter '" + parameter.name() + "' at position '" + i + "' to be static," + " but found a dynamic attribute.");
}
}
}
}
use of io.siddhi.annotation.ParameterOverload in project siddhi by wso2.
the class AbstractAnnotationProcessor method parameterOverloadValidation.
/**
* This method uses for validate @Extension / @ParameterOverload element.
*
* @param parameterOverloads parameter array which needs to be validate.
* @param parameters the set of supported parameters
* @throws AnnotationValidationException whenever if the validate rule violate, throws the annotation validate
* exception with proper message.
*/
public void parameterOverloadValidation(ParameterOverload[] parameterOverloads, Parameter[] parameters) throws AnnotationValidationException {
Map<String, Parameter> parameterMap = new HashMap<>();
Set<String> mandatoryParameterSet = new HashSet<>();
for (Parameter parameter : parameters) {
parameterMap.put(parameter.name(), parameter);
if (!parameter.optional()) {
mandatoryParameterSet.add(parameter.name());
}
}
for (ParameterOverload parameterOverload : parameterOverloads) {
String[] overloadParameterNames = parameterOverload.parameterNames();
for (String overloadParameterName : overloadParameterNames) {
// Check if the @Parameter name is empty.
if (overloadParameterName.isEmpty()) {
throw new AnnotationValidationException(MessageFormat.format("The @Extension -> " + "@ParameterOverload -> parameterNames annotated in class {0} is null or empty.", extensionClassFullName));
} else if (!(PARAMETER_NAME_PATTERN.matcher(overloadParameterName).find() || REPETITIVE_PARAMETER_NOTATION.equals(overloadParameterName))) {
// Check if the @Parameter name is in a correct format 'abc.def.ghi' using regex pattern.
throw new AnnotationValidationException(MessageFormat.format("The @Extension -> " + "@ParameterOverload -> parameterNames {0} annotated in class {1} is not " + "in proper format 'abc.def.ghi'.", overloadParameterName, extensionClassFullName));
}
if (!(parameterMap.containsKey(overloadParameterName) || REPETITIVE_PARAMETER_NOTATION.equals(overloadParameterName))) {
throw new AnnotationValidationException(MessageFormat.format("The @Extension -> " + "@ParameterOverload -> parameterNames {0} annotated in class {1} is not defined in " + "@Extension -> @Parameter.", overloadParameterName, extensionClassFullName));
}
}
}
if (parameterOverloads.length > 0) {
Set<String> mandatoryParameterSetViaOverload = new HashSet<>(parameterMap.keySet());
for (Iterator<String> iterator = mandatoryParameterSetViaOverload.iterator(); iterator.hasNext(); ) {
String parameter = iterator.next();
for (ParameterOverload parameterOverload : parameterOverloads) {
boolean contains = false;
for (String parameterName : parameterOverload.parameterNames()) {
if (parameter.equalsIgnoreCase(parameterName)) {
contains = true;
break;
}
}
if (!contains) {
iterator.remove();
break;
}
}
}
if (!mandatoryParameterSetViaOverload.equals(mandatoryParameterSet)) {
throw new AnnotationValidationException("Mandatory parameter information in ParameterOverload " + "and based on 'optional' annotation is a mismatch. The parameters '" + mandatoryParameterSetViaOverload + "' always appearing in ParameterOverload, but '" + mandatoryParameterSet + "' are defined as not 'optional' in the annotations.");
}
}
}
use of io.siddhi.annotation.ParameterOverload in project siddhi by wso2.
the class InputParameterValidator method getSupportedParamOverloads.
private static String getSupportedParamOverloads(Map<String, Parameter> parameterMap, ParameterOverload[] parameterOverloads) {
StringJoiner stringJoiner = new StringJoiner(", ");
for (ParameterOverload parameterOverload : parameterOverloads) {
String[] parameterNames = parameterOverload.parameterNames();
if (parameterNames.length != 0) {
StringJoiner paramOverloadStringJoiner = new StringJoiner(", ", "(", ")");
for (int i = 0; i < parameterNames.length; i++) {
StringBuilder stringBuilder = new StringBuilder();
if (!SiddhiConstants.REPETITIVE_PARAMETER_NOTATION.equals(parameterNames[i])) {
stringBuilder.append(getFormattedStringForDataType(parameterMap.get(parameterNames[i]).type()));
stringBuilder.append(" ").append(parameterNames[i]);
} else {
stringBuilder.append(getFormattedStringForDataType(parameterMap.get(parameterNames[i - 1]).type()));
stringBuilder.append(" ").append(SiddhiConstants.REPETITIVE_PARAMETER_NOTATION);
}
paramOverloadStringJoiner.add(stringBuilder);
}
stringJoiner.add(paramOverloadStringJoiner.toString());
}
}
return stringJoiner.toString();
}
use of io.siddhi.annotation.ParameterOverload in project siddhi by wso2.
the class DocumentationUtils method addExtensionMetaDataIntoNamespaceList.
/**
* Generate extension meta data from the annotated data in the class
*
* @param namespaceList The list of namespaces to which the new extension will be added
* @param extensionClass Class from which meta data should be extracted from
* @param logger The maven plugin logger
* @param includeOrigin Add origin to the docs
*/
private static void addExtensionMetaDataIntoNamespaceList(List<NamespaceMetaData> namespaceList, Class<?> extensionClass, Log logger, boolean includeOrigin) {
Extension extensionAnnotation = extensionClass.getAnnotation(Extension.class);
if (extensionAnnotation != null) {
// Discarding extension classes without annotation
ExtensionMetaData extensionMetaData = new ExtensionMetaData();
// Finding extension type
String extensionType = null;
for (Map.Entry<ExtensionType, Class<?>> entry : ExtensionType.getSuperClassMap().entrySet()) {
Class<?> superClass = entry.getValue();
if (superClass.isAssignableFrom(extensionClass) && superClass != extensionClass) {
extensionType = entry.getKey().getValue();
break;
}
}
// Discarding the extension if it belongs to an unknown type
if (extensionType == null) {
logger.warn("Discarding extension (belonging to an unknown extension type): " + extensionClass.getCanonicalName());
return;
}
extensionMetaData.setName(extensionAnnotation.name());
extensionMetaData.setDescription(extensionAnnotation.description());
extensionMetaData.setDeprecated(extensionAnnotation.deprecated());
if (includeOrigin) {
Manifest manifest = getManifest(extensionClass);
Attributes attributes = manifest.getMainAttributes();
extensionMetaData.setOriginName(attributes.getValue("Bundle-Name"));
extensionMetaData.setOriginVersion(attributes.getValue("Bundle-Version"));
}
// Adding query parameters
ParameterMetaData[] parameters = new ParameterMetaData[extensionAnnotation.parameters().length];
Map<String, ParameterMetaData> parameterMap = new HashMap<>();
for (int i = 0; i < extensionAnnotation.parameters().length; i++) {
Parameter parameterAnnotation = extensionAnnotation.parameters()[i];
ParameterMetaData parameter = new ParameterMetaData();
parameter.setName(parameterAnnotation.name());
parameter.setType(Arrays.asList(parameterAnnotation.type()));
parameter.setDescription(parameterAnnotation.description());
parameter.setOptional(parameterAnnotation.optional());
parameter.setDynamic(parameterAnnotation.dynamic());
parameter.setDefaultValue(parameterAnnotation.defaultValue());
parameterMap.put(parameter.getName(), parameter);
parameters[i] = parameter;
}
extensionMetaData.setParameters(Arrays.asList(parameters));
// Adding parameter overloads
if (extensionAnnotation.parameterOverloads().length > 0) {
ParameterOverloadMetaData[] parameterOverloads = new ParameterOverloadMetaData[extensionAnnotation.parameterOverloads().length];
for (int i = 0; i < extensionAnnotation.parameterOverloads().length; i++) {
ParameterOverload parameterOverloadAnnotation = extensionAnnotation.parameterOverloads()[i];
ParameterOverloadMetaData parameterOverload = new ParameterOverloadMetaData();
ParameterMetaData[] overloadParameters = new ParameterMetaData[parameterOverloadAnnotation.parameterNames().length];
for (int j = 0; j < parameterOverloadAnnotation.parameterNames().length; j++) {
ParameterMetaData parameterMetaData = parameterMap.get(parameterOverloadAnnotation.parameterNames()[j]);
if (parameterMetaData != null) {
overloadParameters[j] = parameterMetaData;
} else if (parameterOverloadAnnotation.parameterNames()[j].equals(SiddhiConstants.REPETITIVE_PARAMETER_NOTATION)) {
ParameterMetaData repetitiveParamMetaData = new ParameterMetaData();
ParameterMetaData previousParameterMetaData = parameterMap.get(parameterOverloadAnnotation.parameterNames()[j - 1]);
repetitiveParamMetaData.setName(SiddhiConstants.REPETITIVE_PARAMETER_NOTATION);
repetitiveParamMetaData.setType(previousParameterMetaData.getType());
repetitiveParamMetaData.setDescription(previousParameterMetaData.getDescription());
repetitiveParamMetaData.setOptional(previousParameterMetaData.isOptional());
repetitiveParamMetaData.setDynamic(previousParameterMetaData.isDynamic());
repetitiveParamMetaData.setDefaultValue(previousParameterMetaData.getDefaultValue());
overloadParameters[j] = repetitiveParamMetaData;
}
}
parameterOverload.setParameters(Arrays.asList(overloadParameters));
parameterOverloads[i] = parameterOverload;
}
extensionMetaData.setParameterOverloads(Arrays.asList(parameterOverloads));
}
// Adding system parameters
SystemParameterMetaData[] systemParameters = new SystemParameterMetaData[extensionAnnotation.systemParameter().length];
for (int i = 0; i < extensionAnnotation.systemParameter().length; i++) {
SystemParameter systemParameterAnnotation = extensionAnnotation.systemParameter()[i];
SystemParameterMetaData systemParameter = new SystemParameterMetaData();
systemParameter.setName(systemParameterAnnotation.name());
systemParameter.setDescription(systemParameterAnnotation.description());
systemParameter.setDefaultValue(systemParameterAnnotation.defaultValue());
systemParameter.setPossibleParameters(Arrays.asList(systemParameterAnnotation.possibleParameters()));
systemParameters[i] = systemParameter;
}
extensionMetaData.setSystemParameters(Arrays.asList(systemParameters));
// Adding return attributes
ReturnAttributeMetaData[] returnAttributes = new ReturnAttributeMetaData[extensionAnnotation.returnAttributes().length];
for (int i = 0; i < extensionAnnotation.returnAttributes().length; i++) {
ReturnAttribute parameterAnnotation = extensionAnnotation.returnAttributes()[i];
ReturnAttributeMetaData returnAttribute = new ReturnAttributeMetaData();
returnAttribute.setName(parameterAnnotation.name());
returnAttribute.setType(Arrays.asList(parameterAnnotation.type()));
returnAttribute.setDescription(parameterAnnotation.description());
returnAttributes[i] = returnAttribute;
}
extensionMetaData.setReturnAttributes(Arrays.asList(returnAttributes));
// Adding examples
ExampleMetaData[] examples = new ExampleMetaData[extensionAnnotation.examples().length];
for (int i = 0; i < extensionAnnotation.examples().length; i++) {
Example exampleAnnotation = extensionAnnotation.examples()[i];
ExampleMetaData exampleMetaData = new ExampleMetaData();
exampleMetaData.setSyntax(exampleAnnotation.syntax());
exampleMetaData.setDescription(exampleAnnotation.description());
examples[i] = exampleMetaData;
}
extensionMetaData.setExamples(Arrays.asList(examples));
// Finding the namespace
String namespaceName = extensionAnnotation.namespace();
if (Objects.equals(namespaceName, "")) {
namespaceName = Constants.CORE_NAMESPACE;
}
// Finding the relevant namespace in the namespace list
NamespaceMetaData namespace = null;
for (NamespaceMetaData existingNamespace : namespaceList) {
if (Objects.equals(existingNamespace.getName(), namespaceName)) {
namespace = existingNamespace;
break;
}
}
// Creating namespace if it doesn't exist
if (namespace == null) {
namespace = new NamespaceMetaData();
namespace.setName(namespaceName);
namespace.setExtensionMap(new TreeMap<>());
namespaceList.add(namespace);
}
// Adding to the relevant extension metadata list in the namespace
List<ExtensionMetaData> extensionMetaDataList = namespace.getExtensionMap().computeIfAbsent(extensionType, k -> new ArrayList<>());
extensionMetaDataList.add(extensionMetaData);
}
}
Aggregations