<commit_before>/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat Middleware LLC, and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * Licensed 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.
 */

package org.jboss.shrinkwrap.descriptor.metadata;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.TransformerException;

import org.jboss.shrinkwrap.descriptor.metadata.dom.DomWriter;
import org.jboss.shrinkwrap.descriptor.metadata.dtd.MetadataDtdEventListener;
import org.jboss.shrinkwrap.descriptor.metadata.xslt.XsltTransformer;
import org.w3c.dom.Document;
import org.w3c.dom.traversal.DocumentTraversal;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.traversal.TreeWalker;
import org.xml.sax.InputSource;

import com.sun.xml.dtdparser.DTDParser;

/**
 * This class is the entry point for parsing either xsd or dtd files, and based on the extracted metadata information,
 * the class is also able to produce Shrinkdesc API and implementation source code.
 * is parsed.
 * <p>
 * The class will start a DTD parsing when the files are ending with '.dtd'. Otherwise, the files are considered as XSD's. 
 *
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 */
public class MetadataParser
{
   private static final Logger log = Logger.getLogger(MetadataParser.class.getName());

   private final FilterChain filterChain = new FilterChain();
   
   private final Metadata metadata = new Metadata();

   private String pathToMetadata;

   public Metadata getMetadata()
   {
      return metadata;
   }

   /**
    * Parses one or more XSD schemas or DTD and produces java classes based on the parsing results.
    * @param path specifies where to create the interface, implementation and test case java classes.
    * @param confList list <code>MetadataParserConfiguration</code> objects.
    * @param verbose if true, additional parsing information are printed out, otherwise not.
    * @throws Exception 
    */
   @SuppressWarnings("unchecked")
public void parse(final MetadataParserPath path, final List<?> confList, final List<?> javadocTags, final boolean verbose) throws Exception
   {
	  checkArguments(path, confList);
	   
      pathToMetadata = createTempFile(verbose);
      
      if (log.isLoggable(Level.FINE)) {
          log.fine("Path to temporary metadata file: " + pathToMetadata);
      }

      for (int i = 0; i < confList.size(); i++)
      {
         final MetadataParserConfiguration metadataConf = (MetadataParserConfiguration) confList.get(i);

         metadata.setCurrentNamespace(metadataConf.getNameSpace());
         metadata.setCurrentSchmema(metadataConf.getPathToXsd());
         metadata.setCurrentPackageApi(metadataConf.getPackageApi());
         metadata.setCurrentPackageImpl(metadataConf.getPackageImpl());

         final MetadataDescriptor metadataDescriptor = new MetadataDescriptor(metadataConf.getDescriptorName());
         metadataDescriptor.setRootElementName(metadataConf.getElementName());
         metadataDescriptor.setRootElementType(metadataConf.getElementType());
         metadataDescriptor.setSchemaName(metadataConf.getPathToXsd());
         metadataDescriptor.setPackageApi(metadataConf.getPackageApi());
         metadataDescriptor.setPackageImpl(metadataConf.getPackageImpl());
         metadataDescriptor.setNamespace(metadataConf.getNameSpace());
         metadataDescriptor.setNamespaces(metadataConf.getNamespaces());
         metadataDescriptor.setGenerateClasses(metadataConf.generateClasses);
         metadata.getMetadataDescriptorList().add(metadataDescriptor);
         
         if(log.isLoggable(Level.FINE)){
             log.fine(metadataConf.getPathToXsd());
         }
         
         if (metadataConf.getPathToXsd().endsWith(".dtd"))
         {
            final InputSource in = new InputSource(new FileReader(metadataConf.getPathToXsd()));
            final MetadataDtdEventListener dtdEventListener = new MetadataDtdEventListener(metadata, verbose);
            final DTDParser parser = new DTDParser();
            parser.setDtdHandler(dtdEventListener);
            parser.parse(in);
         }
         else
         {
            final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            final DocumentBuilder loader = factory.newDocumentBuilder();
            final Document document = loader.parse(metadataConf.getPathToXsd());

            if(log.isLoggable(Level.FINE)){
                log.fine(document.getDocumentURI());
            }
            
            final DocumentTraversal traversal = (DocumentTraversal) document;
            final TreeWalker walker = traversal.createTreeWalker(document.getDocumentElement(),
                  NodeFilter.SHOW_ELEMENT, null, true);
            
            final StringBuilder sb = verbose ? new StringBuilder() : null;
            
            filterChain.traverseAndFilter(walker, "", metadata, sb);
            
            if(sb!=null){
                log.info(sb.toString());
            }
         }
      }

      /**
       * Analyze the data types defined in the elements. If an element data types points to a type defined in the data type
       * section, and the data type is simple type like xsd:string then change the element data type directly here.
       */
      metadata.preResolveDataTypes();

      if (pathToMetadata != null)
      {
         new DomWriter().write(metadata, pathToMetadata, (List<MetadataJavaDoc>)javadocTags);
      }

      if (verbose)
      {
         new MetadataUtil().log(metadata);
      }

      if (path.getPathToApi() != null && path.getPathToImpl() != null)
      {
         generateCode(path, verbose);
      }
   }

   /**
    * Generates source code by applying the <code>ddJavaAll.xsl</code> XSLT extracted from the resource stream.
    * @throws TransformerException
    */
   public void generateCode(final MetadataParserPath path, final boolean verbose) throws TransformerException
   {
      /** initialize the map which will overwrite global parameters as defined in metadata.xsl/ddJava.xsl */
      final Map<String, String> xsltParameters = new HashMap<String, String>();
      xsltParameters.put("gOutputFolder", path.getPathToImpl());
      xsltParameters.put("gOutputFolderApi", path.getPathToApi());
      xsltParameters.put("gOutputFolderTest", path.getPathToTest());
      xsltParameters.put("gOutputFolderService", path.getPathToServices());
      xsltParameters.put("gVerbose", Boolean.toString(verbose));

      final InputStream is = MetadataParser.class.getResourceAsStream("/META-INF/ddJavaAll.xsl");
      if(log.isLoggable(Level.FINE)){
          log.fine("Stream resource: " + is);
      }

      XsltTransformer.simpleTransform(pathToMetadata, is, new File("./tempddJava.xml"), xsltParameters);
   }

   /**
    * Returns the path and name of the generated metadata xml file, if configured to produce it and the <code>parse</code><commit_msg>[SHRINKDESC-137] Fix build under Windows<commit_after>/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat Middleware LLC, and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * Licensed 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.
 */

package org.jboss.shrinkwrap.descriptor.metadata;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.TransformerException;

import org.jboss.shrinkwrap.descriptor.metadata.dom.DomWriter;
import org.jboss.shrinkwrap.descriptor.metadata.dtd.MetadataDtdEventListener;
import org.jboss.shrinkwrap.descriptor.metadata.xslt.XsltTransformer;
import org.w3c.dom.Document;
import org.w3c.dom.traversal.DocumentTraversal;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.traversal.TreeWalker;
import org.xml.sax.InputSource;

import com.sun.xml.dtdparser.DTDParser;

/**
 * This class is the entry point for parsing either xsd or dtd files, and based on the extracted metadata information,
 * the class is also able to produce Shrinkdesc API and implementation source code.
 * is parsed.
 * <p>
 * The class will start a DTD parsing when the files are ending with '.dtd'. Otherwise, the files are considered as XSD's. 
 *
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 */
public class MetadataParser
{
   private static final Logger log = Logger.getLogger(MetadataParser.class.getName());

   private final FilterChain filterChain = new FilterChain();
   
   private final Metadata metadata = new Metadata();

   private String pathToMetadata;

   public Metadata getMetadata()
   {
      return metadata;
   }

   /**
    * Parses one or more XSD schemas or DTD and produces java classes based on the parsing results.
    * @param path specifies where to create the interface, implementation and test case java classes.
    * @param confList list <code>MetadataParserConfiguration</code> objects.
    * @param verbose if true, additional parsing information are printed out, otherwise not.
    * @throws Exception 
    */
   @SuppressWarnings("unchecked")
public void parse(final MetadataParserPath path, final List<?> confList, final List<?> javadocTags, final boolean verbose) throws Exception
   {
	  checkArguments(path, confList);
	   
      pathToMetadata = createTempFile(verbose);
      
      if (log.isLoggable(Level.FINE)) {
          log.fine("Path to temporary metadata file: " + pathToMetadata);
      }

      for (int i = 0; i < confList.size(); i++)
      {
         final MetadataParserConfiguration metadataConf = (MetadataParserConfiguration) confList.get(i);

         metadata.setCurrentNamespace(metadataConf.getNameSpace());
         metadata.setCurrentSchmema(metadataConf.getPathToXsd());
         metadata.setCurrentPackageApi(metadataConf.getPackageApi());
         metadata.setCurrentPackageImpl(metadataConf.getPackageImpl());

         final MetadataDescriptor metadataDescriptor = new MetadataDescriptor(metadataConf.getDescriptorName());
         metadataDescriptor.setRootElementName(metadataConf.getElementName());
         metadataDescriptor.setRootElementType(metadataConf.getElementType());
         metadataDescriptor.setSchemaName(metadataConf.getPathToXsd());
         metadataDescriptor.setPackageApi(metadataConf.getPackageApi());
         metadataDescriptor.setPackageImpl(metadataConf.getPackageImpl());
         metadataDescriptor.setNamespace(metadataConf.getNameSpace());
         metadataDescriptor.setNamespaces(metadataConf.getNamespaces());
         metadataDescriptor.setGenerateClasses(metadataConf.generateClasses);
         metadata.getMetadataDescriptorList().add(metadataDescriptor);
         
         if(log.isLoggable(Level.FINE)){
             log.fine(metadataConf.getPathToXsd());
         }
         
         if (metadataConf.getPathToXsd().endsWith(".dtd"))
         {
            final InputSource in = new InputSource(new FileReader(metadataConf.getPathToXsd()));
            final MetadataDtdEventListener dtdEventListener = new MetadataDtdEventListener(metadata, verbose);
            final DTDParser parser = new DTDParser();
            parser.setDtdHandler(dtdEventListener);
            parser.parse(in);
         }
         else
         {
            final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            final DocumentBuilder loader = factory.newDocumentBuilder();
            final Document document = loader.parse(metadataConf.getPathToXsd());

            if(log.isLoggable(Level.FINE)){
                log.fine(document.getDocumentURI());
            }
            
            final DocumentTraversal traversal = (DocumentTraversal) document;
            final TreeWalker walker = traversal.createTreeWalker(document.getDocumentElement(),
                  NodeFilter.SHOW_ELEMENT, null, true);
            
            final StringBuilder sb = verbose ? new StringBuilder() : null;
            
            filterChain.traverseAndFilter(walker, "", metadata, sb);
            
            if(sb!=null){
                log.info(sb.toString());
            }
         }
      }

      /**
       * Analyze the data types defined in the elements. If an element data types points to a type defined in the data type
       * section, and the data type is simple type like xsd:string then change the element data type directly here.
       */
      metadata.preResolveDataTypes();

      if (pathToMetadata != null)
      {
         new DomWriter().write(metadata, pathToMetadata, (List<MetadataJavaDoc>)javadocTags);
      }

      if (verbose)
      {
         new MetadataUtil().log(metadata);
      }

      if (path.getPathToApi() != null && path.getPathToImpl() != null)
      {
         generateCode(path, verbose);
      }
   }

   /**
    * Generates source code by applying the <code>ddJavaAll.xsl</code> XSLT extracted from the resource stream.
    * @throws TransformerException
    */
   public void generateCode(final MetadataParserPath path, final boolean verbose) throws TransformerException
   {
      /** initialize the map which will overwrite global parameters as defined in metadata.xsl/ddJava.xsl */
      final Map<String, String> xsltParameters = new HashMap<String, String>();
      xsltParameters.put("gOutputFolder", getURIPath(path.getPathToImpl()) );
      xsltParameters.put("gOutputFolderApi", getURIPath(path.getPathToApi()));
      xsltParameters.put("gOutputFolderTest", getURIPath(path.getPathToTest()));
      xsltParameters.put("gOutputFolderService", getURIPath(path.getPathToServices()));
      xsltParameters.put("gVerbose", Boolean.toString(verbose));

      final InputStream is = MetadataParser.class.getResourceAsStream("/META-INF/ddJavaAll.xsl");
      if(log.isLoggable(Level.FINE)){
          log.fine("Stream resource: " + is);
      }

      XsltTransformer.simpleTransform(pathToMetadata, is, new File("./tempddJava.xml"), xsltParameters);
   }

    private String getURIPath(final String path) {
        if(path != null) {
            return new File(path).toURI().getPath();
        }
        else {
            return "";
        }
    }

   /**
    * Returns the path and name of the generated metadata xml file, if configured to produce it and the <code>parse</code>
{'fraction_non_alphanumeric': 0.09400150905432596, 'fraction_numerical': 0.001823440643863179, 'mean_word_length': 3.3173181324647123, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 14}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3877522', 'n_tokens_mistral': 4252, 'n_tokens_neox': 4094, 'n_words': 1135}