/* * Copyright 2015 by Thomas Lottermann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package notaql.engines.hbase.parser.path; import notaql.datamodel.Step; import notaql.engines.hbase.model.path.AnyFamilyStep; import notaql.model.EvaluationException; import notaql.model.path.*; import notaql.parser.TransformationParser; import notaql.parser.antlr.NotaQL2ColumnInBaseVisitor; import notaql.parser.antlr.NotaQL2ColumnInParser; import org.antlr.v4.runtime.misc.NotNull; import java.util.LinkedList; import java.util.List; /** * Extracts an InputPath from given parse tree. */ public class HBaseInputPathVisitor extends NotaQL2ColumnInBaseVisitor<InputPath> { private final TransformationParser parser; private boolean relative; public HBaseInputPathVisitor(TransformationParser parser, boolean relative) { this.parser = parser; this.relative = relative; } /** * Here we parse the .split() method * @param ctx * @return */ @Override public InputPath visitSplittedInputPath(@NotNull NotaQL2ColumnInParser.SplittedInputPathContext ctx) { // TODO: Generify split function? at least encapsulate it for all parsers to use final List<InputPathStep> pathSteps = new LinkedList<>(visit(ctx.firstInputPathStep()).getPathSteps()); if(ctx.atom() != null) { String string = ctx.atom().getText().replace("\\'", "'"); string = string.substring(1, string.length() - 1); pathSteps.add(new StringSplitMethodStep(string)); } else { pathSteps.add(new StringSplitMethodStep()); } pathSteps.add(new AnyBoundCurrentStep()); return new InputPath(relative, pathSteps); } /** * Here we parse the row id input (IN._r) * @param ctx * @return */ @Override public InputPath visitRowInputPathStep(@NotNull NotaQL2ColumnInParser.RowInputPathStepContext ctx) { return new InputPath(relative, new IdStep<>(new Step<>("_id"))); } /** * Here we parse cell input (e.g. IN._c?(@ > 3)). * This also means delegating stuff to another input path parser * @param ctx * @return */ @Override public InputPath visitCellInputPathStep(@NotNull NotaQL2ColumnInParser.CellInputPathStepContext ctx) { final InputPathStep familyStep = ctx.colFamilyFilter==null ? new AnyBoundCurrentStep() : new BoundIdStep<>(new Step<>(ctx.colFamilyFilter.getText())); List<InputPathStep> pathSteps = new LinkedList<>(); pathSteps.add(familyStep); if(ctx.predicate() == null) pathSteps.add(new AnyBoundCurrentStep()); else pathSteps.add(new PredicateStep(parser.getPredicateVisitor().evaluate(ctx.predicate().getText()))); if(ctx.source.getType()==NotaQL2ColumnInParser.Col) pathSteps.add(new NamePathMethodStep()); return new InputPath(relative, pathSteps); } /** * Here we parse constant steps (e.g. IN.a) * @param ctx * @return */ @Override public InputPath visitColIdInputPathStep(@NotNull NotaQL2ColumnInParser.ColIdInputPathStepContext ctx) { final InputPathStep familyStep = ctx.colId().colFamily==null ? new AnyFamilyStep() : new IdStep<>(new Step<>(ctx.colId().colFamily.getText())); return new InputPath( relative, familyStep, new IdStep<>(new Step<>(ctx.colId().colName.getText())) ); } /** * Here we parse resolved paths (e.g. IN.$(IN.a)). * @param ctx * @return */ @Override public InputPath visitResolvedInputPathStep(@NotNull NotaQL2ColumnInParser.ResolvedInputPathStepContext ctx) { final InputPathStep familyStep = ctx.colFamily==null ? new AnyBoundCurrentStep() : new BoundIdStep<>(new Step<>(ctx.colFamily.getText())); return new InputPath( relative, familyStep, new ResolvedIdStep(parser.getInputPathVisitor().evaluateAbsolute(ctx.absoluteInputPath().path().getText())) ); } /** * Here we parse the @ step. This is only allowed in a relative path. * @param ctx * @return */ @Override public InputPath visitRelativeCurrentCellPathStep(@NotNull NotaQL2ColumnInParser.RelativeCurrentCellPathStepContext ctx) { if(!relative) throw new EvaluationException("'IN' is not allowed as input path"); return new InputPath( true ); } }