001/*
002 * PermissionsEx
003 * Copyright (C) zml and PermissionsEx contributors
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package ca.stellardrift.permissionsex.impl.subject;
018
019import ca.stellardrift.permissionsex.impl.PermissionsEx;
020import ca.stellardrift.permissionsex.subject.SubjectRef;
021import ca.stellardrift.permissionsex.subject.SubjectType;
022import com.google.errorprone.annotations.concurrent.LazyInit;
023import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
024import org.checkerframework.checker.nullness.qual.Nullable;
025
026public final class LazySubjectRef implements SubjectRef<Object> {
027    private final PermissionsEx<?> pex;
028    private final String type;
029    private final String ident;
030    private @LazyInit @MonotonicNonNull SubjectRef<?> resolved;
031
032    public LazySubjectRef(PermissionsEx<?> pex, String type, String ident) {
033        this.pex = pex;
034        this.type = type;
035        this.ident = ident;
036    }
037
038    @Override
039    @SuppressWarnings("unchecked")
040    public SubjectType<Object> type() {
041        return (SubjectType<Object>) this.resolved().type();
042    }
043
044    @Override
045    public Object identifier() {
046        return this.resolved().serializedIdentifier();
047    }
048
049    public String serializedType() {
050        return this.type;
051    }
052
053    @Override
054    public String serializedIdentifier() {
055        final @Nullable SubjectRef<?> resolved = this.resolved;
056        if (resolved != null) {
057            return resolved.serializedIdentifier();
058        } else {
059            return this.ident;
060        }
061    }
062
063    public SubjectRef<?> resolved() {
064        if (this.resolved != null) {
065            return this.resolved;
066        }
067        return this.resolved = this.pex.deserializeSubjectRef(this.type, this.ident);
068    }
069
070    @Override
071    public int hashCode() {
072        return this.resolved().hashCode();
073    }
074
075    @Override
076    public boolean equals(final Object other) {
077        if (other instanceof LazySubjectRef) {
078            final LazySubjectRef that = (LazySubjectRef) other;
079            if (this.resolved != null || that.resolved != null) {
080                return this.resolved().equals(that.resolved());
081            } else {
082                return this.type.equals(that.type)
083                    && this.ident.equals(that.ident);
084            }
085        } else if (other instanceof SubjectRef<?>) {
086            return this.resolved().equals(other);
087        } else {
088            return false;
089        }
090    }
091
092    @Override
093    public String toString() {
094        return "LazySubjectRef{"
095            + "type=" + this.type
096            + ", identifier=" + this.ident
097            + ", resolved=" + this.resolved
098            + '}';
099    }
100
101}