diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..4ae5a63
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,51 @@
+
+ 4.0.0
+
+ com.acmerocket.waiter
+ waiter
+ 1.0-SNAPSHOT
+ jar
+
+ waiter
+ http://maven.apache.org
+
+
+ UTF-8
+
+
+
+
+ junit
+ junit
+ 4.10
+ test
+
+
+ com.intellij
+ annotations
+ 9.0.4
+
+
+ org.hamcrest
+ hamcrest-all
+ 1.1
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.0.2
+
+ 1.6
+ 1.6
+
+
+
+
+
+
diff --git a/src/main/java/com/softwarecraftsmen/CanNeverHappenException.java b/src/main/java/com/softwarecraftsmen/CanNeverHappenException.java
new file mode 100755
index 0000000..0b9bc5d
--- /dev/null
+++ b/src/main/java/com/softwarecraftsmen/CanNeverHappenException.java
@@ -0,0 +1,17 @@
+/**
+ * This file is Copyright © 2008 Software Craftsmen Limited. All Rights Reserved.
+ */
+package com.softwarecraftsmen;
+
+import org.jetbrains.annotations.NotNull;
+
+public class CanNeverHappenException extends RuntimeException
+{
+ public CanNeverHappenException(final @NotNull Exception cause)
+ {
+ super(cause);
+ }
+
+ public CanNeverHappenException()
+ {}
+}
diff --git a/src/main/java/com/softwarecraftsmen/Optional.java b/src/main/java/com/softwarecraftsmen/Optional.java
new file mode 100755
index 0000000..b86f9b5
--- /dev/null
+++ b/src/main/java/com/softwarecraftsmen/Optional.java
@@ -0,0 +1,109 @@
+package com.softwarecraftsmen;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+import static java.util.Collections.emptySet;
+
+public class Optional implements Set
+{
+ private Set internalSet;
+ private final T singleValue;
+
+ private Optional()
+ {
+ internalSet = emptySet();
+ singleValue = null;
+ }
+
+ public Optional(final @NotNull T singleValue)
+ {
+ internalSet = new LinkedHashSet(1);
+ this.singleValue = singleValue;
+ internalSet.add(this.singleValue);
+ }
+
+ @Nullable
+ public T value()
+ {
+ if (isEmpty())
+ {
+ throw new IllegalStateException("IsEmpty");
+ }
+ return singleValue;
+ }
+
+ public int size()
+ {
+ return internalSet.size();
+ }
+
+ public boolean isEmpty()
+ {
+ return internalSet.isEmpty();
+ }
+
+ public boolean contains(final @NotNull Object o)
+ {
+ return internalSet.contains(o);
+ }
+
+ @NotNull
+ public Iterator iterator()
+ {
+ return internalSet.iterator();
+ }
+
+ @NotNull
+ public Object[] toArray()
+ {
+ return internalSet.toArray();
+ }
+
+ @NotNull
+ public T[] toArray(final @NotNull T[] a)
+ {
+ return internalSet.toArray(a);
+ }
+
+ public boolean add(final @NotNull T t)
+ {
+ throw new UnsupportedOperationException("add");
+ }
+
+ public boolean remove(final Object o)
+ {
+ throw new UnsupportedOperationException("remove");
+ }
+
+ public boolean containsAll(final @NotNull Collection> c)
+ {
+ return internalSet.containsAll(c);
+ }
+
+ public boolean addAll(final @NotNull Collection extends T> c)
+ {
+ throw new UnsupportedOperationException("addAll");
+ }
+
+ public boolean retainAll(final Collection> c)
+ {
+ throw new UnsupportedOperationException("retainAll");
+ }
+
+ public boolean removeAll(final Collection> c)
+ {
+ throw new UnsupportedOperationException("removeAll");
+ }
+
+ public void clear()
+ {
+ throw new UnsupportedOperationException("clear");
+ }
+
+ public static Optional empty()
+ {
+ return new Optional();
+ }
+}
diff --git a/src/main/java/com/softwarecraftsmen/Pair.java b/src/main/java/com/softwarecraftsmen/Pair.java
new file mode 100644
index 0000000..5987da8
--- /dev/null
+++ b/src/main/java/com/softwarecraftsmen/Pair.java
@@ -0,0 +1,48 @@
+/**
+ * This file is Copyright © 2008 Software Craftsmen Limited. All Rights Reserved.
+ */
+package com.softwarecraftsmen;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public final class Pair
+{
+ private final A name;
+ private final B internetClassType;
+
+ public Pair(final @NotNull A name, final @NotNull B internetClassType)
+ {
+ this.name = name;
+ this.internetClassType = internetClassType;
+ }
+
+ public boolean equals(final @Nullable Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass())
+ {
+ return false;
+ }
+
+ final Pair key = (Pair) o;
+ return internetClassType == key.internetClassType && name.equals(key.name);
+ }
+
+ public int hashCode()
+ {
+ int result;
+ result = name.hashCode();
+ result = 31 * result + internetClassType.hashCode();
+ return result;
+ }
+
+ @NotNull
+ public String toString()
+ {
+ return com.softwarecraftsmen.toString.ToString.string(this, name, internetClassType);
+ }
+}
diff --git a/src/main/java/com/softwarecraftsmen/dns/HostInformation.java b/src/main/java/com/softwarecraftsmen/dns/HostInformation.java
new file mode 100755
index 0000000..f8ffb8f
--- /dev/null
+++ b/src/main/java/com/softwarecraftsmen/dns/HostInformation.java
@@ -0,0 +1,68 @@
+package com.softwarecraftsmen.dns;
+
+import static com.softwarecraftsmen.toString.ToString.string;
+import com.softwarecraftsmen.dns.messaging.serializer.AtomicWriter;
+import com.softwarecraftsmen.dns.messaging.serializer.Serializable;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class HostInformation implements Serializable
+{
+ public final String cpuType;
+ public final String operatingSystemType;
+
+ public HostInformation(final @NotNull String cpuType, final @NotNull String operatingSystemType)
+ {
+ this.cpuType = cpuType;
+ this.operatingSystemType = operatingSystemType;
+ if (cpuType.length() > 255)
+ {
+ throw new IllegalArgumentException("cpuType is a character strign which DNS restricts to a maximum length of 255 characters");
+ }
+ if (operatingSystemType.length() > 255)
+ {
+ throw new IllegalArgumentException("operatingSystemType is a character strign which DNS restricts to a maximum length of 255 characters");
+ }
+ }
+
+ @NotNull
+ public String toString()
+ {
+ return string(this, cpuType, operatingSystemType);
+ }
+
+ public boolean equals(final @Nullable Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass())
+ {
+ return false;
+ }
+
+ final HostInformation that = (HostInformation) o;
+ return cpuType.equals(that.cpuType) && operatingSystemType.equals(that.operatingSystemType);
+ }
+
+ public int hashCode()
+ {
+ int result;
+ result = cpuType.hashCode();
+ result = 31 * result + operatingSystemType.hashCode();
+ return result;
+ }
+
+ public void serialize(final @NotNull AtomicWriter writer)
+ {
+ writer.writeCharacterString(cpuType);
+ writer.writeCharacterString(operatingSystemType);
+ }
+
+ @NotNull
+ public static HostInformation hostInformation(final @NotNull String cpuType, final @NotNull String operatingSystemType)
+ {
+ return new HostInformation(cpuType, operatingSystemType);
+ }
+}
diff --git a/src/main/java/com/softwarecraftsmen/dns/MailBox.java b/src/main/java/com/softwarecraftsmen/dns/MailBox.java
new file mode 100644
index 0000000..093abdf
--- /dev/null
+++ b/src/main/java/com/softwarecraftsmen/dns/MailBox.java
@@ -0,0 +1,81 @@
+package com.softwarecraftsmen.dns;
+
+import com.softwarecraftsmen.dns.messaging.serializer.AtomicWriter;
+import static com.softwarecraftsmen.dns.labels.SimpleLabel.simpleLabel;
+import com.softwarecraftsmen.dns.labels.Label;
+import com.softwarecraftsmen.dns.names.Name;
+import com.softwarecraftsmen.dns.names.DomainName;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static java.lang.String.format;
+import java.util.ArrayList;
+import java.util.List;
+import static java.util.Locale.UK;
+
+public class MailBox implements Name
+{
+ private final String userName;
+ private final DomainName domainName;
+
+ public MailBox(final @NotNull String userName, final @NotNull DomainName domainName)
+ {
+ this.userName = userName;
+ this.domainName = domainName;
+ if (userName.length() > 63)
+ {
+ throw new IllegalArgumentException("An userName must be less than 64 characters in length");
+ }
+ }
+
+ @NotNull
+ public String toString()
+ {
+ return format(UK, "%1$s@%2$s", userName, domainName);
+ }
+
+ public boolean equals(final @Nullable Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass())
+ {
+ return false;
+ }
+
+ final MailBox mailBox = (MailBox) o;
+ return domainName.equals(mailBox.domainName) && userName.equals(mailBox.userName);
+ }
+
+ public int hashCode()
+ {
+ int result;
+ result = userName.hashCode();
+ result = 31 * result + domainName.hashCode();
+ return result;
+ }
+
+ public void serialize(final @NotNull AtomicWriter writer)
+ {
+ writer.writeCharacterString(userName);
+ domainName.serialize(writer);
+ }
+
+ @NotNull
+ public static MailBox mailBox(final @NotNull String userName, final @NotNull DomainName domainName)
+ {
+ return new MailBox(userName, domainName);
+ }
+
+ @NotNull
+ public List