@SuppressWarnings("unchecked")
public Object transform(Object response, TransformationContext context) {
try {
DataType<List<DataType>> sourceType = context.getSourceDataType();
Operation sourceOp = context.getSourceOperation();
boolean sourceWrapped = sourceOp != null && sourceOp.isWrapperStyle() && sourceOp.getWrapper() != null;
boolean sourceNotSubjectToWrapping = sourceOp != null && sourceOp.isNotSubjectToWrapping();
WrapperHandler sourceWrapperHandler = null;
String sourceDataBinding = getDataBinding(sourceOp);
sourceWrapperHandler = getWrapperHandler(sourceDataBinding, sourceWrapped);
DataType<List<DataType>> targetType = context.getTargetDataType();
Operation targetOp = (Operation)context.getTargetOperation();
boolean targetWrapped = targetOp != null && targetOp.isWrapperStyle() && targetOp.getWrapper() != null;
boolean targetNotSubjectToWrapping = targetOp != null && targetOp.isNotSubjectToWrapping();
WrapperHandler targetWrapperHandler = null;
String targetDataBinding = getDataBinding(targetOp);
targetWrapperHandler = getWrapperHandler(targetDataBinding, targetWrapped);
if ((!sourceWrapped &&!sourceNotSubjectToWrapping) && targetWrapped) {
// Unwrapped --> Wrapped
WrapperInfo wrapper = targetOp.getWrapper();
ElementInfo wrapperElement = wrapper.getOutputWrapperElement();
List<ElementInfo> childElements = wrapper.getOutputChildElements();
Class<?> targetWrapperClass = wrapper != null ? wrapper.getOutputWrapperClass() : null;
Object[] outputs = null;
if ( !sourceOp.hasArrayWrappedOutput() ) {
outputs = new Object[] {response};
} else {
outputs = (Object[])response;
}
// If the source can be wrapped, wrapped it first
if (sourceWrapperHandler != null) {
WrapperInfo sourceWrapperInfo = sourceOp.getWrapper();
DataType sourceWrapperType =
sourceWrapperInfo != null ? sourceWrapperInfo.getOutputWrapperType() : null;
if (sourceWrapperType != null && matches(sourceOp.getWrapper(), targetOp.getWrapper())) {
Class<?> sourceWrapperClass = sourceWrapperType.getPhysical();
Object sourceWrapper = sourceWrapperHandler.create(sourceOp, false);
if (sourceWrapper != null) {
if (!childElements.isEmpty()) {
// Set the return value
sourceWrapperHandler.setChildren(sourceWrapper,
outputs,
sourceOp,
false);
}
Object targetWrapper =
mediator.mediate(sourceWrapper, sourceWrapperType, targetType.getLogical().get(0), context
.getMetadata());
return targetWrapper;
}
}
}
Object targetWrapper = targetWrapperHandler.create(targetOp, false);
if (childElements.isEmpty()) {
// void output
return targetWrapper;
}
// No source wrapper, so we want to transform the child and then wrap the child-level target with the
// target wrapper handler.
Object[] targetChildren = new Object[outputs.length];
for (int i = 0; i < outputs.length; i++) {
DataType<XMLType> targetOutputType = wrapper.getUnwrappedOutputType().getLogical().get(i);
targetChildren[i] =
mediator.mediate(outputs[i], sourceType.getLogical().get(i), targetOutputType, context.getMetadata());
}
targetWrapperHandler.setChildren(targetWrapper,
targetChildren,
targetOp,
false);
return targetWrapper;
} else if (sourceWrapped && (!targetWrapped && !targetNotSubjectToWrapping)) {
// Wrapped to Unwrapped
Object sourceWrapper = response;
List<ElementInfo> childElements = sourceOp.getWrapper().getOutputChildElements();
if (childElements.isEmpty()) {
// The void output
return null;
}
if (targetWrapperHandler != null) {
ElementInfo wrapperElement = sourceOp.getWrapper().getOutputWrapperElement();
// FIXME: This is a workaround for the wsdless support as it passes in child elements
// under the wrapper that only matches by position
if (sourceWrapperHandler.isInstance(sourceWrapper, sourceOp, false)) {
WrapperInfo targetWrapperInfo = targetOp.getWrapper();
DataType targetWrapperType =
targetWrapperInfo != null ? targetWrapperInfo.getOutputWrapperType() : null;
if (targetWrapperType != null && matches(sourceOp.getWrapper(), targetOp.getWrapper())) {
Object targetWrapper =
mediator.mediate(sourceWrapper, sourceType.getLogical().get(0), targetWrapperType, context
.getMetadata());
List targetChildren = targetWrapperHandler.getChildren(targetWrapper, targetOp, false);
if (targetOp.hasArrayWrappedOutput()) {
return targetChildren.toArray();
} else {
return targetChildren.get(0);
}
}
}
}
// Otherwise we need to unwrap on the source side, and then transform each child
Object[] sourceChildren = sourceWrapperHandler.getChildren(sourceWrapper, sourceOp, false).toArray();
Object[] target = new Object[sourceChildren.length];
for (int i = 0; i < sourceChildren.length; i++) {
DataType<XMLType> childType = sourceOp.getWrapper().getUnwrappedOutputType().getLogical().get(i);
target[i] =
mediator.mediate(sourceChildren[i], childType, targetType.getLogical().get(i), context
.getMetadata());
}
if (targetOp.hasArrayWrappedOutput()) {
return target;
} else {
if (target.length > 1 ) {
throw new IllegalStateException("Expecting only one output based on Operation model, found: " +
target.length + " # of outputs.");
}
return target[0];
}
} else {
Object[] outputs = null;
if ( !sourceOp.hasArrayWrappedOutput() ) {
outputs = new Object[] {response};
} else {
outputs = (Object[])response;
}
Object[] target = new Object[outputs.length];
for (int i = 0; i < outputs.length; i++) {
Object child =
mediator.mediate(outputs[i], sourceType.getLogical().get(i), targetType.getLogical().get(i), context
.getMetadata());
target[i] = child;
}
if (targetOp.hasArrayWrappedOutput()) {
return target;
} else {
if (target.length > 1 ) {
throw new IllegalStateException("Expecting only one output based on Operation model, found: " +
target.length + " # of outputs.");