private String asString(final P<?> p) {
        final StringBuilder sb = new StringBuilder();
        if (p instanceof TextP) {
            sb.append("TextP.").append(p.getPredicateName()).append("(");
            sb.append(argAsString(p.getValue()));
        } else if (p instanceof ConnectiveP) {
            // ConnectiveP gets some special handling because it's reduced to and(P, P, P) and we want it
            // generated the way it was written which was P.and(P).and(P)
            final List<P<?>> list = ((ConnectiveP) p).getPredicates();
            final String connector = p.getPredicateName();
            for (int i = 0; i < list.size(); i++) {
                sb.append(argAsString(list.get(i)));

                // for the first/last P there is no parent to close
                if (i > 0 && i < list.size() - 1) sb.append(")");

                // add teh connector for all but last P
                if (i < list.size() - 1) {
                    sb.append(".").append(connector).append("(");
                }
            }
        } else {
            sb.append("P.").append(p.getPredicateName()).append("(");
            sb.append(argAsString(p.getValue()));
        }
        sb.append(")");
        return sb.toString();
    }
This class helps to build a gremlin-lang compatible string representation based on a {@link TraversalSource}
and then a {@link Traversal}.
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java