Added Version and CoreService/Manager as an initial outline of a bootstrap coordinator.
diff --git a/core/api/src/main/java/org/onlab/onos/CoreService.java b/core/api/src/main/java/org/onlab/onos/CoreService.java
new file mode 100644
index 0000000..32c36c5
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/CoreService.java
@@ -0,0 +1,15 @@
+package org.onlab.onos;
+
+/**
+ * Service for interacting with the core system of the controller.
+ */
+public interface CoreService {
+
+ /**
+ * Returns the product version.
+ *
+ * @return product version
+ */
+ Version version();
+
+}
diff --git a/core/api/src/main/java/org/onlab/onos/Version.java b/core/api/src/main/java/org/onlab/onos/Version.java
new file mode 100644
index 0000000..5d071b7
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/Version.java
@@ -0,0 +1,113 @@
+package org.onlab.onos;
+
+import java.util.Objects;
+
+import static java.lang.Integer.parseInt;
+
+/**
+ * Representation of the product version.
+ */
+public final class Version {
+
+ public static final String FORMAT = "%d.%d.%d.%s";
+
+ private final int major;
+ private final int minor;
+ private final int patch;
+ private final String build;
+
+ private final String format;
+
+ // Creates a new version descriptor
+ private Version(int major, int minor, int patch, String build) {
+ this.major = major;
+ this.minor = minor;
+ this.patch = patch;
+ this.build = build;
+ this.format = String.format(FORMAT, major, minor, patch, build);
+ }
+
+
+ /**
+ * Creates a new version from the specified constituent numbers.
+ *
+ * @param major major version number
+ * @param minor minod version number
+ * @param patch version patch number
+ * @param build build string
+ * @return version descriptor
+ */
+ public static Version version(int major, int minor, int patch, String build) {
+ return new Version(major, minor, patch, build);
+ }
+
+ /**
+ * Creates a new version by parsing the specified string.
+ *
+ * @param string version string
+ * @return version descriptor
+ */
+ public static Version version(String string) {
+ String[] fields = string.split("[.-]");
+ return new Version(parseInt(fields[0]), parseInt(fields[1]),
+ parseInt(fields[2]), fields[3]);
+ }
+
+ /**
+ * Returns the major version number.
+ *
+ * @return major version number
+ */
+ public int major() {
+ return major;
+ }
+
+ /**
+ * Returns the minor version number.
+ *
+ * @return minor version number
+ */
+ public int minor() {
+ return minor;
+ }
+
+ /**
+ * Returns the version patch number.
+ *
+ * @return patch number
+ */
+ public int patch() {
+ return patch;
+ }
+
+ /**
+ * Returns the version build string.
+ *
+ * @return build string
+ */
+ public String build() {
+ return build;
+ }
+
+ @Override
+ public String toString() {
+ return format;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(format);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Version) {
+ final Version other = (Version) obj;
+ return Objects.equals(this.format, other.format);
+ }
+ return false;
+ }
+}
diff --git a/core/api/src/test/java/org/onlab/onos/VersionTest.java b/core/api/src/test/java/org/onlab/onos/VersionTest.java
new file mode 100644
index 0000000..e357f9d
--- /dev/null
+++ b/core/api/src/test/java/org/onlab/onos/VersionTest.java
@@ -0,0 +1,50 @@
+package org.onlab.onos;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+import static org.onlab.onos.Version.version;
+
+/**
+ * Tests of the version descriptor.
+ */
+public class VersionTest {
+
+ @Test
+ public void fromParts() {
+ Version v = version(1, 2, 3, "4321");
+ assertEquals("wrong major", 1, v.major());
+ assertEquals("wrong minor", 2, v.minor());
+ assertEquals("wrong patch", 3, v.patch());
+ assertEquals("wrong build", "4321", v.build());
+ }
+
+ @Test
+ public void fromString() {
+ Version v = version("1.2.3.4321");
+ assertEquals("wrong major", 1, v.major());
+ assertEquals("wrong minor", 2, v.minor());
+ assertEquals("wrong patch", 3, v.patch());
+ assertEquals("wrong build", "4321", v.build());
+ }
+
+ @Test
+ public void snapshot() {
+ Version v = version("1.2.3-SNAPSHOT");
+ assertEquals("wrong major", 1, v.major());
+ assertEquals("wrong minor", 2, v.minor());
+ assertEquals("wrong patch", 3, v.patch());
+ assertEquals("wrong build", "SNAPSHOT", v.build());
+ }
+
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(version("1.2.3.4321"), version(1, 2, 3, "4321"))
+ .addEqualityGroup(version("1.9.3.4321"), version(1, 9, 3, "4321"))
+ .addEqualityGroup(version("1.2.8.4321"), version(1, 2, 8, "4321"))
+ .addEqualityGroup(version("1.2.3.x"), version(1, 2, 3, "x"))
+ .testEquals();
+ }
+}
\ No newline at end of file