Integrate AbstractIetfInetUtil 85/105985/2
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 16 May 2023 01:23:44 +0000 (03:23 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 16 May 2023 01:50:20 +0000 (03:50 +0200)
We have a single specialization, remove INSTANCE and make sure methods
are static.

JIRA: MDSAL-826
Change-Id: I051482f26837d216bbd68c3705beb0c6ec609b2d
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
model/ietf/rfc6991-ietf-inet-types/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev130715/AbstractIetfInetUtil.java [deleted file]
model/ietf/rfc6991-ietf-inet-types/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev130715/IetfInetUtil.java
model/ietf/rfc6991-ietf-inet-types/src/test/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev130715/IetfInetUtilTest.java

diff --git a/model/ietf/rfc6991-ietf-inet-types/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev130715/AbstractIetfInetUtil.java b/model/ietf/rfc6991-ietf-inet-types/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev130715/AbstractIetfInetUtil.java
deleted file mode 100644 (file)
index 729a303..0000000
+++ /dev/null
@@ -1,641 +0,0 @@
-/*
- * Copyright (c) 2016 Pantheon Technologies s.r.o. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.annotations.Beta;
-import com.google.common.net.InetAddresses;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.AbstractMap.SimpleImmutableEntry;
-import java.util.Map.Entry;
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.mdsal.binding.spec.reflect.StringValueObjectFactory;
-import org.opendaylight.mdsal.model.ietf.util.Ipv4Utils;
-import org.opendaylight.mdsal.model.ietf.util.Ipv6Utils;
-
-/**
- * A set of utility methods to efficiently instantiate various ietf-inet-types DTOs.
- */
-@Beta
-@SuppressWarnings("checkstyle:classTypeParameterName")
-public abstract class AbstractIetfInetUtil {
-    private static final StringValueObjectFactory<Ipv4AddressNoZone> V4NZ_FACTORY =
-        StringValueObjectFactory.create(Ipv4AddressNoZone.class, "0.0.0.0");
-    private static final StringValueObjectFactory<Ipv4Prefix> P4_FACTORY =
-        StringValueObjectFactory.create(Ipv4Prefix.class, "0.0.0.0/0");
-    private static final StringValueObjectFactory<Ipv6AddressNoZone> V6NZ_FACTORY =
-        StringValueObjectFactory.create(Ipv6AddressNoZone.class, "::0");
-    private static final StringValueObjectFactory<Ipv6Prefix> P6_FACTORY =
-        StringValueObjectFactory.create(Ipv6Prefix.class, "::0/0");
-
-    /**
-     * Create an IpAddress by interpreting input bytes as an IPv4 or IPv6 address, based on array length.
-     *
-     * @param bytes 4-byte (IPv4) or 6-byte (IPv6) array
-     * @return An IpAddress object
-     * @throws IllegalArgumentException if bytes has length different from 4 or 6
-     * @throws NullPointerException if bytes is null
-     */
-    public final @NonNull IpAddress ipAddressFor(final byte @NonNull[] bytes) {
-        return switch (bytes.length) {
-            case Ipv4Utils.INET4_LENGTH -> new IpAddress(ipv4AddressFor(bytes));
-            case Ipv6Utils.INET6_LENGTH -> new IpAddress(ipv6AddressFor(bytes));
-            default -> throwInvalidArray(bytes);
-        };
-    }
-
-    public final @NonNull IpAddress ipAddressFor(final @NonNull InetAddress addr) {
-        requireAddress(addr);
-        if (addr instanceof Inet4Address) {
-            return new IpAddress(ipv4AddressFor(addr));
-        } else if (addr instanceof Inet6Address) {
-            return new IpAddress(ipv6AddressFor(addr));
-        } else {
-            throw unhandledAddress(addr);
-        }
-    }
-
-    private static <T> @NonNull T requireAddress(final T addr) {
-        return requireNonNull(addr, "Address must not be null");
-    }
-
-    /**
-     * Create an IpAddress by interpreting input bytes as an IPv4 or IPv6 address, based on array length.
-     *
-     * @param bytes 4-byte (IPv4) or 6-byte (IPv6) array
-     * @return A no-zone IpAddress object
-     * @throws IllegalArgumentException if bytes has length different from 4 or 6
-     * @throws NullPointerException if bytes is null
-     */
-    public final @NonNull IpAddressNoZone ipAddressNoZoneFor(final byte @NonNull[] bytes) {
-        return switch (bytes.length) {
-            case Ipv4Utils.INET4_LENGTH -> new IpAddressNoZone(ipv4AddressFor(bytes));
-            case Ipv6Utils.INET6_LENGTH -> new IpAddressNoZone(ipv6AddressFor(bytes));
-            default -> throwInvalidArray(bytes);
-        };
-    }
-
-    public final @NonNull IpAddressNoZone ipAddressNoZoneFor(final @NonNull InetAddress addr) {
-        requireAddress(addr);
-        if (addr instanceof Inet4Address) {
-            return new IpAddressNoZone(ipv4AddressFor(addr));
-        } else if (addr instanceof Inet6Address) {
-            return new IpAddressNoZone(ipv6AddressFor(addr));
-        } else {
-            throw unhandledAddress(addr);
-        }
-    }
-
-    private static <T> T throwInvalidArray(final byte[] bytes) {
-        throw new IllegalArgumentException("Invalid array length " + bytes.length);
-    }
-
-    private static IllegalArgumentException unhandledAddress(final InetAddress addr) {
-        return new IllegalArgumentException("Unhandled address " + addr);
-    }
-
-    /**
-     * Create an IpPrefix by combining the address with a mask. The address
-     * bytes are interpreted as an address and the specified mask is concatenated to
-     * it. The address bytes are not masked.
-     *
-     * @param bytes Input address as a 4-byte (IPv4) or 16-byte (IPv6) array
-     * @param mask Prefix mask
-     * @return An IpPrefix object
-     * @throws IllegalArgumentException if bytes has length different from 4 or 16 or if mask is not
-     *         in range 0-32 or 0-128 respectively
-     * @throws NullPointerException if bytes is null
-     */
-    public final @NonNull IpPrefix ipPrefixFor(final byte @NonNull[] bytes, final int mask) {
-        return switch (bytes.length) {
-            case Ipv4Utils.INET4_LENGTH -> new IpPrefix(ipv4PrefixFor(bytes, mask));
-            case Ipv6Utils.INET6_LENGTH -> new IpPrefix(ipv6PrefixFor(bytes, mask));
-            default -> throwInvalidArray(bytes);
-        };
-    }
-
-    public final @NonNull IpPrefix ipPrefixFor(final @NonNull InetAddress addr, final int mask) {
-        requireAddress(addr);
-        if (addr instanceof Inet4Address) {
-            return new IpPrefix(ipv4PrefixFor(addr, mask));
-        } else if (addr instanceof Inet6Address) {
-            return new IpPrefix(ipv6PrefixFor(addr, mask));
-        } else {
-            throw unhandledAddress(addr);
-        }
-    }
-
-    public final @NonNull IpPrefix ipPrefixFor(final @NonNull IpAddress addr) {
-        final var v4 = addr.getIpv4Address();
-        return v4 != null ? new IpPrefix(ipv4PrefixFor(v4)) : new IpPrefix(ipv6PrefixFor(coerceIpv6Address(addr)));
-    }
-
-    public final @NonNull IpPrefix ipPrefixForNoZone(final @NonNull IpAddressNoZone addr) {
-        final var v4 = addr.getIpv4AddressNoZone();
-        return v4 != null ? new IpPrefix(ipv4PrefixFor(inet4AddressForNoZone(v4)))
-            : new IpPrefix(ipv6PrefixFor(coerceIpv6AddressNoZone(addr)));
-    }
-
-    public final @NonNull InetAddress inetAddressFor(final @NonNull IpAddress addr) {
-        final var v4 = addr.getIpv4Address();
-        return v4 != null ? inet4AddressFor(v4) : inet6AddressFor(coerceIpv6Address(addr));
-    }
-
-    public final @NonNull InetAddress inetAddressForNoZone(final @NonNull IpAddressNoZone addr) {
-        final var v4 = addr.getIpv4AddressNoZone();
-        return v4 != null ? inet4AddressForNoZone(v4) : inet6AddressForNoZone(coerceIpv6AddressNoZone(addr));
-    }
-
-    public final @NonNull Inet4Address inet4AddressFor(final @NonNull Ipv4Address addr) {
-        try {
-            return (Inet4Address) InetAddress.getByAddress(ipv4AddressBytes(addr));
-        } catch (UnknownHostException e) {
-            throw new IllegalArgumentException("Invalid address " + addr, e);
-        }
-    }
-
-    public final @NonNull Inet4Address inet4AddressForNoZone(final @NonNull Ipv4AddressNoZone addr) {
-        try {
-            return (Inet4Address) InetAddress.getByAddress(ipv4AddressNoZoneBytes(addr));
-        } catch (UnknownHostException e) {
-            throw new IllegalArgumentException("Invalid address " + addr, e);
-        }
-    }
-
-    public final @NonNull Inet6Address inet6AddressFor(final @NonNull Ipv6Address addr) {
-        try {
-            return (Inet6Address) InetAddress.getByAddress(ipv6AddressBytes(addr));
-        } catch (UnknownHostException e) {
-            throw new IllegalArgumentException("Invalid address " + addr, e);
-        }
-    }
-
-    public final @NonNull Inet6Address inet6AddressForNoZone(final @NonNull Ipv6AddressNoZone addr) {
-        try {
-            return (Inet6Address) InetAddress.getByAddress(ipv6AddressNoZoneBytes(addr));
-        } catch (UnknownHostException e) {
-            throw new IllegalArgumentException("Invalid address " + addr, e);
-        }
-    }
-
-    /**
-     * Create an Ipv4AddressNoZone by interpreting input bytes as an IPv4 address.
-     *
-     * @param bytes 4-byte array
-     * @return An Ipv4AddressNoZone object
-     * @throws IllegalArgumentException if bytes has length different from 4
-     * @throws NullPointerException if bytes is null
-     */
-    public final @NonNull Ipv4AddressNoZone ipv4AddressFor(final byte @NonNull[] bytes) {
-        return V4NZ_FACTORY.newInstance(Ipv4Utils.addressString(bytes));
-    }
-
-    /**
-     * Create an Ipv4AddressNoZone by interpreting an {@link Inet4Address}.
-     *
-     * @param addr An {@link Inet4Address}
-     * @return An Ipv4AddressNoZone object
-     * @throws IllegalArgumentException if addr is not an {@link Inet4Address}
-     * @throws NullPointerException if addr is null
-     */
-    public final @NonNull Ipv4AddressNoZone ipv4AddressFor(final @NonNull InetAddress addr) {
-        return V4NZ_FACTORY.newInstance(addressStringV4(addr));
-    }
-
-    /**
-     * Create an Ipv4AddressNoZone by interpreting input 32 bits as an IPv4 address in big-endian format.
-     *
-     * @param bits 32 bits, big endian
-     * @return An Ipv4AddressNoZone object
-     */
-    public final @NonNull Ipv4AddressNoZone ipv4AddressFor(final int bits) {
-        return V4NZ_FACTORY.newInstance(Ipv4Utils.addressString(bits));
-    }
-
-    /**
-     * Create an Ipv4AddressNoZone by interpreting an Ipv4Address.
-     *
-     * @param addr An Ipv4Address
-     * @return An Ipv4AddressNoZone object
-     * @throws NullPointerException if addr is null
-     */
-    public final @NonNull Ipv4AddressNoZone ipv4AddressNoZoneFor(final @NonNull Ipv4Address addr) {
-        requireAddress(addr);
-        return addr instanceof Ipv4AddressNoZone noZone ? noZone
-            :  V4NZ_FACTORY.newInstance(stripZone(addr.getValue()));
-    }
-
-    public final @NonNull Ipv4AddressNoZone ipv4AddressFrom(final @NonNull Ipv4Prefix prefix) {
-        return prefixToAddress(V4NZ_FACTORY, prefix.getValue());
-    }
-
-    public final byte @NonNull[] ipv4AddressBytes(final @NonNull Ipv4Address addr) {
-        /*
-         * This implementation relies heavily on the input string having been validated to comply with
-         * the Ipv4Address pattern, which may include a zone index.
-         */
-        final var str = addr.getValue();
-        final int percent = str.indexOf('%');
-        return Ipv4Utils.addressBytes(str, percent == -1 ? str.length() : percent);
-    }
-
-    public final int ipv4AddressBits(final @NonNull Ipv4Address addr) {
-        final var str = addr.getValue();
-        final int percent = str.indexOf('%');
-        return Ipv4Utils.addressBits(str, percent == -1 ? str.length() : percent);
-    }
-
-    public final byte @NonNull[] ipv4AddressNoZoneBytes(final @NonNull Ipv4AddressNoZone addr) {
-        /*
-         * This implementation relies heavily on the input string having been validated to comply with
-         * the Ipv4AddressNoZone pattern, which must not include a zone index.
-         */
-        final String str = addr.getValue();
-        return Ipv4Utils.addressBytes(str, str.length());
-    }
-
-    public final int ipv4AddressNoZoneBits(final @NonNull Ipv4AddressNoZone addr) {
-        final var str = addr.getValue();
-        return Ipv4Utils.addressBits(str, str.length());
-    }
-
-    /**
-     * Create a /32 Ipv4Prefix by interpreting input bytes as an IPv4 address.
-     *
-     * @param bytes four-byte array
-     * @return An Ipv4Prefix object
-     * @throws IllegalArgumentException if bytes has length different from 4
-     * @throws NullPointerException if bytes is null
-     */
-    public final @NonNull Ipv4Prefix ipv4PrefixFor(final byte @NonNull[] bytes) {
-        return P4_FACTORY.newInstance(prefixStringV4(bytes));
-    }
-
-    /**
-     * Create a Ipv4Prefix by combining the address with a mask. The address
-     * bytes are interpreted as an address and the specified mask is concatenated to
-     * it. The address bytes are not masked, hence input <code>address = { 1, 2, 3, 4 }</code>
-     * and <code>mask=24</code> will result in <code>1.2.3.4/24</code>.
-     *
-     * @param address Input address as a 4-byte array
-     * @param mask Prefix mask
-     * @return An Ipv4Prefix object
-     * @throws IllegalArgumentException if bytes has length different from 4 or if mask is not in range 0-32
-     * @throws NullPointerException if bytes is null
-     */
-    public final @NonNull Ipv4Prefix ipv4PrefixFor(final byte @NonNull[] address, final int mask) {
-        return P4_FACTORY.newInstance(prefixStringV4(address, mask));
-    }
-
-    /**
-     * Create a /32 Ipv4Prefix for an {@link Inet4Address}.
-     *
-     * @param addr An {@link Inet4Address}
-     * @return An Ipv4Prefix object
-     * @throws IllegalArgumentException if addr is not an Inet4Address
-     * @throws NullPointerException if addr is null
-     */
-    public final @NonNull Ipv4Prefix ipv4PrefixFor(final @NonNull InetAddress addr) {
-        return P4_FACTORY.newInstance(addressStringV4(addr) + "/32");
-    }
-
-    /**
-     * Create a Ipv4Prefix by combining the address with a mask. The address bytes are not masked.
-     *
-     * @param addr An {@link Inet4Address}
-     * @param mask Prefix mask
-     * @return An Ipv4Prefix object
-     * @throws IllegalArgumentException if addr is not an Inet4Address or if mask is not in range 0-32
-     * @throws NullPointerException if addr is null
-     */
-    public final @NonNull Ipv4Prefix ipv4PrefixFor(final @NonNull InetAddress addr, final int mask) {
-        return newIpv4Prefix(addressStringV4(addr), mask);
-    }
-
-    public final @NonNull Ipv4Prefix ipv4PrefixFor(final @NonNull Ipv4Address addr) {
-        return P4_FACTORY.newInstance(stripZone(addr.getValue()) + "/32");
-    }
-
-    public final @NonNull Ipv4Prefix ipv4PrefixFor(final @NonNull Ipv4Address addr, final int mask) {
-        return newIpv4Prefix(stripZone(addr.getValue()), mask);
-    }
-
-    public final @NonNull Ipv4Prefix ipv4PrefixForNoZone(final @NonNull Ipv4AddressNoZone addr) {
-        return P4_FACTORY.newInstance(addr.getValue() + "/32");
-    }
-
-    public final @NonNull Ipv4Prefix ipv4PrefixForNoZone(final @NonNull Ipv4AddressNoZone addr, final int mask) {
-        return newIpv4Prefix(addr.getValue(), mask);
-    }
-
-    public final @NonNull Ipv4Prefix ipv4PrefixForShort(final byte @NonNull[] address, final int mask) {
-        if (mask == 0) {
-            // Easy case, reuse the template
-            return P4_FACTORY.getTemplate();
-        }
-
-        return v4PrefixForShort(address, 0, mask / Byte.SIZE + (mask % Byte.SIZE == 0 ? 0 : 1), mask);
-    }
-
-    public final @NonNull Ipv4Prefix ipv4PrefixForShort(final byte @NonNull[] array, final int startOffset,
-            final int mask) {
-        if (mask == 0) {
-            // Easy case, reuse the template
-            return P4_FACTORY.getTemplate();
-        }
-
-        return v4PrefixForShort(array, startOffset, mask / Byte.SIZE + (mask % Byte.SIZE == 0 ? 0 : 1), mask);
-    }
-
-    private static String stripZone(final String str) {
-        final int percent = str.indexOf('%');
-        return percent == -1 ? str : str.substring(0, percent);
-    }
-
-    private @NonNull Ipv4Prefix newIpv4Prefix(final String addr, final int mask) {
-        checkArgument(mask >= 0 && mask <= 32, "Invalid mask %s", mask);
-        return P4_FACTORY.newInstance(addr + '/' + mask);
-    }
-
-    public final @NonNull Entry<Ipv4AddressNoZone, Integer> splitIpv4Prefix(final @NonNull Ipv4Prefix prefix) {
-        return splitPrefix(V4NZ_FACTORY, prefix.getValue());
-    }
-
-    public final byte @NonNull[] ipv4PrefixToBytes(final @NonNull Ipv4Prefix prefix) {
-        final var str = prefix.getValue();
-        final int slash = str.lastIndexOf('/');
-
-        final byte[] bytes = new byte[Ipv4Utils.INET4_LENGTH + 1];
-        Ipv4Utils.fillIpv4Bytes(bytes, 0, str, 0, slash);
-        bytes[Ipv4Utils.INET4_LENGTH] = (byte)Integer.parseInt(str.substring(slash + 1), 10);
-        return bytes;
-    }
-
-    /**
-     * Create an Ipv6Address by interpreting input bytes as an IPv6 address.
-     *
-     * @param bytes 16-byte array
-     * @return An Ipv6Address object
-     * @throws IllegalArgumentException if bytes has length different from 16
-     * @throws NullPointerException if bytes is null
-     */
-    public final @NonNull Ipv6AddressNoZone ipv6AddressFor(final byte @NonNull[] bytes) {
-        return V6NZ_FACTORY.newInstance(addressStringV6(bytes));
-    }
-
-    /**
-     * Create an Ipv6Address by interpreting an {@link Inet6Address}.
-     *
-     * @param addr An {@link Inet6Address}
-     * @return An Ipv6Address object
-     * @throws IllegalArgumentException if addr is not an {@link Inet6Address}
-     * @throws NullPointerException if addr is null
-     */
-    public final @NonNull Ipv6AddressNoZone ipv6AddressFor(final @NonNull InetAddress addr) {
-        return V6NZ_FACTORY.newInstance(addressStringV6(addr));
-    }
-
-    /**
-     * Create an Ipv6AddressNoZone by interpreting an Ipv6Address.
-     *
-     * @param addr An Ipv6Address
-     * @return An Ipv6AddressNoZone object
-     * @throws NullPointerException if addr is null
-     */
-    public final @NonNull Ipv6AddressNoZone ipv6AddressNoZoneFor(final @NonNull Ipv6Address addr) {
-        requireAddress(addr);
-        return addr instanceof Ipv6AddressNoZone noZone ? noZone
-                : V6NZ_FACTORY.newInstance(stripZone(addr.getValue()));
-    }
-
-    public final @NonNull Ipv6AddressNoZone ipv6AddressFrom(final @NonNull Ipv6Prefix prefix) {
-        return prefixToAddress(V6NZ_FACTORY, prefix.getValue());
-    }
-
-    public final byte @NonNull[] ipv6AddressBytes(final @NonNull Ipv6Address addr) {
-        final var str = addr.getValue();
-        final int percent = str.indexOf('%');
-        return ipv6StringBytes(str, percent == -1 ? str.length() : percent);
-    }
-
-    public final byte @NonNull[] ipv6AddressNoZoneBytes(final @NonNull Ipv6Address addr) {
-        final var str = addr.getValue();
-        return ipv6StringBytes(str, str.length());
-    }
-
-    private static byte @NonNull[] ipv6StringBytes(final @NonNull String str, final int limit) {
-        final byte[] bytes = new byte[Ipv6Utils.INET6_LENGTH];
-        Ipv6Utils.fillIpv6Bytes(bytes, str, limit);
-        return bytes;
-    }
-
-    /**
-     * Create a /128 Ipv6Prefix by interpreting input bytes as an IPv6 address.
-     *
-     * @param bytes four-byte array
-     * @return An Ipv6Prefix object
-     * @throws IllegalArgumentException if bytes has length different from 16
-     * @throws NullPointerException if bytes is null
-     */
-    public final @NonNull Ipv6Prefix ipv6PrefixFor(final byte @NonNull[] bytes) {
-        return P6_FACTORY.newInstance(addressStringV6(bytes) + "/128");
-    }
-
-    /**
-     * Create a Ipv6Prefix by combining the address with a mask. The address
-     * bytes are interpreted as an address and the specified mask is concatenated to
-     * it. The address bytes are not masked.
-     *
-     * @param address Input address as a 16-byte array
-     * @param mask Prefix mask
-     * @return An Ipv6Prefix object
-     * @throws IllegalArgumentException if bytes has length different from 16 or if mask is not in range 0-128
-     * @throws NullPointerException if bytes is null
-     */
-    public final @NonNull Ipv6Prefix ipv6PrefixFor(final byte @NonNull[] address, final int mask) {
-        checkArgument(mask >= 0 && mask <= 128, "Invalid mask %s", mask);
-        return P6_FACTORY.newInstance(addressStringV6(address) + '/' + mask);
-    }
-
-    /**
-     * Create a /128 Ipv6Prefix by interpreting input bytes as an IPv6 address.
-     *
-     * @param addr an {@link Inet6Address}
-     * @return An Ipv6Prefix object
-     * @throws IllegalArgumentException if addr is not an Inet6Address
-     * @throws NullPointerException if addr is null
-     */
-    public final @NonNull Ipv6Prefix ipv6PrefixFor(final @NonNull InetAddress addr) {
-        return P6_FACTORY.newInstance(addressStringV6(addr) + "/128");
-    }
-
-    /**
-     * Create a Ipv6Prefix by combining the address with a mask. The address
-     * bytes are interpreted as an address and the specified mask is concatenated to
-     * it. The address bytes are not masked.
-     *
-     * @param addr Input address
-     * @param mask Prefix mask
-     * @return An Ipv6Prefix object
-     * @throws IllegalArgumentException if addr is not an Inet6Address or if mask is not in range 0-128
-     * @throws NullPointerException if addr is null
-     */
-    public final @NonNull Ipv6Prefix ipv6PrefixFor(final @NonNull InetAddress addr, final int mask) {
-        checkArgument(mask >= 0 && mask <= 128, "Invalid mask %s", mask);
-        return P6_FACTORY.newInstance(addressStringV6(addr) + '/' + mask);
-    }
-
-    public final @NonNull Ipv6Prefix ipv6PrefixFor(final @NonNull Ipv6Address addr) {
-        return P6_FACTORY.newInstance(stripZone(addr.getValue()) + "/128");
-    }
-
-    public final @NonNull Ipv6Prefix ipv6PrefixFor(final @NonNull Ipv6Address addr, final int mask) {
-        return newIpv6Prefix(stripZone(addr.getValue()), mask);
-    }
-
-    public final @NonNull Ipv6Prefix ipv6PrefixForNoZone(final @NonNull Ipv6AddressNoZone addr) {
-        return P6_FACTORY.newInstance(addr.getValue() + "/128");
-    }
-
-    public final @NonNull Ipv6Prefix ipv6PrefixForNoZone(final @NonNull Ipv6AddressNoZone addr, final int mask) {
-        return newIpv6Prefix(addr.getValue(), mask);
-    }
-
-    public final @NonNull Ipv6Prefix ipv6PrefixForShort(final byte @NonNull[] address, final int mask) {
-        return ipv6PrefixForShort(address, 0, mask);
-    }
-
-    public final @NonNull Ipv6Prefix ipv6PrefixForShort(final byte @NonNull[] array, final int startOffset,
-            final int mask) {
-        if (mask == 0) {
-            // Easy case, reuse the template
-            return P6_FACTORY.getTemplate();
-        }
-
-        checkArgument(mask > 0 && mask <= 128, "Invalid mask %s", mask);
-        final int size = mask / Byte.SIZE + (mask % Byte.SIZE == 0 ? 0 : 1);
-
-        // Until we can instantiate an IPv6 address for a partial array, use a temporary buffer
-        byte[] tmp = new byte[Ipv6Utils.INET6_LENGTH];
-        System.arraycopy(array, startOffset, tmp, 0, size);
-        return ipv6PrefixFor(tmp, mask);
-    }
-
-    private Ipv6Prefix newIpv6Prefix(final String addr, final int mask) {
-        checkArgument(mask >= 0 && mask <= 128, "Invalid mask %s", mask);
-        return P6_FACTORY.newInstance(addr + '/' + mask);
-    }
-
-    public final @NonNull Entry<Ipv6AddressNoZone, Integer> splitIpv6Prefix(final @NonNull Ipv6Prefix prefix) {
-        return splitPrefix(V6NZ_FACTORY, prefix.getValue());
-    }
-
-    private static <T> @NonNull T prefixToAddress(final StringValueObjectFactory<T> factory, final String str) {
-        return factory.newInstance(str.substring(0, str.lastIndexOf('/')));
-    }
-
-    private static <T> @NonNull Entry<T, Integer> splitPrefix(final StringValueObjectFactory<T> factory,
-            final String str) {
-        final int slash = str.lastIndexOf('/');
-        return new SimpleImmutableEntry<>(factory.newInstance(str.substring(0, slash)),
-                Integer.valueOf(str.substring(slash + 1)));
-    }
-
-    public final byte @NonNull[] ipv6PrefixToBytes(final @NonNull Ipv6Prefix prefix) {
-        final var str = prefix.getValue();
-        final byte[] bytes = new byte[Ipv6Utils.INET6_LENGTH + 1];
-        final int slash = str.lastIndexOf('/');
-        Ipv6Utils.fillIpv6Bytes(bytes, str, slash);
-        bytes[Ipv6Utils.INET6_LENGTH] = (byte)Integer.parseInt(str.substring(slash + 1), 10);
-        return bytes;
-    }
-
-    private static @NonNull String addressStringV4(final InetAddress addr) {
-        requireAddress(addr);
-        checkArgument(addr instanceof Inet4Address, "Address has to be an Inet4Address");
-        return addr.getHostAddress();
-    }
-
-    private static String addressStringV6(final byte @NonNull[] bytes) {
-        checkArgument(bytes.length == Ipv6Utils.INET6_LENGTH, "IPv6 address length is 16 bytes");
-
-        try {
-            return addressStringV6(Inet6Address.getByAddress(null, bytes, null));
-        } catch (UnknownHostException e) {
-            throw new IllegalArgumentException(String.format("Invalid input %s", bytes), e);
-        }
-    }
-
-    private static String addressStringV6(final InetAddress addr) {
-        requireAddress(addr);
-        checkArgument(addr instanceof Inet6Address, "Address has to be an Inet6Address");
-        return addressStringV6((Inet6Address) addr);
-    }
-
-    private static String addressStringV6(final Inet6Address addr) {
-        return InetAddresses.toAddrString(addr);
-    }
-
-    private static String prefixStringV4(final byte @NonNull[] bytes) {
-        final StringBuilder sb = new StringBuilder(18);
-        Ipv4Utils.appendIpv4String(sb, bytes);
-        return sb.append("/32").toString();
-    }
-
-    private static String prefixStringV4(final byte @NonNull[] bytes, final int mask) {
-        checkArgument(mask >= 0 && mask <= 32, "Invalid mask %s", mask);
-
-        final StringBuilder sb = new StringBuilder(18);
-        Ipv4Utils.appendIpv4String(sb, bytes);
-        return sb.append('/').append(mask).toString();
-    }
-
-    private @NonNull Ipv4Prefix v4PrefixForShort(final byte @NonNull[] array, final int startOffset, final int size,
-            final int mask) {
-        if (startOffset == 0 && size == Ipv4Utils.INET4_LENGTH && array.length == Ipv4Utils.INET4_LENGTH) {
-            // Easy case, fall back to non-short
-            return ipv4PrefixFor(array, mask);
-        }
-
-        final StringBuilder sb = new StringBuilder(18);
-
-        // Add from address
-        sb.append(Byte.toUnsignedInt(array[startOffset]));
-        for (int i = 1; i < size; i++) {
-            sb.append('.').append(Byte.toUnsignedInt(array[startOffset + i]));
-        }
-
-        // Add zeros
-        for (int i = size; i < Ipv4Utils.INET4_LENGTH; i++) {
-            sb.append(".0");
-        }
-
-        // Add mask
-        checkArgument(mask > 0 && mask <= 32, "Invalid mask %s", mask);
-        sb.append('/').append(mask);
-
-        return P4_FACTORY.newInstance(sb.toString());
-    }
-
-    private static @NonNull Ipv6Address coerceIpv6Address(final @NonNull IpAddress addr) {
-        final var ret = addr.getIpv6Address();
-        checkArgument(ret != null, "Address %s is neither IPv4 nor IPv6", addr);
-        return ret;
-    }
-
-    private static @NonNull Ipv6AddressNoZone coerceIpv6AddressNoZone(final @NonNull IpAddressNoZone addr) {
-        final var ret = addr.getIpv6AddressNoZone();
-        checkArgument(ret != null, "Address %s is neither IPv4 nor IPv6", addr);
-        return ret;
-    }
-}
index ae7943f2f91142b48149bcc548491a1695ad89ed..5060ed73223dd5de3821210f2ff69ac17b300263 100644 (file)
@@ -7,22 +7,39 @@
  */
 package org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Verify.verify;
+import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.Beta;
+import com.google.common.net.InetAddresses;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.AbstractMap.SimpleImmutableEntry;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map.Entry;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.spec.reflect.StringValueObjectFactory;
+import org.opendaylight.mdsal.model.ietf.util.Ipv4Utils;
+import org.opendaylight.mdsal.model.ietf.util.Ipv6Utils;
 
 /**
- * A set of utility methods to efficiently instantiate various ietf-inet-types DTOs.
+ * A set of utility methods to efficiently instantiate various {@code ietf-inet-types} DTOs.
  */
-@Beta
-public final class IetfInetUtil extends AbstractIetfInetUtil {
-    public static final @NonNull IetfInetUtil INSTANCE = new IetfInetUtil();
-
+public final class IetfInetUtil {
+    private static final StringValueObjectFactory<Ipv4AddressNoZone> V4NZ_FACTORY =
+        StringValueObjectFactory.create(Ipv4AddressNoZone.class, "0.0.0.0");
+    private static final StringValueObjectFactory<Ipv4Prefix> P4_FACTORY =
+        StringValueObjectFactory.create(Ipv4Prefix.class, "0.0.0.0/0");
+    private static final StringValueObjectFactory<Ipv6AddressNoZone> V6NZ_FACTORY =
+        StringValueObjectFactory.create(Ipv6AddressNoZone.class, "::0");
+    private static final StringValueObjectFactory<Ipv6Prefix> P6_FACTORY =
+        StringValueObjectFactory.create(Ipv6Prefix.class, "::0/0");
     private static final Pattern HOST_IPV4_PATTERN = Pattern.compile(
         "(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"
             + "(%[\\p{N}\\p{L}]+)?");
@@ -50,10 +67,6 @@ public final class IetfInetUtil extends AbstractIetfInetUtil {
         IPPREFIX_IPV4_PATTERN = Pattern.compile(Ipv4Prefix.PATTERN_CONSTANTS.get(0));
     }
 
-    private IetfInetUtil() {
-        // Hidden on purpose
-    }
-
     @Beta
     public static Host hostFor(final String str) {
         final Matcher ipv4Matcher = HOST_IPV4_PATTERN.matcher(str);
@@ -115,4 +128,605 @@ public final class IetfInetUtil extends AbstractIetfInetUtil {
         return IPPREFIX_IPV4_PATTERN.matcher(defaultValue).matches() ? new IpPrefix(new Ipv4Prefix(defaultValue))
                 : new IpPrefix(new Ipv6Prefix(defaultValue));
     }
+
+    /**
+     * Create an IpAddress by interpreting input bytes as an IPv4 or IPv6 address, based on array length.
+     *
+     * @param bytes 4-byte (IPv4) or 6-byte (IPv6) array
+     * @return An IpAddress object
+     * @throws IllegalArgumentException if bytes has length different from 4 or 6
+     * @throws NullPointerException if bytes is null
+     */
+    public static @NonNull IpAddress ipAddressFor(final byte @NonNull[] bytes) {
+        return switch (bytes.length) {
+            case Ipv4Utils.INET4_LENGTH -> new IpAddress(ipv4AddressFor(bytes));
+            case Ipv6Utils.INET6_LENGTH -> new IpAddress(ipv6AddressFor(bytes));
+            default -> throwInvalidArray(bytes);
+        };
+    }
+
+    public static @NonNull IpAddress ipAddressFor(final @NonNull InetAddress addr) {
+        requireAddress(addr);
+        if (addr instanceof Inet4Address) {
+            return new IpAddress(ipv4AddressFor(addr));
+        } else if (addr instanceof Inet6Address) {
+            return new IpAddress(ipv6AddressFor(addr));
+        } else {
+            throw unhandledAddress(addr);
+        }
+    }
+
+    private static <T> @NonNull T requireAddress(final T addr) {
+        return requireNonNull(addr, "Address must not be null");
+    }
+
+    /**
+     * Create an IpAddress by interpreting input bytes as an IPv4 or IPv6 address, based on array length.
+     *
+     * @param bytes 4-byte (IPv4) or 6-byte (IPv6) array
+     * @return A no-zone IpAddress object
+     * @throws IllegalArgumentException if bytes has length different from 4 or 6
+     * @throws NullPointerException if bytes is null
+     */
+    public static @NonNull IpAddressNoZone ipAddressNoZoneFor(final byte @NonNull[] bytes) {
+        return switch (bytes.length) {
+            case Ipv4Utils.INET4_LENGTH -> new IpAddressNoZone(ipv4AddressFor(bytes));
+            case Ipv6Utils.INET6_LENGTH -> new IpAddressNoZone(ipv6AddressFor(bytes));
+            default -> throwInvalidArray(bytes);
+        };
+    }
+
+    public static @NonNull IpAddressNoZone ipAddressNoZoneFor(final @NonNull InetAddress addr) {
+        requireAddress(addr);
+        if (addr instanceof Inet4Address) {
+            return new IpAddressNoZone(ipv4AddressFor(addr));
+        } else if (addr instanceof Inet6Address) {
+            return new IpAddressNoZone(ipv6AddressFor(addr));
+        } else {
+            throw unhandledAddress(addr);
+        }
+    }
+
+    private static <T> T throwInvalidArray(final byte[] bytes) {
+        throw new IllegalArgumentException("Invalid array length " + bytes.length);
+    }
+
+    private static IllegalArgumentException unhandledAddress(final InetAddress addr) {
+        return new IllegalArgumentException("Unhandled address " + addr);
+    }
+
+    /**
+     * Create an IpPrefix by combining the address with a mask. The address
+     * bytes are interpreted as an address and the specified mask is concatenated to
+     * it. The address bytes are not masked.
+     *
+     * @param bytes Input address as a 4-byte (IPv4) or 16-byte (IPv6) array
+     * @param mask Prefix mask
+     * @return An IpPrefix object
+     * @throws IllegalArgumentException if bytes has length different from 4 or 16 or if mask is not
+     *         in range 0-32 or 0-128 respectively
+     * @throws NullPointerException if bytes is null
+     */
+    public static @NonNull IpPrefix ipPrefixFor(final byte @NonNull[] bytes, final int mask) {
+        return switch (bytes.length) {
+            case Ipv4Utils.INET4_LENGTH -> new IpPrefix(ipv4PrefixFor(bytes, mask));
+            case Ipv6Utils.INET6_LENGTH -> new IpPrefix(ipv6PrefixFor(bytes, mask));
+            default -> throwInvalidArray(bytes);
+        };
+    }
+
+    public static @NonNull IpPrefix ipPrefixFor(final @NonNull InetAddress addr, final int mask) {
+        requireAddress(addr);
+        if (addr instanceof Inet4Address) {
+            return new IpPrefix(ipv4PrefixFor(addr, mask));
+        } else if (addr instanceof Inet6Address) {
+            return new IpPrefix(ipv6PrefixFor(addr, mask));
+        } else {
+            throw unhandledAddress(addr);
+        }
+    }
+
+    public static @NonNull IpPrefix ipPrefixFor(final @NonNull IpAddress addr) {
+        final var v4 = addr.getIpv4Address();
+        return v4 != null ? new IpPrefix(ipv4PrefixFor(v4)) : new IpPrefix(ipv6PrefixFor(coerceIpv6Address(addr)));
+    }
+
+    public static @NonNull IpPrefix ipPrefixForNoZone(final @NonNull IpAddressNoZone addr) {
+        final var v4 = addr.getIpv4AddressNoZone();
+        return v4 != null ? new IpPrefix(ipv4PrefixFor(inet4AddressForNoZone(v4)))
+            : new IpPrefix(ipv6PrefixFor(coerceIpv6AddressNoZone(addr)));
+    }
+
+    public static @NonNull InetAddress inetAddressFor(final @NonNull IpAddress addr) {
+        final var v4 = addr.getIpv4Address();
+        return v4 != null ? inet4AddressFor(v4) : inet6AddressFor(coerceIpv6Address(addr));
+    }
+
+    public static @NonNull InetAddress inetAddressForNoZone(final @NonNull IpAddressNoZone addr) {
+        final var v4 = addr.getIpv4AddressNoZone();
+        return v4 != null ? inet4AddressForNoZone(v4) : inet6AddressForNoZone(coerceIpv6AddressNoZone(addr));
+    }
+
+    public static @NonNull Inet4Address inet4AddressFor(final @NonNull Ipv4Address addr) {
+        try {
+            return (Inet4Address) InetAddress.getByAddress(ipv4AddressBytes(addr));
+        } catch (UnknownHostException e) {
+            throw new IllegalArgumentException("Invalid address " + addr, e);
+        }
+    }
+
+    public static @NonNull Inet4Address inet4AddressForNoZone(final @NonNull Ipv4AddressNoZone addr) {
+        try {
+            return (Inet4Address) InetAddress.getByAddress(ipv4AddressNoZoneBytes(addr));
+        } catch (UnknownHostException e) {
+            throw new IllegalArgumentException("Invalid address " + addr, e);
+        }
+    }
+
+    public static @NonNull Inet6Address inet6AddressFor(final @NonNull Ipv6Address addr) {
+        try {
+            return (Inet6Address) InetAddress.getByAddress(ipv6AddressBytes(addr));
+        } catch (UnknownHostException e) {
+            throw new IllegalArgumentException("Invalid address " + addr, e);
+        }
+    }
+
+    public static @NonNull Inet6Address inet6AddressForNoZone(final @NonNull Ipv6AddressNoZone addr) {
+        try {
+            return (Inet6Address) InetAddress.getByAddress(ipv6AddressNoZoneBytes(addr));
+        } catch (UnknownHostException e) {
+            throw new IllegalArgumentException("Invalid address " + addr, e);
+        }
+    }
+
+    /**
+     * Create an Ipv4AddressNoZone by interpreting input bytes as an IPv4 address.
+     *
+     * @param bytes 4-byte array
+     * @return An Ipv4AddressNoZone object
+     * @throws IllegalArgumentException if bytes has length different from 4
+     * @throws NullPointerException if bytes is null
+     */
+    public static @NonNull Ipv4AddressNoZone ipv4AddressFor(final byte @NonNull[] bytes) {
+        return V4NZ_FACTORY.newInstance(Ipv4Utils.addressString(bytes));
+    }
+
+    /**
+     * Create an Ipv4AddressNoZone by interpreting an {@link Inet4Address}.
+     *
+     * @param addr An {@link Inet4Address}
+     * @return An Ipv4AddressNoZone object
+     * @throws IllegalArgumentException if addr is not an {@link Inet4Address}
+     * @throws NullPointerException if addr is null
+     */
+    public static @NonNull Ipv4AddressNoZone ipv4AddressFor(final @NonNull InetAddress addr) {
+        return V4NZ_FACTORY.newInstance(addressStringV4(addr));
+    }
+
+    /**
+     * Create an Ipv4AddressNoZone by interpreting input 32 bits as an IPv4 address in big-endian format.
+     *
+     * @param bits 32 bits, big endian
+     * @return An Ipv4AddressNoZone object
+     */
+    public static @NonNull Ipv4AddressNoZone ipv4AddressFor(final int bits) {
+        return V4NZ_FACTORY.newInstance(Ipv4Utils.addressString(bits));
+    }
+
+    /**
+     * Create an Ipv4AddressNoZone by interpreting an Ipv4Address.
+     *
+     * @param addr An Ipv4Address
+     * @return An Ipv4AddressNoZone object
+     * @throws NullPointerException if {@code addr} is {@code null}
+     */
+    public static @NonNull Ipv4AddressNoZone ipv4AddressNoZoneFor(final @NonNull Ipv4Address addr) {
+        requireAddress(addr);
+        return addr instanceof Ipv4AddressNoZone noZone ? noZone
+            :  V4NZ_FACTORY.newInstance(stripZone(addr.getValue()));
+    }
+
+    public static @NonNull Ipv4AddressNoZone ipv4AddressFrom(final @NonNull Ipv4Prefix prefix) {
+        return prefixToAddress(V4NZ_FACTORY, prefix.getValue());
+    }
+
+    public static byte @NonNull[] ipv4AddressBytes(final @NonNull Ipv4Address addr) {
+        /*
+         * This implementation relies heavily on the input string having been validated to comply with
+         * the Ipv4Address pattern, which may include a zone index.
+         */
+        final var str = addr.getValue();
+        final int percent = str.indexOf('%');
+        return Ipv4Utils.addressBytes(str, percent == -1 ? str.length() : percent);
+    }
+
+    public static int ipv4AddressBits(final @NonNull Ipv4Address addr) {
+        final var str = addr.getValue();
+        final int percent = str.indexOf('%');
+        return Ipv4Utils.addressBits(str, percent == -1 ? str.length() : percent);
+    }
+
+    public static byte @NonNull[] ipv4AddressNoZoneBytes(final @NonNull Ipv4AddressNoZone addr) {
+        /*
+         * This implementation relies heavily on the input string having been validated to comply with
+         * the Ipv4AddressNoZone pattern, which must not include a zone index.
+         */
+        final String str = addr.getValue();
+        return Ipv4Utils.addressBytes(str, str.length());
+    }
+
+    public static int ipv4AddressNoZoneBits(final @NonNull Ipv4AddressNoZone addr) {
+        final var str = addr.getValue();
+        return Ipv4Utils.addressBits(str, str.length());
+    }
+
+    /**
+     * Create a /32 Ipv4Prefix by interpreting input bytes as an IPv4 address.
+     *
+     * @param bytes four-byte array
+     * @return An Ipv4Prefix object
+     * @throws IllegalArgumentException if bytes has length different from 4
+     * @throws NullPointerException if bytes is null
+     */
+    public static @NonNull Ipv4Prefix ipv4PrefixFor(final byte @NonNull[] bytes) {
+        return P4_FACTORY.newInstance(prefixStringV4(bytes));
+    }
+
+    /**
+     * Create a Ipv4Prefix by combining the address with a mask. The address
+     * bytes are interpreted as an address and the specified mask is concatenated to
+     * it. The address bytes are not masked, hence input <code>address = { 1, 2, 3, 4 }</code>
+     * and <code>mask=24</code> will result in <code>1.2.3.4/24</code>.
+     *
+     * @param address Input address as a 4-byte array
+     * @param mask Prefix mask
+     * @return An Ipv4Prefix object
+     * @throws IllegalArgumentException if bytes has length different from 4 or if mask is not in range 0-32
+     * @throws NullPointerException if bytes is null
+     */
+    public static @NonNull Ipv4Prefix ipv4PrefixFor(final byte @NonNull[] address, final int mask) {
+        return P4_FACTORY.newInstance(prefixStringV4(address, mask));
+    }
+
+    /**
+     * Create a /32 Ipv4Prefix for an {@link Inet4Address}.
+     *
+     * @param addr An {@link Inet4Address}
+     * @return An Ipv4Prefix object
+     * @throws IllegalArgumentException if addr is not an Inet4Address
+     * @throws NullPointerException if addr is null
+     */
+    public static @NonNull Ipv4Prefix ipv4PrefixFor(final @NonNull InetAddress addr) {
+        return P4_FACTORY.newInstance(addressStringV4(addr) + "/32");
+    }
+
+    /**
+     * Create a Ipv4Prefix by combining the address with a mask. The address bytes are not masked.
+     *
+     * @param addr An {@link Inet4Address}
+     * @param mask Prefix mask
+     * @return An Ipv4Prefix object
+     * @throws IllegalArgumentException if addr is not an Inet4Address or if mask is not in range 0-32
+     * @throws NullPointerException if addr is null
+     */
+    public static @NonNull Ipv4Prefix ipv4PrefixFor(final @NonNull InetAddress addr, final int mask) {
+        return newIpv4Prefix(addressStringV4(addr), mask);
+    }
+
+    public static @NonNull Ipv4Prefix ipv4PrefixFor(final @NonNull Ipv4Address addr) {
+        return P4_FACTORY.newInstance(stripZone(addr.getValue()) + "/32");
+    }
+
+    public static @NonNull Ipv4Prefix ipv4PrefixFor(final @NonNull Ipv4Address addr, final int mask) {
+        return newIpv4Prefix(stripZone(addr.getValue()), mask);
+    }
+
+    public static @NonNull Ipv4Prefix ipv4PrefixForNoZone(final @NonNull Ipv4AddressNoZone addr) {
+        return P4_FACTORY.newInstance(addr.getValue() + "/32");
+    }
+
+    public static @NonNull Ipv4Prefix ipv4PrefixForNoZone(final @NonNull Ipv4AddressNoZone addr, final int mask) {
+        return newIpv4Prefix(addr.getValue(), mask);
+    }
+
+    public static @NonNull Ipv4Prefix ipv4PrefixForShort(final byte @NonNull[] address, final int mask) {
+        if (mask == 0) {
+            // Easy case, reuse the template
+            return P4_FACTORY.getTemplate();
+        }
+
+        return v4PrefixForShort(address, 0, mask / Byte.SIZE + (mask % Byte.SIZE == 0 ? 0 : 1), mask);
+    }
+
+    public static @NonNull Ipv4Prefix ipv4PrefixForShort(final byte @NonNull[] array, final int startOffset,
+            final int mask) {
+        if (mask == 0) {
+            // Easy case, reuse the template
+            return P4_FACTORY.getTemplate();
+        }
+
+        return v4PrefixForShort(array, startOffset, mask / Byte.SIZE + (mask % Byte.SIZE == 0 ? 0 : 1), mask);
+    }
+
+    private static String stripZone(final String str) {
+        final int percent = str.indexOf('%');
+        return percent == -1 ? str : str.substring(0, percent);
+    }
+
+    private static @NonNull Ipv4Prefix newIpv4Prefix(final String addr, final int mask) {
+        checkArgument(mask >= 0 && mask <= 32, "Invalid mask %s", mask);
+        return P4_FACTORY.newInstance(addr + '/' + mask);
+    }
+
+    public static @NonNull Entry<Ipv4AddressNoZone, Integer> splitIpv4Prefix(final @NonNull Ipv4Prefix prefix) {
+        return splitPrefix(V4NZ_FACTORY, prefix.getValue());
+    }
+
+    public static byte @NonNull[] ipv4PrefixToBytes(final @NonNull Ipv4Prefix prefix) {
+        final var str = prefix.getValue();
+        final int slash = str.lastIndexOf('/');
+
+        final byte[] bytes = new byte[Ipv4Utils.INET4_LENGTH + 1];
+        Ipv4Utils.fillIpv4Bytes(bytes, 0, str, 0, slash);
+        bytes[Ipv4Utils.INET4_LENGTH] = (byte)Integer.parseInt(str.substring(slash + 1), 10);
+        return bytes;
+    }
+
+    /**
+     * Create an Ipv6Address by interpreting input bytes as an IPv6 address.
+     *
+     * @param bytes 16-byte array
+     * @return An Ipv6Address object
+     * @throws IllegalArgumentException if bytes has length different from 16
+     * @throws NullPointerException if {@code bytes} is {@code null}
+     */
+    public static @NonNull Ipv6AddressNoZone ipv6AddressFor(final byte @NonNull[] bytes) {
+        return V6NZ_FACTORY.newInstance(addressStringV6(bytes));
+    }
+
+    /**
+     * Create an Ipv6Address by interpreting an {@link Inet6Address}.
+     *
+     * @param addr An {@link Inet6Address}
+     * @return An Ipv6Address object
+     * @throws IllegalArgumentException if @{code addr} is not an {@link Inet6Address}
+     * @throws NullPointerException if {@code addr} is {@code null}
+     */
+    public static @NonNull Ipv6AddressNoZone ipv6AddressFor(final @NonNull InetAddress addr) {
+        return V6NZ_FACTORY.newInstance(addressStringV6(addr));
+    }
+
+    /**
+     * Create an Ipv6AddressNoZone by interpreting an Ipv6Address.
+     *
+     * @param addr An Ipv6Address
+     * @return An Ipv6AddressNoZone object
+     * @throws NullPointerException if addr is null
+     */
+    public static @NonNull Ipv6AddressNoZone ipv6AddressNoZoneFor(final @NonNull Ipv6Address addr) {
+        requireAddress(addr);
+        return addr instanceof Ipv6AddressNoZone noZone ? noZone
+                : V6NZ_FACTORY.newInstance(stripZone(addr.getValue()));
+    }
+
+    public static @NonNull Ipv6AddressNoZone ipv6AddressFrom(final @NonNull Ipv6Prefix prefix) {
+        return prefixToAddress(V6NZ_FACTORY, prefix.getValue());
+    }
+
+    public static byte @NonNull[] ipv6AddressBytes(final @NonNull Ipv6Address addr) {
+        final var str = addr.getValue();
+        final int percent = str.indexOf('%');
+        return ipv6StringBytes(str, percent == -1 ? str.length() : percent);
+    }
+
+    public static byte @NonNull[] ipv6AddressNoZoneBytes(final @NonNull Ipv6Address addr) {
+        final var str = addr.getValue();
+        return ipv6StringBytes(str, str.length());
+    }
+
+    private static byte @NonNull[] ipv6StringBytes(final @NonNull String str, final int limit) {
+        final byte[] bytes = new byte[Ipv6Utils.INET6_LENGTH];
+        Ipv6Utils.fillIpv6Bytes(bytes, str, limit);
+        return bytes;
+    }
+
+    /**
+     * Create a /128 Ipv6Prefix by interpreting input bytes as an IPv6 address.
+     *
+     * @param bytes four-byte array
+     * @return An Ipv6Prefix object
+     * @throws IllegalArgumentException if bytes has length different from 16
+     * @throws NullPointerException if bytes is null
+     */
+    public static @NonNull Ipv6Prefix ipv6PrefixFor(final byte @NonNull[] bytes) {
+        return P6_FACTORY.newInstance(addressStringV6(bytes) + "/128");
+    }
+
+    /**
+     * Create a Ipv6Prefix by combining the address with a mask. The address
+     * bytes are interpreted as an address and the specified mask is concatenated to
+     * it. The address bytes are not masked.
+     *
+     * @param address Input address as a 16-byte array
+     * @param mask Prefix mask
+     * @return An Ipv6Prefix object
+     * @throws IllegalArgumentException if bytes has length different from 16 or if mask is not in range 0-128
+     * @throws NullPointerException if bytes is null
+     */
+    public static @NonNull Ipv6Prefix ipv6PrefixFor(final byte @NonNull[] address, final int mask) {
+        checkArgument(mask >= 0 && mask <= 128, "Invalid mask %s", mask);
+        return P6_FACTORY.newInstance(addressStringV6(address) + '/' + mask);
+    }
+
+    /**
+     * Create a /128 Ipv6Prefix by interpreting input bytes as an IPv6 address.
+     *
+     * @param addr an {@link Inet6Address}
+     * @return An Ipv6Prefix object
+     * @throws IllegalArgumentException if addr is not an Inet6Address
+     * @throws NullPointerException if addr is null
+     */
+    public static @NonNull Ipv6Prefix ipv6PrefixFor(final @NonNull InetAddress addr) {
+        return P6_FACTORY.newInstance(addressStringV6(addr) + "/128");
+    }
+
+    /**
+     * Create a Ipv6Prefix by combining the address with a mask. The address
+     * bytes are interpreted as an address and the specified mask is concatenated to
+     * it. The address bytes are not masked.
+     *
+     * @param addr Input address
+     * @param mask Prefix mask
+     * @return An Ipv6Prefix object
+     * @throws IllegalArgumentException if addr is not an Inet6Address or if mask is not in range 0-128
+     * @throws NullPointerException if addr is null
+     */
+    public static @NonNull Ipv6Prefix ipv6PrefixFor(final @NonNull InetAddress addr, final int mask) {
+        checkArgument(mask >= 0 && mask <= 128, "Invalid mask %s", mask);
+        return P6_FACTORY.newInstance(addressStringV6(addr) + '/' + mask);
+    }
+
+    public static @NonNull Ipv6Prefix ipv6PrefixFor(final @NonNull Ipv6Address addr) {
+        return P6_FACTORY.newInstance(stripZone(addr.getValue()) + "/128");
+    }
+
+    public static @NonNull Ipv6Prefix ipv6PrefixFor(final @NonNull Ipv6Address addr, final int mask) {
+        return newIpv6Prefix(stripZone(addr.getValue()), mask);
+    }
+
+    public static @NonNull Ipv6Prefix ipv6PrefixForNoZone(final @NonNull Ipv6AddressNoZone addr) {
+        return P6_FACTORY.newInstance(addr.getValue() + "/128");
+    }
+
+    public static @NonNull Ipv6Prefix ipv6PrefixForNoZone(final @NonNull Ipv6AddressNoZone addr, final int mask) {
+        return newIpv6Prefix(addr.getValue(), mask);
+    }
+
+    public static @NonNull Ipv6Prefix ipv6PrefixForShort(final byte @NonNull[] address, final int mask) {
+        return ipv6PrefixForShort(address, 0, mask);
+    }
+
+    public static @NonNull Ipv6Prefix ipv6PrefixForShort(final byte @NonNull[] array, final int startOffset,
+            final int mask) {
+        if (mask == 0) {
+            // Easy case, reuse the template
+            return P6_FACTORY.getTemplate();
+        }
+
+        checkArgument(mask > 0 && mask <= 128, "Invalid mask %s", mask);
+        final int size = mask / Byte.SIZE + (mask % Byte.SIZE == 0 ? 0 : 1);
+
+        // Until we can instantiate an IPv6 address for a partial array, use a temporary buffer
+        byte[] tmp = new byte[Ipv6Utils.INET6_LENGTH];
+        System.arraycopy(array, startOffset, tmp, 0, size);
+        return ipv6PrefixFor(tmp, mask);
+    }
+
+    private static Ipv6Prefix newIpv6Prefix(final String addr, final int mask) {
+        checkArgument(mask >= 0 && mask <= 128, "Invalid mask %s", mask);
+        return P6_FACTORY.newInstance(addr + '/' + mask);
+    }
+
+    public static @NonNull Entry<Ipv6AddressNoZone, Integer> splitIpv6Prefix(final @NonNull Ipv6Prefix prefix) {
+        return splitPrefix(V6NZ_FACTORY, prefix.getValue());
+    }
+
+    private static <T> @NonNull T prefixToAddress(final StringValueObjectFactory<T> factory, final String str) {
+        return factory.newInstance(str.substring(0, str.lastIndexOf('/')));
+    }
+
+    private static <T> @NonNull Entry<T, Integer> splitPrefix(final StringValueObjectFactory<T> factory,
+            final String str) {
+        final int slash = str.lastIndexOf('/');
+        return new SimpleImmutableEntry<>(factory.newInstance(str.substring(0, slash)),
+                Integer.valueOf(str.substring(slash + 1)));
+    }
+
+    public static byte @NonNull[] ipv6PrefixToBytes(final @NonNull Ipv6Prefix prefix) {
+        final var str = prefix.getValue();
+        final byte[] bytes = new byte[Ipv6Utils.INET6_LENGTH + 1];
+        final int slash = str.lastIndexOf('/');
+        Ipv6Utils.fillIpv6Bytes(bytes, str, slash);
+        bytes[Ipv6Utils.INET6_LENGTH] = (byte)Integer.parseInt(str.substring(slash + 1), 10);
+        return bytes;
+    }
+
+    private static @NonNull String addressStringV4(final InetAddress addr) {
+        requireAddress(addr);
+        checkArgument(addr instanceof Inet4Address, "Address has to be an Inet4Address");
+        return addr.getHostAddress();
+    }
+
+    private static String addressStringV6(final byte @NonNull[] bytes) {
+        checkArgument(bytes.length == Ipv6Utils.INET6_LENGTH, "IPv6 address length is 16 bytes");
+
+        try {
+            return addressStringV6(Inet6Address.getByAddress(null, bytes, null));
+        } catch (UnknownHostException e) {
+            throw new IllegalArgumentException(String.format("Invalid input %s", bytes), e);
+        }
+    }
+
+    private static String addressStringV6(final InetAddress addr) {
+        requireAddress(addr);
+        checkArgument(addr instanceof Inet6Address, "Address has to be an Inet6Address");
+        return addressStringV6((Inet6Address) addr);
+    }
+
+    private static String addressStringV6(final Inet6Address addr) {
+        return InetAddresses.toAddrString(addr);
+    }
+
+    private static String prefixStringV4(final byte @NonNull[] bytes) {
+        final StringBuilder sb = new StringBuilder(18);
+        Ipv4Utils.appendIpv4String(sb, bytes);
+        return sb.append("/32").toString();
+    }
+
+    private static String prefixStringV4(final byte @NonNull[] bytes, final int mask) {
+        checkArgument(mask >= 0 && mask <= 32, "Invalid mask %s", mask);
+
+        final StringBuilder sb = new StringBuilder(18);
+        Ipv4Utils.appendIpv4String(sb, bytes);
+        return sb.append('/').append(mask).toString();
+    }
+
+    private static @NonNull Ipv4Prefix v4PrefixForShort(final byte @NonNull[] array, final int startOffset,
+            final int size, final int mask) {
+        if (startOffset == 0 && size == Ipv4Utils.INET4_LENGTH && array.length == Ipv4Utils.INET4_LENGTH) {
+            // Easy case, fall back to non-short
+            return ipv4PrefixFor(array, mask);
+        }
+
+        final StringBuilder sb = new StringBuilder(18);
+
+        // Add from address
+        sb.append(Byte.toUnsignedInt(array[startOffset]));
+        for (int i = 1; i < size; i++) {
+            sb.append('.').append(Byte.toUnsignedInt(array[startOffset + i]));
+        }
+
+        // Add zeros
+        for (int i = size; i < Ipv4Utils.INET4_LENGTH; i++) {
+            sb.append(".0");
+        }
+
+        // Add mask
+        checkArgument(mask > 0 && mask <= 32, "Invalid mask %s", mask);
+        sb.append('/').append(mask);
+
+        return P4_FACTORY.newInstance(sb.toString());
+    }
+
+    private static @NonNull Ipv6Address coerceIpv6Address(final @NonNull IpAddress addr) {
+        final var ret = addr.getIpv6Address();
+        checkArgument(ret != null, "Address %s is neither IPv4 nor IPv6", addr);
+        return ret;
+    }
+
+    private static @NonNull Ipv6AddressNoZone coerceIpv6AddressNoZone(final @NonNull IpAddressNoZone addr) {
+        final var ret = addr.getIpv6AddressNoZone();
+        checkArgument(ret != null, "Address %s is neither IPv4 nor IPv6", addr);
+        return ret;
+    }
 }
index 6d7f1a8078d93071635f0bcf3f4013ab68cc30f7..85c124d71f297cd308e5cdc1935d18deae9a0c78 100644 (file)
@@ -17,7 +17,6 @@ import static org.junit.Assert.assertThrows;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
-import static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil.INSTANCE;
 
 import com.google.common.net.InetAddresses;
 import java.net.Inet4Address;
@@ -52,32 +51,32 @@ public class IetfInetUtilTest {
 
     @Test
     public void testAddressToString() {
-        assertEquals(new Ipv4Prefix("1.2.3.4/8"), INSTANCE.ipv4PrefixFor(new Ipv4Address("1.2.3.4%1"), 8));
-        assertEquals(new Ipv6Prefix("ff00::/8"), INSTANCE.ipv6PrefixFor(new Ipv6Address("ff00::%bar"), 8));
+        assertEquals(new Ipv4Prefix("1.2.3.4/8"), IetfInetUtil.ipv4PrefixFor(new Ipv4Address("1.2.3.4%1"), 8));
+        assertEquals(new Ipv6Prefix("ff00::/8"), IetfInetUtil.ipv6PrefixFor(new Ipv6Address("ff00::%bar"), 8));
     }
 
     @Test
     public void testIpv4ZoneStripping() {
         final Ipv4AddressNoZone noZone = new Ipv4AddressNoZone("1.2.3.4");
-        assertSame(noZone, INSTANCE.ipv4AddressNoZoneFor(noZone));
+        assertSame(noZone, IetfInetUtil.ipv4AddressNoZoneFor(noZone));
 
         final Ipv4Address withoutZone = new Ipv4Address(noZone);
-        final Ipv4AddressNoZone stripped = INSTANCE.ipv4AddressNoZoneFor(withoutZone);
+        final Ipv4AddressNoZone stripped = IetfInetUtil.ipv4AddressNoZoneFor(withoutZone);
         assertSame(withoutZone.getValue(), stripped.getValue());
 
-        assertEquals(noZone, INSTANCE.ipv4AddressNoZoneFor(new Ipv4Address("1.2.3.4%1")));
+        assertEquals(noZone, IetfInetUtil.ipv4AddressNoZoneFor(new Ipv4Address("1.2.3.4%1")));
     }
 
     @Test
     public void testIpv6ZoneStripping() {
         final Ipv6AddressNoZone noZone = new Ipv6AddressNoZone("ff00::");
-        assertSame(noZone, INSTANCE.ipv6AddressNoZoneFor(noZone));
+        assertSame(noZone, IetfInetUtil.ipv6AddressNoZoneFor(noZone));
 
         final Ipv6Address withoutZone = new Ipv6Address(noZone);
-        final Ipv6AddressNoZone stripped = INSTANCE.ipv6AddressNoZoneFor(withoutZone);
+        final Ipv6AddressNoZone stripped = IetfInetUtil.ipv6AddressNoZoneFor(withoutZone);
         assertSame(withoutZone.getValue(), stripped.getValue());
 
-        assertEquals(noZone, INSTANCE.ipv6AddressNoZoneFor(new Ipv6Address("ff00::%1")));
+        assertEquals(noZone, IetfInetUtil.ipv6AddressNoZoneFor(new Ipv6Address("ff00::%1")));
     }
 
     @Test
@@ -93,32 +92,32 @@ public class IetfInetUtilTest {
         assertV4Equals("128.16.0.127", "%5");
 
         assertEquals(new IpAddress(new Ipv4Address("1.2.3.4")),
-            INSTANCE.ipAddressFor(INSTANCE.ipv4AddressBytes(new Ipv4Address("1.2.3.4"))));
+            IetfInetUtil.ipAddressFor(IetfInetUtil.ipv4AddressBytes(new Ipv4Address("1.2.3.4"))));
         assertNotEquals(new IpAddress(new Ipv4Address("2.3.4.5")),
-            INSTANCE.ipAddressFor(INSTANCE.ipv4AddressBytes(new Ipv4Address("1.2.3.4"))));
+            IetfInetUtil.ipAddressFor(IetfInetUtil.ipv4AddressBytes(new Ipv4Address("1.2.3.4"))));
 
         assertEquals(new IpAddress(new Ipv6Address("fe80::2002:b3ff:fe1e:8329")),
-            INSTANCE.ipAddressFor(INSTANCE.ipv6AddressBytes(new Ipv6Address("FE80::2002:B3FF:FE1E:8329"))));
+            IetfInetUtil.ipAddressFor(IetfInetUtil.ipv6AddressBytes(new Ipv6Address("FE80::2002:B3FF:FE1E:8329"))));
         assertNotEquals(new IpAddress(new Ipv6Address("feff::2002:b3ff:fe1e:8329")),
-            INSTANCE.ipAddressFor(INSTANCE.ipv6AddressBytes(new Ipv6Address("FE80::2002:B3FF:FE1E:8329"))));
+            IetfInetUtil.ipAddressFor(IetfInetUtil.ipv6AddressBytes(new Ipv6Address("FE80::2002:B3FF:FE1E:8329"))));
 
         assertEquals(new IpAddress(new Ipv4Address("1.2.3.4")),
-            INSTANCE.ipAddressFor(INSTANCE.inetAddressFor(new IpAddress(new Ipv4Address("1.2.3.4")))));
+            IetfInetUtil.ipAddressFor(IetfInetUtil.inetAddressFor(new IpAddress(new Ipv4Address("1.2.3.4")))));
         assertNotEquals(new IpAddress(new Ipv4Address("2.3.4.5")),
-            INSTANCE.ipAddressFor(INSTANCE.inetAddressFor(new IpAddress(new Ipv4Address("1.2.3.4")))));
+            IetfInetUtil.ipAddressFor(IetfInetUtil.inetAddressFor(new IpAddress(new Ipv4Address("1.2.3.4")))));
 
         assertEquals(new IpAddress(new Ipv6Address("fe80::2002:b3ff:fe1e:8329")),
-            INSTANCE.ipAddressFor(INSTANCE.inetAddressFor(
+            IetfInetUtil.ipAddressFor(IetfInetUtil.inetAddressFor(
                 new IpAddress(new Ipv6Address("FE80::2002:B3FF:FE1E:8329")))));
         assertNotEquals(new IpAddress(new Ipv6Address("FEFF::2002:B3FF:FE1E:8329")),
-            INSTANCE.ipAddressFor(INSTANCE.inetAddressFor(
+            IetfInetUtil.ipAddressFor(IetfInetUtil.inetAddressFor(
                 new IpAddress(new Ipv6Address("FE80::2002:B3FF:FE1E:8329")))));
     }
 
     @Test
     public void illegalArrayLengthForAddressTest() {
         final IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
-            () -> INSTANCE.ipAddressFor(new byte[] { 0, 0, 0 }));
+            () -> IetfInetUtil.ipAddressFor(new byte[] { 0, 0, 0 }));
         assertEquals("Invalid array length 3", ex.getMessage());
     }
 
@@ -127,14 +126,14 @@ public class IetfInetUtilTest {
         final InetAddress adr = mock(InetAddress.class);
         doReturn("testAddress").when(adr).toString();
         final IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
-            () -> INSTANCE.ipAddressFor(adr));
+            () -> IetfInetUtil.ipAddressFor(adr));
         assertEquals("Unhandled address testAddress", ex.getMessage());
     }
 
     @Test
     public void illegalArrayLengthforPrefixTest() {
         final IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
-            () -> INSTANCE.ipPrefixFor(new byte[] { 0, 0, 0 }, 0));
+            () -> IetfInetUtil.ipPrefixFor(new byte[] { 0, 0, 0 }, 0));
         assertEquals("Invalid array length 3", ex.getMessage());
     }
 
@@ -144,56 +143,63 @@ public class IetfInetUtilTest {
         doReturn("testAddress").when(adr).toString();
 
         final IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
-            () -> INSTANCE.ipPrefixFor(adr, 0));
+            () -> IetfInetUtil.ipPrefixFor(adr, 0));
         assertEquals("Unhandled address testAddress", ex.getMessage());
     }
 
     @Test
     public void ipv4Tests() {
-        assertEquals("1.2.3.4", INSTANCE.ipv4AddressFrom(new Ipv4Prefix("1.2.3.4/16")).getValue());
+        assertEquals("1.2.3.4", IetfInetUtil.ipv4AddressFrom(new Ipv4Prefix("1.2.3.4/16")).getValue());
         final var ipv4address = new Ipv4Address("1.2.3.4");
         final var ipAddress = new IpAddress(ipv4address);
-        assertEquals("1.2.3.4/32", INSTANCE.ipv4PrefixFor(INSTANCE.ipv4AddressBytes(ipv4address)).getValue());
-        assertEquals("1.2.3.4/32", INSTANCE.ipv4PrefixFor(INSTANCE.inetAddressFor(ipAddress)).getValue());
-        assertEquals("1.2.3.4/32", INSTANCE.ipv4PrefixFor(ipv4address).getValue());
-        assertEquals("1.2.3.4/16", INSTANCE.ipv4PrefixFor(ipv4address, 16).getValue());
-
-        assertEquals("0.0.0.0/0", INSTANCE.ipv4PrefixForShort(INSTANCE.ipv4AddressBytes(ipv4address), 0).getValue());
-        assertEquals("1.2.3.4/32", INSTANCE.ipv4PrefixForShort(INSTANCE.ipv4AddressBytes(ipv4address), 32).getValue());
-        assertEquals("0.0.0.0/0", INSTANCE.ipv4PrefixForShort(INSTANCE.ipv4AddressBytes(ipv4address), 0, 0).getValue());
+        assertEquals("1.2.3.4/32", IetfInetUtil.ipv4PrefixFor(IetfInetUtil.ipv4AddressBytes(ipv4address)).getValue());
+        assertEquals("1.2.3.4/32", IetfInetUtil.ipv4PrefixFor(IetfInetUtil.inetAddressFor(ipAddress)).getValue());
+        assertEquals("1.2.3.4/32", IetfInetUtil.ipv4PrefixFor(ipv4address).getValue());
+        assertEquals("1.2.3.4/16", IetfInetUtil.ipv4PrefixFor(ipv4address, 16).getValue());
+
+        assertEquals("0.0.0.0/0",
+            IetfInetUtil.ipv4PrefixForShort(IetfInetUtil.ipv4AddressBytes(ipv4address), 0).getValue());
+        assertEquals("1.2.3.4/32",
+            IetfInetUtil.ipv4PrefixForShort(IetfInetUtil.ipv4AddressBytes(ipv4address), 32).getValue());
+        assertEquals("0.0.0.0/0",
+            IetfInetUtil.ipv4PrefixForShort(IetfInetUtil.ipv4AddressBytes(ipv4address), 0, 0).getValue());
         assertEquals("1.2.3.4/32",
-            INSTANCE.ipv4PrefixForShort(INSTANCE.ipv4AddressBytes(ipv4address), 0, 32).getValue());
-        assertEquals("2.3.4.5/32", INSTANCE.ipv4PrefixForShort(new byte[] { 1, 2, 3, 4, 5 }, 1, 32).getValue());
-        assertEquals("1.0.0.0/1", INSTANCE.ipv4PrefixForShort(new byte[] { 1, 2, 3, 4, 5 }, 0, 1).getValue());
+            IetfInetUtil.ipv4PrefixForShort(IetfInetUtil.ipv4AddressBytes(ipv4address), 0, 32).getValue());
+        assertEquals("2.3.4.5/32", IetfInetUtil.ipv4PrefixForShort(new byte[] { 1, 2, 3, 4, 5 }, 1, 32).getValue());
+        assertEquals("1.0.0.0/1", IetfInetUtil.ipv4PrefixForShort(new byte[] { 1, 2, 3, 4, 5 }, 0, 1).getValue());
 
         final var ipv4Prefix = new Ipv4Prefix("1.2.3.4/16");
-        assertEquals("1.2.3.4", INSTANCE.splitIpv4Prefix(ipv4Prefix).getKey().getValue());
-        assertEquals((Integer) 16, INSTANCE.splitIpv4Prefix(ipv4Prefix).getValue());
-        assertArrayEquals(new byte[] { 1,2,3,4,16 }, INSTANCE.ipv4PrefixToBytes(ipv4Prefix));
+        assertEquals("1.2.3.4", IetfInetUtil.splitIpv4Prefix(ipv4Prefix).getKey().getValue());
+        assertEquals((Integer) 16, IetfInetUtil.splitIpv4Prefix(ipv4Prefix).getValue());
+        assertArrayEquals(new byte[] { 1,2,3,4,16 }, IetfInetUtil.ipv4PrefixToBytes(ipv4Prefix));
     }
 
     @Test
     public void ipv6Tests() {
-        assertEquals("::0", INSTANCE.ipv6AddressFrom(new Ipv6Prefix("::0/128")).getValue());
+        assertEquals("::0", IetfInetUtil.ipv6AddressFrom(new Ipv6Prefix("::0/128")).getValue());
         final var ipv6address = new Ipv6Address("::0");
         final var ipAddress = new IpAddress(ipv6address);
 
-        assertEquals("::/128", INSTANCE.ipv6PrefixFor(INSTANCE.ipv6AddressBytes(ipv6address)).getValue());
-        assertEquals("::/128", INSTANCE.ipv6PrefixFor(INSTANCE.inetAddressFor(ipAddress)).getValue());
-        assertEquals("::0/128", INSTANCE.ipv6PrefixFor(ipv6address).getValue());
-        assertEquals("::0/16", INSTANCE.ipv6PrefixFor(ipv6address, 16).getValue());
-
-        assertEquals("::0/0", INSTANCE.ipv6PrefixForShort(INSTANCE.ipv6AddressBytes(ipv6address), 0).getValue());
-        assertEquals("::/64", INSTANCE.ipv6PrefixForShort(INSTANCE.ipv6AddressBytes(ipv6address), 64).getValue());
-        assertEquals("::0/0", INSTANCE.ipv6PrefixForShort(INSTANCE.ipv6AddressBytes(ipv6address), 0, 0).getValue());
-        assertEquals("::/32", INSTANCE.ipv6PrefixForShort(INSTANCE.ipv6AddressBytes(ipv6address), 0, 32).getValue());
-
-        assertEquals(Map.entry(new Ipv6Address("::"), 32), INSTANCE.splitIpv6Prefix(new Ipv6Prefix("::/32")));
+        assertEquals("::/128", IetfInetUtil.ipv6PrefixFor(IetfInetUtil.ipv6AddressBytes(ipv6address)).getValue());
+        assertEquals("::/128", IetfInetUtil.ipv6PrefixFor(IetfInetUtil.inetAddressFor(ipAddress)).getValue());
+        assertEquals("::0/128", IetfInetUtil.ipv6PrefixFor(ipv6address).getValue());
+        assertEquals("::0/16", IetfInetUtil.ipv6PrefixFor(ipv6address, 16).getValue());
+
+        assertEquals("::0/0",
+            IetfInetUtil.ipv6PrefixForShort(IetfInetUtil.ipv6AddressBytes(ipv6address), 0).getValue());
+        assertEquals("::/64",
+            IetfInetUtil.ipv6PrefixForShort(IetfInetUtil.ipv6AddressBytes(ipv6address), 64).getValue());
+        assertEquals("::0/0",
+            IetfInetUtil.ipv6PrefixForShort(IetfInetUtil.ipv6AddressBytes(ipv6address), 0, 0).getValue());
+        assertEquals("::/32",
+            IetfInetUtil.ipv6PrefixForShort(IetfInetUtil.ipv6AddressBytes(ipv6address), 0, 32).getValue());
+
+        assertEquals(Map.entry(new Ipv6Address("::"), 32), IetfInetUtil.splitIpv6Prefix(new Ipv6Prefix("::/32")));
         assertArrayEquals(new byte[] { 0, 10, 0, 0, 0, 0, 0, 0, 0, 11, 0, 12, 0, 13, 0, 14, 64 },
-            INSTANCE.ipv6PrefixToBytes(new Ipv6Prefix("A::B:C:D:E/64")));
+            IetfInetUtil.ipv6PrefixToBytes(new Ipv6Prefix("A::B:C:D:E/64")));
 
         // verify that an IPv4-mapped IPv6 address gets parsed as an IPv6 address
-        assertEquals("::ffff:ab0:eb", INSTANCE.ipv6AddressFor(
+        assertEquals("::ffff:ab0:eb", IetfInetUtil.ipv6AddressFor(
                 new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xff, (byte) 0xff, 0x0a, (byte) 0xb0, 0, (byte) 0xeb})
                 .getValue());
     }
@@ -201,21 +207,21 @@ public class IetfInetUtilTest {
     @Test
     public void prefixTest() {
         assertEquals(new IpPrefix(new Ipv4Prefix("0.0.0.0/16")),
-            INSTANCE.ipPrefixFor(INSTANCE.inetAddressFor(new IpAddress(new Ipv4Address("0.0.0.0"))), 16));
+            IetfInetUtil.ipPrefixFor(IetfInetUtil.inetAddressFor(new IpAddress(new Ipv4Address("0.0.0.0"))), 16));
         assertEquals(new IpPrefix(new Ipv6Prefix("::/64")),
-            INSTANCE.ipPrefixFor(INSTANCE.inetAddressFor(new IpAddress(new Ipv6Address("::"))), 64));
+            IetfInetUtil.ipPrefixFor(IetfInetUtil.inetAddressFor(new IpAddress(new Ipv6Address("::"))), 64));
 
         assertEquals(new IpPrefix(new Ipv4Prefix("0.0.0.0/16")),
-            INSTANCE.ipPrefixFor(new byte[] { 0, 0, 0, 0 }, 16));
+            IetfInetUtil.ipPrefixFor(new byte[] { 0, 0, 0, 0 }, 16));
         assertEquals(new IpPrefix(new Ipv6Prefix("::/64")),
-            INSTANCE.ipPrefixFor(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 64));
+            IetfInetUtil.ipPrefixFor(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 64));
     }
 
     @Test
     public void inetAddressTest() {
-        assertThat(INSTANCE.inetAddressFor(new IpAddress(new Ipv4Address("1.2.3.4"))),
+        assertThat(IetfInetUtil.inetAddressFor(new IpAddress(new Ipv4Address("1.2.3.4"))),
             instanceOf(Inet4Address.class));
-        assertThat(INSTANCE.inetAddressFor(new IpAddress(new Ipv6Address("FE80::2002:B3FF:FE1E:8329"))),
+        assertThat(IetfInetUtil.inetAddressFor(new IpAddress(new Ipv6Address("FE80::2002:B3FF:FE1E:8329"))),
             instanceOf(Inet6Address.class));
     }
 
@@ -228,7 +234,7 @@ public class IetfInetUtilTest {
         }).when(ipClass).getValue();
 
         final IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
-            () -> INSTANCE.inet4AddressFor(ipClass));
+            () -> IetfInetUtil.inet4AddressFor(ipClass));
         assertEquals("Invalid address testClass", ex.getMessage());
     }
 
@@ -241,36 +247,35 @@ public class IetfInetUtilTest {
         }).when(ipClass).getValue();
 
         final IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
-            () -> INSTANCE.inet6AddressFor(ipClass));
+            () -> IetfInetUtil.inet6AddressFor(ipClass));
         assertEquals("Invalid address testClass", ex.getMessage());
     }
 
     @Test
     public void testIpv4AddressForBits() {
-        assertEquals("1.2.3.4", INSTANCE.ipv4AddressFor(0x01020304).getValue());
-        assertEquals("255.255.255.255", INSTANCE.ipv4AddressFor(0xFFFFFFFF).getValue());
+        assertEquals("1.2.3.4", IetfInetUtil.ipv4AddressFor(0x01020304).getValue());
+        assertEquals("255.255.255.255", IetfInetUtil.ipv4AddressFor(0xFFFFFFFF).getValue());
     }
 
     @Test
     public void testIpv4AddressBits() {
-        assertEquals(0x01020304, INSTANCE.ipv4AddressBits(new Ipv4Address("1.2.3.4")));
-        assertEquals(0xFFFFFFFF, INSTANCE.ipv4AddressBits(new Ipv4Address("255.255.255.255")));
+        assertEquals(0x01020304, IetfInetUtil.ipv4AddressBits(new Ipv4Address("1.2.3.4")));
+        assertEquals(0xFFFFFFFF, IetfInetUtil.ipv4AddressBits(new Ipv4Address("255.255.255.255")));
     }
 
     @Test
     public void testIpv4AddressNoZoneBits() {
-        assertEquals(0x01020304, INSTANCE.ipv4AddressNoZoneBits(new Ipv4AddressNoZone("1.2.3.4")));
-        assertEquals(0xFFFFFFFF, INSTANCE.ipv4AddressNoZoneBits(new Ipv4AddressNoZone("255.255.255.255")));
+        assertEquals(0x01020304, IetfInetUtil.ipv4AddressNoZoneBits(new Ipv4AddressNoZone("1.2.3.4")));
+        assertEquals(0xFFFFFFFF, IetfInetUtil.ipv4AddressNoZoneBits(new Ipv4AddressNoZone("255.255.255.255")));
     }
 
     private static void assertV4Equals(final String literal, final String append) {
         final byte[] expected = InetAddresses.forString(literal).getAddress();
-        final byte[] actual = INSTANCE.ipv4AddressBytes(new Ipv4Address(literal + append));
+        final byte[] actual = IetfInetUtil.ipv4AddressBytes(new Ipv4Address(literal + append));
         assertArrayEquals(expected, actual);
     }
 
     private static void assertV4Equals(final String literal) {
         assertV4Equals(literal, "");
     }
-
 }