ObjectExpression.java

package org.sterling.runtime.expression;

import static java.util.Collections.sort;
import static org.sterling.runtime.expression.ExpressionConversions.convertSymbol;
import static org.sterling.runtime.expression.ExpressionFactory.declaration;
import static org.sterling.runtime.expression.ExpressionFactory.member;
import static org.sterling.util.StringUtil.stringify;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import org.sterling.SterlingException;

public class ObjectExpression extends Expression {

    private final Map<Symbol, Expression> members;

    public ObjectExpression(Set<DeclaredExpression> members) {
        Map<Symbol, Expression> map = new HashMap<>();
        for (DeclaredExpression declaration : members) {
            map.put(declaration.getSymbol(), declaration.getExpression());
        }
        this.members = new ConcurrentHashMap<>(map);
    }

    @Override
    public <R, D> R accept(ExpressionVisitor<R, D> visitor, D data) throws SterlingException {
        return visitor.visitObjectExpression(this, data);
    }

    @Override
    public Expression access(Expression member) throws SterlingException {
        Symbol symbol = convertSymbol(member);
        if (members.containsKey(symbol)) {
            return member(this, members.get(symbol));
        } else {
            return super.access(symbol);
        }
    }

    @Override
    public boolean equals(Object o) {
        return o == this || o instanceof ObjectExpression && members.equals(((ObjectExpression) o).members);
    }

    public Set<DeclaredExpression> getMembers() {
        Set<DeclaredExpression> declarations = new HashSet<>();
        for (Symbol symbol : members.keySet()) {
            declarations.add(declaration(symbol, members.get(symbol)));
        }
        return declarations;
    }

    @Override
    public int hashCode() {
        return Objects.hash(members);
    }

    @Override
    public String toString() {
        List<DeclaredExpression> declarations = new ArrayList<>();
        for (Symbol symbol : members.keySet()) {
            declarations.add(declaration(symbol, members.get(symbol)));
        }
        sort(declarations, new DeclarationComparator());
        return stringify(this, declarations);
    }

    private static final class DeclarationComparator implements Comparator<DeclaredExpression> {

        @Override
        public int compare(DeclaredExpression o1, DeclaredExpression o2) {
            return o1.getSymbol().getValue().compareTo(o2.getSymbol().getValue());
        }
    }
}