/**
   * Process the root WADL file and generate code.
   *
   * @param rootDesc the URI of the WADL file to process
   * @throws javax.xml.bind.JAXBException if the WADL file is invalid, a referenced WADL file is
   *     invalid, or if the code generator encounters a problem.
   * @throws java.io.IOException if the specified WADL file cannot be read.
   * @throws com.sun.codemodel.JClassAlreadyExistsException if, during code generation, the WADL
   *     processor attempts to create a duplicate class. This indicates a structural problem with
   *     the WADL file, e.g. duplicate peer resource entries.
   */
  public void process(URI rootDesc)
      throws JAXBException, IOException, JClassAlreadyExistsException {
    // read in root WADL file
    JAXBContext jbc =
        JAXBContext.newInstance("org.jvnet.ws.wadl", this.getClass().getClassLoader());
    u = jbc.createUnmarshaller();
    s2j = new SchemaCompilerImpl();
    errorListener = new SchemaCompilerErrorListener();
    if (!autoPackage) s2j.setDefaultPackageName(pkg);
    s2j.setErrorListener(errorListener);
    idMap = new HashMap<String, Object>();
    ifaceMap = new HashMap<String, ResourceTypeNode>();
    Application a = processDescription(rootDesc);
    ResourceNode r = buildAst(a, rootDesc);

    // generate code
    s2jModel = s2j.bind();
    if (s2jModel != null) {
      codeModel = s2jModel.generateCode(null, errorListener);
      Iterator<JPackage> packages = codeModel.packages();
      StringBuilder buf = new StringBuilder();
      while (packages.hasNext()) {
        JPackage genPkg = packages.next();
        if (!genPkg.isDefined("ObjectFactory")) continue;
        if (buf.length() > 0) buf.append(':');
        buf.append(genPkg.name());
      }
      generatedPackages = buf.toString();
      jPkg = codeModel._package(pkg);
      generateResourceTypeInterfaces();
      generateEndpointClass(r);
      codeModel.build(outputDir);
    }
  }
  private static void processPacket(
      PacketType packet, JPackage dirPackage, JCodeModel codeModel, boolean fromClient)
      throws JClassAlreadyExistsException {
    // get the packet info
    String packetName =
        (packet.getInfo() == null || packet.getInfo().getName() == null)
            ? "Unknown"
            : packet.getInfo().getName();
    String packetNamePrefixed = "P" + String.format("%03d", packet.getHeader()) + "_" + packetName;
    String packetDescription =
        (packet.getInfo() == null
                || packet.getInfo().getDescription() == null
                || packet.getInfo().getDescription().isEmpty())
            ? ""
            : "\n" + WordUtils.wrap(packet.getInfo().getDescription(), /* maximumLength */ 50);

    JDefinedClass packetClass =
        dirPackage._class(JMod.FINAL | JMod.PUBLIC, packetNamePrefixed)._extends(GWMessage.class);

    LOGGER.info("+-Processing packet: {}", packetNamePrefixed);
    LOGGER.debug("|+-Packet description: {}", packetDescription);

    StringBuilder packetJavadoc =
        new StringBuilder("Auto-generated by PacketCodeGen.").append(packetDescription);

    JDocComment jDocComment = packetClass.javadoc();
    jDocComment.add(packetJavadoc.toString());

    AtomicInteger numberOfUnknowns = new AtomicInteger(); // unknown field number

    // get all fields in this packet
    for (FieldType field : packet.getField()) {
      processField(field, packetClass, codeModel, numberOfUnknowns, fromClient);
    }

    // generate the header method
    JMethod headerMeth = packetClass.method(JMod.PUBLIC, short.class, "getHeader");
    headerMeth.annotate(Override.class);
    headerMeth.body()._return(JExpr.lit(packet.getHeader().intValue()));

    // generate getters, setters
    for (JFieldVar fieldVar : packetClass.fields().values()) {
      processAccessors(fieldVar, packetClass, fromClient);
    }

    // generate the toString method
    processToString(packetClass, codeModel);
  }