001/*
002 * JDrupes Builder
003 * Copyright (C) 2025 Michael N. Lipp
004 * 
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
017 */
018
019package org.jdrupes.builder.core;
020
021import java.util.Collections;
022import java.util.LinkedHashSet;
023import java.util.Objects;
024import java.util.SequencedSet;
025import java.util.Set;
026import org.jdrupes.builder.api.Resource;
027import org.jdrupes.builder.api.ResourceType;
028import org.jdrupes.builder.api.Resources;
029
030/// Represents a set of resources. Resources are added by [add].
031/// The [stream] method returns a stream of the added resources.
032/// The [stream] method preserves the order in which the resources
033/// were added.
034///
035/// @param <T> the type of the contained resources
036///
037public class DefaultResources<T extends Resource> extends ResourceObject
038        implements Resources<T> {
039
040    private final Set<T> content;
041
042    /// Instantiates a new resource set.
043    ///
044    /// @param type the type of this instance as resource
045    ///
046    protected DefaultResources(ResourceType<?> type) {
047        super(type);
048        content = Collections.synchronizedSet(new LinkedHashSet<>());
049    }
050
051    @Override
052    public Resources<T> add(T resource) {
053        content.add(resource);
054        return this;
055    }
056
057    @Override
058    public boolean isEmpty() {
059        return content.isEmpty();
060    }
061
062    @Override
063    @SuppressWarnings({ "PMD.AvoidSynchronizedStatement" })
064    public SequencedSet<T> get() {
065        synchronized (content) {
066            return new LinkedHashSet<>(content);
067        }
068    }
069
070    @Override
071    public Resources<T> clear() {
072        content.clear();
073        return this;
074    }
075
076    @Override
077    public int hashCode() {
078        final int prime = 31;
079        int result = super.hashCode();
080        result = prime * result + Objects.hash(content);
081        return result;
082    }
083
084    @Override
085    public boolean equals(Object obj) {
086        if (this == obj) {
087            return true;
088        }
089        if (!super.equals(obj)) {
090            return false;
091        }
092        return (obj instanceof DefaultResources<?> other)
093            && Objects.equals(content, other.content);
094    }
095
096    @Override
097    public String toString() {
098        return type().toString() + " (" + asOfLocalized()
099            + ") with " + content.size() + " elements";
100    }
101
102}