code: package it.unibz.inf.ontop.injection.impl;
  
  import it.unibz.inf.ontop.exception.InvalidMappingException;
  import it.unibz.inf.ontop.exception.MappingIOException;
  import it.unibz.inf.ontop.exception.OBDASpecificationException;
  import it.unibz.inf.ontop.exception.InvalidOntopConfigurationException;
  import it.unibz.inf.ontop.injection.OntopMappingSQLAllConfiguration;
  import it.unibz.inf.ontop.injection.OntopMappingSQLAllSettings;
  import it.unibz.inf.ontop.spec.mapping.pp.SQLPPMapping;
  import it.unibz.inf.ontop.spec.OBDASpecification;
  import org.apache.commons.rdf.api.Graph;
  
  import javax.annotation.Nonnull;
  import java.io.File;
  import java.io.Reader;
  import java.net.URI;
  import java.net.URISyntaxException;
  import java.util.Optional;
  import java.util.Properties;
  
  public class OntopMappingSQLAllConfigurationImpl extends OntopMappingSQLConfigurationImpl
          implements OntopMappingSQLAllConfiguration {
  
  
      private final OntopMappingSQLAllSettings settings;
      private final OntopMappingSQLAllOptions options;
  
      OntopMappingSQLAllConfigurationImpl(OntopMappingSQLAllSettings settings, OntopMappingSQLAllOptions options) {
          super(settings, options.mappingSQLOptions);
          this.settings = settings;
          this.options = options;
      }
  
      @Override
      public OntopMappingSQLAllSettings getSettings() {
          return settings;
      }
  
      @Override
      protected OBDASpecification loadOBDASpecification() throws OBDASpecificationException {
          return loadSpecification(Optional::empty);
      }
  
      OBDASpecification loadSpecification(OntologySupplier ontologySupplier)
              throws OBDASpecificationException {
  
          return loadSpecification(ontologySupplier,
                  () -> options.mappingFile,
                  () -> options.mappingReader,
                  () -> options.mappingGraph,
                  () -> options.constraintFile,
                  () -> options.dbMetadataFile,
                  () -> options.dbMetadataReader,
                  () -> options.lensesFile,
                  () -> options.lensesReader);
      }
  
      @Override
      public Optional<SQLPPMapping> loadPPMapping() throws MappingIOException, InvalidMappingException {
          return loadPPMapping(
                  () -> options.mappingFile,
                  () -> options.mappingReader,
                  () -> options.mappingGraph);
      }
  
      /**
       * Please overload isMappingDefined() instead.
       */
      @Override
      boolean isInputMappingDefined() {
          return super.isInputMappingDefined()
                  || options.mappingFile.isPresent()
                  || options.mappingGraph.isPresent()
                  || options.mappingReader.isPresent();
      }
  
  
      static class OntopMappingSQLAllOptions {
          private final Optional<File> mappingFile;
          private final Optional<Reader> mappingReader;
          private final Optional<Graph> mappingGraph;
          private final Optional<File> constraintFile;
          private final Optional<File> dbMetadataFile;
          private final Optional<Reader> dbMetadataReader;
          private final Optional<File> lensesFile;
          private final Optional<Reader> lensesReader;
          final OntopMappingSQLOptions mappingSQLOptions;
  
  
          OntopMappingSQLAllOptions(Optional<File> mappingFile, Optional<Reader> mappingReader,
                                    Optional<Graph> mappingGraph, Optional<File> constraintFile,
                                    Optional<File> dbMetadataFile, Optional<Reader> dbMetadataReader,
                                    Optional<File> lensesFile, Optional<Reader> lensesReader,
                                    OntopMappingSQLOptions mappingSQLOptions) {
              this.mappingFile = mappingFile;
              this.mappingReader = mappingReader;
              this.mappingGraph = mappingGraph;
              this.constraintFile = constraintFile;
              this.dbMetadataFile = dbMetadataFile;
              this.dbMetadataReader = dbMetadataReader;
              this.lensesFile = lensesFile;
              this.lensesReader = lensesReader;
              this.mappingSQLOptions = mappingSQLOptions;
          }
      }
  
  
      static class StandardMappingSQLAllBuilderFragment<B extends OntopMappingSQLAllConfiguration.Builder<B>>
              implements OntopMappingSQLAllBuilderFragment<B> {
          private final B builder;
          private final Runnable declareMappingDefinedCB;
          private final Runnable declareImplicitConstraintSetDefinedCB;
          private final Runnable declareDBMetadataSetDefinedCB;
          private final Runnable declareLensesDefinedCB;
  
          private Optional<File> mappingFile = Optional.empty();
          private Optional<Reader> mappingReader = Optional.empty();
          private Optional<Graph> mappingGraph = Optional.empty();
          private Optional<File> constraintFile = Optional.empty();
          private Optional<File> dbMetadataFile = Optional.empty();
          private Optional<Reader> dbMetadataReader = Optional.empty();
          private Optional<File> lensesFile = Optional.empty();
          private Optional<Reader> lensesReader = Optional.empty();
          private boolean useR2rml = false;
  
  
          /**
           * Default constructor
           */
          protected StandardMappingSQLAllBuilderFragment(B builder, Runnable declareMappingDefinedCB,
                                                         Runnable declareImplicitConstraintSetDefinedCB,
                                                         Runnable declareDBMetadataSetDefinedCB,
                                                         Runnable declareLensesDefinedCB) {
              this.builder = builder;
              this.declareMappingDefinedCB = declareMappingDefinedCB;
              this.declareImplicitConstraintSetDefinedCB = declareImplicitConstraintSetDefinedCB;
              this.declareDBMetadataSetDefinedCB = declareDBMetadataSetDefinedCB;
              this.declareLensesDefinedCB = declareLensesDefinedCB;
          }
  
  
          @Override
          public B nativeOntopMappingFile(@Nonnull File mappingFile) {
              declareMappingDefinedCB.run();
              this.mappingFile = Optional.of(mappingFile);
              return builder;
          }
  
          @Override
          public B nativeOntopMappingFile(@Nonnull String mappingFilename) {
              setMappingFile(mappingFilename);
              return builder;
          }
  
          @Override
          public B nativeOntopMappingReader(@Nonnull Reader mappingReader) {
              declareMappingDefinedCB.run();
              this.mappingReader = Optional.of(mappingReader);
              return builder;
          }
  
          @Override
          public B r2rmlMappingFile(@Nonnull File mappingFile) {
              declareMappingDefinedCB.run();
              useR2rml = true;
              this.mappingFile = Optional.of(mappingFile);
              return builder;
          }
  
          @Override
          public B r2rmlMappingFile(@Nonnull String mappingFilename) {
              declareMappingDefinedCB.run();
              useR2rml = true;
  
              try {
                  URI fileURI = new URI(mappingFilename);
                  String scheme = fileURI.getScheme();
                  if (scheme == null) {
                      this.mappingFile = Optional.of(new File(fileURI.getPath()));
                  }
                  else if (scheme.equals("file")) {
                      this.mappingFile = Optional.of(new File(fileURI));
                  }
                  else {
                      throw new InvalidOntopConfigurationException("Currently only local files are supported" +
                              "as R2RML mapping files");
                  }
                  return builder;
              } catch (URISyntaxException e) {
                  throw new InvalidOntopConfigurationException("Invalid mapping file path: " + e.getMessage());
              }
          }
  
          @Override
          public B r2rmlMappingReader(@Nonnull Reader mappingReader) {
              declareMappingDefinedCB.run();
              useR2rml = true;
              this.mappingReader = Optional.of(mappingReader);
              return builder;
          }
  
          @Override
          public B r2rmlMappingGraph(@Nonnull Graph rdfGraph) {
              declareMappingDefinedCB.run();
              useR2rml = true;
              this.mappingGraph = Optional.of(rdfGraph);
              return builder;
          }
  
          @Override
          public B basicImplicitConstraintFile(@Nonnull File constraintFile) {
              declareImplicitConstraintSetDefinedCB.run();
              this.constraintFile = Optional.of(constraintFile);
              return builder;
          }
  
          @Override
          public B basicImplicitConstraintFile(@Nonnull String constraintFilename) {
              declareImplicitConstraintSetDefinedCB.run();
              try {
                  URI fileURI = new URI(constraintFilename);
                  String scheme = fileURI.getScheme();
                  if (scheme == null) {
                      this.constraintFile = Optional.of(new File(fileURI.getPath()));
                  }
                  else if (scheme.equals("file")) {
                      this.constraintFile = Optional.of(new File(fileURI));
                  }
                  else {
                      throw new InvalidOntopConfigurationException("Currently only local files are supported" +
                              "as implicit constraint files");
                  }
                  return builder;
              } catch (URISyntaxException e) {
                  throw new InvalidOntopConfigurationException("Invalid implicit constraint file path: " + e.getMessage());
              }
          }
  
              @Override
              public B dbMetadataFile(@Nonnull File dbMetadataFile) {
                  declareDBMetadataSetDefinedCB.run();
                  this.dbMetadataFile = Optional.of(dbMetadataFile);
                  return builder;
              }
  
              @Override
              public B dbMetadataFile(@Nonnull String dbMetadataFilename) {
                  declareDBMetadataSetDefinedCB.run();
                  try {
                      URI fileURI = new URI(dbMetadataFilename);
                      String scheme = fileURI.getScheme();
                      if (scheme == null) {
                          this.dbMetadataFile = Optional.of(new File(fileURI.getPath()));
                      }
                      else if (scheme.equals("file")) {
                          this.dbMetadataFile = Optional.of(new File(fileURI));
                      }
                      else {
                          throw new InvalidOntopConfigurationException("Currently only local files are supported" +
                                  "as db-metadata files");
                      }
                      return builder;
                  } catch (URISyntaxException e) {
                      throw new InvalidOntopConfigurationException("Invalid db-metadata file path: " + e.getMessage());
                  }
              }
  
          @Override
          public B dbMetadataReader(@Nonnull Reader dbMetadataReader) {
              declareDBMetadataSetDefinedCB.run();
              this.dbMetadataReader = Optional.of(dbMetadataReader);
              return builder;
          }
  
          @Override
          public B lensesFile(@Nonnull File lensesFile) {
              declareLensesDefinedCB.run();
              this.lensesFile = Optional.of(lensesFile);
              return builder;
          }
  
          @Override
          public B lensesFile(@Nonnull String lensesFilename) {
              declareLensesDefinedCB.run();
              try {
                  URI fileURI = new URI(lensesFilename);
                  String scheme = fileURI.getScheme();
                  if (scheme == null) {
                      this.lensesFile = Optional.of(new File(fileURI.getPath()));
                  }
                  else if (scheme.equals("file")) {
                      this.lensesFile = Optional.of(new File(fileURI));
                  }
                  else {
                      throw new InvalidOntopConfigurationException("Currently only local files are supported" +
                              "as lerses files");
                  }
                  return builder;
              } catch (URISyntaxException e) {
                  throw new InvalidOntopConfigurationException("Invalid lenses file path: " + e.getMessage());
              }
          }
  
          @Override
          public B lensesReader(@Nonnull Reader lensesReader) {
              declareLensesDefinedCB.run();
              this.lensesReader = Optional.of(lensesReader);
              return builder;
          }
  
  
          protected Properties generateProperties() {
              Properties p = new Properties();
  
              // Never puts the mapping file path
  
              return p;
          }
  
          boolean isR2rml() {
              return useR2rml;
          }
  
          protected final void setMappingFile(String mappingFilename) {
              declareMappingDefinedCB.run();
              try {
                  URI fileURI = new URI(mappingFilename);
                  String scheme = fileURI.getScheme();
                  if (scheme == null) {
                      this.mappingFile = Optional.of(new File(fileURI.getPath()));
                  }
                  else if (scheme.equals("file")) {
                      this.mappingFile = Optional.of(new File(fileURI));
                  }
                  else {
                      throw new InvalidOntopConfigurationException("Currently only local files are supported" +
                              "as mapping files");
                  }
              } catch (URISyntaxException e) {
                  throw new InvalidOntopConfigurationException("Invalid mapping file path: " + e.getMessage());
              }
          }
  
          final OntopMappingSQLAllOptions generateMappingSQLAllOptions(OntopMappingSQLOptions mappingOptions) {
                  return new OntopMappingSQLAllOptions(mappingFile, mappingReader, mappingGraph, constraintFile,
                          dbMetadataFile, dbMetadataReader, lensesFile, lensesReader, mappingOptions);
          }
  
      }
  
      protected abstract static class OntopMappingSQLAllBuilderMixin<B extends OntopMappingSQLAllConfiguration.Builder<B>>
              extends OntopMappingSQLBuilderMixin<B>
              implements OntopMappingSQLAllConfiguration.Builder<B> {
  
          private final StandardMappingSQLAllBuilderFragment<B> localFragmentBuilder;
          private boolean isImplicitConstraintSetDefined = false;
  
          OntopMappingSQLAllBuilderMixin() {
              B builder = (B) this;
              this.localFragmentBuilder = new StandardMappingSQLAllBuilderFragment<>(builder,
                      this::declareMappingDefined, this::declareImplicitConstraintSetDefined,
                      this::declareDBMetadataDefined, this::declareLensesDefined);
          }
  
          @Override
          public B nativeOntopMappingFile(@Nonnull File mappingFile) {
              return localFragmentBuilder.nativeOntopMappingFile(mappingFile);
          }
  
          @Override
          public B nativeOntopMappingFile(@Nonnull String mappingFilename) {
              return localFragmentBuilder.nativeOntopMappingFile(mappingFilename);
          }
  
          @Override
          public B nativeOntopMappingReader(@Nonnull Reader mappingReader) {
              return localFragmentBuilder.nativeOntopMappingReader(mappingReader);
          }
  
          @Override
          public B r2rmlMappingFile(@Nonnull File mappingFile) {
              return localFragmentBuilder.r2rmlMappingFile(mappingFile);
          }
  
          @Override
          public B r2rmlMappingFile(@Nonnull String mappingFilename) {
              return localFragmentBuilder.r2rmlMappingFile(mappingFilename);
          }
  
          @Override
          public B r2rmlMappingReader(@Nonnull Reader mappingReader) {
              return localFragmentBuilder.r2rmlMappingReader(mappingReader);
          }
  
          @Override
          public B r2rmlMappingGraph(@Nonnull Graph rdfGraph) {
              return localFragmentBuilder.r2rmlMappingGraph(rdfGraph);
          }
  
          @Override
          public B basicImplicitConstraintFile(@Nonnull File constraintFile) {
              return localFragmentBuilder.basicImplicitConstraintFile(constraintFile);
          }
  
          @Override
          public B basicImplicitConstraintFile(@Nonnull String constraintFilename) {
              return localFragmentBuilder.basicImplicitConstraintFile(constraintFilename);
          }
  
          @Override
          public B dbMetadataFile(@Nonnull File dbmetadataFile) {
              return localFragmentBuilder.dbMetadataFile(dbmetadataFile);
          }
  
          @Override
          public B dbMetadataFile(@Nonnull String dbmetadataFilename) {
              return localFragmentBuilder.dbMetadataFile(dbmetadataFilename);
          }
  
          @Override
          public B dbMetadataReader(@Nonnull Reader dbMetadataReader) {
              return localFragmentBuilder.dbMetadataReader(dbMetadataReader);
          }
  
          @Override
          public B lensesFile(@Nonnull File ontopViewFile) {
              return localFragmentBuilder.lensesFile(ontopViewFile);
          }
  
          @Override
          public B lensesFile(@Nonnull String lensesFilename) {
              return localFragmentBuilder.lensesFile(lensesFilename);
          }
  
          @Override
          public B lensesReader(@Nonnull Reader lensesReader) {
              return localFragmentBuilder.lensesReader(lensesReader);
          }
  
          final OntopMappingSQLAllOptions generateMappingSQLAllOptions() {
              OntopMappingSQLOptions sqlMappingOptions = generateMappingSQLOptions();
              return localFragmentBuilder.generateMappingSQLAllOptions(sqlMappingOptions);
          }
  
          @Override
          protected Properties generateProperties() {
              Properties p = super.generateProperties();
              p.putAll(localFragmentBuilder.generateProperties());
              return p;
          }
  
          boolean isR2rml() {
              return localFragmentBuilder.isR2rml();
          }
  
          void declareImplicitConstraintSetDefined() {
              if (isImplicitConstraintSetDefined)
                  throw new InvalidOntopConfigurationException("The implicit constraint file is already defined");
              isImplicitConstraintSetDefined = true;
          }
  
      }
  
      public static class BuilderImpl<B extends OntopMappingSQLAllConfiguration.Builder<B>>
              extends OntopMappingSQLAllBuilderMixin<B> {
  
          @Override
          public OntopMappingSQLAllConfiguration build() {
              OntopMappingSQLAllSettings settings = new OntopMappingSQLAllSettingsImpl(generateProperties(), isR2rml());
              OntopMappingSQLAllOptions options = generateMappingSQLAllOptions();
  
              return new OntopMappingSQLAllConfigurationImpl(settings, options);
          }
  
      }
  }
  