/** Builds the XML Schema tree into memory. */
  public void parse() {
    try {

      File file = new File(fileName);

      XSOMParser schemaParser = new XSOMParser();
      schemaParser.parse(file);
      XSSchemaSet schemaSet = schemaParser.getResult();
      XSSchema schema = schemaSet.getSchema(1);

      this.createResult(schema);

    } catch (SAXException | IOException ex) {
      Logger.getLogger(SchemaParser.class.getName()).log(Level.SEVERE, null, ex);
    }
  }
    /**
     * Performs schema compilation and prints the status/error into the
     * specified PrintStream.
     *
     * <p>
     * This method could be used to trigger XJC from other tools,
     * such as Ant or IDE.
     *
     * @param    args
     *        specified command line parameters. If there is an error
     *        in the parameters, {@link BadCommandLineException} will
     *        be thrown.
     * @param    listener
     *      Receives messages from XJC reporting progress/errors.
     *
     * @return
     *      If the compiler runs successfully, this method returns 0.
     *      All non-zero values indicate an error. The error message
     *      will be sent to the specified PrintStream.
     */
    public static int run(String[] args, @NotNull final XJCListener listener) throws BadCommandLineException {

        // recognize those special options before we start parsing options.
        for (String arg : args) {
            if (arg.equals("-version")) {
                listener.message(Messages.format(Messages.VERSION));
                return -1;
            }
        }

        final OptionsEx opt = new OptionsEx();
        opt.setSchemaLanguage(Language.XMLSCHEMA);  // disable auto-guessing
        try {
            opt.parseArguments(args);
        } catch (WeAreDone _) {
            return -1;
        } catch(BadCommandLineException e) {
            e.initOptions(opt);
            throw e;
        }

        // display a warning if the user specified the default package
        // this should work, but is generally a bad idea
        if(opt.defaultPackage != null && opt.defaultPackage.length()==0) {
            listener.message(Messages.format(Messages.WARNING_MSG, Messages.format(Messages.DEFAULT_PACKAGE_WARNING)));
        }


        // set up the context class loader so that the user-specified classes
        // can be loaded from there
        final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(
            opt.getUserClassLoader(contextClassLoader));

        // parse a grammar file
        //-----------------------------------------
        try {
            if( !opt.quiet ) {
                listener.message(Messages.format(Messages.PARSING_SCHEMA));
            }

            final boolean[] hadWarning = new boolean[1];

            ErrorReceiver receiver = new ErrorReceiverFilter(listener) {
                public void info(SAXParseException exception) {
                    if(opt.verbose)
                        super.info(exception);
                }
                public void warning(SAXParseException exception) {
                    hadWarning[0] = true;
                    if(!opt.quiet)
                        super.warning(exception);
                }
                @Override
                public void pollAbort() throws AbortException {
                    if(listener.isCanceled())
                        throw new AbortException();
                }
            };

            if( opt.mode==Mode.FOREST ) {
                // dump DOM forest and quit
                ModelLoader loader  = new ModelLoader( opt, new JCodeModel(), receiver );
                try {
                    DOMForest forest = loader.buildDOMForest(new XMLSchemaInternalizationLogic());
                    forest.dump(System.out);
                    return 0;
                } catch (SAXException e) {
                    // the error should have already been reported
                } catch (IOException e) {
                    receiver.error(e);
                }

                return -1;
            }

            if( opt.mode==Mode.GBIND ) {
                try {
                    XSSchemaSet xss = new ModelLoader(opt, new JCodeModel(), receiver).loadXMLSchema();
                    Iterator<XSComplexType> it = xss.iterateComplexTypes();
                    while (it.hasNext()) {
                        XSComplexType ct =  it.next();
                        XSParticle p = ct.getContentType().asParticle();
                        if(p==null)     continue;

                        Expression tree = ExpressionBuilder.createTree(p);
                        System.out.println("Graph for "+ct.getName());
                        System.out.println(tree.toString());
                        Graph g = new Graph(tree);
                        System.out.println(g.toString());
                        System.out.println();
                    }
                    return 0;
                } catch (SAXException e) {
                    // the error should have already been reported
                }
                return -1;
            }
            
            Model model = ModelLoader.load( opt, new JCodeModel(), receiver );

            if (model == null) {
                listener.message(Messages.format(Messages.PARSE_FAILED));
                return -1;
            }

            if( !opt.quiet ) {
                listener.message(Messages.format(Messages.COMPILING_SCHEMA));
            }

            switch (opt.mode) {
            case SIGNATURE :
                try {
                    SignatureWriter.write(
                        BeanGenerator.generate(model,receiver),
                        new OutputStreamWriter(System.out));
                    return 0;
                } catch (IOException e) {
                    receiver.error(e);
                    return -1;
                }

            case CODE :
            case DRYRUN :
            case ZIP :
                {
                    // generate actual code
                    receiver.debug("generating code");
                    {// don't want to hold outline in memory for too long.
                        Outline outline = model.generateCode(opt,receiver);
                        if(outline==null) {
                            listener.message(
                                Messages.format(Messages.FAILED_TO_GENERATE_CODE));
                            return -1;
                        }

                        listener.compiled(outline);
                    }

                    if( opt.mode == Mode.DRYRUN )
                        break;  // enough

                    // then print them out
                    try {
                        CodeWriter cw;
                        if( opt.mode==Mode.ZIP ) {
                            OutputStream os;
                            if(opt.targetDir.getPath().equals("."))
                                os = System.out;
                            else
                                os = new FileOutputStream(opt.targetDir);

                            cw = opt.createCodeWriter(new ZipCodeWriter(os));
                        } else
                            cw = opt.createCodeWriter();

                        if( !opt.quiet ) {
                            cw = new ProgressCodeWriter(cw,listener, model.codeModel.countArtifacts());
                        }
                        model.codeModel.build(cw);
                    } catch (IOException e) {
                        receiver.error(e);
                        return -1;
                    }

                    break;
                }
            default :
                assert false;
            }

            if(opt.debugMode) {
                try {
                    new FileOutputStream(new File(opt.targetDir,hadWarning[0]?"hadWarning":"noWarning")).close();
                } catch (IOException e) {
                    receiver.error(e);
                    return -1;
                }
            }

            return 0;
        } catch( StackOverflowError e ) {
            if(opt.verbose)
                // in the debug mode, propagate the error so that
                // the full stack trace will be dumped to the screen.
                throw e;
            else {
                // otherwise just print a suggested workaround and
                // quit without filling the user's screen
                listener.message(Messages.format(Messages.STACK_OVERFLOW));
                return -1;
            }
        }
    }