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.lang.reflect.Proxy;
022import java.util.Objects;
023import org.jdrupes.builder.api.Proxyable;
024import org.jdrupes.builder.api.Resource;
025import org.jdrupes.builder.api.ResourceType;
026
027/// A base class for [Resource]s.
028///
029public abstract class ResourceObject implements Resource, Proxyable {
030
031    private final ResourceType<?> type;
032
033    /// Create a new instance.
034    ///
035    protected ResourceObject() {
036        this.type = new ResourceType<>(getClass(), null);
037    }
038
039    /// Create a new instance.
040    ///
041    /// @param type the type
042    ///
043    protected ResourceObject(ResourceType<?> type) {
044        this.type = Objects.requireNonNull(type);
045    }
046
047    /* default */ @SuppressWarnings("unchecked")
048    static <T extends Resource> T createResource(ResourceType<T> type) {
049        return (T) Proxy.newProxyInstance(type.rawType().getClassLoader(),
050            new Class<?>[] { type.rawType(), Proxyable.class },
051            new ForwardingHandler(new ResourceObject(type) {}));
052    }
053
054    @Override
055    public ResourceType<?> type() {
056        return type;
057    }
058
059    @Override
060    public int hashCode() {
061        return Objects.hash(type());
062    }
063
064    @Override
065    public boolean equals(Object obj) {
066        if (this == obj) {
067            return true;
068        }
069        if (obj == null) {
070            return false;
071        }
072        return (obj instanceof ResourceObject other)
073            && Objects.equals(type(), other.type());
074    }
075
076    @Override
077    public String toString() {
078        return type().toString() + " (" + asOfLocalized() + ")";
079    }
080}