Skip to content

Commit

Permalink
update progress
Browse files Browse the repository at this point in the history
  • Loading branch information
domko17 committed Nov 15, 2023
1 parent b7e5b0b commit 663ed12
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ negation: NOT_KEYWORD;



filter: left=filter (SEP+ AND_KEYWORD SEP+ right=filter) #andFilter
| left=filter (SEP+ OR_KEYWORD SEP+ right=filter) #orFilter
filter: left=filter SEP+ AND_KEYWORD SEP+ right=filter #andFilter
| left=filter SEP+ OR_KEYWORD SEP+ right=filter #orFilter
| negation SEP+ subfilterSpec #notFilter
| itemFilter #genFilter
| subfilterSpec #subFilter;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.evolveum.midpoint.prism.impl.query.lang;
package com.evolveum.axiom.lang.antlr;

import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
Expand All @@ -14,7 +14,7 @@ public class AxiomQueryError {
private final String message;
private final RecognitionException e;

AxiomQueryError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e)
public AxiomQueryError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e)
{
this.recognizer = recognizer;
this.offendingSymbol = offendingSymbol;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
package com.evolveum.axiom.lang.antlr;

import org.antlr.v4.runtime.BaseErrorListener;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.misc.Interval;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeVisitor;

import java.util.ArrayList;
import java.util.List;

/**
* Created by Dominik.
*/
public class AxiomQueryErrorListener extends BaseErrorListener {
public static AxiomQueryErrorListener INSTANCE = new AxiomQueryErrorListener();

public List<AxiomQueryError> errorList = new ArrayList<>();

@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol,
int line, int charPositionInLine,
Expand All @@ -21,6 +27,6 @@ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol,
sourceName = String.format("%s:%d:%d: ", sourceName, line, charPositionInLine);
}

System.err.println(sourceName + "line " + ": " + charPositionInLine + " - " + msg);
errorList.add(new AxiomQueryError(recognizer, offendingSymbol, line, charPositionInLine, msg, e));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,41 @@
import com.evolveum.axiom.lang.antlr.query.AxiomQueryParser;
import com.evolveum.axiom.lang.antlr.query.AxiomQueryLexer;

import java.util.List;

public class AxiomQuerySource {

private final AxiomQueryParser.RootContext root;
private List<AxiomQueryError> syntaxErrorList;

public AxiomQuerySource(AxiomQueryParser.RootContext root) {
public AxiomQuerySource(AxiomQueryParser.RootContext root, List<AxiomQueryError> syntaxErrorList) {
this.root = root;
this.syntaxErrorList = syntaxErrorList;
}

public static final AxiomQuerySource from(String query) {
CodePointCharStream stream = CharStreams.fromString(query);
AxiomQueryLexer lexer = new AxiomQueryLexer(stream);
AxiomQueryParser parser = new AxiomQueryParser(new CommonTokenStream(lexer));
AxiomQueryErrorListener axiomQueryErrorListener = new AxiomQueryErrorListener();
// DO NOT log to STDIN
lexer.removeErrorListeners();
parser.removeErrorListeners();
parser.addErrorListener(AxiomQueryErrorListener.INSTANCE);
parser.addErrorListener(axiomQueryErrorListener);

var root = parser.root();
if (root.filter() == null) {
throw new IllegalArgumentException("Unable to parse query: " + query);
}
return new AxiomQuerySource(root);

return new AxiomQuerySource(root, axiomQueryErrorListener.errorList);
}

public AxiomQueryParser.RootContext root() {
return root;
}

public List<AxiomQueryError> getSyntaxError() {
return syntaxErrorList;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
* Created by Dominik.
*/
public class AxiomQueryCompletionVisitor extends AxiomQueryParserBaseVisitor<Object> {
private ParseTree lastNode;
private String lastType = null;
private ParseTree lastNode = null;
private ParseTree lastType = null;

@Override
public Object visitTerminal(TerminalNode node) {
Expand All @@ -30,8 +30,8 @@ public Object visitChildren(RuleNode node) {
@Override
public Object visitItemFilter(ItemFilterContext ctx) {
for (int i = ctx.getChildCount() - 1; i >= 0; i--) {
if (ctx.getChild(i).getText().equals(FilterNames.TYPE.getLocalPart())) lastType = ctx.getChild(i + 2).getText();
if (ctx.getChild(i).getText().equals(FilterNames.META_TYPE)) lastType = ctx.getChild(i + 4).getText();
if (ctx.getChild(i).getText().equals(FilterNames.TYPE.getLocalPart())) lastType = ctx.getChild(i + 2);
if (ctx.getChild(i).getText().equals(FilterNames.META_TYPE)) lastType = ctx.getChild(i + 4);
}

return super.visitItemFilter(ctx);
Expand All @@ -41,7 +41,7 @@ public ParseTree getLastNode() {
return lastNode;
}

public String getLastType() {
public ParseTree getLastType() {
return lastType;
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
package com.evolveum.midpoint.prism.impl.query.lang;

import com.evolveum.axiom.lang.antlr.AxiomQueryError;
import com.evolveum.axiom.lang.antlr.AxiomQuerySource;
import com.evolveum.axiom.lang.antlr.query.AxiomQueryParser;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.impl.marshaller.ItemPathHolder;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.query.AxiomQueryLangService;

import com.evolveum.midpoint.prism.schema.SchemaRegistry;

import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.RuleNode;
import org.jetbrains.annotations.NotNull;

import static com.evolveum.axiom.lang.antlr.query.AxiomQueryParser.*;

import java.util.ArrayList;
import java.util.List;

import static com.evolveum.midpoint.prism.impl.query.lang.FilterNames.EQUAL;

/**
* Created by Dominik.
*/
Expand All @@ -33,11 +41,66 @@ public List<String> queryCompletion(String query) {
AxiomQuerySource axiomQuerySource = AxiomQuerySource.from(query);
AxiomQueryCompletionVisitor axiomQueryCompletionVisitor = new AxiomQueryCompletionVisitor();
axiomQueryCompletionVisitor.visit(axiomQuerySource.root());
// last type in tree
axiomQueryCompletionVisitor.getLastType();
// last tokens in tree
axiomQueryCompletionVisitor.getLastNode().getParent().getParent().getParent().getText();

if (findItemFilter(axiomQueryCompletionVisitor.getLastNode()) instanceof AxiomQueryParser.RootContext) {
// TODO add the case if there is a node with one child
} else if(findItemFilter(axiomQueryCompletionVisitor.getLastNode()) instanceof AxiomQueryParser.ItemFilterContext) {
generateSuggestion(findItemFilter(axiomQueryCompletionVisitor.getLastNode()));
}

return null;
}

private List<String> generateSuggestion(@NotNull RuleNode ruleNode) {
List<String> suggestions = new ArrayList<>();
int childCount = ruleNode.getChildCount();
SchemaRegistry schemaRegistry = PrismContext.get().getSchemaRegistry();
PrismObjectDefinition<?> prismObjectDefinition = schemaRegistry.findObjectDefinitionByCompileTimeClass(userType);

for(int i = 0; i < childCount; ++i) {
if (ruleNode.getChild(i) instanceof AxiomQueryParser.DescendantPathContext ) {
ItemPath itemPath = ItemPathHolder.parseFromString(ruleNode.getChild(i).getText());
prismObjectDefinition.findItemDefinition(itemPath, ItemDefinition.class);
for (ItemDefinition<?> itemDefinition: prismObjectDefinition.getDefinitions()) {
suggestions.add(itemDefinition.getItemName().getLocalPart());
}
} else if(ruleNode.getChild(i) instanceof AxiomQueryParser.SelfPathContext) {
if (ruleNode.getChild(i).getText().equals(".")) {

}
} else if(ruleNode.getChild(i) instanceof AxiomQueryParser.FilterNameContext ruleContext) {
suggestions = FilterNamesProvider.findFilterNamesByItemDefinition(prismObjectDefinition, ruleContext);
} else if(ruleNode.getChild(i) instanceof AxiomQueryParser.FilterNameAliasContext ruleContext) {
suggestions = FilterNamesProvider.findFilterNamesByItemDefinition(prismObjectDefinition, ruleContext);
} else if(ruleNode.getChild(i) instanceof AxiomQueryParser.SubfilterOrValueContext) {
if (ruleNode.getChild(i - 2).getText().equals(FilterNames.NAME_TO_ALIAS.get(EQUAL)) && ruleNode.getChild(i - 4).getText().equals(FilterNames.META_TYPE)) {
suggestions.add("UserType");
}
if (ruleNode.getChild(i - 2).getText().equals(FilterNames.TYPE.getLocalPart()) && ruleNode.getChild(i - 4).getText().equals(".")) {
suggestions.add("UserType");
}
if (ruleNode.getChild(i - 2).getText().equals(FilterNames.NAME_TO_ALIAS.get(EQUAL)) && ruleNode.getChild(i - 4).getText().equals(FilterNames.META_PATH)) {
for (ItemDefinition<?> itemDefinition: prismObjectDefinition.getDefinitions()) {
suggestions.add(itemDefinition.getItemName().getLocalPart());
}
}
}
}

return suggestions;
}


private RuleNode findItemFilter(@NotNull ParseTree parseTreeTerminal) {
RuleNode ruleNode = (RuleNode) parseTreeTerminal.getParent();

while (
ruleNode.getRuleContext().getRuleIndex() != AxiomQueryParser.RULE_root &&
ruleNode.getRuleContext().getRuleIndex() != AxiomQueryParser.RULE_itemFilter
) {
ruleNode = (RuleNode) ruleNode.getParent();
}

return ruleNode;
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package com.evolveum.midpoint.prism.impl.query.lang;

import com.evolveum.axiom.lang.antlr.AxiomQueryError;
import com.evolveum.axiom.lang.antlr.query.AxiomQueryParser;
import com.evolveum.axiom.lang.antlr.query.AxiomQueryParser.*;
import com.evolveum.axiom.lang.antlr.query.AxiomQueryParserBaseVisitor;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.impl.marshaller.ItemPathHolder;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.schema.SchemaRegistry;

import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.RuleNode;
import org.jetbrains.annotations.Nullable;

import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.List;

Expand All @@ -26,6 +30,8 @@ public class AxiomQueryValidationVisitor extends AxiomQueryParserBaseVisitor<Obj

private ItemDefinition<?> itemDefinition;

private final SchemaRegistry schemaRegistry = PrismContext.get().getSchemaRegistry();

public AxiomQueryValidationVisitor(PrismContext prismContext, Class userType) {
this.context = prismContext;
this.userType = userType;
Expand Down Expand Up @@ -66,19 +72,21 @@ public Object visitItemFilter(ItemFilterContext ctx) {
}

private Class<?> checkType(String type) {
// if (Class.forName(type)) {
// if (schemaRegistry.findTypeDefinitionByType(new QName(type)) == null) {
// errorList.add(new AxiomQueryError(null,
// null,
// 0, 0,
// "Does not existing type " + type,
// null)
// );
// } else {
// this.type = schemaRegistry.findTypeDefinitionByType(new QName(type));
// }
return null;
}

private ItemDefinition<?> checkItemPath(@Nullable Class<?> type, String path) {
ItemDefinition<?> itemDefinition = PrismContext.get().getSchemaRegistry().findObjectDefinitionByCompileTimeClass(this.userType);
ItemDefinition<?> itemDefinition = schemaRegistry.findObjectDefinitionByCompileTimeClass(this.userType);
ItemPath itemPath = ItemPathHolder.parseFromString(path);

if (itemDefinition.findItemDefinition(itemPath, ItemDefinition.class) == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.evolveum.midpoint.prism.ItemDefinition;
import com.evolveum.midpoint.prism.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.PrismReferenceDefinition;
import com.evolveum.midpoint.prism.impl.PrismObjectDefinitionImpl;

import java.util.List;

Expand All @@ -21,7 +22,7 @@ public static List<String> findFilterNamesByItemDefinition(ItemDefinition<?> ite

if (ruleContext instanceof FilterNameContext || ruleContext instanceof FilterNameAliasContext) {

if (itemDefinition instanceof PrismPropertyDefinition) {
if (itemDefinition instanceof PrismPropertyDefinition || itemDefinition instanceof PrismObjectDefinitionImpl) {
suggestions.add(EQUAL.getLocalPart());
suggestions.add(LESS.getLocalPart());
suggestions.add(GREATER.getLocalPart());
Expand Down

0 comments on commit 663ed12

Please sign in to comment.