class DefaultAtlasExpressionProcessor {

    public static void processExpression(DefaultAtlasSession session, String expression) {
        if (expression == null || expression.trim().isEmpty()) {
            return;
        }

        try {
            Map<String, Field> sourceFieldMap = new HashMap<>();
            Field parent = session.head().getSourceField();
            if (parent != null && !AtlasUtil.isEmpty(parent.getDocId()) && !AtlasUtil.isEmpty(parent.getPath())) {
                 sourceFieldMap.put(parent.getDocId() + ":" + parent.getPath(), parent);
            }
            // Anonymous FieldGroup is just a wrapping, peel it off
            if (parent instanceof FieldGroup && AtlasUtil.isEmpty(parent.getPath())) {
                FieldGroup parentGroup = FieldGroup.class.cast(parent);
                for (Field child : parentGroup.getField()) {
                    if (!(AtlasUtil.isEmpty(child.getDocId()) && AtlasUtil.isEmpty(child.getPath()))) {
                         sourceFieldMap.put(child.getDocId() + ":" + child.getPath(), child);
                    }
                }
            }

            Expression parsedExpression = Expression.parse(expression, DefaultAtlasFunctionResolver.getInstance());
            Object answer = parsedExpression.evaluate((path) -> {
                if (path == null || path.isEmpty()) {
                    return null;
                }
                try {
                    String[] splitted = path.split(":", 2);
                    AtlasFieldReader reader = session.getFieldReader(splitted[0]);
                    Field f = sourceFieldMap.get(path);
                    if (f == null) {
                        return null;
                    }
                    session.head().setSourceField(f);
                    return reader.read(session);
                } catch (Exception e) {
                    throw new ExpressionException(e);
                }
            });
            if (answer instanceof Field) {
                session.head().setSourceField((Field)answer);
            } else {
                Field from = session.head().getSourceField();
                SimpleField to = new SimpleField();
                AtlasModelFactory.copyField(from, to, false);
                to.setValue(answer);
                session.head().setSourceField(to);
            }
        } catch (Exception e) {
            AtlasUtil.addAudit(session, null,
                    String.format("Expression processing error: %s", e.getMessage()),
                    expression, AuditStatus.ERROR, null);
            if (LOG.isDebugEnabled()) {
                LOG.debug("", e);
            }
        }
    }

}