public AbstractMessage visitSourcePath()

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();
  }