class OperationFactory {

    Composite resetResource(ResourceAddress address, Set<String> attributes,
            Metadata metadata) {
        List<Operation> operations = new ArrayList<>();
        ResourceDescription description = metadata.getDescription();

        // collect all attributes from the 'requires' list of this attribute
        // HashMultimap<String, String> requires = HashMultimap.create();
        TreeSet<String> requires = new TreeSet<>();
        ModelNode attributesDescription = description.get(ATTRIBUTES);
        attributes.forEach(attribute -> {
            ModelNode attributeDescription = attributesDescription.get(attribute);
            if (attributeDescription != null && attributeDescription.hasDefined(REQUIRES)) {
                failSafeList(attributeDescription, REQUIRES).forEach(node -> requires.add(node.asString()));
                        /*.map(ModelNode::asString)
                        .forEach(requiresName -> {
                            requires.add(requiresName);
                        });*/
            }
        });

        attributes.stream()
                .map(attribute -> description.findAttribute(ATTRIBUTES, attribute))
                .filter(Objects::nonNull)
                .forEach(property -> {
                    ModelNode attributeDescription = property.getValue();
                    boolean nillable = attributeDescription.hasDefined(NILLABLE) &&
                            attributeDescription.get(NILLABLE).asBoolean();
                    boolean readOnly = attributeDescription.hasDefined(ACCESS_TYPE) &&
                            READ_ONLY.equals(attributeDescription.get(ACCESS_TYPE).asString());
                    boolean alternatives = attributeDescription.hasDefined(ALTERNATIVES) &&
                            !attributeDescription.get(ALTERNATIVES).asList().isEmpty();
                    boolean requiredBy = requires.contains(property.getName());

                    if (nillable && !readOnly && !alternatives && !requiredBy) {
                        boolean hasDefault = attributeDescription.hasDefined(DEFAULT);
                        ModelType type = attributeDescription.get(TYPE).asType();
                        switch (type) {
                            case BIG_DECIMAL:
                            case BIG_INTEGER:
                            case BOOLEAN:
                            case BYTES:
                            case DOUBLE:
                            case INT:
                            case LONG:
                                if (hasDefault) {
                                    operations.add(undefineAttribute(address, attributeName(property.getName())));
                                }
                                break;
                            case EXPRESSION:
                            case LIST:
                            case OBJECT:
                            case PROPERTY:
                            case STRING:
                                operations.add(undefineAttribute(address, attributeName(property.getName())));
                                break;
                            case TYPE:
                            case UNDEFINED:
                                break;
                            default:
                                break;
                        }
                    }
                });
        return new Composite(operations);
    }

    public  OperationFactory();
    public  OperationFactory(Function<String, String> nameFn);

}