class NameAwareAttribute implements Attribute, Iterable<Object> {

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        NameAwareAttribute that = (NameAwareAttribute) o;

        if (id != null ? !id.equals(that.id) : that.id != null) return false;
        if(this.values.size() != that.values.size()) {
            return false;
        }

        if(this.orderMatters != that.orderMatters || this.size() != that.size()) {
            return false;
        }

        if(this.hasValuesAsNames() != that.hasValuesAsNames()) {
            return false;
        }

        Set<?> myValues = this.values;
        Set<?> theirValues = that.values;
        if(this.hasValuesAsNames()) {
            // We have Name values - compare these to get
            // syntactically correct comparison of the values

            myValues = this.valuesAsNames.keySet();
            theirValues = that.valuesAsNames.keySet();
        }

        if(orderMatters) {
            Iterator<?> thisIterator = myValues.iterator();
            Iterator<?> thatIterator = theirValues.iterator();
            while(thisIterator.hasNext()) {
                if(!ObjectUtils.nullSafeEquals(thisIterator.next(), thatIterator.next())) {
                    return false;
                }
            }

            return true;
        } else {
            for (Object value : myValues) {
                if(!CollectionUtils.contains(theirValues.iterator(), value)) {
                    return false;
                }
            }

            return true;
        }
    }

    public  NameAwareAttribute(String id, Object value);
    public  NameAwareAttribute(Attribute attribute);
    public  NameAwareAttribute(String id);
    public  NameAwareAttribute(String id, boolean orderMatters);

}