Class ExpressionRegistry


  • public class ExpressionRegistry
    extends java.lang.Object
    This registry contains the necessary information used by Hermes parser. When parsing a JPQL query, the JPQLGrammar given to JPQLExpression will give access to this registry.

    Provisional API: This interface is part of an interim API that is still under development and expected to change significantly before reaching stability. It is available at this early stage to solicit feedback from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken (repeatedly) as the API evolves.

    Version:
    2.5
    See Also:
    JPQLGrammar, ExpressionFactory, JPQLQueryBNF
    Author:
    Pascal Filion
    Since:
    2.4
    • Constructor Summary

      Constructors 
      Constructor Description
      ExpressionRegistry()
      Creates the only instance of ExpressionRegistry.
    • Constructor Detail

      • ExpressionRegistry

        public ExpressionRegistry()
        Creates the only instance of ExpressionRegistry.
    • Method Detail

      • addChildBNF

        public void addChildBNF​(java.lang.String queryBNFId,
                                java.lang.String childQueryBNFId)
        Adds to the given query BNF a child BNF.
        Parameters:
        queryBNFId - The unique identifier of the parent BNF to add a child BNF
        childQueryBNFId - The unique identifier of the child to add to the parent BNF
        Throws:
        java.lang.NullPointerException - The JPQLQueryBNF identified by the given ID does not exist
      • addChildFactory

        public void addChildFactory​(java.lang.String queryBNFId,
                                    java.lang.String childExpressionFactoryId)
        Adds to the given unique identifier of an ExpressionFactory to the given query BNF.
        Parameters:
        queryBNFId - The unique identifier of the parent BNF
        childExpressionFactoryId - The unique identifier of the ExpressionFactory to add to the given query BNF
        Throws:
        java.lang.NullPointerException - The JPQLQueryBNF identified by the given ID does not exist
      • addIdentifier

        public void addIdentifier​(java.lang.String expressionFactoryId,
                                  java.lang.String identifier)
        Adds the given JPQL identifier to this factory.
        Parameters:
        expressionFactoryId - The unique identifier of the ExpressionFactory to add more JPQL identifiers
        identifier - The JPQL identifier this factory will parse
      • addIdentifiers

        public void addIdentifiers​(java.lang.String expressionFactoryId,
                                   java.lang.String... identifiers)
        Adds the given JPQL identifiers to this factory.
        Parameters:
        expressionFactoryId - The unique identifier of the ExpressionFactory to add more JPQL identifiers
        identifiers - The JPQL identifiers this factory will parse
      • expressionFactoryForIdentifier

        public ExpressionFactory expressionFactoryForIdentifier​(java.lang.String identifier)
        Retrieves the ExpressionFactory that is responsible for creating the Expression object that represents the given JPQL identifier.
        Parameters:
        identifier - The JPQL identifier for which its factory is searched
        Returns:
        Either the ExpressionFactory that creates the Expression or null if none was found
      • getExpressionFactory

        public ExpressionFactory getExpressionFactory​(java.lang.String expressionFactoryId)
        Retrieves the registered ExpressionFactory that was registered for the given unique identifier.
        Parameters:
        expressionFactoryId - The unique identifier of the ExpressionFactory to retrieve
        Returns:
        The ExpressionFactory mapped with the given unique identifier
      • getIdentifierRole

        public IdentifierRole getIdentifierRole​(java.lang.String identifier)
        Retrieves the IdentifierRole of the given JPQL identifier. A role helps to describe the purpose of the identifier in a JPQL query.
        Parameters:
        identifier - The JPQL identifier for which its role is returned
        Returns:
        The IdentifierRole of the given JPQL identifier
      • getIdentifiers

        public java.util.Set<java.lang.String> getIdentifiers()
        Returns the JPQL identifiers that are supported by the JPQL grammar.
        Returns:
        The supported JPQL identifiers
      • getIdentifiers

        public java.lang.Iterable<java.lang.String> getIdentifiers​(java.lang.String queryBNFId)
        Retrieves the JPQL identifiers that are supported by the BNF rule with the given unique identifier. The JPQL identifiers are retrieved by scanning the ExpressionFactory registered with the BNF rule and its child BNF rules.
        Returns:
        The list of JPQL identifiers that are supported by a BNF rule
      • getIdentifierVersion

        public JPAVersion getIdentifierVersion​(java.lang.String identifier)
        Retrieves the JPA version in which the identifier was first introduced.
        Returns:
        The version in which the identifier was introduced
      • getQueryBNF

        public JPQLQueryBNF getQueryBNF​(java.lang.String queryBNFId)
        Retrieves the BNF object that was registered for the given unique identifier.
        Parameters:
        queryBNFId - The unique identifier of the JPQLQueryBNF to retrieve
        Returns:
        The JPQLQueryBNF representing a section of the grammar
      • initialize

        protected void initialize()
        Instantiates the only instance of various API used by the parser.
      • isIdentifier

        public boolean isIdentifier​(java.lang.String text)
        Determines if the given word is a JPQL identifier. The check is case insensitive.
        Parameters:
        text - The string value to test if it's a JPQL identifier based on what is registered with this ExpressionRegistry
        Returns:
        true if the word is an identifier, false otherwise
      • registerBNF

        public void registerBNF​(JPQLQueryBNF queryBNF)
        Registers the given JPQLQueryBNF. The BNF will be registered using its unique identifier.
        Parameters:
        queryBNF - The JPQLQueryBNF to store
        Throws:
        java.lang.NullPointerException - The JPQLQueryBNF cannot be null
      • registerIdentifierRole

        public void registerIdentifierRole​(java.lang.String identifier,
                                           IdentifierRole role)
        Registers the IdentifierRole for the given JPQL identifier.
        Parameters:
        identifier - The JPQL identifier to register its role within a JPQL query
        role - The role of the given JPQL identifier
        Throws:
        java.lang.NullPointerException - The JPQL identifier and the IdentifierRole cannot be null
      • registerIdentifierVersion

        public void registerIdentifierVersion​(java.lang.String identifier,
                                              JPAVersion version)
        Registers the JPAVersion for which the given JPQL identifier was defined.
        Parameters:
        identifier - The JPQL identifier to register in which version it was added to the grammar
        version - The version when the JPQL identifier was added to the grammar
        Throws:
        java.lang.NullPointerException - The JPQL identifier and the JPAVersion cannot be null
      • setFallbackBNFId

        public void setFallbackBNFId​(java.lang.String queryBNFId,
                                     java.lang.String fallbackBNFId)
        When parsing the query and no JPQLQueryBNFs can help to parse the query, then it will fall back on the given one.
        Parameters:
        queryBNFId - The unique identifier of the BNF to modify its fallback BNF unique identifier
        fallbackBNFId - The unique identifier of the JPQLQueryBNF to use in the last resort
        Throws:
        java.lang.NullPointerException - The JPQLQueryBNF identified by the given ID does not exist
      • setFallbackExpressionFactoryId

        public void setFallbackExpressionFactoryId​(java.lang.String queryBNFId,
                                                   java.lang.String fallbackExpressionFactoryId)
        Sets the unique identifier of the ExpressionFactory to use when the fall back BNF ID is not null. This will be used to parse a portion of the query when the registered expression factories cannot parse it.

        Note: This method is only called if JPQLQueryBNF. getFallbackBNFId() does not return null.

        Parameters:
        queryBNFId - The unique identifier of the BNF to modify its fallback expression factory unique identifier
        Throws:
        java.lang.NullPointerException - The JPQLQueryBNF identified by the given ID does not exist
      • setHandleCollection

        public void setHandleCollection​(java.lang.String queryBNFId,
                                        boolean handleCollection)
        Determines whether the Expression handles a collection of sub-expressions that are separated by commas.
        Parameters:
        queryBNFId - The unique identifier of the JPQLQueryBNF
        handleCollection - true if the sub-expression to parse might have several sub-expressions separated by commas; false otherwise
      • setHandleNestedArray

        public void setHandleNestedArray​(java.lang.String queryBNFId,
                                         boolean handleNestedArray)
        Sets whether the BNF with the given ID supports nested array or not. A nested array is a sub- expression with its child being a collection expression: (item_1, item_2, ..., item_n).
        Parameters:
        queryBNFId - The unique identifier of the JPQLQueryBNF
        handleNestedArray - true if the expression represented by this BNF can be a nested array; false otherwise
        Since:
        2.5
      • setHandleSubExpression

        public void setHandleSubExpression​(java.lang.String queryBNFId,
                                           boolean handleSubExpression)
        Sets whether the query BNF with the given ID handles parsing a sub-expression, i.e. parsing an expression encapsulated by parenthesis. Which in fact would be handled by the fallback ExpressionFactory. The default behavior is to not handle it.

        A good example for using this option is when an Expression cannot use any ExpressionFactory for creating a child object, parsing will use the fallback ExpressionFactory, if one was specified. So when this is set to true, the fallback ExpressionFactory will be immediately invoked.

        Let's say we want to parse "SELECT e FROM (SELECT a FROM Address a) e", FromClause cannot use a factory for parsing the entity name (that's what usually the FROM clause has) so it uses the fallback factory to create IdentificationVariableDeclaration. Then IdentificationVariableDeclaration also cannot use any factory to create its child object so it uses the fallback factory to create RangeVariableDeclaration. By changing the status of for handling the sub-expression for the BNFs for those objects, then a subquery can be created by RangeVariableDeclaration.

        FromClause
          |- IdentificationVariableDeclaration
               |- RangeVariableDeclaration
                    |- SubExpression(subquery)
        In order to get this working, the following would have to be done into the grammar:
         public class MyJPQLGrammar extends AbstractJPQLGrammar {
           @Override
           protected void initializeBNFs() {
              setHandleSubExpression(InternalFromClauseBNF.ID,                true);
              setHandleSubExpression(InternalSimpleFromClauseBNF.ID,          true);
              setHandleSubExpression(IdentificationVariableDeclarationBNF.ID, true);
              setHandleSubExpression(RangeVariableDeclarationBNF.ID,          true);
           }
         }
        Parameters:
        queryBNFId - The unique identifier of the JPQLQueryBNF
        handleSubExpression - true to let the creation of a sub-expression be created by the fallback ExpressionFactory registered with this BNF; false otherwise (which is the default value)