class SoapCallFactory {

  @SuppressWarnings("unchecked")
  public OMElement createCall(String sessionId, String methodPath, Object arg) {
    OMElement method = fac.createOMElement(CORE_CALL, mag);

    // Register XML namespaces in method
    method.declareNamespace(soapEnc);
    method.declareNamespace(soapXml);
    method.declareNamespace(xsi);
    method.declareNamespace(xsd);

    OMElement paramSession = fac.createOMElement(SESSION_ID, noNs);
    paramSession.addChild(fac.createOMText(paramSession, sessionId));
    method.addChild(paramSession);

    OMElement resourcePath = fac.createOMElement(RESOURCE_PATH, noNs);
    resourcePath.addChild(fac.createOMText(resourcePath, methodPath));
    method.addChild(resourcePath);

    OMElement paramArgs;
    if (arg instanceof Iterable) {
      Iterable<Object> args = (Iterable<Object>) arg;
      paramArgs = fac.createOMElement(ARGUMENTS, noNs);
      paramArgs.addAttribute("arrayType", xsd.getPrefix() + ":ur-type[" + Iterables.size(args) + "]", soapEnc);
      paramArgs.addAttribute("type", soapEnc.getPrefix() + ":Array", xsi);

      for (Object argument : args) {
        paramArgs.addChild(typedElement(noNs, "item", argument));
      }
    } else if (arg instanceof Map) {
      Map<String, Object> args = (Map<String, Object>) arg;
      paramArgs = typedElement(noNs, ARGUMENTS, arg);
      paramArgs.addAttribute("arrayType", xsd.getPrefix() + ":Map[" + args.size() + "]", soapEnc);
      paramArgs.addAttribute("type", soapEnc.getPrefix() + ":Array", xsi);
    } else if (arg != null && (arg.getClass().isArray() || arg.getClass().getName().equals("sun.org.mozilla.javascript.internal.NativeArray"))) {
      Object[] args = (Object[]) arg;
      paramArgs = fac.createOMElement(ARGUMENTS, noNs);
      paramArgs.addAttribute("arrayType", xsd.getPrefix() + ":ur-type[" + args.length + "]", soapEnc);
      paramArgs.addAttribute("type", soapEnc.getPrefix() + ":Array", xsi);

      for (Object argument : args) {
        paramArgs.addChild(typedElement(noNs, "item", argument));
      }
    } else {
      paramArgs = typedElement(noNs, ARGUMENTS, arg);
    }
    method.addChild(paramArgs);

    return method;
  }

}

class SoapCallFactoryTest {

  private final static Logger log;
  private SoapCallFactory soapCallFactory;

  @Test
  @Ignore("Assertion failing")
  public void createCallProductUpdatePrice() throws ScriptException {

    ImmutableList<ProductUpdatePrice> products = ImmutableList.of(new ProductUpdatePrice("ajah_a", new BigDecimal(500000), new BigDecimal(600000)),
        new ProductUpdatePrice("zibalabel_b_06", new BigDecimal(500000), new BigDecimal(600000)));
    OMElement element = soapCallFactory.createCall("abc", ResourcePath.ProductUpdatePrice.getPath(), new Object[] { products });
    log.info("createCallProductUpdatePrice {}", element);
    assertNotNull(element);
    assertEquals(1, Iterators.size(element.getChildElements()));
  }

}