I am developing a NamedQueryManager EJB that receives a JPQL string from a client and returns a query that only selects data that the user is authorized to read. For example, if the client program wants Companies, it would create the following query and send to the NamedQueryManager.
- SELECT c FROM Company c
The NamedQueryManager would consider the query and the current user and if the user doesn't have full permissions to read Company entities would return a query similar to the following:
- SELECT c FROM Company c where c.reader = :user
Instead of creating my own parser, I investigated EclipseLink 2.6.1 and found that I could perform the following to parse the query:
JPQLExpression jpql = new JPQLExpression(jpqlString, new JPQLGrammar2_1());
if (jpql.getQueryStatement() instanceof SelectStatement) {
logger.debug("JPQL Expression is a Select statement.");
} else if (jpql.getQueryStatement() instanceof UpdateStatement) {
logger.debug("JPQL Expression is a Update statement.");
} else if (jpql.getQueryStatement() instanceof DeleteStatement) {
logger.debug("JPQL Expression is a Delete statement.");
} else {
logger.debug("JPQL Expression is an unknown statement.");
}
I could then loop through the children of the QueryStatement and determine the pieces of the statement. For example, the following loops through the Select clause.
SelectStatement st = (SelectStatement) jpql.getQueryStatement();
logger.debug("JPQL Select Statement: {}", st);
logger.debug("********************");
SelectClause sc = (SelectClause) st.getSelectClause();
logger.debug("Select Clause: {}", sc);
for (Expression e : sc.children()) {
logger.debug("Child: {}", e);
}
for (Expression e : sc.orderedChildren()) {
logger.debug("Ordered Child: {}", e);
}
So my question is am I on the correct path for using EclipseLink to parse and modify my JPQL?
I am comfortable with the parsing but how do I modify? Should I build a new JPQL string using the parsed JPQL or can I add information to the parsed JPQL directly to create the new query?
I began investigating how I could determine if the passed jpql string is valid and found references to the HermesParser class in the org.eclipse.persistence.internal.jpa.jpql package.
Should I stay away from "internal" packages?
I don't think that the following code which I am using to parse the jpql string uses the HermesParser but the org.eclipse.persistence.jpa.jpql.parser package-info states that "This is the core of Hermes,..."
JPQLExpression jpql = new JPQLExpression(jpqlString, new JPQLGrammar2_1());
So this leads me to ask what is Hermes?
Any big picture help or references would be greatly appreciated.
Note: This is a continuation of the following question.
Should I use @NamedQuery annotation or addNamedQuery method?