// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
import javax.xml.transform.*;
import java.io.*;
public class XmlToHtmlConverter extends XmlToHtmlConverterData {
    // To turn off generation of API docs for certain roles, comment out
    public static void main(String[] args) {
        XmlToHtmlConverter x = new XmlToHtmlConverter();
        x.populateForRootAdmin();
        x.populateForDomainAdmin();
        x.populateForUser();
        x.generateToc();
        x.generateIndividualCommandPages();
    }
    public void generateToc() {
        try {
            TransformerFactory tFactory = TransformerFactory.newInstance();
            // Generate the TOC for the API reference for User role
            Transformer transformer =
              tFactory.newTransformer
                 (new javax.xml.transform.stream.StreamSource
                    ("generatetocforuser.xsl"));
            // Modify this path to match your own setup.
            transformer.transform
              (new javax.xml.transform.stream.StreamSource
                    ("regular_user/regularUserSummary.xml"),
               new javax.xml.transform.stream.StreamResult
                    ( new FileOutputStream("html/TOC_User.html")));
            // Generate the TOC for root administrator role
            Transformer transformer1 =
              tFactory.newTransformer
                 (new javax.xml.transform.stream.StreamSource
                    ("generatetocforadmin.xsl"));
            // Modify this path to match your own setup.
            transformer1.transform
              (new javax.xml.transform.stream.StreamSource
                    ("root_admin/rootAdminSummary.xml"),
            // Modify this path to your own desired output location.
               new javax.xml.transform.stream.StreamResult
                    ( new FileOutputStream("html/TOC_Root_Admin.html")));
            // Generate the TOC for domain admin role
            Transformer transformer2 =
              tFactory.newTransformer
                 (new javax.xml.transform.stream.StreamSource
                    ("generatetocfordomainadmin.xsl"));

            // The XML to be transformed must be at the location below.
            // Modify this path to match your own setup.
            transformer2.transform
              (new javax.xml.transform.stream.StreamSource
                    ("domain_admin/domainAdminSummary.xml"),
            // Modify this path to your own desired output location.
               new javax.xml.transform.stream.StreamResult
                    ( new FileOutputStream("html/TOC_Domain_Admin.html")));

        }
        catch (Exception e) {
            e.printStackTrace( );
        }
    }

    // Create man pages
    public void generateIndividualCommandPages() {
        for(String commandName : rootAdminCommandNames) {

                try {

                    TransformerFactory tFactory = TransformerFactory.newInstance();
                    Transformer transformer =
                      tFactory.newTransformer
                         (new javax.xml.transform.stream.StreamSource
                            ("generateadmincommands.xsl"));

                    transformer.transform
                    // Modify this path to the location of the input files on your system.
                      (new javax.xml.transform.stream.StreamSource
                            ("root_admin/"+commandName+".xml"),
                    // Modify this path with the desired output location.
                       new javax.xml.transform.stream.StreamResult
                            ( new FileOutputStream("html/root_admin/"+commandName+".html")));
                } catch (Exception e) {
                    e.printStackTrace( );
                }
        }

        for(String commandName : domainAdminCommandNames) {

            try {

                TransformerFactory tFactory = TransformerFactory.newInstance();
                Transformer transformer =
                  tFactory.newTransformer
                     (new javax.xml.transform.stream.StreamSource
                        ("generatedomainadmincommands.xsl"));

                transformer.transform
                // Modify this path with the location of the input files on your system.
                  (new javax.xml.transform.stream.StreamSource
                        ("domain_admin/"+commandName+".xml"),
                // Modify this path to the desired output location.
                   new javax.xml.transform.stream.StreamResult
                        ( new FileOutputStream("html/domain_admin/"+commandName+".html")));
            } catch (Exception e) {
                e.printStackTrace( );
            }
        }

        for(String commandName : userCommandNames) {

            try {

                TransformerFactory tFactory = TransformerFactory.newInstance();

                Transformer transformer =
                  tFactory.newTransformer
                     (new javax.xml.transform.stream.StreamSource
                        ("generateusercommands.xsl"));

                transformer.transform
                  (new javax.xml.transform.stream.StreamSource
                        ("regular_user/"+commandName+".xml"),
                   new javax.xml.transform.stream.StreamResult
                        ( new FileOutputStream("html/user/"+commandName+".html")));
            } catch (Exception e) {
                e.printStackTrace( );
            }
        }
    }
}
