in transpiler/src/main/java/com/google/cloud/verticals/foundations/dataharmonization/Transpiler.java [841:910]
public AbstractMessage visitSourcePath(SourcePathContext ctx) {
// read path head
ValueSource currentValue = (ValueSource) ctx.sourcePathHead().accept(this);
Source currentSource = buildSource(ctx);
boolean iterate = false;
// start to process path segment
// 1. trim tailing [] and set iterate field if it exists
List<SourcePathSegmentContext> segs = new ArrayList<>(ctx.sourcePathSegment());
if (!segs.isEmpty() && Iterables.getLast(segs).getText().equals("[]")) {
iterate = true;
segs = segs.subList(0, segs.size() - 1);
}
// 2. set up accumulator for segments
StringBuilder path = new StringBuilder();
// 3. loop through all path segment
for (SourcePathSegmentContext seg : segs) {
// 3.1 if the new segment is field or index -> append it to segment
if (seg instanceof PathFieldNameContext) {
String delim = ((PathFieldNameContext) seg).fieldName().PATH_DELIM().getText();
String field = ((PathFieldNameContext) seg).fieldName().getText().substring(delim.length());
path.append(delim);
path.append(TranspilerHelper.preprocessString(field));
} else if (seg instanceof PathIndexContext) {
if (seg.getText().equals("[]")) {
throw new IllegalArgumentException(
"Having iteration in the middle of source path "
+ ctx.getText()
+ " is currently not supported. Please consider using equivalent wildcard"
+ " expression.");
}
path.append(((PathIndexContext) seg).getText());
} else if (seg instanceof PathSelectorContext) {
// 3.2 if the new segment is an selector
// 3.2.1 wrap the previous in get
ValueSource selectee = TranspilerHelper.getPathOnValue(currentValue, currentSource, path);
currentSource = buildSource(seg);
PathSelectorContext pseg = (PathSelectorContext) seg;
FunctionReference selectorRef =
(FunctionReference) pseg.selector().functionName().accept(this);
if (selectorRef.getPackage().isEmpty()) {
selectorRef = FunctionReference.newBuilder(selectorRef).setPackage("*").build();
}
// Use a placeholder for the first argument since it comes from outside the selector:
// selectee[selector <selector expr>] needs to become
// selector(selectee, <selector expr closure>). We've already transpiled selectee, so we
// sub in a placeholder expression and replace it below.
// TODO(rpolyano): Consider using a oneof class instead here.
List<ExpressionContext> args = Arrays.asList(placeholder, pseg.selector().expression());
FunctionCall call =
Functions.getSignature(selectorRef, args.size())
.transpileFunctionCall(this, selectorRef, args, seg);
call = FunctionCall.newBuilder(call).setArgs(0, selectee).build();
currentValue = ValueSource.newBuilder().setFunctionCall(call).build();
path = new StringBuilder();
} else {
throw new IllegalArgumentException("Unexpected path segment type " + seg);
}
}
ValueSource result = TranspilerHelper.getPathOnValue(currentValue, currentSource, path);
ValueSource.Builder resultBuilder = result.toBuilder();
resultBuilder.setMeta(
withSymbol(
resultBuilder.getMetaBuilder(), ctx, environment, variableDefinitionEnvironments));
return resultBuilder.setIterate(iterate).build();
}