Unify prefix splitting
[mdsal.git] / model / ietf / ietf-type-util / src / main / java / org / opendaylight / mdsal / model / ietf / util / AbstractIetfInetUtil.java
index be279ee1682d31b5695caeb25bc4359d8a3e9789..4c79def9d3327c170cdc658ea012c72791e9274f 100644 (file)
@@ -15,13 +15,13 @@ 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 javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.binding.util.StringValueObjectFactory;
 
 /**
  * A set of utility methods to efficiently instantiate various ietf-inet-types DTOs.
- *
- * FIXME: IPv6 addresses are not emitted in canonical format as specified by the model.
  */
 @Beta
 public abstract class AbstractIetfInetUtil<A4, P4, A6, P6, A> {
@@ -40,6 +40,10 @@ public abstract class AbstractIetfInetUtil<A4, P4, A6, P6, A> {
 
     protected abstract A ipv4Address(A4 addr);
     protected abstract A ipv6Address(A6 addr);
+    protected abstract String ipv4AddressString(A4 addr);
+    protected abstract String ipv6AddressString(A6 addr);
+    protected abstract String ipv4PrefixString(P4 prefix);
+    protected abstract String ipv6PrefixString(P6 prefix);
 
     @Nonnull public final A ipAddressFor(@Nonnull final byte[] bytes) {
         switch (bytes.length) {
@@ -89,6 +93,10 @@ public abstract class AbstractIetfInetUtil<A4, P4, A6, P6, A> {
         return address4Factory.newInstance(addr.getHostAddress());
     }
 
+    @Nonnull public final A4 ipv4AddressFrom(@Nonnull final P4 prefix) {
+        return prefixToAddress(address4Factory, ipv4PrefixString(prefix));
+    }
+
     /**
      * Create a /32 Ipv4Prefix by interpreting input bytes as an IPv4 address.
      *
@@ -147,6 +155,21 @@ public abstract class AbstractIetfInetUtil<A4, P4, A6, P6, A> {
         return prefix4Factory.newInstance(addr.getHostAddress() + '/' + mask);
     }
 
+    @Nonnull public final P4 ipv4PrefixFor(@Nonnull final A4 addr) {
+        Preconditions.checkNotNull(addr, "Address must not be null");
+        return prefix4Factory.newInstance(ipv4AddressString(addr) + "/32");
+    }
+
+    @Nonnull public final P4 ipv4PrefixFor(@Nonnull final A4 addr, final int mask) {
+        Preconditions.checkNotNull(addr, "Address must not be null");
+        Preconditions.checkArgument(mask >= 0 && mask <= 32, "Invalid mask %s", mask);
+        return prefix4Factory.newInstance(ipv4AddressString(addr) + '/' + mask);
+    }
+
+    @Nonnull public final Entry<A4, Integer> splitIpv4Prefix(@Nonnull final P4 prefix) {
+        return splitPrefix(address4Factory, ipv4PrefixString(prefix));
+    }
+
     /**
      * Create an Ipv6Address by interpreting input bytes as an IPv6 address.
      *
@@ -170,7 +193,11 @@ public abstract class AbstractIetfInetUtil<A4, P4, A6, P6, A> {
     @Nonnull public final A6 ipv6AddressFor(@Nonnull final InetAddress addr) {
         Preconditions.checkNotNull(addr, "Address must not be null");
         Preconditions.checkArgument(addr instanceof Inet6Address, "Address has to be an Inet6Address");
-        return address6Factory.newInstance(addr.getHostAddress());
+        return address6Factory.newInstance(addressStringV6(addr));
+    }
+
+    @Nonnull public final A6 ipv6AddressFrom(@Nonnull final P6 prefix) {
+        return prefixToAddress(address6Factory, ipv6PrefixString(prefix));
     }
 
     /**
@@ -231,6 +258,31 @@ public abstract class AbstractIetfInetUtil<A4, P4, A6, P6, A> {
         return prefix6Factory.newInstance(addressStringV6(addr) + '/' + mask);
     }
 
+    @Nonnull public final P6 ipv6PrefixFor(@Nonnull final A6 addr) {
+        Preconditions.checkNotNull(addr, "Address must not be null");
+        return prefix6Factory.newInstance(ipv6AddressString(addr) + "/128");
+    }
+
+    @Nonnull public final P6 ipv6PrefixFor(@Nonnull final A6 addr, final int mask) {
+        Preconditions.checkNotNull(addr, "Address must not be null");
+        Preconditions.checkArgument(mask >= 0 && mask <= 128, "Invalid mask %s", mask);
+        return prefix6Factory.newInstance(ipv6AddressString(addr) + '/' + mask);
+    }
+
+    @Nonnull public final Entry<A6, Integer> splitIpv6Prefix(@Nonnull final P6 prefix) {
+        return splitPrefix(address6Factory, ipv6PrefixString(prefix));
+    }
+
+    private static <T> T prefixToAddress(final StringValueObjectFactory<T> factory, final String str) {
+        return factory.newInstance(str.substring(0, str.lastIndexOf('/')));
+    }
+
+    private static <T> 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)));
+    }
+
     private static void appendIpv4String(final StringBuilder sb, final byte[] bytes) {
         Preconditions.checkArgument(bytes.length == 4, "IPv4 address length is 4 bytes");