code: package it.unibz.inf.ontop.model.term.functionsymbol;
  
  import com.google.common.collect.ImmutableSet;
  import it.unibz.inf.ontop.iq.tools.TypeConstantDictionary;
  import it.unibz.inf.ontop.model.term.RDFTermTypeConstant;
  import it.unibz.inf.ontop.model.term.functionsymbol.db.DBFunctionSymbol;
  import it.unibz.inf.ontop.model.term.functionsymbol.db.DBFunctionSymbolFactory;
  import it.unibz.inf.ontop.model.type.DBTermType;
  import it.unibz.inf.ontop.model.type.RDFTermType;
  import org.apache.commons.rdf.api.IRI;
  
  import java.util.Optional;
  import java.util.function.Function;
  
  /**
   * Accessible through Guice (recommended) or through CoreSingletons.
   */
  public interface FunctionSymbolFactory {
  
      RDFTermFunctionSymbol getRDFTermFunctionSymbol();
  
      DBFunctionSymbolFactory getDBFunctionSymbolFactory();
  
      BooleanFunctionSymbol getIsARDFTermTypeFunctionSymbol(RDFTermType rdfTermType);
  
      /**
       * See https://www.w3.org/TR/sparql11-query/#func-arg-compatibility
       */
      BooleanFunctionSymbol getAreCompatibleRDFStringFunctionSymbol();
  
      BooleanFunctionSymbol getLexicalNonStrictEqualityFunctionSymbol();
  
      /**
       * To be used when parsing the mapping and when an equality is found.
       * Is expected to replaced later by a proper equality (may be strict or not)
       */
      NotYetTypedEqualityFunctionSymbol getNotYetTypedEquality();
  
      BooleanFunctionSymbol getLexicalInequalityFunctionSymbol(InequalityLabel inequalityLabel);
  
      BooleanFunctionSymbol getLexicalEBVFunctionSymbol();
  
      /**
       * Used for wrapping SPARQL boolean functional terms to make them becoming ImmutableExpressions
       *
       * Such a wrapping consists in converting XSD booleans into DB booleans.
       */
      BooleanFunctionSymbol getRDF2DBBooleanFunctionSymbol();
  
      RDFTermTypeFunctionSymbol getRDFTermTypeFunctionSymbol(TypeConstantDictionary dictionary,
                                                             ImmutableSet<RDFTermTypeConstant> possibleConstants,
                                                             boolean isSimplifiable);
  
      // SPARQL functions
  
      Optional<SPARQLFunctionSymbol> getSPARQLFunctionSymbol(String officialName, int arity);
  
      default SPARQLFunctionSymbol getRequiredSPARQLFunctionSymbol(String officialName, int arity) {
          return getSPARQLFunctionSymbol(officialName, arity)
                  .orElseThrow(() -> new IllegalArgumentException("The SPARQL function " + officialName
                          + " is not available for the arity " + arity));
      }
  
      Optional<SPARQLFunctionSymbol> getSPARQLDistinctAggregateFunctionSymbol(String officialName, int arity);
  
      default SPARQLFunctionSymbol getRequiredSPARQLDistinctAggregateFunctionSymbol(String officialName, int arity){
          return getSPARQLDistinctAggregateFunctionSymbol(officialName, arity)
                  .orElseThrow(() -> new IllegalArgumentException("The SPARQL distinct aggregate function " + officialName
                          + " with arity " + arity + " is not available"));
      }
  
      SPARQLAggregationFunctionSymbol getSPARQLGroupConcatFunctionSymbol(String separator, boolean isDistinct);
  
      SPARQLFunctionSymbol getIRIFunctionSymbol(IRI baseIRI);
      SPARQLFunctionSymbol getIRIFunctionSymbol();
  
      /**
       * Special function capturing the EBV logic
       * https://www.w3.org/TR/sparql11-query/#ebv
       *
       * Returns an XSD.BOOLEAN
       */
      FunctionSymbol getSPARQLEffectiveBooleanValueFunctionSymbol();
  
      FunctionSymbol getCommonDenominatorFunctionSymbol(int arity);
  
      /**
       * Binary
       */
      FunctionSymbol getCommonPropagatedOrSubstitutedNumericTypeFunctionSymbol();
  
      /**
       * Do NOT confuse it with the LANG SPARQL function
       *
       * This function symbol takes a RDF type term as input.
       * and returns
       *   * NULL if it is not a literal
       *   * "" if the literal type does not have a language tag
       *   * the language tag if available
       */
      FunctionSymbol getLangTagFunctionSymbol();
  
      /**
       * Do NOT confuse it with the LANG DATATYPE function
       *
       * This function symbol takes an RDF type term as input.
       * and returns
       *   * NULL if it is not a literal
       *   * the string of the datatype IRI
       */
      FunctionSymbol getRDFDatatypeStringFunctionSymbol();
  
      /**
       * Do NOT confuse it with the langMatches SPARQL function
       *
       * Not a DBFunctionSymbol as it is not delegated to the DB (too complex logic)
       */
      BooleanFunctionSymbol getLexicalLangMatches();
  
      FunctionSymbol getBinaryNumericLexicalFunctionSymbol(String dbNumericOperationName);
  
      FunctionSymbol getUnaryLatelyTypedFunctionSymbol(Function<DBTermType, Optional<DBFunctionSymbol>> dbFunctionSymbolFct,
                                                       DBTermType targetType);
  
      FunctionSymbol getUnaryLexicalFunctionSymbol(Function<DBTermType, Optional<DBFunctionSymbol>> dbFunctionSymbolFct);
  
      FunctionSymbol getBinaryLatelyTypedFunctionSymbol(Function<DBTermType, Optional<DBFunctionSymbol>> dbFunctionSymbolFct,
                                                        DBTermType targetType);
  
      FunctionSymbol getExtractLexicalTermFromRDFTerm();
  }
  