001/*
002 * Copyright 2015-2024 the original author or authors
003 *
004 * This software is licensed under the Apache License, Version 2.0,
005 * the GNU Lesser General Public License version 2 or later ("LGPL")
006 * and the WTFPL.
007 * You may choose either license to govern your use of this software only
008 * upon the condition that you accept all of the terms of either
009 * the Apache License 2.0, the LGPL 2.1+ or the WTFPL.
010 */
011package org.minidns;
012
013import java.util.Collections;
014import java.util.LinkedHashSet;
015import java.util.Set;
016
017import org.minidns.dnsname.DnsName;
018import org.minidns.record.Data;
019import org.minidns.record.Record;
020import org.minidns.record.Record.CLASS;
021import org.minidns.record.Record.TYPE;
022
023public final class RrSet {
024
025    public final DnsName name;
026    public final TYPE type;
027    public final CLASS clazz;
028    public final Set<Record<? extends Data>> records;
029
030    private RrSet(DnsName name, TYPE type, CLASS clazz, Set<Record<? extends Data>> records) {
031        this.name = name;
032        this.type = type;
033        this.clazz = clazz;
034        this.records = Collections.unmodifiableSet(records);
035    }
036
037    @Override
038    public String toString() {
039        StringBuilder sb = new StringBuilder();
040        sb.append(name).append('\t').append(clazz).append('\t').append(type).append('\n');
041        for (Record<?> record : records) {
042            sb.append(record).append('\n');
043        }
044        return sb.toString();
045    }
046
047    public static Builder builder() {
048        return new Builder();
049    }
050
051    public static final class Builder {
052        private DnsName name;
053        private TYPE type;
054        private CLASS clazz;
055        Set<Record<? extends Data>> records = new LinkedHashSet<>(8);
056
057        private Builder() {
058        }
059
060        public Builder addRecord(Record<? extends Data> record) {
061            if (name == null) {
062                name = record.name;
063                type = record.type;
064                clazz = record.clazz;
065            } else if (!couldContain(record)) {
066                throw new IllegalArgumentException(
067                        "Can not add " + record + " to RRSet " + name + ' ' + type + ' ' + clazz);
068            }
069
070            boolean didNotExist = records.add(record);
071            assert didNotExist;
072
073            return this;
074        }
075
076        public boolean couldContain(Record<? extends Data> record) {
077            if (name == null) {
078                return true;
079            }
080            return name.equals(record.name) && type == record.type && clazz == record.clazz;
081        }
082
083        public boolean addIfPossible(Record<? extends Data> record) {
084            if (!couldContain(record)) {
085                return false;
086            }
087            addRecord(record);
088            return true;
089        }
090
091        public RrSet build() {
092            if (name == null) {
093                // There is no RR added to this builder.
094                throw new IllegalStateException();
095            }
096            return new RrSet(name, type, clazz, records);
097        }
098    }
099}