content: /*****************************************************************
   *   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
   *
   *    https://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.apache.cayenne.gen.xml;
  
  import java.net.URISyntaxException;
  import java.net.URL;
  import java.nio.file.Files;
  import java.nio.file.Path;
  import java.nio.file.Paths;
  
  import org.apache.cayenne.CayenneRuntimeException;
  import org.apache.cayenne.configuration.xml.DataChannelMetaData;
  import org.apache.cayenne.configuration.xml.NamespaceAwareNestedTagHandler;
  import org.apache.cayenne.gen.CgenConfiguration;
  import org.apache.cayenne.gen.CgenConfigList;
  import org.apache.cayenne.gen.CgenTemplate;
  import org.apache.cayenne.gen.TemplateType;
  import org.apache.cayenne.gen.internal.Utils;
  import org.apache.cayenne.map.DataMap;
  import org.xml.sax.Attributes;
  
  /**
   * @since 4.1
   */
  public class CgenConfigHandler extends NamespaceAwareNestedTagHandler {
  
      public static final String CONFIG_TAG = "cgen";
  
      private static final String NAME = "name";
      private static final String OUTPUT_DIRECTORY_TAG = "destDir";
      private static final String GENERATION_MODE_TAG = "mode";
      private static final String SUBCLASS_TEMPLATE_TAG = "template";
      private static final String SUPERCLASS_TEMPLATE_TAG = "superTemplate";
      private static final String EMBEDDABLE_TEMPLATE_TAG = "embeddableTemplate";
      private static final String EMBEDDABLE_SUPER_TEMPLATE_TAG = "embeddableSuperTemplate";
      private static final String DATAMAP_TEMPLATE_TAG = "dataMapTemplate";
      private static final String DATAMAP_SUPER_TEMPLATE_TAG = "dataMapSuperTemplate";
      private static final String OUTPUT_PATTERN_TAG = "outputPattern";
      private static final String MAKE_PAIRS_TAG = "makePairs";
      private static final String USE_PKG_PATH_TAG = "usePkgPath";
      private static final String OVERWRITE_SUBCLASSES_TAG = "overwrite";
      private static final String CREATE_PROPERTY_NAMES_TAG = "createPropertyNames";
      private static final String EXCLUDE_ENTITIES_TAG = "excludeEntities";
      private static final String EXCLUDE_EMBEDDABLES_TAG = "excludeEmbeddables";
      private static final String CREATE_PK_PROPERTIES = "createPKProperties";
      private static final String SUPER_PKG_TAG = "superPkg";
  
      public static final String TRUE = "true";
  
      private DataChannelMetaData metaData;
      private CgenConfiguration configuration;
  
      CgenConfigHandler(NamespaceAwareNestedTagHandler parentHandler, DataChannelMetaData metaData) {
          super(parentHandler);
          this.metaData = metaData;
          this.targetNamespace = CgenExtension.NAMESPACE;
          this.configuration = new CgenConfiguration();
      }
  
      @Override
      protected boolean processElement(String namespaceURI, String localName, Attributes attributes) {
          if (CONFIG_TAG.equals(localName)) {
              createConfig();
              return true;
          }
          return false;
      }
  
      @Override
      protected boolean processCharData(String localName, String data) {
          switch (localName) {
              case NAME:
                  setName(data);
                  break;
              case OUTPUT_DIRECTORY_TAG:
                  createOutputDir(data);
                  break;
              case GENERATION_MODE_TAG:
                  createGenerationMode(data);
                  break;
              case EXCLUDE_ENTITIES_TAG:
                  createExcludeEntities(data);
                  break;
              case EXCLUDE_EMBEDDABLES_TAG:
                  createExcludeEmbeddables(data);
                  break;
              case SUBCLASS_TEMPLATE_TAG:
                  createSubclassTemplate(data);
                  break;
              case SUPERCLASS_TEMPLATE_TAG:
                  createSuperclassTemplate(data);
                  break;
              case EMBEDDABLE_TEMPLATE_TAG:
                  createEmbeddableTemplate(data);
                  break;
              case EMBEDDABLE_SUPER_TEMPLATE_TAG:
                  createEmbeddableSuperTemplate(data);
              case DATAMAP_TEMPLATE_TAG:
                  createDataMapTemplate(data);
                  break;
              case DATAMAP_SUPER_TEMPLATE_TAG:
                  createDataMapSuperTemplate(data);
                  break;
              case OUTPUT_PATTERN_TAG:
                  createOutputPattern(data);
                  break;
              case MAKE_PAIRS_TAG:
                  createMakePairs(data);
                  break;
              case USE_PKG_PATH_TAG:
                  createUsePkgPath(data);
                  break;
              case OVERWRITE_SUBCLASSES_TAG:
                  createOverwriteSubclasses(data);
                  break;
              case CREATE_PROPERTY_NAMES_TAG:
                  createPropertyNamesTag(data);
                  break;
              case CREATE_PK_PROPERTIES:
                  createPkPropertiesTag(data);
                  break;
              case SUPER_PKG_TAG:
                  createSuperPkg(data);
                  break;
          }
          return true;
      }
  
      private void setName(String name) {
          if (name.trim().length() == 0) {
              return;
          }
          configuration.setName(name);
      }
  
      private void createOutputDir(String path) {
          if (path.trim().length() == 0) {
              return;
          }
          configuration.updateOutputPath(Paths.get(path));
      }
  
      private void createGenerationMode(String mode) {
          if (mode.trim().length() == 0) {
              return;
          }
          configuration.setArtifactsGenerationMode(mode);
      }
  
      private void createExcludeEntities(String entities) {
          if (entities.trim().length() == 0) {
              return;
          }
          configuration.parseExcludedEntities(entities);
      }
  
      private void createExcludeEmbeddables(String embeddables) {
          if (embeddables.trim().length() == 0) {
              return;
          }
          configuration.parseExcludedEmbeddables(embeddables);
      }
  
      private void createSubclassTemplate(String template) {
  
          if (template.trim().length() == 0) {
              return;
          }
          if (TemplateType.isDefault(template)) {
              configuration.setTemplate(TemplateType.ENTITY_SUBCLASS.defaultTemplate());
          } else {
              configuration.setTemplate(new CgenTemplate(template, false,TemplateType.ENTITY_SUBCLASS));
          }
      }
  
      private void createSuperclassTemplate(String template) {
          if (template.trim().length() == 0) {
              return;
          }
          if (TemplateType.isDefault(template)) {
              configuration.setSuperTemplate(TemplateType.ENTITY_SUPERCLASS.defaultTemplate());
          } else {
              configuration.setSuperTemplate(new CgenTemplate(template,false,TemplateType.ENTITY_SUBCLASS));
          }
      }
  
      private void createEmbeddableTemplate(String template) {
          if (template.trim().length() == 0) {
              return;
          }
          if (TemplateType.isDefault(template)) {
              configuration.setEmbeddableTemplate(TemplateType.EMBEDDABLE_SUBCLASS.defaultTemplate());
          } else {
              configuration.setEmbeddableTemplate(new CgenTemplate(template,false,TemplateType.EMBEDDABLE_SUBCLASS));
          }
      }
  
      private void createEmbeddableSuperTemplate(String template) {
          if (template.trim().length() == 0) {
              return;
          }
          if (TemplateType.isDefault(template)) {
              configuration.setEmbeddableSuperTemplate(TemplateType.EMBEDDABLE_SUPERCLASS.defaultTemplate());
          } else {
              configuration.setEmbeddableSuperTemplate(new CgenTemplate(template,false,TemplateType.EMBEDDABLE_SUPERCLASS));
          }
      }
  
      private void createDataMapTemplate(String template) {
          if (template.trim().length() == 0) {
              return;
          }
          if (TemplateType.isDefault(template)) {
              configuration.setDataMapTemplate(TemplateType.DATAMAP_SUBCLASS.defaultTemplate());
          } else {
              configuration.setDataMapTemplate(new CgenTemplate(template,false,TemplateType.DATAMAP_SUBCLASS));
          }
      }
  
      private void createDataMapSuperTemplate(String template) {
          if (template.trim().length() == 0) {
              return;
          }
          if (TemplateType.isDefault(template)) {
              configuration.setDataMapSuperTemplate(TemplateType.DATAMAP_SUPERCLASS.defaultTemplate());
          } else {
              configuration.setDataMapSuperTemplate(new CgenTemplate(template,false,TemplateType.DATAMAP_SUPERCLASS));
          }
      }
  
      private void createOutputPattern(String pattern) {
          if (pattern.trim().length() == 0) {
              return;
          }
          configuration.setOutputPattern(pattern);
      }
  
      private void createMakePairs(String makePairs) {
          if (makePairs.trim().length() == 0) {
              return;
          }
          configuration.setMakePairs(makePairs.equals(TRUE));
      }
  
      private void createUsePkgPath(String data) {
          if (data.trim().length() == 0) {
              return;
          }
          configuration.setUsePkgPath(data.equals(TRUE));
      }
  
      private void createOverwriteSubclasses(String data) {
          if (data.trim().length() == 0) {
              return;
          }
          configuration.setOverwrite(data.equals(TRUE));
      }
  
      private void createPropertyNamesTag(String data) {
          if (data.trim().length() == 0) {
              return;
          }
          configuration.setCreatePropertyNames(data.equals(TRUE));
      }
  
      private void createPkPropertiesTag(String data) {
          if (data.trim().length() == 0) {
              return;
          }
          configuration.setCreatePKProperties(data.equals(TRUE));
      }
  
      private void createSuperPkg(String data) {
          if (data.trim().length() == 0) {
              return;
          }
          configuration.setSuperPkg(data);
      }
  
      private void createConfig() {
          loaderContext.addDataMapListener(dataMap -> {
              configuration.setDataMap(dataMap);
              configuration.setRootPath(Utils.getRootPathForDataMap(dataMap));
              configuration.resolveExcludedEntities();
              configuration.resolveExcludedEmbeddables();
  
              CgenConfigList configurations = CgenConfigHandler.this.metaData.get(dataMap, CgenConfigList.class);
              if (configurations == null) {
                  configurations = new CgenConfigList();
                  CgenConfigHandler.this.metaData.add(dataMap, configurations);
              }
              configurations.add(configuration);
          });
      }
  }
  