下面列出了javax.validation.Constraint#org.jboss.jandex.AnnotationTarget 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@BuildStep
void registerForReflection(BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
BuildProducer<UnbannedReflectiveBuildItem> unbannedClass, CombinedIndexBuildItem combinedIndex) {
IndexView index = combinedIndex.getIndex();
// Google calendar component configuration class reflection
Collection<AnnotationInstance> uriParams = index
.getAnnotations(DotName.createSimple("org.apache.camel.spi.UriParams"));
String[] googleDriveConfigClasses = uriParams.stream()
.map(annotation -> annotation.target())
.filter(annotationTarget -> annotationTarget.kind().equals(AnnotationTarget.Kind.CLASS))
.map(annotationTarget -> annotationTarget.asClass().name().toString())
.filter(className -> className.startsWith("org.apache.camel.component.google.calendar"))
.toArray(String[]::new);
reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, googleDriveConfigClasses));
unbannedClass.produce(new UnbannedReflectiveBuildItem(googleDriveConfigClasses));
}
@BuildStep
void disableCamelMicroProfileHealthChecks(BuildProducer<AnnotationsTransformerBuildItem> transformers,
CamelMicroProfileHealthConfig config) {
if (!config.enabled) {
// Veto the Camel MicroProfile checks to disable them
transformers.produce(new AnnotationsTransformerBuildItem(context -> {
if (context.isClass()) {
AnnotationTarget target = context.getTarget();
if (isCamelMicroProfileHealthCheck(target.asClass())) {
AnnotationInstance annotationInstance = AnnotationInstance.create(VETOED_DOTNAME, target,
new AnnotationValue[0]);
context.transform().add(annotationInstance).done();
}
}
}));
}
}
@BuildStep
void registerForReflection(BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
BuildProducer<UnbannedReflectiveBuildItem> unbannedClass, CombinedIndexBuildItem combinedIndex) {
IndexView index = combinedIndex.getIndex();
// Google drive component configuration class reflection
Collection<AnnotationInstance> uriParams = index
.getAnnotations(DotName.createSimple("org.apache.camel.spi.UriParams"));
String[] googleDriveConfigClasses = uriParams.stream()
.map(annotation -> annotation.target())
.filter(annotationTarget -> annotationTarget.kind().equals(AnnotationTarget.Kind.CLASS))
.map(annotationTarget -> annotationTarget.asClass().name().toString())
.filter(className -> className.startsWith("org.apache.camel.component.google.drive"))
.toArray(String[]::new);
reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, googleDriveConfigClasses));
unbannedClass.produce(new UnbannedReflectiveBuildItem(googleDriveConfigClasses));
}
@BuildStep
void registerForReflection(BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
BuildProducer<UnbannedReflectiveBuildItem> unbannedClass, CombinedIndexBuildItem combinedIndex) {
IndexView index = combinedIndex.getIndex();
// Google sheets component configuration class reflection
Collection<AnnotationInstance> uriParams = index
.getAnnotations(DotName.createSimple("org.apache.camel.spi.UriParams"));
String[] googleMailConfigClasses = uriParams.stream()
.map(annotation -> annotation.target())
.filter(annotationTarget -> annotationTarget.kind().equals(AnnotationTarget.Kind.CLASS))
.map(annotationTarget -> annotationTarget.asClass().name().toString())
.filter(className -> className.startsWith("org.apache.camel.component.google.sheets"))
.toArray(String[]::new);
reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, googleMailConfigClasses));
unbannedClass.produce(new UnbannedReflectiveBuildItem(googleMailConfigClasses));
}
@Override
public boolean shouldIgnore(AnnotationTarget target, PathEntry parentPathEntry) {
if (target.kind() == AnnotationTarget.Kind.FIELD) {
FieldInfo field = target.asField();
// If field has transient modifier, e.g. `transient String foo;`, then hide it.
if (Modifier.isTransient(field.flags())) {
// Unless field is annotated with @Schema to explicitly un-hide it.
AnnotationInstance schemaAnnotation = TypeUtil.getSchemaAnnotation(target);
if (schemaAnnotation != null) {
return JandexUtil.booleanValue(schemaAnnotation, SchemaConstant.PROP_HIDDEN).orElse(true);
}
return true;
}
}
return false;
}
private static Integer initAlternativePriority(AnnotationTarget target, Integer alternativePriority,
List<StereotypeInfo> stereotypes, BeanDeployment deployment) {
if (alternativePriority == null) {
// No @Priority or @AlernativePriority used - try stereotypes
alternativePriority = initStereotypeAlternativePriority(stereotypes);
}
Integer computedPriority = deployment.computeAlternativePriority(target, stereotypes);
if (computedPriority != null) {
if (alternativePriority != null) {
LOGGER.infof(
"Computed priority [%s] overrides the priority [%s] declared via @Priority or @AlernativePriority",
computedPriority, alternativePriority);
}
alternativePriority = computedPriority;
}
return alternativePriority;
}
/**
*
* @param beanTarget
* @param beanDeployment
* @return the list of injections
*/
static List<Injection> forBean(AnnotationTarget beanTarget, BeanInfo declaringBean, BeanDeployment beanDeployment,
InjectionPointModifier transformer) {
if (Kind.CLASS.equals(beanTarget.kind())) {
List<Injection> injections = new ArrayList<>();
forClassBean(beanTarget.asClass(), beanTarget.asClass(), beanDeployment, injections, transformer, false);
Set<AnnotationTarget> injectConstructors = injections.stream().filter(Injection::isConstructor)
.map(Injection::getTarget).collect(Collectors.toSet());
if (injectConstructors.size() > 1) {
throw new DefinitionException(
"Multiple @Inject constructors found on " + beanTarget.asClass().name() + ":\n"
+ injectConstructors.stream().map(Object::toString).collect(Collectors.joining("\n")));
}
return injections;
} else if (Kind.METHOD.equals(beanTarget.kind())) {
if (beanTarget.asMethod().parameters().isEmpty()) {
return Collections.emptyList();
}
// All parameters are injection points
return Collections.singletonList(
new Injection(beanTarget.asMethod(),
InjectionPointInfo.fromMethod(beanTarget.asMethod(), declaringBean.getImplClazz(),
beanDeployment, transformer)));
}
throw new IllegalArgumentException("Unsupported annotation target");
}
boolean haveSameAnnotatedTarget(ParameterContext context, AnnotationTarget target, String name) {
/*
* Consider names to match if one is unspecified or they are equal.
*/
boolean nameMatches = (context.name == null || name == null || Objects.equals(context.name, name));
if (target.equals(context.target)) {
/*
* The name must match for annotations on a method because it is
* ambiguous which parameters is being referenced.
*/
return nameMatches || target.kind() != Kind.METHOD;
}
if (nameMatches && target.kind() == Kind.METHOD && context.target.kind() == Kind.METHOD_PARAMETER) {
return context.target.asMethodParameter().method().equals(target);
}
return false;
}
/**
* Scan and parse a Spring DefaultValue property on the mapping annotation.
* If the target is a Java primitive, the value will be parsed into an equivalent
* wrapper object.
*
* @param target target annotated with a Spring mapping
* @return the default value
*/
static Object getDefaultValue(AnnotationTarget target) {
AnnotationInstance defaultValueAnno = TypeUtil.getAnnotation(target, SpringConstants.QUERY_PARAM);
Object defaultValue = null;
if (defaultValueAnno != null) {
AnnotationValue value = defaultValueAnno.value("defaultValue");
if (value != null && !value.asString().isEmpty()) {
String defaultValueString = value.asString();
defaultValue = defaultValueString;
Type targetType = getType(target);
if (targetType != null && targetType.kind() == Type.Kind.PRIMITIVE) {
Primitive primitive = targetType.asPrimitiveType().primitive();
Object primitiveValue = primitiveToObject(primitive, defaultValueString);
if (primitiveValue != null) {
defaultValue = primitiveValue;
}
}
}
}
return defaultValue;
}
/**
* Find the full path of the target. Method-level targets will include
* both the path to the resource and the path to the method joined with a '/'.
*
* @param target target item for which the path is being generated
* @return full path (excluding application path) of the target
*/
static String fullPathOf(AnnotationTarget target) {
String pathSegment = null;
switch (target.kind()) {
case FIELD:
pathSegment = pathOf(target.asField().declaringClass());
break;
case METHOD:
pathSegment = methodPath(target.asMethod());
break;
case METHOD_PARAMETER:
pathSegment = methodPath(target.asMethodParameter().method());
break;
default:
break;
}
return pathSegment;
}
@BuildStep
SpringBeanNameToDotNameBuildItem createBeanNamesMap(BeanArchiveIndexBuildItem beanArchiveIndexBuildItem) {
final Map<String, DotName> result = new HashMap<>();
final IndexView index = beanArchiveIndexBuildItem.getIndex();
final Collection<AnnotationInstance> stereotypeInstances = new ArrayList<>();
stereotypeInstances.addAll(index.getAnnotations(SPRING_COMPONENT));
stereotypeInstances.addAll(index.getAnnotations(SPRING_REPOSITORY));
stereotypeInstances.addAll(index.getAnnotations(SPRING_SERVICE));
for (AnnotationInstance stereotypeInstance : stereotypeInstances) {
if (stereotypeInstance.target().kind() != AnnotationTarget.Kind.CLASS) {
continue;
}
result.put(getBeanNameFromStereotypeInstance(stereotypeInstance), stereotypeInstance.target().asClass().name());
}
for (AnnotationInstance beanInstance : index.getAnnotations(BEAN_ANNOTATION)) {
if (beanInstance.target().kind() != AnnotationTarget.Kind.METHOD) {
continue;
}
result.put(getBeanNameFromBeanInstance(beanInstance), beanInstance.target().asMethod().returnType().name());
}
return new SpringBeanNameToDotNameBuildItem(result);
}
public static ClassInfo getDeclaringClass(AnnotationTarget type) {
switch (type.kind()) {
case FIELD:
return type.asField().declaringClass();
case METHOD:
return type.asMethod().declaringClass();
case METHOD_PARAMETER:
MethodParameterInfo parameter = type.asMethodParameter();
return parameter.method().declaringClass();
case CLASS:
case TYPE:
break;
}
return null;
}
private boolean isUserDefinedProducerMissing(IndexView index, DotName annotationName) {
for (AnnotationInstance annotationInstance : index.getAnnotations(annotationName)) {
if (annotationInstance.target().kind() == AnnotationTarget.Kind.METHOD) {
if (annotationInstance.target().asMethod().hasAnnotation(PRODUCES)) {
return false;
}
} else if (annotationInstance.target().kind() == AnnotationTarget.Kind.FIELD) {
for (AnnotationInstance i : annotationInstance.target().asField().annotations()) {
if (i.name().equals(PRODUCES)) {
return false;
}
}
}
}
return true;
}
private static String initStereotypeName(List<StereotypeInfo> stereotypes, AnnotationTarget target) {
if (stereotypes.isEmpty()) {
return null;
}
for (StereotypeInfo stereotype : stereotypes) {
if (stereotype.isNamed()) {
switch (target.kind()) {
case CLASS:
return getDefaultName(target.asClass());
case FIELD:
return target.asField()
.name();
case METHOD:
return getDefaultName(target.asMethod());
default:
break;
}
}
}
return null;
}
void decimalMax(AnnotationTarget target, Schema schema) {
AnnotationInstance constraint = getConstraint(target, BV_DECIMAL_MAX);
if (constraint != null && schema.getMaximum() == null) {
String decimalValue = stringValue(constraint, VALUE);
try {
BigDecimal decimal = new BigDecimal(decimalValue);
schema.setMaximum(decimal);
Optional<Boolean> inclusive = booleanValue(constraint, INCLUSIVE);
if (schema.getExclusiveMaximum() == null && inclusive.isPresent() && !inclusive.get()) {
schema.setExclusiveMaximum(Boolean.TRUE);
}
} catch (@SuppressWarnings("unused") NumberFormatException e) {
DataObjectLogging.log.invalidAnnotationFormat(decimalValue);
}
}
}
public static FieldOrMethod getFieldOrMethod(Index index, ClassInfo annotatedClass,
AnnotationTarget annotatedFieldOrMethod, boolean isPanache) {
switch (annotatedFieldOrMethod.kind()) {
case FIELD:
// try to find a getter for this field
FieldInfo field = annotatedFieldOrMethod.asField();
return new FieldOrMethod(field,
findGetter(index, annotatedClass, field, Modifier.isPublic(field.flags()) && isPanache));
case METHOD:
// skip the field entirely
return new FieldOrMethod(null, annotatedFieldOrMethod.asMethod());
default:
throw new IllegalArgumentException(
"annotatedFieldOrMethod must be a field or method: " + annotatedFieldOrMethod);
}
}
@BuildStep
NativeImageProxyDefinitionBuildItem stmProxies() {
final DotName TRANSACTIONAL = DotName.createSimple(Transactional.class.getName());
IndexView index = combinedIndexBuildItem.getIndex();
Collection<String> proxies = new ArrayList<>();
for (AnnotationInstance stm : index.getAnnotations(TRANSACTIONAL)) {
if (AnnotationTarget.Kind.CLASS.equals(stm.target().kind())) {
DotName name = stm.target().asClass().name();
proxies.add(name.toString());
log.debugf("Registering transactional interface %s%n", name);
for (ClassInfo ci : index.getAllKnownImplementors(name)) {
reflectiveHierarchyClass.produce(
new ReflectiveHierarchyBuildItem(Type.create(ci.name(), Type.Kind.CLASS)));
}
}
}
String[] classNames = proxies.toArray(new String[0]);
reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, classNames));
return new NativeImageProxyDefinitionBuildItem(classNames);
}
InjectionPointInfo(Type requiredType, Set<AnnotationInstance> requiredQualifiers, InjectionPointKind kind,
AnnotationTarget target, int position, boolean isTransientReference) {
this.typeAndQualifiers = new TypeAndQualifiers(requiredType,
requiredQualifiers.isEmpty()
? Collections.singleton(AnnotationInstance.create(DotNames.DEFAULT, null, Collections.emptyList()))
: requiredQualifiers);
this.resolvedBean = new AtomicReference<BeanInfo>(null);
this.kind = kind;
this.hasDefaultedQualifier = requiredQualifiers.isEmpty();
this.target = target;
this.position = position;
this.isTransientReference = isTransientReference;
}
private AnnotationInstance createCacheInvalidateBinding(MethodInfo method, AnnotationInstance annotation,
AnnotationTarget target) {
List<AnnotationValue> parameters = new ArrayList<>();
parameters.add(getCacheName(annotation));
findCacheKeyParameters(method).ifPresent(parameters::add);
return createBinding(CacheInvalidateInterceptorBinding.class, target, toArray(parameters));
}
@BuildStep
AnnotationsTransformerBuildItem transformBeanScope(BeanArchiveIndexBuildItem index,
CustomScopeAnnotationsBuildItem scopes) {
return new AnnotationsTransformerBuildItem(new AnnotationsTransformer() {
@Override
public boolean appliesTo(AnnotationTarget.Kind kind) {
return kind == org.jboss.jandex.AnnotationTarget.Kind.CLASS;
}
@Override
public void transform(AnnotationsTransformer.TransformationContext ctx) {
if (ctx.isClass()) {
ClassInfo clazz = ctx.getTarget().asClass();
Map<DotName, List<AnnotationInstance>> annotations = clazz.annotations();
if (scopes.isScopeDeclaredOn(clazz)
|| annotations.containsKey(ReactiveMessagingDotNames.JAXRS_PATH)
|| annotations.containsKey(ReactiveMessagingDotNames.REST_CONTROLLER)
|| annotations.containsKey(ReactiveMessagingDotNames.JAXRS_PROVIDER)) {
// Skip - has a built-in scope annotation or is a JAX-RS endpoint/provider
return;
}
if (annotations.containsKey(ReactiveMessagingDotNames.INCOMING)
|| annotations.containsKey(ReactiveMessagingDotNames.OUTGOING)) {
LOGGER.debugf(
"Found reactive messaging annotations on a class %s with no scope defined - adding @Dependent",
ctx.getTarget());
ctx.transform().add(Dependent.class).done();
}
}
}
});
}
/**
* Determine if the paramTarget is annotated with the RestEasy
* {@link org.jboss.resteasy.annotations.providers.multipart.PartType @PartType}
* annotation and add the value to the encodings map.
*
* @param encodings map of encodings applicable to the current {@link MediaType} being processed
* @param paramName name of the current form parameter being mapped to a schema property
* @param paramTarget the target annotated with {@link javax.ws.rs.FormParam FormParam}
*
*/
static void addEncoding(Map<String, Encoding> encodings, String paramName, AnnotationTarget paramTarget) {
if (paramTarget == null) {
return;
}
AnnotationInstance type = TypeUtil.getAnnotation(paramTarget, RestEasyConstants.PART_TYPE);
if (type != null) {
Encoding encoding = new EncodingImpl();
encoding.setContentType(type.value().asString());
encodings.put(paramName, encoding);
}
}
/**
* Retrieves the "value" parameter from annotation to be used as the name.
* If no value was specified or an empty value, return the name of the annotation
* target.
*
* @param annotation parameter annotation
* @return the name of the parameter
*/
static String paramName(AnnotationInstance annotation) {
AnnotationValue value = annotation.value();
String valueString = null;
if (value != null) {
valueString = value.asString();
if (valueString.length() > 0) {
return valueString;
}
}
AnnotationTarget target = annotation.target();
switch (target.kind()) {
case FIELD:
valueString = target.asField().name();
break;
case METHOD_PARAMETER:
valueString = target.asMethodParameter().name();
break;
case METHOD:
// This is a bean property setter
MethodInfo method = target.asMethod();
if (method.parameters().size() == 1) {
String methodName = method.name();
if (methodName.startsWith("set")) {
valueString = Introspector.decapitalize(methodName.substring(3));
} else {
valueString = methodName;
}
}
break;
default:
break;
}
return valueString;
}
public boolean isIgnore(AnnotationTarget annotationTarget, DataObjectDeque.PathEntry pathEntry) {
for (IgnoreAnnotationHandler handler : IGNORE_ANNOTATION_MAP.values()) {
boolean result = handler.shouldIgnore(annotationTarget, pathEntry);
if (result) {
return true;
}
}
return false;
}
private static void enlistEmbeddedsAndElementCollections(IndexView index, JpaEntitiesBuildItem domainObjectCollector,
Set<String> enumTypeCollector, Set<String> javaTypeCollector, Set<DotName> unindexedClasses) {
Set<DotName> embeddedTypes = new HashSet<>();
for (DotName embeddedAnnotation : EMBEDDED_ANNOTATIONS) {
Collection<AnnotationInstance> annotations = index.getAnnotations(embeddedAnnotation);
for (AnnotationInstance annotation : annotations) {
AnnotationTarget target = annotation.target();
switch (target.kind()) {
case FIELD:
collectEmbeddedTypes(embeddedTypes, target.asField().type());
break;
case METHOD:
collectEmbeddedTypes(embeddedTypes, target.asMethod().returnType());
break;
default:
throw new IllegalStateException(
"[internal error] " + embeddedAnnotation + " placed on a unknown element: " + target);
}
}
}
for (DotName embeddedType : embeddedTypes) {
addClassHierarchyToReflectiveList(index, domainObjectCollector, enumTypeCollector, javaTypeCollector, embeddedType,
unindexedClasses);
}
}
/**
* Determines the type of the target. Method annotations will give
* the name of a single argument, assumed to be a "setter" method.
*
* @param target target object
* @return object type
*/
static Type getType(AnnotationTarget target) {
if (target == null) {
return null;
}
Type type = null;
switch (target.kind()) {
case FIELD:
type = target.asField().type();
break;
case METHOD:
List<Type> methodParams = target.asMethod().parameters();
if (methodParams.size() == 1) {
// This is a bean property setter
type = methodParams.get(0);
}
break;
case METHOD_PARAMETER:
type = getMethodParameterType(target.asMethodParameter());
break;
default:
break;
}
return type;
}
@Override
public boolean shouldIgnore(AnnotationTarget target, PathEntry parentPathEntry) {
AnnotationInstance annotationInstance = TypeUtil.getAnnotation(target, getName());
if (annotationInstance != null) {
return JandexUtil.booleanValue(annotationInstance, SchemaConstant.PROP_HIDDEN).orElse(false);
}
return false;
}
/**
* Meant to be called with instances of @Component, @Service, @Repository
*/
private String getBeanNameFromStereotypeInstance(AnnotationInstance annotationInstance) {
if (annotationInstance.target().kind() != AnnotationTarget.Kind.CLASS) {
throw new IllegalStateException(
"AnnotationInstance " + annotationInstance + " is an invalid target. Only Class targets are supported");
}
final AnnotationValue value = annotationInstance.value();
if ((value == null) || value.asString().isEmpty()) {
return getDefaultBeanNameFromClass(annotationInstance.target().asClass().name().toString());
} else {
return value.asString();
}
}
private boolean annotationTargetIsCamelApi(AnnotationTarget target) {
/**
* Verify whether an annotation is applied to org.apache.camel types. If the declaring class
* has the org.apache.camel package prefix, it is ignored since we are only interested in
* annotations declared within user classes.
*/
if (target != null) {
if (target.kind().equals(Kind.CLASS)) {
ClassInfo classInfo = target.asClass();
if (isCamelApi(classInfo.name())) {
return false;
}
Type superType = classInfo.superClassType();
if (superType != null && isCamelApi(superType.name())) {
return true;
}
return classInfo.interfaceNames().stream().anyMatch(interfaceName -> isCamelApi(interfaceName));
} else if (target.kind().equals(Kind.FIELD)) {
FieldInfo fieldInfo = target.asField();
return !isCamelApi(fieldInfo.declaringClass().name()) && isCamelApi(fieldInfo.type().name());
} else if (target.kind().equals(Kind.METHOD)) {
MethodInfo methodInfo = target.asMethod();
return !isCamelApi(methodInfo.declaringClass().name()) && isCamelApi(methodInfo.returnType().name());
}
}
return false;
}
/**
* Attempts to find a property with the specified name, ie. a public non-static non-synthetic field with the given name or a
* public non-static non-synthetic method with no params and the given name.
*
* @param name
* @param clazz
* @param index
* @return the property or null
*/
private AnnotationTarget findProperty(String name, ClassInfo clazz, IndexView index) {
while (clazz != null) {
// Fields
for (FieldInfo field : clazz.fields()) {
if (Modifier.isPublic(field.flags()) && !Modifier.isStatic(field.flags())
&& !ValueResolverGenerator.isSynthetic(field.flags()) && field.name().equals(name)) {
return field;
}
}
// Methods
for (MethodInfo method : clazz.methods()) {
if (Modifier.isPublic(method.flags()) && !Modifier.isStatic(method.flags())
&& !ValueResolverGenerator.isSynthetic(method.flags()) && (method.name().equals(name)
|| ValueResolverGenerator.getPropertyName(method.name()).equals(name))) {
return method;
}
}
DotName superName = clazz.superName();
if (superName == null) {
clazz = null;
} else {
clazz = index.getClassByName(clazz.superName());
}
}
return null;
}
/**
* Converts the collection of parameter annotations to properties set on the
* given schema.
*
* @param schema the {@link Schema} on which the properties will be set
* @param encodings map of encodings applicable to the current {@link MediaType} being processed
* @param params the name/value pairs of annotations for conversion to schema properties
*/
void setSchemaProperties(Schema schema,
Map<String, Encoding> encodings,
Map<String, AnnotationInstance> params) {
for (Entry<String, AnnotationInstance> param : params.entrySet()) {
String paramName = param.getKey();
AnnotationTarget paramTarget = param.getValue().target();
Type paramType = getType(paramTarget);
Schema paramSchema = SchemaFactory.typeToSchema(index, paramType, extensions);
Object defaultValue = getDefaultValue(paramTarget);
if (paramSchema.getDefaultValue() == null) {
paramSchema.setDefaultValue(defaultValue);
}
BeanValidationScanner.applyConstraints(paramTarget,
paramSchema,
paramName,
(target, name) -> {
List<String> requiredProperties = schema.getRequired();
if (requiredProperties == null || !requiredProperties.contains(name)) {
schema.addRequired(name);
}
});
if (paramSchema.getNullable() == null && TypeUtil.isOptional(paramType)) {
paramSchema.setNullable(Boolean.TRUE);
}
if (schema.getProperties() != null) {
paramSchema = mergeObjects(schema.getProperties().get(paramName), paramSchema);
}
schema.addProperty(paramName, paramSchema);
}
}