List<AttachmentScanResult> scanResult = ReflectiveAttachmentRefScanner.scanMethod(method);
Class[] parameterTypes = method.getParameterTypes();
Type[] genericTypes = method.getGenericParameterTypes();
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
ParameterMetaData wrapperParameter = null, wrapperOutputParameter = null;
List<WrappedParameter> wrappedParameters = null, wrappedOutputParameters = null;
// Force paramter style to wrapped
if (method.isAnnotationPresent(RequestWrapper.class) || method.isAnnotationPresent(ResponseWrapper.class))
{
epMetaData.setParameterStyle(ParameterStyle.WRAPPED);
}
if (opMetaData.isDocumentWrapped())
{
wrapperParameter = createRequestWrapper(opMetaData, method);
wrappedParameters = new ArrayList<WrappedParameter>(parameterTypes.length);
wrapperParameter.setWrappedParameters(wrappedParameters);
if (!opMetaData.isOneWay())
{
wrapperOutputParameter = createResponseWrapper(opMetaData, method);
wrappedOutputParameters = new ArrayList<WrappedParameter>(parameterTypes.length + 1);
wrapperOutputParameter.setWrappedParameters(wrappedOutputParameters);
}
}
for (int i = 0; i < parameterTypes.length; i++)
{
Class javaType = parameterTypes[i];
Type genericType = genericTypes[i];
String javaTypeName = javaType.getName();
WebParam anWebParam = getWebParamAnnotation(method, i);
boolean isHeader = anWebParam != null && anWebParam.header();
boolean isWrapped = opMetaData.isDocumentWrapped() && !isHeader;
ParameterMode mode = getParameterMode(anWebParam, javaType);
// Assert one-way
if (opMetaData.isOneWay() && mode != ParameterMode.IN)
throw new IllegalArgumentException("A one-way operation can not have output parameters [" + "method = " + method.getName() + ", parameter = " + i + "]");
if (HolderUtils.isHolderType(javaType))
{
genericType = HolderUtils.getGenericValueType(genericType);
javaType = JavaUtils.erasure(genericType);
javaTypeName = javaType.getName();
}
if (isWrapped)
{
QName wrappedElementName = getWebParamName(opMetaData, i, anWebParam);
String variable = convertToVariable(wrappedElementName.getLocalPart());
WrappedParameter wrappedParameter = new WrappedParameter(wrappedElementName, javaTypeName, variable, i);
wrappedParameter.setTypeArguments(convertTypeArguments(javaType, genericType));
if (mode != ParameterMode.OUT)
wrappedParameters.add(wrappedParameter);
if (mode != ParameterMode.IN)
{
wrappedParameter.setHolder(true);
// WrappedParameters can not be shared between request/response objects (accessors)
if (mode == ParameterMode.INOUT)
wrappedParameter = new WrappedParameter(wrappedParameter);
wrappedOutputParameters.add(wrappedParameter);
}
processAttachmentAnnotationsWrapped(scanResult, i, wrappedParameter);
}
else
{
QName xmlName = getWebParamName(opMetaData, i, anWebParam);
ParameterMetaData paramMetaData = new ParameterMetaData(opMetaData, xmlName, javaTypeName);
paramMetaData.setInHeader(isHeader);
paramMetaData.setIndex(i);
paramMetaData.setMode(mode);
/*
* Note: The TCK enforces the following rule in the spec regarding
* partName: "This is only used if the operation is rpc style or if
* the operation is document style and the parameter style is BARE."
*
* This seems to be a flaw in the spec, because the intention is
* obviously to prevent the ambiguity of wrapped parameters that
* specify different partName values. There is, however, no reason
* that this limitation should apply to header parameters since they
* are never wrapped. In order to comply we adhere to this confusing
* rule, although I will ask for clarification.
*/
if (anWebParam != null && !opMetaData.isDocumentWrapped() && anWebParam.partName().length() > 0)
paramMetaData.setPartName(anWebParam.partName());
opMetaData.addParameter(paramMetaData);
javaTypes.add(javaType);
typeRefs.add(new TypeReference(xmlName, genericType, parameterAnnotations[i]));
processAttachmentAnnotations(scanResult, i, paramMetaData);
processMIMEBinding(epMetaData, opMetaData, paramMetaData);
}
}
// Build result meta data
Class returnType = method.getReturnType();
Type genericReturnType = method.getGenericReturnType();
String returnTypeName = returnType.getName();
if (!(returnType == void.class))
{
if (opMetaData.isOneWay())
throw new IllegalArgumentException("[JSR-181 2.5.1] The method '" + method.getName() + "' can not have a return value if it is marked OneWay");
WebResult anWebResult = method.getAnnotation(WebResult.class);
boolean isHeader = anWebResult != null && anWebResult.header();
boolean isWrappedBody = opMetaData.isDocumentWrapped() && !isHeader;
QName xmlName = getWebResultName(opMetaData, anWebResult);
if (isWrappedBody)
{
WrappedParameter wrapped = new WrappedParameter(xmlName, returnTypeName, convertToVariable(xmlName.getLocalPart()), -1);
wrapped.setTypeArguments(convertTypeArguments(returnType, genericReturnType));
// insert at the beginning just for prettiness
wrappedOutputParameters.add(0, wrapped);
processAttachmentAnnotationsWrapped(scanResult, -1, wrapped);
}
else
{
ParameterMetaData retMetaData = new ParameterMetaData(opMetaData, xmlName, returnTypeName);
retMetaData.setInHeader(isHeader);
retMetaData.setIndex(-1);
retMetaData.setMode(ParameterMode.OUT);
// Special case: If we have a document/literal wrapped message, then
// the return metadata must be the wrapper type that is sent in the
// body. So, in order to handle headers that are mapped to the java
// return value, we have to add them to a parameter with an index of
// -1 to signify the return value. All other binding styles use the
// expected return value mechanism.
if (opMetaData.isDocumentWrapped())
{
opMetaData.addParameter(retMetaData);
}
else
{
// See above comment in the parameter for loop section as to why
// we prevent customization of part names on document wrapped
// header parameters.
if (anWebResult != null && anWebResult.partName().length() > 0)
retMetaData.setPartName(anWebResult.partName());
opMetaData.setReturnParameter(retMetaData);
}
javaTypes.add(returnType);