changeset 25:dd0992bd51aa

Add Maven Central upload, refactor lang-schema and json libs to thermostat-common library - merge common-json and common-lang-schema packages into thermostat- common. - add targets to generate Javadoc and source jars, and modify sources to remove some Javadoc warnings. - add targets to sign and deploy thermostat-common to Maven Central. Reviewed-by: sgehwolf, neugens Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-September/025214.html
author Simon Tooke <stooke@redhat.com>
date Fri, 29 Sep 2017 14:48:00 -0400
parents e7a2adb465d1
children 33cf0b946e3d
files common/json/pom.xml common/json/src/main/java/com/redhat/thermostat/common/json/JsonUtil.java common/json/src/main/java/com/redhat/thermostat/common/json/models/ApiDef.java common/json/src/main/java/com/redhat/thermostat/common/json/models/SchemaDef.java common/json/src/main/java/com/redhat/thermostat/common/json/models/SchemaType.java common/json/src/main/java/com/redhat/thermostat/common/json/models/SwaggerDef.java common/json/src/main/java/com/redhat/thermostat/common/yaml/JsonToYaml.java common/json/src/main/java/com/redhat/thermostat/common/yaml/RefResolver.java common/json/src/main/java/com/redhat/thermostat/common/yaml/YamlToJson.java common/json/src/test/java/com/redhat/thermostat/common/json/JsonUtilTest.java common/json/src/test/java/com/redhat/thermostat/common/json/models/SchemaDefTest.java common/json/src/test/java/com/redhat/thermostat/common/yaml/JsonToYamlTest.java common/json/src/test/java/com/redhat/thermostat/common/yaml/RefResolverTest.java common/json/src/test/java/com/redhat/thermostat/common/yaml/YamlToJsonTest.java common/json/src/test/resources/jvms-swagger.json common/json/src/test/resources/jvms-swagger.yaml common/json/src/test/resources/systems-swagger.json common/json/src/test/resources/systems-swagger.yaml common/pom.xml common/src/main/java/com/redhat/thermostat/common/json/JsonUtil.java common/src/main/java/com/redhat/thermostat/common/json/models/ApiDef.java common/src/main/java/com/redhat/thermostat/common/json/models/SchemaDef.java common/src/main/java/com/redhat/thermostat/common/json/models/SchemaType.java common/src/main/java/com/redhat/thermostat/common/json/models/SwaggerDef.java common/src/main/java/com/redhat/thermostat/common/yaml/JsonToYaml.java common/src/main/java/com/redhat/thermostat/common/yaml/RefResolver.java common/src/main/java/com/redhat/thermostat/common/yaml/YamlToJson.java common/src/main/java/com/redhat/thermostat/lang/schema/JSONService.java common/src/main/java/com/redhat/thermostat/lang/schema/SchemaBuilder.java common/src/main/java/com/redhat/thermostat/lang/schema/SchemaValidationException.java common/src/main/java/com/redhat/thermostat/lang/schema/annotations/Maximum.java common/src/main/java/com/redhat/thermostat/lang/schema/annotations/Minimum.java common/src/main/java/com/redhat/thermostat/lang/schema/annotations/Schema.java common/src/main/java/com/redhat/thermostat/lang/schema/annotations/Type.java common/src/main/java/com/redhat/thermostat/lang/schema/internal/JSONServiceImpl.java common/src/main/java/com/redhat/thermostat/lang/schema/internal/SchemaBuilderImpl.java common/src/main/java/com/redhat/thermostat/lang/schema/models/Id.java common/src/main/java/com/redhat/thermostat/lang/schema/models/Pid.java common/src/main/java/com/redhat/thermostat/lang/schema/models/ProcessState.java common/src/main/java/com/redhat/thermostat/lang/schema/models/Timestamp.java common/src/test/java/com/redhat/thermostat/common/json/JsonUtilTest.java common/src/test/java/com/redhat/thermostat/common/json/models/SchemaDefTest.java common/src/test/java/com/redhat/thermostat/common/yaml/JsonToYamlTest.java common/src/test/java/com/redhat/thermostat/common/yaml/RefResolverTest.java common/src/test/java/com/redhat/thermostat/common/yaml/YamlToJsonTest.java common/src/test/java/com/redhat/thermostat/lang/schema/internal/JSONServiceTest.java common/src/test/java/com/redhat/thermostat/lang/schema/internal/SchemaBuilderTest.java common/src/test/resources/jvms-swagger.json common/src/test/resources/jvms-swagger.yaml common/src/test/resources/systems-swagger.json common/src/test/resources/systems-swagger.yaml common/type-system/src/main/java/com/redhat/thermostat/lang/schema/JSONService.java common/type-system/src/main/java/com/redhat/thermostat/lang/schema/SchemaBuilder.java common/type-system/src/main/java/com/redhat/thermostat/lang/schema/SchemaValidationException.java common/type-system/src/main/java/com/redhat/thermostat/lang/schema/annotations/Maximum.java common/type-system/src/main/java/com/redhat/thermostat/lang/schema/annotations/Minimum.java common/type-system/src/main/java/com/redhat/thermostat/lang/schema/annotations/Schema.java common/type-system/src/main/java/com/redhat/thermostat/lang/schema/annotations/Type.java common/type-system/src/main/java/com/redhat/thermostat/lang/schema/internal/JSONServiceImpl.java common/type-system/src/main/java/com/redhat/thermostat/lang/schema/internal/SchemaBuilderImpl.java common/type-system/src/main/java/com/redhat/thermostat/lang/schema/models/Id.java common/type-system/src/main/java/com/redhat/thermostat/lang/schema/models/Pid.java common/type-system/src/main/java/com/redhat/thermostat/lang/schema/models/ProcessState.java common/type-system/src/main/java/com/redhat/thermostat/lang/schema/models/Timestamp.java common/type-system/src/test/java/com/redhat/thermostat/lang/schema/internal/JSONServiceTest.java common/type-system/src/test/java/com/redhat/thermostat/lang/schema/internal/SchemaBuilderTest.java
diffstat 66 files changed, 4650 insertions(+), 4512 deletions(-) [+]
line wrap: on
line diff
--- a/common/json/pom.xml	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Copyright 2012-2017 Red Hat, Inc.
-
- This file is part of Thermostat.
-
- Thermostat is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- Thermostat is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Thermostat; see the file COPYING.  If not see
- <http://www.gnu.org/licenses/>.
-
- Linking this code with other modules is making a combined work
- based on this code.  Thus, the terms and conditions of the GNU
- General Public License cover the whole combination.
-
- As a special exception, the copyright holders of this code give
- you permission to link this code with independent modules to
- produce an executable, regardless of the license terms of these
- independent modules, and to copy and distribute the resulting
- executable under terms of your choice, provided that you also
- meet, for each linked independent module, the terms and conditions
- of the license of that module.  An independent module is a module
- which is not derived from or based on this code.  If you modify
- this code, you may extend this exception to your version of the
- library, but you are not obligated to do so.  If you do not wish
- to do so, delete this exception statement from your version.
-
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>com.redhat.thermostat</groupId>
-        <artifactId>base-common</artifactId>
-        <version>1.99.12-SNAPSHOT</version>
-    </parent>
-
-    <artifactId>base-common-json</artifactId>
-    <packaging>jar</packaging>
-
-    <name>Thermostat Common JSON / YAML Libraries</name>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.google.code.gson</groupId>
-            <artifactId>gson</artifactId>
-            <version>2.6.2</version>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>4.12</version>
-        </dependency>
-        <dependency>
-            <groupId>com.redhat.thermostat.lang.schema</groupId>
-            <artifactId>thermostat-lang-schema</artifactId>
-            <version>1.99.12-SNAPSHOT</version>
-        </dependency>
-    </dependencies>
-
-</project>
\ No newline at end of file
--- a/common/json/src/main/java/com/redhat/thermostat/common/json/JsonUtil.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.common.json;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-
-import java.util.Map;
-import java.util.NoSuchElementException;
-
-/**
- * misc GSON utility classes
- */
-public class JsonUtil {
-
-    static String capitalize(final String s) {
-        return s.substring(0, 1).toUpperCase() + s.substring(1);
-    }
-
-    /**
-     * access a nested JSON object via a path string
-     * "foo.bar.2.fred" is equivalent to
-     * root.getAsJsonObject().get("foo").getAsJsonObject().get("bar").getAsJsonArray().get(2).getAsJsonObject().get("fred")
-     *
-     * @param root object to access
-     * @param path path into object
-     * @return element within root
-     */
-    public static JsonElement fetch(final JsonElement root, final String path) {
-        String[] pathelements = path.split("[.]");
-        // NOTE - it would be nice to parse foo[N] to foo.N to allow normal subscripting
-        return fetch(root, pathelements, 0);
-    }
-
-    /**
-     * access a nexted JSON object via a path string
-     * "foo.bar.2.fred" is equivalent to
-     * root.getAsJsonObject().get("foo").getAsJsonObject().get("bar").getAsJsonArray().get(2).getAsJsonObject().get("fred")
-     *
-     * @param root      object to access
-     * @param path      path into object
-     * @param delimiter delimiter regex for path antries (default '.')
-     * @return element within root
-     */
-    public static JsonElement fetch(final JsonElement root, final String path, final String delimiter) {
-        String[] pathelements = path.split(delimiter);
-        return fetch(root, pathelements, 0);
-    }
-
-    private static JsonElement fetch(final JsonElement e, final String[] pathelements, int idx) {
-        if (idx == pathelements.length) {
-            // we've fallen off the end of the input path - now it's time to return the current object.
-            return e;
-        } else if (idx > pathelements.length) {
-            throw new IndexOutOfBoundsException("Internal error in JsonUtil.fetch() - index = " + idx);
-        } else {
-            if (e.isJsonObject()) {
-                JsonObject obj = e.getAsJsonObject();
-                JsonElement next = obj.get(pathelements[idx]);
-                if (next == null) {
-                    throw new NoSuchElementException(pathelements[idx]);
-                } else {
-                    return fetch(next, pathelements, idx + 1);
-                }
-            } else if (e.isJsonArray()) {
-                JsonArray arr = e.getAsJsonArray();
-                int n = Integer.parseInt(pathelements[idx]);
-                if (arr.size() <= n) {
-                    throw new ArrayIndexOutOfBoundsException(n);
-                } else {
-                    return fetch(arr.get(n), pathelements, idx + 1);
-                }
-            } else {
-                throw new NoSuchElementException(pathelements[idx]);
-            }
-        }
-    }
-
-    /**
-     * perform a deep copy of a JsonElement
-     *
-     * @param jsonElement element to copy
-     * @return deep copy of the element tree
-     */
-    // why isn't JsonElement.deepCopy() public?
-    public static JsonElement deepCopy(JsonElement jsonElement) {
-        if (jsonElement.isJsonPrimitive() || jsonElement.isJsonNull()) {
-            return jsonElement;       // these are immutables anyway
-        } else if (jsonElement.isJsonObject()) {
-            return deepCopy(jsonElement.getAsJsonObject());
-        } else if (jsonElement.isJsonArray()) {
-            return deepCopy(jsonElement.getAsJsonArray());
-        } else {
-            throw new UnsupportedOperationException("Unsupported element: " + jsonElement);
-        }
-    }
-
-    private static JsonObject deepCopy(JsonObject jsonObject) {
-        JsonObject result = new JsonObject();
-        for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
-            result.add(entry.getKey(), deepCopy(entry.getValue()));
-        }
-        return result;
-    }
-
-    private static JsonArray deepCopy(JsonArray jsonArray) {
-        JsonArray result = new JsonArray();
-        for (JsonElement e : jsonArray) {
-            result.add(deepCopy(e));
-        }
-        return result;
-    }
-}
-
--- a/common/json/src/main/java/com/redhat/thermostat/common/json/models/ApiDef.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.common.json.models;
-
-import com.google.gson.JsonObject;
-import com.google.gson.annotations.SerializedName;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Java representation of a Swagger-defined web API endpoint
- */
-public class ApiDef {
-
-    String path;
-    String description;
-    JsonObject root;
-    List<ParameterDef>  parameters;
-    MethodDef get;
-    MethodDef put;
-    MethodDef post;
-    MethodDef delete;
-
-    public static class MethodDef {
-        List<ParameterDef> parameters;
-        String description;
-        Map<Integer, ResponseDef> responses;
-
-        public String getDescription() {
-            return this.description;
-        }
-    }
-
-    static class ResponseDef {
-        String description;
-        JsonObject schema;
-    }
-
-    static class ParameterDef {
-        enum In { query, path, body };
-        enum Type { integer, string, bool };
-        String name;
-        String description;
-        In in;
-        Type type;
-        boolean required;
-        @SerializedName("default")
-        String deflt;
-    }
-
-    public void setPath(String path) {
-        this.path = path;
-    }
-
-    public MethodDef getGETAPI() {
-        return get;
-    }
-
-    public MethodDef getPOSTAPI() {
-        return post;
-    }
-
-    public MethodDef getDELETEAPI() {
-        return delete;
-    }
-
-    public MethodDef getPUTAPI() {
-        return put;
-    }
-}
--- a/common/json/src/main/java/com/redhat/thermostat/common/json/models/SchemaDef.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,208 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.common.json.models;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.annotations.SerializedName;
-
-import com.redhat.thermostat.common.yaml.JsonToYaml;
-import com.redhat.thermostat.lang.schema.annotations.Schema;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Partiual Java representation of a JSON Schema (see json-schema.org)
- */
-public class SchemaDef implements SchemaType {
-
-    private static final Gson gson;
-    private static final int DEFAULT_MAXDEPTH = 1;
-
-    static {
-        final boolean ENABLE_PRETTY_PRINT = false;
-        if (ENABLE_PRETTY_PRINT) {
-            GsonBuilder gbuilder = new GsonBuilder();
-            gbuilder.setPrettyPrinting();
-            gson = gbuilder.create();
-        } else {
-            gson = new Gson();
-        }
-    }
-
-    @SerializedName("$schema")
-    private String schema;
-    @SerializedName("$id")
-    private String id;
-    private String title;
-    private String description;
-    private Map<String, SchemaType> properties;
-    private List<String> required;
-
-    /** standard JSON schema properties that are not yet implemented:
-     private int multipleOf;
-     private long maximum;
-     private long exclusiveMaximum;
-     private long minimum;
-     private long exclusiveMinimum;
-     private int maxLength;
-     private int minLength;
-     private String pattern;
-     private int maxItems;
-     private int minItems;
-     private boolean uniqueItems;
-     private int maxProperties;
-     private int minProperties;
-     (and more, see json-schema.org)
-     ***/
-
-    // for GSon
-    public SchemaDef() {}
-
-    public SchemaDef(Object target) {
-        this(target.getClass(), DEFAULT_MAXDEPTH);
-    }
-
-    public SchemaDef(Object target, int maxDepth) {
-        this(target.getClass(), maxDepth);
-    }
-
-    public SchemaDef(Class target) {
-        this(target, true, DEFAULT_MAXDEPTH);
-    }
-
-    public SchemaDef(Class target, int maxDepth) {
-        this(target, true, maxDepth);
-    }
-
-    private SchemaDef(Class target, boolean rootLevel, int maxDepth) {
-        if (rootLevel) {
-            schema = "http://json-schema.org/draft-04/schema#";
-        }
-        Field[] fields = target.getDeclaredFields();
-        if (fields.length > 0) {
-            properties = new HashMap<>(fields.length);
-            required = new ArrayList<>();
-            for (Field field : fields) {
-                final boolean isTransient =  Modifier.isTransient(field.getModifiers());
-                if (!isTransient) {
-                    String fname = field.getAnnotation(SerializedName.class) != null ? field.getAnnotation(SerializedName.class).value() : field.getName();
-                    Schema schema = field.getAnnotation(Schema.class);
-                    String descr = null;
-                    if (schema != null) {
-                        if (!schema.name().isEmpty()) {
-                            fname = schema.name();
-                        }
-                        descr = schema.description();
-                        if (schema.required()) {
-                            required.add(fname);
-                        }
-                    }
-                    if (field.getType().isPrimitive()) {
-                        String tt = field.getType().getSimpleName();
-                        properties.put(fname, new SimpleType(tt, descr));
-                    } else if (maxDepth > 1){
-                        properties.put(fname, new SchemaDef(field.getType(), false, maxDepth - 1));
-                    } else {
-                        properties.put(fname, new SimpleType(field.getType().getSimpleName(), descr));
-                    }
-                }
-            }
-            if (required.isEmpty()) {
-                required = null;
-            }
-        }
-    }
-
-    public Map<String, SchemaType> getProperties() {
-        return this.properties;
-    }
-
-    public List<String> getRequired() {
-        return this.required;
-    }
-
-    public JsonObject toJsonObject() {
-        JsonElement el = gson.toJsonTree(this);
-        return el.isJsonObject() ? el.getAsJsonObject() : null;
-    }
-
-    public String toString() {
-        return gson.toJson(this);
-    }
-
-    @Override
-    public TypeClass getTypeClass() {
-        return TypeClass.OBJECT;
-    }
-
-    public static class SimpleType implements SchemaType {
-        transient TypeClass type;
-        @SerializedName("type")
-        String typeStr;
-        String description;
-        SimpleType(String tname, String descr) {
-            if ("string".equals(tname)) {
-                type = TypeClass.STRING;
-            } else if ("int".equals(tname) || "float".equals(tname) || "double".equals(tname) || "long".equals(tname) || "number".equals(tname)) {
-                type = TypeClass.NUMBER;
-            } else if ("Integer".equals(tname) || "Float".equals(tname) || "Double".equals(tname) || "Long".equals(tname)) {
-                type = TypeClass.NUMBER;
-            } else if ("boolean".equals(tname) || "Boolean".equals(tname)) {
-                type = TypeClass.BOOLEAN;
-            } else {
-                type = TypeClass.OBJECT;
-            }
-            this.typeStr = type == TypeClass.OBJECT ? tname : type.toString();
-            this.description = descr;
-        }
-        @Override
-        public TypeClass getTypeClass() {
-            return type;
-        }
-        public String getTypeName() {
-            return type == TypeClass.OBJECT ? typeStr : type.toString();
-        }
-    }
-}
--- a/common/json/src/main/java/com/redhat/thermostat/common/json/models/SchemaType.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.common.json.models;
-
-/**
- * the type of a JSON schema element
- */
-public interface SchemaType {
-    TypeClass getTypeClass();
-
-    enum TypeClass {
-
-        OBJECT("object"),
-        ARRAY("array"),
-        NUMBER("number"),
-        STRING("string"),
-        BOOLEAN("boolean"),
-        NULL("null");
-
-        private final String typeString;
-
-        private TypeClass(String s) {
-            typeString = s;
-        }
-
-        @Override
-        public String toString() {
-            return typeString;
-        }
-    }
-}
--- a/common/json/src/main/java/com/redhat/thermostat/common/json/models/SwaggerDef.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.common.json.models;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Java representation of a Swagger file
- */
-public class SwaggerDef {
-
-    String swagger;
-    InfoDef info;
-    List<String> consumes;
-    List<String> produces;
-    String basePath;
-    Map<String, ApiDef> paths;
-
-    static class InfoDef {
-        String version;
-        String title;
-        LicenseDef license;
-    }
-
-    static class LicenseDef {
-        String name;
-        String url;
-    }
-
-    static class SwaggerSchema extends SchemaDef {
-        private String type;
-    }
-
-    public String getBasePath() {
-        return basePath;
-    }
-
-    public Map<String, ApiDef> getPaths() {
-        return paths;
-    }
-}
--- a/common/json/src/main/java/com/redhat/thermostat/common/yaml/JsonToYaml.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.common.yaml;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.Map;
-
-/**
- * convert JSON object to YAML string
- */
-public class JsonToYaml {
-
-    private Writer out;
-    private int indent = 2;
-
-    public void setIndentation(int i) {
-        this.indent = i;
-    }
-
-    String jsonToYamlString(JsonObject root) throws IOException {
-        this.out = new StringWriter();
-        jsonToYaml(root, out);
-        return out.toString();
-    }
-
-    public void jsonToYaml(JsonObject root, Writer out) throws IOException {
-        this.out = out;
-        jsonToYaml(root, 0);
-    }
-
-    private void dispatch(JsonElement el, int currentIndent) throws IOException {
-        if (el.isJsonPrimitive()) {
-            final JsonPrimitive pr = el.getAsJsonPrimitive();
-            if (pr.isBoolean() || pr.isNumber()) {
-                out.append(el.getAsString()).append('\n');
-            } else {
-                out.append("'").append(el.getAsString()).append("'\n");
-            }
-        } else if (el.isJsonArray()) {
-            out.append('\n');
-            jsonToYaml(el.getAsJsonArray(), currentIndent);
-        } else if (el.isJsonObject()) {
-            out.append('\n');
-            jsonToYaml(el.getAsJsonObject(), currentIndent);
-        } else {
-            throw new UnsupportedOperationException("Unsupported element: " + el);
-        }
-    }
-
-    private void jsonToYaml(JsonObject obj, int currentIndent) throws IOException {
-        final int newindent = currentIndent + indent;
-        for (final Map.Entry<String, JsonElement> entry : obj.entrySet()) {
-            doIndent(currentIndent);
-            out.append(entry.getKey()).append(": ");
-            dispatch(entry.getValue(), newindent);
-        }
-    }
-
-    private void jsonToYaml(JsonArray array, int currentIndent) throws IOException {
-        for (final JsonElement el : array) {
-            doIndent(currentIndent);
-            out.append("- ");
-            if (el.isJsonArray()) {
-                jsonToYaml(el.getAsJsonArray(), 0);
-            } else if (el.isJsonObject()) {
-                jsonToYaml(el.getAsJsonObject(), 0);
-            } else {
-                dispatch(el, 0);
-            }
-        }
-    }
-
-    private void doIndent(int currentIndent) throws IOException {
-        for (int i = 0; i < currentIndent; i++)
-            out.append(' ');
-    }
-}
-
--- a/common/json/src/main/java/com/redhat/thermostat/common/yaml/RefResolver.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.common.yaml;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.redhat.thermostat.common.json.JsonUtil;
-
-import java.io.IOException;
-import java.util.Map;
-
-/**
- * Given a JSON object (created from a Swagger YAML or JSON file), resolve all $ref paths
- * TODO: currently doesn't test for circular references
- */
-public class RefResolver {
-
-    public static JsonObject resolvePath(JsonObject defsroot, JsonObject current, String path) throws IOException {
-        String[] pathElements = path.split("/");
-        for (String pe : pathElements) {
-            if ("#".equals(pe)) {
-                current = defsroot;
-            } else if (current.has(pe)) {
-                current = current.getAsJsonObject(pe);
-            } else {
-                throw new IOException("unresolvable reference '" + pe + "' in path '" + path + "'");
-            }
-        }
-        return current;
-    }
-
-    private static final String REF_MEMBER = "$ref";
-
-    public static JsonElement resolveRefs(JsonObject defsRoot, JsonElement objToResolve) throws IOException {
-
-        if (objToResolve.isJsonObject()) {
-            final JsonObject obj = objToResolve.getAsJsonObject();
-            for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
-                if (REF_MEMBER.equals(entry.getKey())) {
-                    String ref = entry.getValue().getAsString();
-                    obj.remove(REF_MEMBER);
-                    JsonObject refObject = resolvePath(defsRoot, obj, ref);
-                    resolveRefs(defsRoot, refObject);
-                    // hoist all members of refObject to contents
-                    for (Map.Entry<String, JsonElement> refentry : refObject.entrySet()) {
-                        obj.add(refentry.getKey(), JsonUtil.deepCopy(refentry.getValue()));
-                    }
-                } else {
-                    resolveRefs(defsRoot, entry.getValue());
-                }
-            }
-        } else if (objToResolve.isJsonArray()) {
-            final JsonArray contents = objToResolve.getAsJsonArray();
-            for (int i = 0; i < contents.size(); i++) {
-                JsonElement el = contents.get(i);
-                if (el.isJsonObject()) {
-                    contents.set(i, resolveRefs(defsRoot, el.getAsJsonObject()));
-                }
-            }
-        }
-        return objToResolve;
-    }
-
-}
\ No newline at end of file
--- a/common/json/src/main/java/com/redhat/thermostat/common/yaml/YamlToJson.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,309 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.common.yaml;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonNull;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.Stack;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Utility class to read YAML files and convert to GSON objects
- *
- * Limitations:
- * Only enough code to read Swagger YAML is implemented
- * $ref only works within the same document, not across the network
- */
-public class YamlToJson {
-
-    public YamlToJson() {
-    }
-
-    public JsonObject yamlToJsonObject(final File fn) throws IOException {
-        try (final Reader in = new FileReader(fn)) {
-            return yamlToJsonObject(in);
-        }
-    }
-
-    public JsonObject yamlToJsonObject(final String yaml) throws IOException {
-        try (final Reader in = new StringReader(yaml)) {
-            return yamlToJsonObject(in);
-        }
-    }
-
-    public JsonObject yamlToJsonObject(final Reader in) throws IOException {
-        try (final PushableReader pr = new PushableReader(in instanceof BufferedReader ? (BufferedReader)in : new BufferedReader(in));) {
-            final JsonObject obj = new JsonObject();
-            yamlToJson(pr, obj, 0);
-            pr.close();
-            return obj;
-        }
-    }
-
-    private void yamlToJson(PushableReader in, JsonElement parent, int currentIndent) throws IOException {
-        for (String s = in.readLine(); s != null; s = in.readLine()) {
-            YamlLine line = new YamlLine(s);
-            if (line.indent == 0 && line.value == null && line.name == null) {
-                // blsnk or unparseable line
-                continue;
-            }
-            if (line.indent < currentIndent) {
-                in.push(s);
-                return;
-            }
-            final JsonElement child;
-            if (line.hasColon) {
-                if (line.value != null && !line.value.isEmpty()) {
-                    if (">-".equals(line.value)) {
-                        //the next few lines are the value for the current line
-                        child = makeUnquotedPrimitive(absorb(in, currentIndent));
-                    } else {
-                        JsonElement ce = makeUnquotedPrimitive(line.value);
-                        if (parent.isJsonArray()) {
-                            JsonObject childobj = new JsonObject();
-                            childobj.add(makeUnquotedString(line.name), ce);
-                            child = childobj;
-                        } else {
-                            child = ce;
-                        }
-                    }
-                } else {
-                    // no value specified; this could be the start of an object or array
-                    final String next = in.readLine();
-                    boolean isArray = false;
-                    if (next != null) {
-                        YamlLine nextLine = new YamlLine(next);
-                        isArray = nextLine.hasDashPrefix;
-                        in.push(next);
-                    }
-                    child = isArray ? new JsonArray() : new JsonObject();
-                    yamlToJson(in, child, line.indent);
-                }
-            }
-            else {
-                child = (line.value != null) ? makeUnquotedPrimitive(line.value) : new JsonPrimitive("");
-            }
-            if (parent.isJsonArray()) {
-                if (line.hasDashPrefix) {
-                    JsonArray parray = parent.getAsJsonArray();
-                    parray.add(child);
-                } else {
-                    System.err.println("Array member must begin with dash: " + s);
-                }
-            } else if (parent.isJsonObject()) {
-                JsonObject pobject = parent.getAsJsonObject();
-                pobject.add(makeUnquotedString(line.name), child);
-            } else {
-                System.err.println("Error: parent is neither object nor array");
-            }
-            currentIndent = line.indent;
-        }
-    }
-
-    private static String makeUnquotedString(final String s) {
-        String ret = s;
-        if (s.length() >= 2) {
-            if ((s.charAt(0) == '\'') && (s.charAt(s.length() - 1) == '\'')
-                    || (s.charAt(0) == '"') && (s.charAt(s.length() - 1) == '"')) {
-                ret = s.substring(1, s.length() - 1);
-            }
-        }
-        return ret;
-    }
-
-    private static JsonPrimitive makeUnquotedPrimitive(final String s) {
-        final String uqString = makeUnquotedString(s);
-        // anything quoted will return a string, otherwise try to parse
-        if (uqString.length() == s.length()) {
-            if ("true".equals(uqString))
-                return new JsonPrimitive(true);
-            else if ("false".equals(uqString))
-                return new JsonPrimitive(false);
-            else if ("null".equals(uqString))
-                return null;
-            else {
-                // test for number
-                final char c0 = uqString.charAt(0);
-                if (Character.isDigit(c0) || c0 == '+' || c0 == '-') {
-                    try {
-                        return new JsonPrimitive(new Long(uqString));
-                    } catch (NumberFormatException ignored) {
-                        ; // fall through to return String
-                    }
-
-                }
-            }
-        }
-        return new JsonPrimitive(uqString);
-    }
-
-    private static String absorb(PushableReader in, int currentIndent) throws IOException {
-        // append lines until the indentation is the same as the currentIndent
-        StringBuilder a = new StringBuilder();
-        for (String s = in.readLine(); s != null; s = in.readLine()) {
-            int wsCount;
-            for (wsCount = 0; wsCount < s.length(); wsCount++) {
-                if (!Character.isWhitespace(s.charAt(wsCount))) {
-                    break;
-                }
-            }
-            if (wsCount > currentIndent) {
-                a.append(a.length() == 0 ? s.trim() : ' ' + s.trim());
-            } else {
-                in.push(s);
-                break;
-            }
-        }
-        return a.toString();
-    }
-
-    /**
-     * YamlLine - parse a single line of YAML file
-     */
-    static class YamlLine {
-        int indent;
-        String name;
-        String value;
-        boolean hasColon;
-        boolean hasDashPrefix;
-
-        private static final String regexpr = "^([\\s]*)([-]?[\\s]*)([^:]+)([:]?)(.*)$";
-        private static final Pattern p = Pattern.compile(regexpr);
-
-        YamlLine(String line) throws IOException {
-            Matcher m = p.matcher(line);
-            if (m.matches()) {
-                final String s1 = m.group(1); // leading whitespace
-                final String s2 = m.group(2); // optional '-' indicating array element
-                final String s3 = m.group(3); // key
-                final String s4 = m.group(4); // ':'
-                final String s5 = m.group(5).trim(); // value or optional '>-'
-                hasColon = !(s4 == null || s4.isEmpty());
-                hasDashPrefix = !(s2 == null || s2.isEmpty());
-                indent = s1.length() + (hasDashPrefix ? s2.length() : 0);
-                if (hasColon) {
-                    name = s3.trim();
-                    value = s5.trim();
-                } else {
-                    name = null;
-                    value = s3 + s5;
-                    value = value.trim();
-                }
-            } else {
-                if (line.isEmpty()) {
-                    name = null;
-                    value = null;
-                    indent = 0;
-                } else {
-                    throw new IOException("parse error in YAML '" + line + "'");
-                }
-            }
-        }
-    }
-
-    static class PushableReader implements AutoCloseable {
-
-        final Stack<String> stack = new Stack<>();
-        final BufferedReader in;
-
-        PushableReader(BufferedReader in) {
-            this.in = in;
-        }
-
-        String readLine() throws IOException {
-            if (stack.isEmpty()) {
-                return in.readLine();
-            } else {
-                return stack.pop();
-            }
-        }
-
-        void push(String s) {
-            stack.push(s);
-        }
-
-        @Override
-        public void close() throws IOException {
-            in.close();
-        }
-    }
-
-    /*
-     * utility function to convert YAML file to JSON stdout
-     */
-    public static void main(String[] args) {
-        boolean pretty = false;
-        for (final String fn : args) {
-            if ("--pretty".equals(fn)) {
-                pretty = true;
-            } else if ("--help".equals("fn")) {
-                System.err.println("YamlToJason [--pretty] [--help] infile1 [infile2] ...");
-            } else {
-                try {
-                    final YamlToJson y2j = new YamlToJson();
-                    final File fin = new File(fn);
-                    final JsonObject json = y2j.yamlToJsonObject(fin);
-                    if (pretty) {
-                        final GsonBuilder gsonBuilder = new GsonBuilder();
-                        gsonBuilder.setPrettyPrinting();
-                        final Gson gson = gsonBuilder.create();
-                        System.out.println(gson.toJson(json));
-                    } else {
-                        System.out.println(json.toString());
-                    }
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-        }
-    }
-}
--- a/common/json/src/test/java/com/redhat/thermostat/common/json/JsonUtilTest.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.common.json;
-
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParser;
-import org.junit.Test;
-
-import java.util.NoSuchElementException;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-public class JsonUtilTest {
-
-    private static final String JSON =
-            "{\n" +
-                    "  \"parents\" : [ \"homer\", \"marge\" ],\n" +
-                    "  \"children\" : {\n" +
-                    "    \"bart\" : {\n" +
-                    "      \"title\" : \"son\",\n" +
-                    "      \"age\" : \"14\"\n" +
-                    "      },\n" +
-                    "    \"lisa\" : {\n" +
-                    "      \"title\" : \"daughter\",\n" +
-                    "      \"age\" : \"12\"\n" +
-                    "      },\n" +
-                    "    \"maggie\" : {\n" +
-                    "      \"title\" : \"daughter\",\n" +
-                    "      \"age\" : \"1\"\n" +
-                    "      }\n" +
-                    "      \n" +
-                    "  },\n" +
-                    "  \"surname\" : \"simpsons\"\n" +
-                    "}\n";
-
-    @Test
-    public void testCapitalize() {
-        assertEquals("Fred", JsonUtil.capitalize("Fred"));
-        assertEquals("Barney", JsonUtil.capitalize("barney"));
-    }
-
-    @Test
-    public void testDeepCopy() {
-        final JsonParser parser = new JsonParser();
-        final JsonElement j0 = parser.parse(JSON);
-        final JsonElement j1 = JsonUtil.deepCopy(j0);
-        assertEquals(j0, j1);
-
-        j1.getAsJsonObject().get("children").getAsJsonObject().get("bart").getAsJsonObject().addProperty("age", 99);
-        assertNotEquals(j0, j1);
-    }
-
-    @Test
-    public void testFetchObject() {
-        final JsonParser parser = new JsonParser();
-        final JsonElement j0 = parser.parse(JSON);
-        final JsonElement bartAge = JsonUtil.fetch(j0, "children.bart.age");
-        assertEquals(14, bartAge.getAsInt());
-    }
-
-    @Test(expected = NoSuchElementException.class)
-    public void testFetchTooMuch() {
-        final JsonParser parser = new JsonParser();
-        final JsonElement j0 = parser.parse(JSON);
-        JsonUtil.fetch(j0, "children.bart.age.overflow");
-    }
-
-    @Test(expected = NoSuchElementException.class)
-    public void testFetchTooLittle() {
-        final JsonParser parser = new JsonParser();
-        final JsonElement j0 = parser.parse(JSON);
-        JsonUtil.fetch(j0, "");
-    }
-
-    @Test
-    public void testFetchArray() {
-        final JsonParser parser = new JsonParser();
-        final JsonElement j0 = parser.parse(JSON);
-        final JsonElement homer = JsonUtil.fetch(j0, "parents.0");
-        assertEquals("homer", homer.getAsString());
-        final JsonElement marge = JsonUtil.fetch(j0, "parents.1");
-        assertEquals("marge", marge.getAsString());
-    }
-
-    //@Test
-    // disable until this syntax feature is implemented
-    public void testFetchArraySquareBrackets() {
-        final JsonParser parser = new JsonParser();
-        final JsonElement j0 = parser.parse(JSON);
-        final JsonElement homer = JsonUtil.fetch(j0, "parents[0]");
-        assertEquals("homer", homer.getAsString());
-        final JsonElement marge = JsonUtil.fetch(j0, "parents[1]");
-        assertEquals("marge", marge.getAsString());
-    }
-}
--- a/common/json/src/test/java/com/redhat/thermostat/common/json/models/SchemaDefTest.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.common.json.models;
-
-import com.redhat.thermostat.common.yaml.JsonToYaml;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class SchemaDefTest {
-
-    @Test
-    public void testShallowFunctionality() {
-        final SchemaDef def = new SchemaDef(JsonToYaml.class);
-        assertTrue(def.getProperties().get("out") instanceof SchemaDef.SimpleType);
-        final SchemaDef.SimpleType typeOfOut = (SchemaDef.SimpleType)def.getProperties().get("out");
-        assertEquals(SchemaType.TypeClass.OBJECT, typeOfOut.getTypeClass());
-        assertEquals("Writer", typeOfOut.getTypeName());
-    }
-
-    @Test
-    public void testDeepFunctionality() {
-        SchemaDef def = new SchemaDef(JsonToYaml.class, 99);
-        assertTrue(def.getProperties().get("out") instanceof SchemaDef);
-        final SchemaDef typeOfOut = (SchemaDef)def.getProperties().get("out");
-        assertEquals(SchemaType.TypeClass.OBJECT, typeOfOut.getTypeClass());
-        assertFalse(typeOfOut.getProperties().isEmpty());
-    }
-}
--- a/common/json/src/test/java/com/redhat/thermostat/common/yaml/JsonToYamlTest.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.common.yaml;
-
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-
-import org.junit.Test;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.Writer;
-
-
-import static org.junit.Assert.assertEquals;
-
-public class JsonToYamlTest {
-
-    private static final File API1_YAML_FILE = new File("./src/test/resources/systems-swagger.yaml");
-    private static final File API1_JSON_FILE = new File("./src/test/resources/systems-swagger.json");
-
-    @Test
-    public void testConvert() throws IOException {
-
-        // read source JSON file
-        JsonObject goodjson = readFileToJson(API1_JSON_FILE).getAsJsonObject();
-
-        final JsonToYaml j2y = new JsonToYaml();
-
-        // convert to YAML string
-        final String yamlStr = j2y.jsonToYamlString(goodjson);
-
-        // get a temp file name
-        final File tmpFile = mktempfile("JsonToYamlTest.testConvert", ".yaml");
-
-        // write a new YAML file
-        writeFile(tmpFile, yamlStr);
-
-        // read the known good YAML file
-        final YamlToJson y2j = new YamlToJson();
-        final JsonObject goodyaml = y2j.yamlToJsonObject(API1_YAML_FILE);
-        assertEquals(goodjson, goodyaml);
-
-        // read the new YAML file
-        final JsonObject testyaml = y2j.yamlToJsonObject(tmpFile);
-        assertEquals(goodjson, testyaml);
-    }
-
-    private File mktempfile(final String prefix, final String suffix) throws IOException {
-        final File f = File.createTempFile(prefix, suffix);
-        f.deleteOnExit();
-        return f;
-    }
-
-    private JsonElement readFileToJson(File f) throws IOException {
-        try (final Reader in = new BufferedReader(new FileReader(f))) {
-            final JsonParser parser = new JsonParser();
-            return parser.parse(in);
-        } catch (IOException e) {
-            throw e;
-        }
-    }
-
-    private void writeFile(File f, String contents) throws IOException {
-        try (final Writer out = new BufferedWriter(new FileWriter(f))) {
-            out.write(contents);
-            out.close();
-        } catch (IOException e) {
-            throw e;
-        }
-    }
-}
--- a/common/json/src/test/java/com/redhat/thermostat/common/yaml/RefResolverTest.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.common.yaml;
-
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.redhat.thermostat.common.json.JsonUtil;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.IOException;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-public class RefResolverTest {
-
-    private static final File API1_YAML_FILE = new File("./src/test/resources/systems-swagger.yaml");
-
-    @Test
-    public void resolverTest() throws IOException {
-        YamlToJson y2j = new YamlToJson();
-        JsonObject yaml = y2j.yamlToJsonObject(API1_YAML_FILE);
-        assertNotNull(yaml);
-
-        JsonElement getRefType = JsonUtil.fetch(yaml, "paths./systems/{systemId}.get.responses.200.schema.$ref");
-        assertTrue(getRefType.getAsString().endsWith("definitions/systems-get-response"));
-
-        // ref1 is the defintion pointed to by the reference
-        JsonElement ref1 = JsonUtil.fetch(yaml, "definitions.systems-get-response");
-
-        // resolve all refs
-        RefResolver.resolveRefs(yaml, yaml);
-
-        // get the response type, which should no longer be a reference but a copy of the definition pointed to by the reference
-        JsonElement resolvedType = JsonUtil.fetch(yaml, "paths./systems/{systemId}.get.responses.200.schema");
-        assertEquals(ref1, resolvedType);
-    }
-}
--- a/common/json/src/test/java/com/redhat/thermostat/common/yaml/YamlToJsonTest.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.common.yaml;
-
-import com.google.gson.Gson;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.redhat.thermostat.common.json.JsonUtil;
-import com.redhat.thermostat.common.json.models.SwaggerDef;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.IOException;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-public class YamlToJsonTest {
-
-    private static final File API1_YAML_FILE = new File("./src/test/resources/systems-swagger.yaml");
-
-    @Test
-    public void readYamlTest() throws IOException {
-        YamlToJson y2j = new YamlToJson();
-        JsonObject yaml = y2j.yamlToJsonObject(API1_YAML_FILE);
-        assertNotNull(yaml);
-        JsonElement getDescr = JsonUtil.fetch(yaml, "paths./systems/{systemId}.get.description");
-        assertNotNull(getDescr);
-        assertTrue(getDescr.isJsonPrimitive());
-        assertEquals("Get information for system {systemId}.", getDescr.getAsString());
-    }
-
-    @Test
-    public void yamlToModelTest() throws IOException {
-        YamlToJson y2j = new YamlToJson();
-        JsonObject yaml = y2j.yamlToJsonObject(API1_YAML_FILE);
-        assertNotNull(yaml);
-
-        // resolve all refs
-        RefResolver.resolveRefs(yaml, yaml);
-
-        // convert JSON to actual Java class
-        Gson gson = new Gson();
-        SwaggerDef swaggerDef = gson.fromJson(yaml, SwaggerDef.class);
-
-        final String getdescr = JsonUtil.fetch(yaml, "paths./systems/{systemId}.get.description").getAsString();
-        assertEquals(getdescr, swaggerDef.getPaths().get("/systems/{systemId}").getGETAPI().getDescription());
-    }
-
-    private static final String GPL = "GPL v2 with Classpath Exception";
-
-    private static final String YAML_WITH_NULL =
-            "info:\n" +
-            "  title: Thermostat Web Gateway JVM Information API\n" +
-            "  license:\n" +
-            "    name: " + GPL + "\n" +
-            "    url: 'http://www.gnu.org/licenses'\n" +
-            "    org:  null\n" +
-            "    phone: 416-363-6097\n" +
-            "consumes:\n" +
-            "  - application/json\n" +
-            "produces:\n" +
-            "  - application/json\n" +
-            "  - text/html; charset=utf-8\n" +
-            "basePath: /jvms/0.0.1\n";
-
-    @Test
-    public void testNull() throws IOException {
-        YamlToJson y2j = new YamlToJson();
-        JsonObject yaml = y2j.yamlToJsonObject(YAML_WITH_NULL);
-        assertEquals(GPL, JsonUtil.fetch(yaml, "info.license.name").getAsString());
-        final JsonElement nell = JsonUtil.fetch(yaml, "info.license.org");
-        assertTrue(nell.isJsonNull());
-    }
-}
--- a/common/json/src/test/resources/jvms-swagger.json	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,480 +0,0 @@
-{
-  "swagger": "2.0",
-  "info": {
-    "version": "0.0.1",
-    "title": "Thermostat Web Gateway JVM Information API",
-    "license": {
-      "name": "GPL v2 with Classpath Exception",
-      "url": "http://www.gnu.org/licenses"
-    }
-  },
-  "consumes": [
-    "application/json"
-  ],
-  "produces": [
-    "application/json",
-    "text/html; charset=utf-8"
-  ],
-  "basePath": "/jvms/0.0.1",
-  "paths": {
-    "/systems/{systemId}": {
-      "parameters": [
-        {
-          "$ref": "#/parameters/system-id"
-        }
-      ],
-      "get": {
-        "description": "Get jvms for system {systemId}",
-        "parameters": [
-          {
-            "$ref": "#/parameters/limit"
-          },
-          {
-            "$ref": "#/parameters/offset"
-          },
-          {
-            "$ref": "#/parameters/sort"
-          },
-          {
-            "$ref": "#/parameters/include"
-          },
-          {
-            "$ref": "#/parameters/exclude"
-          },
-          {
-            "$ref": "#/parameters/query"
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "OK",
-            "schema": {
-              "$ref": "#/definitions/jvms-get-response"
-            }
-          }
-        }
-      },
-      "post": {
-        "description": "Add jvms for system {systemId}",
-        "parameters": [
-          {
-            "$ref": "#/parameters/jvms-post-body"
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "OK"
-          }
-        }
-      },
-      "delete": {
-        "description": "Delete all jvms on system {systemId}",
-        "responses": {
-          "200": {
-            "description": "OK"
-          }
-        }
-      }
-    },
-    "/systems/{systemId}/jvms/{jvmId}": {
-      "parameters": [
-        {
-          "$ref": "#/parameters/system-id"
-        },
-        {
-          "$ref": "#/parameters/jvm-id"
-        }
-      ],
-      "get": {
-        "description": "Get information for the JVM with id {jvmId} running on system {systemId}",
-        "parameters": [
-          {
-            "$ref": "#/parameters/include"
-          },
-          {
-            "$ref": "#/parameters/exclude"
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "OK",
-            "schema": {
-              "$ref": "#/definitions/jvms-get-response"
-            }
-          }
-        }
-      },
-      "put": {
-        "description": "Update the JVM with id {jvmId} running on system {systemId}",
-        "responses": {
-          "200": {
-            "description": "OK"
-          }
-        },
-        "parameters": [
-          {
-            "$ref": "#/parameters/jvms-put-body"
-          }
-        ]
-      },
-      "delete": {
-        "description": "Delete the JVM with id {jvmId} running on system {systemId}",
-        "responses": {
-          "200": {
-            "description": "OK"
-          }
-        }
-      }
-    },
-    "/tree": {
-      "get": {
-        "description": "Get jvm information organized by systemId",
-        "parameters": [
-          {
-            "$ref": "#/parameters/alive-only"
-          },
-          {
-            "$ref": "#/parameters/include"
-          },
-          {
-            "$ref": "#/parameters/exclude"
-          },
-          {
-            "$ref": "#/parameters/limit"
-          },
-          {
-            "$ref": "#/parameters/offset"
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "OK",
-            "schema": {
-              "$ref": "#/definitions/tree-get-response"
-            }
-          }
-        }
-      }
-    },
-    "/update/systems/{systemId}/ts/{timeStamp}": {
-      "parameters": [
-        {
-          "$ref": "#/parameters/system-id"
-        },
-        {
-          "$ref": "#/parameters/timestamp"
-        }
-      ],
-      "put": {
-        "description": "Set last updated to {timeStamp} for jvm information on system {systemId}",
-        "parameters": [
-          {
-            "$ref": "#/parameters/update-put-body"
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "OK"
-          }
-        }
-      }
-    }
-  },
-  "definitions": {
-    "jvm-get-info": {
-      "type": "object",
-      "properties": {
-        "systemId": {
-          "type": "string"
-        },
-        "agentId": {
-          "type": "string"
-        },
-        "jvmId": {
-          "type": "string"
-        },
-        "mainClass": {
-          "type": "string"
-        },
-        "startTime": {
-          "$ref": "#/definitions/metric"
-        },
-        "stopTime": {
-          "$ref": "#/definitions/metric"
-        },
-        "jvmPid": {
-          "type": "integer"
-        },
-        "javaVersion": {
-          "type": "string"
-        },
-        "javaHome": {
-          "type": "string"
-        },
-        "javaCommandLine": {
-          "type": "string"
-        },
-        "jvmArguments": {
-          "type": "string"
-        },
-        "jvmName": {
-          "type": "string"
-        },
-        "jvmInfo": {
-          "type": "string"
-        },
-        "jvmVersion": {
-          "type": "string"
-        },
-        "classpath": {
-          "type": "string"
-        },
-        "environment": {
-          "type": "array",
-          "items": {
-            "$ref": "#/definitions/environment-items"
-          }
-        },
-        "uid": {
-          "$ref": "#/definitions/metric"
-        },
-        "username": {
-          "type": "string"
-        },
-        "lastUpdated": {
-          "$ref": "#/definitions/metric"
-        }
-      }
-    },
-    "jvm-post-info": {
-      "type": "object",
-      "properties": {
-        "agentId": {
-          "type": "string"
-        },
-        "jvmId": {
-          "type": "string"
-        },
-        "mainClass": {
-          "type": "string"
-        },
-        "startTime": {
-          "$ref": "#/definitions/metric"
-        },
-        "stopTime": {
-          "$ref": "#/definitions/metric"
-        },
-        "jvmPid": {
-          "type": "integer"
-        },
-        "javaVersion": {
-          "type": "string"
-        },
-        "javaHome": {
-          "type": "string"
-        },
-        "javaCommandLine": {
-          "type": "string"
-        },
-        "jvmArguments": {
-          "type": "string"
-        },
-        "jvmName": {
-          "type": "string"
-        },
-        "jvmInfo": {
-          "type": "string"
-        },
-        "jvmVersion": {
-          "type": "string"
-        },
-        "classpath": {
-          "type": "string"
-        },
-        "environment": {
-          "type": "array",
-          "items": {
-            "$ref": "#/definitions/environment-items"
-          }
-        },
-        "uid": {
-          "$ref": "#/definitions/metric"
-        },
-        "username": {
-          "type": "string"
-        },
-        "lastUpdated": {
-          "$ref": "#/definitions/metric"
-        }
-      }
-    },
-    "environment-items": {
-      "type": "object",
-      "properties": {
-        "key": {
-          "type": "string"
-        },
-        "value": {
-          "type": "string"
-        }
-      }
-    },
-    "metric": {
-      "type": "object",
-      "properties": {
-        "$numberLong": {
-          "type": "string"
-        }
-      }
-    },
-    "jvms-get-response": {
-      "type": "object",
-      "properties": {
-        "response": {
-          "type": "array",
-          "items": {
-            "$ref": "#/definitions/jvm-get-info"
-          }
-        }
-      }
-    },
-    "jvms-put-body": {
-      "type": "object",
-      "properties": {
-        "set": {
-          "type": "object"
-        }
-      }
-    },
-    "jvms-post-body": {
-      "type": "array",
-      "items": {
-        "$ref": "#/definitions/jvm-post-info"
-      }
-    },
-    "update-put-body": {
-      "type": "array",
-      "description": "An array of jvm ID strings",
-      "items": {
-        "type": "string"
-      }
-    },
-    "tree-get-response": {
-      "type": "object",
-      "properties": {
-        "systemId": {
-          "type": "string"
-        },
-        "jvms": {
-          "type": "array",
-          "items": {
-            "$ref": "#/definitions/jvm-get-info"
-          }
-        }
-      }
-    }
-  },
-  "parameters": {
-    "system-id": {
-      "name": "systemId",
-      "in": "path",
-      "required": true,
-      "type": "string",
-      "description": "The system ID for the jvms"
-    },
-    "jvm-id": {
-      "name": "jvmId",
-      "in": "path",
-      "required": true,
-      "type": "string",
-      "description": "The ID of the jvm"
-    },
-    "timestamp": {
-      "name": "timeStamp",
-      "in": "path",
-      "required": true,
-      "type": "integer",
-      "format": "int64",
-      "description": "The UNIX timestamp in milliseconds to set the last_updated field for."
-    },
-    "jvms-post-body": {
-      "name": "body",
-      "in": "body",
-      "description": "The jvm information",
-      "required": true,
-      "schema": {
-        "$ref": "#/definitions/jvms-post-body"
-      }
-    },
-    "jvms-put-body": {
-      "name": "body",
-      "in": "body",
-      "description": "The JSON object containing a 'set' object. This contains single item JSON objects that specify the field to replace and the JSON value to replace with. Must not include 'systemId' or 'jvmId' fields. Example { \"set\" : { \"field\" : \"value\", \"field2\":{\"object\":\"item\"} }",
-      "required": true,
-      "schema": {
-        "$ref": "#/definitions/jvms-put-body"
-      }
-    },
-    "update-put-body": {
-      "name": "body",
-      "in": "body",
-      "description": "An array of jvmIds for which to update the last_updated field.",
-      "required": true,
-      "schema": {
-        "$ref": "#/definitions/update-put-body"
-      }
-    },
-    "limit": {
-      "name": "limit",
-      "in": "query",
-      "description": "Limit of items to return. Example '1'",
-      "type": "integer",
-      "required": false,
-      "default": 1
-    },
-    "offset": {
-      "name": "offset",
-      "in": "query",
-      "description": "Offset of items to return. Example '0'",
-      "type": "integer",
-      "required": false,
-      "default": 0
-    },
-    "sort": {
-      "name": "sort",
-      "in": "query",
-      "description": "Sort string. Comma separated list of fields prefixed with '+' for ascending or '-' for descending. Example '?sort=+a,-b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.",
-      "type": "string",
-      "required": false
-    },
-    "query": {
-      "name": "query",
-      "in": "query",
-      "description": "Query string. Comma separated list of key, comparator, value pairs. Comparator supports '==', '<=', '>=', '<', '>', '!='. Example '?query=a==b,c!=d'. Keys are fields in documents and use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.",
-      "type": "string",
-      "required": false
-    },
-    "include": {
-      "name": "include",
-      "in": "query",
-      "description": "Inclusion string. Comma separated list of fields to include in the response. Example '?include=a,b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer. Cannot be used in combination with 'exclude' parameter Overriden by 'exclude' parameter",
-      "type": "string",
-      "required": false
-    },
-    "exclude": {
-      "name": "exclude",
-      "in": "query",
-      "description": "Exclusion string. Comma separated list of fields to exclude in the response. Example '?exclude=a,b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer. Cannot be used in combination with 'include' parameter; takes precedence over 'include' parameter",
-      "type": "string",
-      "required": false
-    },
-    "alive-only": {
-      "name": "aliveOnly",
-      "in": "query",
-      "description": "Whether or not to return only JVMs that are live",
-      "type": "boolean",
-      "default": true,
-      "required": false
-    }
-  }
-}
\ No newline at end of file
--- a/common/json/src/test/resources/jvms-swagger.yaml	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,337 +0,0 @@
-swagger: '2.0'
-info:
-  version: 0.0.1
-  title: Thermostat Web Gateway JVM Information API
-  license:
-    name: GPL v2 with Classpath Exception
-    url: 'http://www.gnu.org/licenses'
-consumes:
-  - application/json
-produces:
-  - application/json
-  - text/html; charset=utf-8
-basePath: /jvms/0.0.1
-paths:
-  '/systems/{systemId}':
-    parameters:
-      - $ref: '#/parameters/system-id'
-    get:
-      description: 'Get jvms for system {systemId}'
-      parameters:
-        - $ref: '#/parameters/limit'
-        - $ref: '#/parameters/offset'
-        - $ref: '#/parameters/sort'
-        - $ref: '#/parameters/include'
-        - $ref: '#/parameters/exclude'
-        - $ref: '#/parameters/query'
-      responses:
-        '200':
-          description: OK
-          schema:
-            $ref: '#/definitions/jvms-get-response'
-    post:
-      description: 'Add jvms for system {systemId}'
-      parameters:
-        - $ref: '#/parameters/jvms-post-body'
-      responses:
-        '200':
-          description: OK
-    delete:
-      description: 'Delete all jvms on system {systemId}'
-      responses:
-        '200':
-          description: OK
-  '/systems/{systemId}/jvms/{jvmId}':
-    parameters:
-    - $ref: '#/parameters/system-id'
-    - $ref: '#/parameters/jvm-id'
-    get:
-      description: 'Get information for the JVM with id {jvmId} running on system {systemId}'
-      parameters:
-        - $ref: '#/parameters/include'
-        - $ref: '#/parameters/exclude'
-      responses:
-        '200':
-          description: OK
-          schema:
-            $ref: '#/definitions/jvms-get-response'
-    put:
-      description: 'Update the JVM with id {jvmId} running on system {systemId}'
-      responses:
-        '200':
-          description: OK
-      parameters:
-      - $ref: "#/parameters/jvms-put-body"
-    delete:
-      description: 'Delete the JVM with id {jvmId} running on system {systemId}'
-      responses:
-        '200':
-          description: OK
-  '/tree':
-    get:
-      description: Get jvm information organized by systemId
-      parameters:
-        - $ref: '#/parameters/alive-only'
-        - $ref: '#/parameters/include'
-        - $ref: '#/parameters/exclude'
-        - $ref: '#/parameters/limit'
-        - $ref: '#/parameters/offset'
-      responses:
-        '200':
-          description: OK
-          schema:
-            $ref: '#/definitions/tree-get-response'
-  '/update/systems/{systemId}/ts/{timeStamp}':
-    parameters:
-      - $ref: '#/parameters/system-id'
-      - $ref: '#/parameters/timestamp'
-    put:
-      description: 'Set last updated to {timeStamp} for jvm information on system {systemId}'
-      parameters:
-      - $ref: "#/parameters/update-put-body"
-      responses:
-        '200':
-          description: OK
-
-definitions:
-  jvm-get-info:
-    type: object
-    properties:
-      systemId:
-        type: string
-      agentId:
-        type: string
-      jvmId:
-        type: string
-      mainClass:
-        type: string
-      startTime:
-        $ref: '#/definitions/metric'
-      stopTime:
-        $ref: '#/definitions/metric'
-      jvmPid:
-        type: integer
-      javaVersion:
-        type: string
-      javaHome:
-        type: string
-      javaCommandLine:
-        type: string
-      jvmArguments:
-        type: string
-      jvmName:
-        type: string
-      jvmInfo:
-        type: string
-      jvmVersion:
-        type: string
-      classpath:
-        type: string
-      environment:
-        type: array
-        items:
-          $ref: '#/definitions/environment-items'
-      uid:
-        $ref: '#/definitions/metric'
-      username:
-        type: string
-      lastUpdated:
-        $ref: '#/definitions/metric'
-
-  jvm-post-info:
-    type: object
-    properties:
-      agentId:
-        type: string
-      jvmId:
-        type: string
-      mainClass:
-        type: string
-      startTime:
-        $ref: '#/definitions/metric'
-      stopTime:
-        $ref: '#/definitions/metric'
-      jvmPid:
-        type: integer
-      javaVersion:
-        type: string
-      javaHome:
-        type: string
-      javaCommandLine:
-        type: string
-      jvmArguments:
-        type: string
-      jvmName:
-        type: string
-      jvmInfo:
-        type: string
-      jvmVersion:
-        type: string
-      classpath:
-        type: string
-      environment:
-        type: array
-        items:
-          $ref: '#/definitions/environment-items'
-      uid:
-        $ref: '#/definitions/metric'
-      username:
-        type: string
-      lastUpdated:
-        $ref: '#/definitions/metric'
-  environment-items:
-    type: object
-    properties:
-      key:
-        type: string
-      value:
-        type: string
-
-  metric:
-    type: object
-    properties:
-      $numberLong:
-        type: string
-
-  jvms-get-response:
-    type: object
-    properties:
-      response:
-        type: array
-        items:
-          $ref: '#/definitions/jvm-get-info'
-  jvms-put-body:
-    type: object
-    properties:
-      set:
-        type: object
-  jvms-post-body:
-    type: array
-    items:
-      $ref: '#/definitions/jvm-post-info'
-
-  update-put-body:
-    type: array
-    description: 'An array of jvm ID strings'
-    items:
-      type: string
-
-  tree-get-response:
-    type: object
-    properties:
-      systemId:
-        type: string
-      jvms:
-        type: array
-        items:
-          $ref: '#/definitions/jvm-get-info'
-parameters:
-  system-id:
-    name: systemId
-    in: path
-    required: true
-    type: string
-    description: The system ID for the jvms
-  jvm-id:
-    name: jvmId
-    in: path
-    required: true
-    type: string
-    description: The ID of the jvm
-  timestamp:
-    name: timeStamp
-    in: path
-    required: true
-    type: integer
-    format: int64
-    description: The UNIX timestamp in milliseconds to set the last_updated field for.
-  jvms-post-body:
-    name: body
-    in: body
-    description: The jvm information
-    required: true
-    schema:
-      $ref: '#/definitions/jvms-post-body'
-  jvms-put-body:
-    name: body
-    in: body
-    description: >-
-      The JSON object containing a 'set' object. This contains single item JSON
-      objects that specify the field to replace and the JSON value to replace with.
-      Must not include 'systemId' or 'jvmId' fields. Example { "set" : {
-      "field" : "value", "field2":{"object":"item"} }
-    required: true
-    schema:
-      $ref: '#/definitions/jvms-put-body'
-  update-put-body:
-    name: body
-    in: body
-    description: >-
-      An array of jvmIds for which to update the last_updated field.
-    required: true
-    schema:
-      $ref: '#/definitions/update-put-body'
-  limit:
-    name: limit
-    in: query
-    description: Limit of items to return. Example '1'
-    type: integer
-    required: false
-    default: 1
-  offset:
-    name: offset
-    in: query
-    description: Offset of items to return. Example '0'
-    type: integer
-    required: false
-    default: 0
-  sort:
-    name: sort
-    in: query
-    description: >-
-      Sort string. Comma separated list of fields prefixed with '+' for
-      ascending or '-' for descending. Example '?sort=+a,-b' Fields use dot
-      notation for embedded documents. Example 'outer.inner' refers to field
-      inner contained in field outer.
-    type: string
-    required: false
-  query:
-    name: query
-    in: query
-    description: >-
-      Query string. Comma separated list of key, comparator, value pairs.
-      Comparator supports '==', '<=', '>=', '<', '>', '!='. Example
-      '?query=a==b,c!=d'. Keys are fields in documents and use dot notation for
-      embedded documents. Example 'outer.inner' refers to field inner contained
-      in field outer.
-    type: string
-    required: false
-  include:
-    name: include
-    in: query
-    description: >-
-      Inclusion string. Comma separated list of fields to include in the
-      response. Example '?include=a,b' Fields use dot notation for embedded
-      documents. Example 'outer.inner' refers to field inner contained in field
-      outer. Cannot be used in combination with 'exclude' parameter Overriden by
-      'exclude' parameter
-    type: string
-    required: false
-  exclude:
-    name: exclude
-    in: query
-    description: >-
-      Exclusion string. Comma separated list of fields to exclude in the
-      response. Example '?exclude=a,b' Fields use dot notation for embedded
-      documents. Example 'outer.inner' refers to field inner contained in field
-      outer. Cannot be used in combination with 'include' parameter; takes
-      precedence over 'include' parameter
-    type: string
-    required: false
-  alive-only:
-    name: aliveOnly
-    in: query
-    description: Whether or not to return only JVMs that are live
-    type: boolean
-    default: true
-    required: false
\ No newline at end of file
--- a/common/json/src/test/resources/systems-swagger.json	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,283 +0,0 @@
-{
-  "swagger": "2.0",
-  "info": {
-    "version": "0.0.1",
-    "title": "Thermostat Web Gateway System Information API",
-    "license": {
-      "name": "GPL v2 with Classpath Exception",
-      "url": "http://www.gnu.org/licenses"
-    }
-  },
-  "consumes": [
-    "application/json"
-  ],
-  "produces": [
-    "application/json",
-    "text/html; charset=utf-8"
-  ],
-  "basePath": "/systems/0.0.1",
-  "paths": {
-    "/": {
-      "get": {
-        "description": "Get information for all systems.",
-        "parameters": [
-          {
-            "$ref": "#/parameters/limit"
-          },
-          {
-            "$ref": "#/parameters/offset"
-          },
-          {
-            "$ref": "#/parameters/sort"
-          },
-          {
-            "$ref": "#/parameters/include"
-          },
-          {
-            "$ref": "#/parameters/exclude"
-          },
-          {
-            "$ref": "#/parameters/query"
-          },
-          {
-            "$ref": "#/parameters/alive"
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "OK",
-            "schema": {
-              "$ref": "#/definitions/systems-get-response"
-            }
-          }
-        }
-      }
-    },
-    "/systems/{systemId}": {
-      "parameters": [
-        {
-          "$ref": "#/parameters/system-id"
-        }
-      ],
-      "get": {
-        "description": "Get information for system {systemId}.",
-        "parameters": [
-          {
-            "$ref": "#/parameters/limit"
-          },
-          {
-            "$ref": "#/parameters/offset"
-          },
-          {
-            "$ref": "#/parameters/sort"
-          },
-          {
-            "$ref": "#/parameters/include"
-          },
-          {
-            "$ref": "#/parameters/exclude"
-          },
-          {
-            "$ref": "#/parameters/query"
-          },
-          {
-            "$ref": "#/parameters/alive"
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "OK",
-            "schema": {
-              "$ref": "#/definitions/systems-get-response"
-            }
-          }
-        }
-      },
-      "put": {
-        "description": "Update information for system {systemId}.",
-        "parameters": [
-          {
-            "$ref": "#/parameters/systems-put-body"
-          },
-          {
-            "$ref": "#/parameters/query"
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "OK"
-          }
-        }
-      },
-      "post": {
-        "description": "Add information for system {systemId}",
-        "parameters": [
-          {
-            "$ref": "#/parameters/system-info-array"
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "OK"
-          }
-        }
-      },
-      "delete": {
-        "description": "Delete information for system ID {systemId}.",
-        "parameters": [
-          {
-            "$ref": "#/parameters/query"
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "OK"
-          }
-        }
-      }
-    }
-  },
-  "definitions": {
-    "systems-get-response": {
-      "type": "object",
-      "properties": {
-        "response": {
-          "$ref": "#/definitions/system-info-array"
-        }
-      }
-    },
-    "system-info-array": {
-      "type": "array",
-      "items": {
-        "$ref": "#/definitions/system-info"
-      }
-    },
-    "system-info": {
-      "type": "object",
-      "properties": {
-        "systemId": {
-          "type": "string"
-        },
-        "agentId": {
-          "type": "string"
-        },
-        "hostname": {
-          "type": "string"
-        },
-        "osName": {
-          "type": "string"
-        },
-        "osKernel": {
-          "type": "string"
-        },
-        "osArch": {
-          "type": "string"
-        },
-        "cpuCount": {
-          "type": "integer"
-        },
-        "cpuModel": {
-          "type": "string"
-        },
-        "totalMemory": {
-          "type": "integer",
-          "format": "int64"
-        },
-        "timeCreated": {
-          "type": "integer",
-          "format": "int64"
-        },
-        "lastUpdated": {
-          "type": "integer",
-          "format": "int64"
-        }
-      }
-    },
-    "systems-put-body": {
-      "type": "object",
-      "properties": {
-        "set": {
-          "type": "object"
-        }
-      }
-    }
-  },
-  "parameters": {
-    "system-id": {
-      "name": "systemId",
-      "in": "path",
-      "required": true,
-      "type": "string"
-    },
-    "system-info-array": {
-      "name": "system-info-array",
-      "in": "body",
-      "description": "The system information",
-      "required": true,
-      "schema": {
-        "$ref": "#/definitions/system-info-array"
-      }
-    },
-    "systems-put-body": {
-      "name": "body",
-      "in": "body",
-      "description": "The JSON object containing a 'set' object. This contains single item JSON objects that specify the field to replace and the JSON value to replace with. Must not include 'systemId' field. Example { \"set\" : { \"field\" : \"value\", \"field2\":{\"object\":\"item\"} }",
-      "required": true,
-      "schema": {
-        "$ref": "#/definitions/systems-put-body"
-      }
-    },
-    "alive": {
-      "name": "alive",
-      "in": "query",
-      "description": "Whether to return only systems that are currently running",
-      "type": "boolean",
-      "required": false,
-      "default": true
-    },
-    "limit": {
-      "name": "limit",
-      "in": "query",
-      "description": "Limit of items to return. Example '1'",
-      "type": "integer",
-      "required": false,
-      "default": 1
-    },
-    "offset": {
-      "name": "offset",
-      "in": "query",
-      "description": "Offset of items to return. Example '0'",
-      "type": "integer",
-      "required": true,
-      "default": 0
-    },
-    "sort": {
-      "name": "sort",
-      "in": "query",
-      "description": "Sort string. Comma separated list of fields prefixed with '+' for ascending or '-' for descending. Example '?sort=+a,-b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.",
-      "type": "string",
-      "required": false
-    },
-    "query": {
-      "name": "query",
-      "in": "query",
-      "description": "Query string. Comma separated list of key, comparator, value pairs. Comparator supports '==', '<=', '>=', '<', '>', '!='. Example '?query=a==b,c!=d'. Keys are fields in documents and use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.",
-      "type": "string",
-      "required": false
-    },
-    "include": {
-      "name": "include",
-      "in": "query",
-      "description": "Inclusion string. Comma separated list of fields to include in the response. Example '?include=a,b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer. Cannot be used in combination with 'exclude' parameter Overriden by 'exclude' parameter",
-      "type": "string",
-      "required": false
-    },
-    "exclude": {
-      "name": "exclude",
-      "in": "query",
-      "description": "Exclusion string. Comma separated list of fields to exclude in the response. Example '?exclude=a,b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer. Cannot be used in combination with 'include' parameter; takes precedence over 'include' parameter",
-      "type": "string",
-      "required": false
-    }
-  }
-}
--- a/common/json/src/test/resources/systems-swagger.yaml	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-swagger: '2.0'
-info:
-  version: 0.0.1
-  title: Thermostat Web Gateway System Information API
-  license:
-    name: GPL v2 with Classpath Exception
-    url: 'http://www.gnu.org/licenses'
-consumes:
-  - application/json
-produces:
-  - application/json
-  - text/html; charset=utf-8
-basePath: /systems/0.0.1
-paths:
-  /:
-    get:
-      description: Get information for all systems.
-      parameters:
-        - $ref: '#/parameters/limit'
-        - $ref: '#/parameters/offset'
-        - $ref: '#/parameters/sort'
-        - $ref: '#/parameters/include'
-        - $ref: '#/parameters/exclude'
-        - $ref: '#/parameters/query'
-        - $ref: '#/parameters/alive'
-      responses:
-        '200':
-          description: OK
-          schema:
-            $ref: '#/definitions/systems-get-response'
-  /systems/{systemId}:
-    parameters:
-      - $ref: '#/parameters/system-id'
-    get:
-      description: Get information for system {systemId}.
-      parameters:
-        - $ref: '#/parameters/limit'
-        - $ref: '#/parameters/offset'
-        - $ref: '#/parameters/sort'
-        - $ref: '#/parameters/include'
-        - $ref: '#/parameters/exclude'
-        - $ref: '#/parameters/query'
-        - $ref: '#/parameters/alive'
-      responses:
-        '200':
-          description: OK
-          schema:
-            $ref: '#/definitions/systems-get-response'
-    put:
-      description: Update information for system {systemId}.
-      parameters:
-        - $ref: '#/parameters/systems-put-body'
-        - $ref: '#/parameters/query'
-      responses:
-        '200':
-          description: OK
-    post:
-      description: Add information for system {systemId}
-      parameters:
-        - $ref: '#/parameters/system-info-array'
-      responses:
-        '200':
-          description: OK
-    delete:
-      description: Delete information for system ID {systemId}.
-      parameters:
-        - $ref: '#/parameters/query'
-      responses:
-        '200':
-          description: OK
-definitions:
-  systems-get-response:
-    type: object
-    properties:
-      response:
-          $ref: '#/definitions/system-info-array'
-  system-info-array:
-    type: array
-    items:
-      $ref: '#/definitions/system-info'
-  system-info:
-    type: object
-    properties:
-      systemId:
-        type: string
-      agentId:
-        type: string
-      hostname:
-        type: string
-      osName:
-        type: string
-      osKernel:
-        type: string
-      osArch:
-        type: string
-      cpuCount:
-        type: integer
-      cpuModel:
-        type: string
-      totalMemory:
-        type: integer
-        format: int64
-      timeCreated:
-        type: integer
-        format: int64
-      lastUpdated:
-        type: integer
-        format: int64
-  systems-put-body:
-    type: object
-    properties:
-      "set":
-        type: object
-parameters:
-  system-id:
-    name: systemId
-    in: path
-    required: true
-    type: string
-  system-info-array:
-    name: system-info-array
-    in: body
-    description: The system information
-    required: true
-    schema:
-      $ref: '#/definitions/system-info-array'
-  systems-put-body:
-    name: body
-    in: body
-    description: >-
-      The JSON object containing a 'set' object. This contains single item JSON
-      objects that specify the field to replace and the JSON value to replace with.
-      Must not include 'systemId' field. Example { "set" : {
-      "field" : "value", "field2":{"object":"item"} }
-    required: true
-    schema:
-      $ref: '#/definitions/systems-put-body'
-  alive:
-    name: alive
-    in: query
-    description: Whether to return only systems that are currently running
-    type: boolean
-    required: false
-    default: true
-  limit:
-    name: limit
-    in: query
-    description: Limit of items to return. Example '1'
-    type: integer
-    required: false
-    default: 1
-  offset:
-    name: offset
-    in: query
-    description: Offset of items to return. Example '0'
-    type: integer
-    required: true
-    default: 0
-  sort:
-    name: sort
-    in: query
-    description: Sort string. Comma separated list of fields prefixed with '+' for ascending or '-' for descending. Example '?sort=+a,-b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.
-    type: string
-    required: false
-  query:
-    name: query
-    in: query
-    description: Query string. Comma separated list of key, comparator, value pairs. Comparator supports '==', '<=', '>=', '<', '>', '!='. Example '?query=a==b,c!=d'. Keys are fields in documents and use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.
-    type: string
-    required: false
-  include:
-    name: include
-    in: query
-    description: >-
-      Inclusion string. Comma separated list of fields to include in the
-      response. Example '?include=a,b' Fields use dot notation for embedded
-      documents. Example 'outer.inner' refers to field inner contained in field
-      outer. Cannot be used in combination with 'exclude' parameter Overriden by
-      'exclude' parameter
-    type: string
-    required: false
-  exclude:
-    name: exclude
-    in: query
-    description: >-
-      Exclusion string. Comma separated list of fields to exclude in the
-      response. Example '?exclude=a,b' Fields use dot notation for embedded
-      documents. Example 'outer.inner' refers to field inner contained in field
-      outer. Cannot be used in combination with 'include' parameter; takes
-      precedence over 'include' parameter
-    type: string
-    required: false
--- a/common/pom.xml	Thu Sep 28 10:50:29 2017 +0200
+++ b/common/pom.xml	Fri Sep 29 14:48:00 2017 -0400
@@ -1,58 +1,235 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Copyright 2012-2017 Red Hat, Inc.
-
- This file is part of Thermostat.
-
- Thermostat is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- Thermostat is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Thermostat; see the file COPYING.  If not see
- <http://www.gnu.org/licenses/>.
-
- Linking this code with other modules is making a combined work
- based on this code.  Thus, the terms and conditions of the GNU
- General Public License cover the whole combination.
-
- As a special exception, the copyright holders of this code give
- you permission to link this code with independent modules to
- produce an executable, regardless of the license terms of these
- independent modules, and to copy and distribute the resulting
- executable under terms of your choice, provided that you also
- meet, for each linked independent module, the terms and conditions
- of the license of that module.  An independent module is a module
- which is not derived from or based on this code.  If you modify
- this code, you may extend this exception to your version of the
- library, but you are not obligated to do so.  If you do not wish
- to do so, delete this exception statement from your version.
-
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
-    <parent>
-        <groupId>com.redhat.thermostat</groupId>
-        <artifactId>thermostat-base</artifactId>
-        <version>1.99.12-SNAPSHOT</version>
-    </parent>
+    <groupId>com.redhat.thermostat</groupId>
+    <artifactId>thermostat-common</artifactId>
+    <version>0.1.0</version>
+    <packaging>bundle</packaging>
+
+    <!-- required for uploading to Maven Central -->
+    <name>Thermostat project - common library</name>
+    <description>A shared library used by other components of Thermostat</description>
+    <url>http://icedtea.classpath.org/thermostat</url>
+    <licenses>
+        <license>
+            <name>GNU General Public License, version 2 (with "classpath exception")</name>
+            <url>https://www.gnu.org/licenses/gpl-2.0.html</url>
+        </license>
+    </licenses>
+    <developers>
+        <developer>
+            <name>Severin Gehwolf</name>
+            <email>sgehwolf@redhat.com</email>
+            <organization>Red Hat, Inc.</organization>
+            <organizationUrl>http://www.redhat.com</organizationUrl>
+        </developer>
+        <developer>
+            <name>Simon Tooke</name>
+            <email>stooke@redhat.com</email>
+            <organization>Red Hat, Inc.</organization>
+            <organizationUrl>http://www.redhat.com</organizationUrl>
+        </developer>
+        <developer>
+           <name>Mario Torre</name>
+           <email>neugens@redhat.com</email>
+           <organization>Red Hat, Inc.</organization>
+           <organizationUrl>http://www.redhat.com</organizationUrl>
+        </developer>
+    </developers>
+    <scm>
+        <connection>scm:hg:http://icedtea.classpath.org/hg/thermostat-ng</connection>
+        <developerConnection>scm:hg:ssh://icedtea.classpath.org/hg/thermostat-ng</developerConnection>
+        <url>http://icedtea.classpath.org/thermostat</url>
+    </scm>
+
+    <properties>
+        <thermostat.java.version>1.7</thermostat.java.version>
+
+        <!-- OSGi version information -->
+        <osgi.core.version>4.3.1</osgi.core.version>
+        <osgi.compendium.version>4.3.1</osgi.compendium.version>
+        <osgi.compendium.osgi-version>4.3.1.201210102024</osgi.compendium.osgi-version>
+        <osgi.compendium.bundle.symbolic-name>osgi.cmpn</osgi.compendium.bundle.symbolic-name>
+        <felix.framework.version>4.2.0</felix.framework.version>
+        <felix.scr.version>1.8.2</felix.scr.version>
+        <felix.scr.annotations.version>1.9.12</felix.scr.annotations.version>
 
-    <artifactId>base-common</artifactId>
-    <packaging>pom</packaging>
+        <!-- other packages -->
+        <gson.version>2.6.2</gson.version>
+        <junit.version>4.12</junit.version>
+    </properties>
+
+    <!-- define repos for staging -->
+    <distributionManagement>
+        <snapshotRepository>
+            <id>ossrh</id>
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+        </snapshotRepository>
+        <repository>
+            <id>ossrh</id>
+            <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+        </repository>
+    </distributionManagement>
+
+    <!-- create a 'deploy' profile, and only sign when deploying (NOT when installing, as would happen if this was in the build section) -->
+    <!-- to deploy properly, use mvn clean deploy -Pdeploy -->
+    <profiles>
+        <profile>
+            <id>deploy</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-gpg-plugin</artifactId>
+                        <version>1.5</version>
+                        <executions>
+                            <execution>
+                                <id>sign-artifacts</id>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>sign</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <!--
+                     3.6+ is JDK 9 compatible. See:
+                     https://cwiki.apache.org/confluence/display/MAVEN/Java+9+-+Jigsaw
+                 -->
+                <version>3.6.1</version>
+                <configuration>
+                    <fork>true</fork>
+                    <meminitial>128m</meminitial>
+                    <maxmem>1024m</maxmem>
+                    <source>${thermostat.java.version}</source>
+                    <target>${thermostat.java.version}</target>
+                </configuration>
+            </plugin>
 
-    <name>Thermostat Base Common</name>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>1.4.0</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-SymbolicName>com.redhat.thermostat.common</Bundle-SymbolicName>
+                        <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
+                        <Export-Package>
+                            com.redhat.thermostat.common.json,
+                            com.redhat.thermostat.common.json.models,
+                            com.redhat.thermostat.common.yaml,
+                            com.redhat.thermostat.lang.schema,
+                            com.redhat.thermostat.lang.schema.models,
+                            com.redhat.thermostat.lang.schema.annotations
+                        </Export-Package>
+                        <Private-Package>
+                            com.redhat.thermostat.lang.schema.internal,
+                        </Private-Package>
+                        <!-- Do not autogenerate uses clauses in Manifests -->
+                        <_nouses>true</_nouses>
+                    </instructions>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>generate-scr-scrdescriptor</id>
+                        <goals>
+                            <goal>scr</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+                <version>3.0.1</version>
+                <executions>
+                    <execution>
+                        <id>attach-sources</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
 
-    <modules>
-        <module>type-system</module>
-        <module>json</module>
-    </modules>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <version>2.9.1</version>
+                <configuration>
+                    <excludePackageNames>*.internal</excludePackageNames>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>attach-javadocs</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.sonatype.plugins</groupId>
+                <artifactId>nexus-staging-maven-plugin</artifactId>
+                <version>1.6.7</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <serverId>ossrh</serverId>
+                    <nexusUrl>https://oss.sonatype.org/</nexusUrl>
+                    <autoReleaseAfterClose>true</autoReleaseAfterClose>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr</artifactId>
+            <version>${felix.scr.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.framework</artifactId>
+            <version>${felix.framework.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+            <version>${felix.scr.annotations.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>${gson.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>${junit.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
 </project>
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/json/JsonUtil.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.json;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+/**
+ * misc GSON utility classes
+ */
+public class JsonUtil {
+
+    static String capitalize(final String s) {
+        return s.substring(0, 1).toUpperCase() + s.substring(1);
+    }
+
+    /**
+     * access a nested JSON object via a path string
+     * "foo.bar.2.fred" is equivalent to
+     * root.getAsJsonObject().get("foo").getAsJsonObject().get("bar").getAsJsonArray().get(2).getAsJsonObject().get("fred")
+     *
+     * @param root object to access
+     * @param path path into object
+     * @return element within root
+     */
+    public static JsonElement fetch(final JsonElement root, final String path) {
+        String[] pathelements = path.split("[.]");
+        // NOTE - it would be nice to parse foo[N] to foo.N to allow normal subscripting
+        return fetch(root, pathelements, 0);
+    }
+
+    /**
+     * access a nexted JSON object via a path string
+     * "foo.bar.2.fred" is equivalent to
+     * root.getAsJsonObject().get("foo").getAsJsonObject().get("bar").getAsJsonArray().get(2).getAsJsonObject().get("fred")
+     *
+     * @param root      object to access
+     * @param path      path into object
+     * @param delimiter delimiter regex for path antries (default '.')
+     * @return element within root
+     */
+    public static JsonElement fetch(final JsonElement root, final String path, final String delimiter) {
+        String[] pathelements = path.split(delimiter);
+        return fetch(root, pathelements, 0);
+    }
+
+    private static JsonElement fetch(final JsonElement e, final String[] pathelements, int idx) {
+        if (idx == pathelements.length) {
+            // we've fallen off the end of the input path - now it's time to return the current object.
+            return e;
+        } else if (idx > pathelements.length) {
+            throw new IndexOutOfBoundsException("Internal error in JsonUtil.fetch() - index = " + idx);
+        } else {
+            if (e.isJsonObject()) {
+                JsonObject obj = e.getAsJsonObject();
+                JsonElement next = obj.get(pathelements[idx]);
+                if (next == null) {
+                    throw new NoSuchElementException(pathelements[idx]);
+                } else {
+                    return fetch(next, pathelements, idx + 1);
+                }
+            } else if (e.isJsonArray()) {
+                JsonArray arr = e.getAsJsonArray();
+                int n = Integer.parseInt(pathelements[idx]);
+                if (arr.size() <= n) {
+                    throw new ArrayIndexOutOfBoundsException(n);
+                } else {
+                    return fetch(arr.get(n), pathelements, idx + 1);
+                }
+            } else {
+                throw new NoSuchElementException(pathelements[idx]);
+            }
+        }
+    }
+
+    /**
+     * perform a deep copy of a JsonElement
+     *
+     * @param jsonElement element to copy
+     * @return deep copy of the element tree
+     */
+    // why isn't JsonElement.deepCopy() public?
+    public static JsonElement deepCopy(JsonElement jsonElement) {
+        if (jsonElement.isJsonPrimitive() || jsonElement.isJsonNull()) {
+            return jsonElement;       // these are immutables anyway
+        } else if (jsonElement.isJsonObject()) {
+            return deepCopy(jsonElement.getAsJsonObject());
+        } else if (jsonElement.isJsonArray()) {
+            return deepCopy(jsonElement.getAsJsonArray());
+        } else {
+            throw new UnsupportedOperationException("Unsupported element: " + jsonElement);
+        }
+    }
+
+    private static JsonObject deepCopy(JsonObject jsonObject) {
+        JsonObject result = new JsonObject();
+        for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
+            result.add(entry.getKey(), deepCopy(entry.getValue()));
+        }
+        return result;
+    }
+
+    private static JsonArray deepCopy(JsonArray jsonArray) {
+        JsonArray result = new JsonArray();
+        for (JsonElement e : jsonArray) {
+            result.add(deepCopy(e));
+        }
+        return result;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/json/models/ApiDef.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.json.models;
+
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.SerializedName;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Java representation of a Swagger-defined web API endpoint
+ */
+public class ApiDef {
+
+    String path;
+    String description;
+    JsonObject root;
+    List<ParameterDef>  parameters;
+    MethodDef get;
+    MethodDef put;
+    MethodDef post;
+    MethodDef delete;
+
+    /**
+     * Java representation of a Swagger endpoint
+     */
+    public static class MethodDef {
+        List<ParameterDef> parameters;
+        String description;
+        Map<Integer, ResponseDef> responses;
+
+        public String getDescription() {
+            return this.description;
+        }
+    }
+
+    static class ResponseDef {
+        String description;
+        JsonObject schema;
+    }
+
+    static class ParameterDef {
+        enum In { query, path, body };
+        enum Type { integer, string, bool };
+        String name;
+        String description;
+        In in;
+        Type type;
+        boolean required;
+        @SerializedName("default")
+        String deflt;
+    }
+
+    public void setPath(String path) {
+        this.path = path;
+    }
+
+    public MethodDef getGETAPI() {
+        return get;
+    }
+
+    public MethodDef getPOSTAPI() {
+        return post;
+    }
+
+    public MethodDef getDELETEAPI() {
+        return delete;
+    }
+
+    public MethodDef getPUTAPI() {
+        return put;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/json/models/SchemaDef.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.json.models;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.SerializedName;
+
+import com.redhat.thermostat.common.yaml.JsonToYaml;
+import com.redhat.thermostat.lang.schema.annotations.Schema;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Partial Java representation of a JSON Schema <br>
+ * (see json-schema.org)
+ */
+public class SchemaDef implements SchemaType {
+
+    private static final Gson gson;
+    private static final int DEFAULT_MAXDEPTH = 1;
+
+    static {
+        final boolean ENABLE_PRETTY_PRINT = false;
+        if (ENABLE_PRETTY_PRINT) {
+            GsonBuilder gbuilder = new GsonBuilder();
+            gbuilder.setPrettyPrinting();
+            gson = gbuilder.create();
+        } else {
+            gson = new Gson();
+        }
+    }
+
+    @SerializedName("$schema")
+    private String schema;
+    @SerializedName("$id")
+    private String id;
+    private String title;
+    private String description;
+    private Map<String, SchemaType> properties;
+    private List<String> required;
+
+    /** standard JSON schema properties that are not yet implemented:
+     private int multipleOf;
+     private long maximum;
+     private long exclusiveMaximum;
+     private long minimum;
+     private long exclusiveMinimum;
+     private int maxLength;
+     private int minLength;
+     private String pattern;
+     private int maxItems;
+     private int minItems;
+     private boolean uniqueItems;
+     private int maxProperties;
+     private int minProperties;
+     (and more, see json-schema.org)
+     ***/
+
+    // for GSon
+    public SchemaDef() {}
+
+    public SchemaDef(Object target) {
+        this(target.getClass(), DEFAULT_MAXDEPTH);
+    }
+
+    public SchemaDef(Object target, int maxDepth) {
+        this(target.getClass(), maxDepth);
+    }
+
+    public SchemaDef(Class target) {
+        this(target, true, DEFAULT_MAXDEPTH);
+    }
+
+    public SchemaDef(Class target, int maxDepth) {
+        this(target, true, maxDepth);
+    }
+
+    private SchemaDef(Class target, boolean rootLevel, int maxDepth) {
+        if (rootLevel) {
+            schema = "http://json-schema.org/draft-04/schema#";
+        }
+        Field[] fields = target.getDeclaredFields();
+        if (fields.length > 0) {
+            properties = new HashMap<>(fields.length);
+            required = new ArrayList<>();
+            for (Field field : fields) {
+                final boolean isTransient =  Modifier.isTransient(field.getModifiers());
+                if (!isTransient) {
+                    String fname = field.getAnnotation(SerializedName.class) != null ? field.getAnnotation(SerializedName.class).value() : field.getName();
+                    Schema schema = field.getAnnotation(Schema.class);
+                    String descr = null;
+                    if (schema != null) {
+                        if (!schema.name().isEmpty()) {
+                            fname = schema.name();
+                        }
+                        descr = schema.description();
+                        if (schema.required()) {
+                            required.add(fname);
+                        }
+                    }
+                    if (field.getType().isPrimitive()) {
+                        String tt = field.getType().getSimpleName();
+                        properties.put(fname, new SimpleType(tt, descr));
+                    } else if (maxDepth > 1){
+                        properties.put(fname, new SchemaDef(field.getType(), false, maxDepth - 1));
+                    } else {
+                        properties.put(fname, new SimpleType(field.getType().getSimpleName(), descr));
+                    }
+                }
+            }
+            if (required.isEmpty()) {
+                required = null;
+            }
+        }
+    }
+
+    public Map<String, SchemaType> getProperties() {
+        return this.properties;
+    }
+
+    public List<String> getRequired() {
+        return this.required;
+    }
+
+    public JsonObject toJsonObject() {
+        JsonElement el = gson.toJsonTree(this);
+        return el.isJsonObject() ? el.getAsJsonObject() : null;
+    }
+
+    public String toString() {
+        return gson.toJson(this);
+    }
+
+    @Override
+    public TypeClass getTypeClass() {
+        return TypeClass.OBJECT;
+    }
+
+    public static class SimpleType implements SchemaType {
+        transient TypeClass type;
+        @SerializedName("type")
+        String typeStr;
+        String description;
+        SimpleType(String tname, String descr) {
+            if ("string".equals(tname)) {
+                type = TypeClass.STRING;
+            } else if ("int".equals(tname) || "float".equals(tname) || "double".equals(tname) || "long".equals(tname) || "number".equals(tname)) {
+                type = TypeClass.NUMBER;
+            } else if ("Integer".equals(tname) || "Float".equals(tname) || "Double".equals(tname) || "Long".equals(tname)) {
+                type = TypeClass.NUMBER;
+            } else if ("boolean".equals(tname) || "Boolean".equals(tname)) {
+                type = TypeClass.BOOLEAN;
+            } else {
+                type = TypeClass.OBJECT;
+            }
+            this.typeStr = type == TypeClass.OBJECT ? tname : type.toString();
+            this.description = descr;
+        }
+        @Override
+        public TypeClass getTypeClass() {
+            return type;
+        }
+        public String getTypeName() {
+            return type == TypeClass.OBJECT ? typeStr : type.toString();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/json/models/SchemaType.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.json.models;
+
+/**
+ * the type of a JSON schema element
+ */
+public interface SchemaType {
+    TypeClass getTypeClass();
+
+    enum TypeClass {
+
+        OBJECT("object"),
+        ARRAY("array"),
+        NUMBER("number"),
+        STRING("string"),
+        BOOLEAN("boolean"),
+        NULL("null");
+
+        private final String typeString;
+
+        private TypeClass(String s) {
+            typeString = s;
+        }
+
+        @Override
+        public String toString() {
+            return typeString;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/json/models/SwaggerDef.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.json.models;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Java representation of a Swagger file
+ */
+public class SwaggerDef {
+
+    String swagger;
+    InfoDef info;
+    List<String> consumes;
+    List<String> produces;
+    String basePath;
+    Map<String, ApiDef> paths;
+
+    static class InfoDef {
+        String version;
+        String title;
+        LicenseDef license;
+    }
+
+    static class LicenseDef {
+        String name;
+        String url;
+    }
+
+    static class SwaggerSchema extends SchemaDef {
+        private String type;
+    }
+
+    public String getBasePath() {
+        return basePath;
+    }
+
+    public Map<String, ApiDef> getPaths() {
+        return paths;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/yaml/JsonToYaml.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.yaml;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Map;
+
+/**
+ * convert JSON object to YAML string
+ */
+public class JsonToYaml {
+
+    private Writer out;
+    private int indent = 2;
+
+    public void setIndentation(int i) {
+        this.indent = i;
+    }
+
+    String jsonToYamlString(JsonObject root) throws IOException {
+        this.out = new StringWriter();
+        jsonToYaml(root, out);
+        return out.toString();
+    }
+
+    public void jsonToYaml(JsonObject root, Writer out) throws IOException {
+        this.out = out;
+        jsonToYaml(root, 0);
+    }
+
+    private void dispatch(JsonElement el, int currentIndent) throws IOException {
+        if (el.isJsonPrimitive()) {
+            final JsonPrimitive pr = el.getAsJsonPrimitive();
+            if (pr.isBoolean() || pr.isNumber()) {
+                out.append(el.getAsString()).append('\n');
+            } else {
+                out.append("'").append(el.getAsString()).append("'\n");
+            }
+        } else if (el.isJsonArray()) {
+            out.append('\n');
+            jsonToYaml(el.getAsJsonArray(), currentIndent);
+        } else if (el.isJsonObject()) {
+            out.append('\n');
+            jsonToYaml(el.getAsJsonObject(), currentIndent);
+        } else {
+            throw new UnsupportedOperationException("Unsupported element: " + el);
+        }
+    }
+
+    private void jsonToYaml(JsonObject obj, int currentIndent) throws IOException {
+        final int newindent = currentIndent + indent;
+        for (final Map.Entry<String, JsonElement> entry : obj.entrySet()) {
+            doIndent(currentIndent);
+            out.append(entry.getKey()).append(": ");
+            dispatch(entry.getValue(), newindent);
+        }
+    }
+
+    private void jsonToYaml(JsonArray array, int currentIndent) throws IOException {
+        for (final JsonElement el : array) {
+            doIndent(currentIndent);
+            out.append("- ");
+            if (el.isJsonArray()) {
+                jsonToYaml(el.getAsJsonArray(), 0);
+            } else if (el.isJsonObject()) {
+                jsonToYaml(el.getAsJsonObject(), 0);
+            } else {
+                dispatch(el, 0);
+            }
+        }
+    }
+
+    private void doIndent(int currentIndent) throws IOException {
+        for (int i = 0; i < currentIndent; i++)
+            out.append(' ');
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/yaml/RefResolver.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.yaml;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.redhat.thermostat.common.json.JsonUtil;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * Given a JSON object (created from a Swagger YAML or JSON file), resolve all $ref paths
+ * TODO: currently doesn't test for circular references
+ */
+public class RefResolver {
+
+    private static final String REF_MEMBER = "$ref";
+
+    /**
+     * resolve a path into an object
+     * @param defsroot root of object that is referred to
+     * @param current current object within defsroot (for relative paths)
+     * @param path path to resolve (e.g. "#/definitions/return-code")
+     * @return object pointed to by path
+     * @throws IOException if path is unresolvable
+     */
+    public static JsonObject resolvePath(JsonObject defsroot, JsonObject current, String path) throws IOException {
+        String[] pathElements = path.split("/");
+        for (String pe : pathElements) {
+            if ("#".equals(pe)) {
+                current = defsroot;
+            } else if (current.has(pe)) {
+                current = current.getAsJsonObject(pe);
+            } else {
+                throw new IOException("unresolvable reference '" + pe + "' in path '" + path + "'");
+            }
+        }
+        return current;
+    }
+
+    /**
+     * replace all $ref paths by nested objects
+     * @param defsRoot root of object that is referred to (usually the same as objeToResolve)
+     * @param objToResolve root of object to resolve references of
+     * @return objsToResolve
+     * @throws IOException if any referencesa are unresolveable
+     */
+    public static JsonElement resolveRefs(JsonObject defsRoot, JsonElement objToResolve) throws IOException {
+
+        if (objToResolve.isJsonObject()) {
+            final JsonObject obj = objToResolve.getAsJsonObject();
+            for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
+                if (REF_MEMBER.equals(entry.getKey())) {
+                    String ref = entry.getValue().getAsString();
+                    obj.remove(REF_MEMBER);
+                    JsonObject refObject = resolvePath(defsRoot, obj, ref);
+                    resolveRefs(defsRoot, refObject);
+                    // hoist all members of refObject to contents
+                    for (Map.Entry<String, JsonElement> refentry : refObject.entrySet()) {
+                        obj.add(refentry.getKey(), JsonUtil.deepCopy(refentry.getValue()));
+                    }
+                } else {
+                    resolveRefs(defsRoot, entry.getValue());
+                }
+            }
+        } else if (objToResolve.isJsonArray()) {
+            final JsonArray contents = objToResolve.getAsJsonArray();
+            for (int i = 0; i < contents.size(); i++) {
+                JsonElement el = contents.get(i);
+                if (el.isJsonObject()) {
+                    contents.set(i, resolveRefs(defsRoot, el.getAsJsonObject()));
+                }
+            }
+        }
+        return objToResolve;
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/yaml/YamlToJson.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.yaml;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Stack;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Utility class to read YAML files and convert to GSON objects
+ *
+ * Limitations:
+ * Only enough code to read Swagger YAML is implemented
+ * $ref only works within the same document, not across the network
+ */
+public class YamlToJson {
+
+    public YamlToJson() {
+    }
+
+    public JsonObject yamlToJsonObject(final File fn) throws IOException {
+        try (final Reader in = new FileReader(fn)) {
+            return yamlToJsonObject(in);
+        }
+    }
+
+    public JsonObject yamlToJsonObject(final String yaml) throws IOException {
+        try (final Reader in = new StringReader(yaml)) {
+            return yamlToJsonObject(in);
+        }
+    }
+
+    public JsonObject yamlToJsonObject(final Reader in) throws IOException {
+        try (final PushableReader pr = new PushableReader(in instanceof BufferedReader ? (BufferedReader)in : new BufferedReader(in));) {
+            final JsonObject obj = new JsonObject();
+            yamlToJson(pr, obj, 0);
+            pr.close();
+            return obj;
+        }
+    }
+
+    private void yamlToJson(PushableReader in, JsonElement parent, int currentIndent) throws IOException {
+        for (String s = in.readLine(); s != null; s = in.readLine()) {
+            YamlLine line = new YamlLine(s);
+            if (line.indent == 0 && line.value == null && line.name == null) {
+                // blsnk or unparseable line
+                continue;
+            }
+            if (line.indent < currentIndent) {
+                in.push(s);
+                return;
+            }
+            final JsonElement child;
+            if (line.hasColon) {
+                if (line.value != null && !line.value.isEmpty()) {
+                    if (">-".equals(line.value)) {
+                        //the next few lines are the value for the current line
+                        child = makeUnquotedPrimitive(absorb(in, currentIndent));
+                    } else {
+                        JsonElement ce = makeUnquotedPrimitive(line.value);
+                        if (parent.isJsonArray()) {
+                            JsonObject childobj = new JsonObject();
+                            childobj.add(makeUnquotedString(line.name), ce);
+                            child = childobj;
+                        } else {
+                            child = ce;
+                        }
+                    }
+                } else {
+                    // no value specified; this could be the start of an object or array
+                    final String next = in.readLine();
+                    boolean isArray = false;
+                    if (next != null) {
+                        YamlLine nextLine = new YamlLine(next);
+                        isArray = nextLine.hasDashPrefix;
+                        in.push(next);
+                    }
+                    child = isArray ? new JsonArray() : new JsonObject();
+                    yamlToJson(in, child, line.indent);
+                }
+            }
+            else {
+                child = (line.value != null) ? makeUnquotedPrimitive(line.value) : new JsonPrimitive("");
+            }
+            if (parent.isJsonArray()) {
+                if (line.hasDashPrefix) {
+                    JsonArray parray = parent.getAsJsonArray();
+                    parray.add(child);
+                } else {
+                    System.err.println("Array member must begin with dash: " + s);
+                }
+            } else if (parent.isJsonObject()) {
+                JsonObject pobject = parent.getAsJsonObject();
+                pobject.add(makeUnquotedString(line.name), child);
+            } else {
+                System.err.println("Error: parent is neither object nor array");
+            }
+            currentIndent = line.indent;
+        }
+    }
+
+    private static String makeUnquotedString(final String s) {
+        String ret = s;
+        if (s.length() >= 2) {
+            if ((s.charAt(0) == '\'') && (s.charAt(s.length() - 1) == '\'')
+                    || (s.charAt(0) == '"') && (s.charAt(s.length() - 1) == '"')) {
+                ret = s.substring(1, s.length() - 1);
+            }
+        }
+        return ret;
+    }
+
+    private static JsonPrimitive makeUnquotedPrimitive(final String s) {
+        final String uqString = makeUnquotedString(s);
+        // anything quoted will return a string, otherwise try to parse
+        if (uqString.length() == s.length()) {
+            if ("true".equals(uqString))
+                return new JsonPrimitive(true);
+            else if ("false".equals(uqString))
+                return new JsonPrimitive(false);
+            else if ("null".equals(uqString))
+                return null;
+            else {
+                // test for number
+                final char c0 = uqString.charAt(0);
+                if (Character.isDigit(c0) || c0 == '+' || c0 == '-') {
+                    try {
+                        return new JsonPrimitive(new Long(uqString));
+                    } catch (NumberFormatException ignored) {
+                        ; // fall through to return String
+                    }
+
+                }
+            }
+        }
+        return new JsonPrimitive(uqString);
+    }
+
+    private static String absorb(PushableReader in, int currentIndent) throws IOException {
+        // append lines until the indentation is the same as the currentIndent
+        StringBuilder a = new StringBuilder();
+        for (String s = in.readLine(); s != null; s = in.readLine()) {
+            int wsCount;
+            for (wsCount = 0; wsCount < s.length(); wsCount++) {
+                if (!Character.isWhitespace(s.charAt(wsCount))) {
+                    break;
+                }
+            }
+            if (wsCount > currentIndent) {
+                a.append(a.length() == 0 ? s.trim() : ' ' + s.trim());
+            } else {
+                in.push(s);
+                break;
+            }
+        }
+        return a.toString();
+    }
+
+    /**
+     * YamlLine - parse a single line of YAML file
+     */
+    static class YamlLine {
+        int indent;
+        String name;
+        String value;
+        boolean hasColon;
+        boolean hasDashPrefix;
+
+        private static final String regexpr = "^([\\s]*)([-]?[\\s]*)([^:]+)([:]?)(.*)$";
+        private static final Pattern p = Pattern.compile(regexpr);
+
+        YamlLine(String line) throws IOException {
+            Matcher m = p.matcher(line);
+            if (m.matches()) {
+                final String s1 = m.group(1); // leading whitespace
+                final String s2 = m.group(2); // optional '-' indicating array element
+                final String s3 = m.group(3); // key
+                final String s4 = m.group(4); // ':'
+                final String s5 = m.group(5).trim(); // value or optional '>-'
+                hasColon = !(s4 == null || s4.isEmpty());
+                hasDashPrefix = !(s2 == null || s2.isEmpty());
+                indent = s1.length() + (hasDashPrefix ? s2.length() : 0);
+                if (hasColon) {
+                    name = s3.trim();
+                    value = s5.trim();
+                } else {
+                    name = null;
+                    value = s3 + s5;
+                    value = value.trim();
+                }
+            } else {
+                if (line.isEmpty()) {
+                    name = null;
+                    value = null;
+                    indent = 0;
+                } else {
+                    throw new IOException("parse error in YAML '" + line + "'");
+                }
+            }
+        }
+    }
+
+    static class PushableReader implements AutoCloseable {
+
+        final Stack<String> stack = new Stack<>();
+        final BufferedReader in;
+
+        PushableReader(BufferedReader in) {
+            this.in = in;
+        }
+
+        String readLine() throws IOException {
+            if (stack.isEmpty()) {
+                return in.readLine();
+            } else {
+                return stack.pop();
+            }
+        }
+
+        void push(String s) {
+            stack.push(s);
+        }
+
+        @Override
+        public void close() throws IOException {
+            in.close();
+        }
+    }
+
+    /*
+     * utility function to convert YAML file to JSON stdout
+     */
+    public static void main(String[] args) {
+        boolean pretty = false;
+        for (final String fn : args) {
+            if ("--pretty".equals(fn)) {
+                pretty = true;
+            } else if ("--help".equals("fn")) {
+                System.err.println("YamlToJason [--pretty] [--help] infile1 [infile2] ...");
+            } else {
+                try {
+                    final YamlToJson y2j = new YamlToJson();
+                    final File fin = new File(fn);
+                    final JsonObject json = y2j.yamlToJsonObject(fin);
+                    if (pretty) {
+                        final GsonBuilder gsonBuilder = new GsonBuilder();
+                        gsonBuilder.setPrettyPrinting();
+                        final Gson gson = gsonBuilder.create();
+                        System.out.println(gson.toJson(json));
+                    } else {
+                        System.out.println(json.toString());
+                    }
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/lang/schema/JSONService.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.lang.schema;
+
+/**
+ * Serialisation service for Java types into JSON.
+ */
+public interface JSONService {
+
+    /**
+     * Serialise the target object to JSON.
+     *
+     * @param target the object to serialize
+     * @return string representation of the target object
+     */
+    String serialiase(Object target);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/lang/schema/SchemaBuilder.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.lang.schema;
+
+/**
+ * JSON schema building service
+ */
+public interface SchemaBuilder {
+
+    /**
+     * Returns the Schema for the given class
+     * @param target the object of which to return the schema
+     * @return string (format: JSON) representation of the schema
+     */
+    String getSchema(Class target);
+
+    /**
+     * Registers a type in the schema
+     * @param target the type to be registered
+     */
+    void registerType(Class target);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/lang/schema/SchemaValidationException.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,24 @@
+package com.redhat.thermostat.lang.schema;
+
+/**
+ */
+public class SchemaValidationException extends RuntimeException {
+    public SchemaValidationException() {
+    }
+
+    public SchemaValidationException(String message) {
+        super(message);
+    }
+
+    public SchemaValidationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public SchemaValidationException(Throwable cause) {
+        super(cause);
+    }
+
+    public SchemaValidationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+        super(message, cause, enableSuppression, writableStackTrace);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/lang/schema/annotations/Maximum.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.lang.schema.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Define the maximum value allowed for the variable it is applied to. <br>
+ * If {@link #exclusive()} is true, the maximum value must be strictly lower
+ * than the value specified by this annotation. The default number returned
+ * by {@link #value()} is {@link Long#MAX_VALUE}.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface Maximum {
+    long value() default Long.MAX_VALUE;
+    boolean exclusive() default false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/lang/schema/annotations/Minimum.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.lang.schema.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Define the minimum value allowed for the variable it is applied to. <br >
+ * If {@link #exclusive()} is true, the minimum value must be strictly greater
+ * than the value specified by this annotation. The default number returned
+ * by {@link #value()} is {@link Long#MIN_VALUE}.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface Minimum {
+    long value() default Long.MIN_VALUE;
+    boolean exclusive() default false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/lang/schema/annotations/Schema.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.lang.schema.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface Schema {
+    String name() default "";
+    String description() default "";
+    boolean required() default false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/lang/schema/annotations/Type.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.lang.schema.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface Type {
+    String name() default "";
+    String description() default "";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/lang/schema/internal/JSONServiceImpl.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.lang.schema.internal;
+
+import com.google.gson.ExclusionStrategy;
+import com.google.gson.FieldAttributes;
+import com.google.gson.GsonBuilder;
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+
+import com.redhat.thermostat.lang.schema.*;
+
+import com.redhat.thermostat.lang.schema.annotations.Schema;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+
+import java.io.IOException;
+
+@Component
+@Service(JSONService.class)
+public class JSONServiceImpl implements JSONService {
+
+    private GsonBuilder builder;
+
+    public JSONServiceImpl() {
+        this(false);
+    }
+
+    public JSONServiceImpl(boolean prettyPrinting) {
+
+
+        builder = new GsonBuilder();
+        if (prettyPrinting) {
+            builder.setPrettyPrinting();
+        }
+
+        AutoAdapter autoAdapter = new AutoAdapter();
+
+        builder.registerTypeAdapter(boolean.class, autoAdapter);
+        builder.registerTypeAdapter(byte.class, autoAdapter);
+        builder.registerTypeAdapter(short.class, autoAdapter);
+        builder.registerTypeAdapter(int.class, autoAdapter);
+        builder.registerTypeAdapter(long.class, autoAdapter);
+        builder.registerTypeAdapter(double.class, autoAdapter);
+        builder.registerTypeAdapter(float.class, autoAdapter);
+
+        builder.registerTypeAdapter(Boolean.class, autoAdapter);
+        builder.registerTypeAdapter(Byte.class, autoAdapter);
+        builder.registerTypeAdapter(Short.class, autoAdapter);
+        builder.registerTypeAdapter(Integer.class, autoAdapter);
+        builder.registerTypeAdapter(Long.class, autoAdapter);
+        builder.registerTypeAdapter(Double.class, autoAdapter);
+        builder.registerTypeAdapter(Float.class, autoAdapter);
+
+        builder.addSerializationExclusionStrategy(new AutoExclusionStategy());
+
+    }
+
+    @Override
+    public String serialiase(Object target) {
+        // TODO - consider registering this class with the schema registry
+        return builder.create().toJson(target);
+    }
+
+    private class AutoAdapter extends TypeAdapter<Object> {
+
+        @Override
+        public void write(JsonWriter out, Object value) throws IOException {
+            out.value("" + value);
+        }
+
+        @Override
+        public Object read(JsonReader in) throws IOException {
+            throw new UnsupportedOperationException("read() not yet implemented");
+        }
+    }
+
+    public class AutoExclusionStategy implements ExclusionStrategy {
+
+        public boolean shouldSkipClass(Class<?> arg0) {
+            return false;
+        }
+
+        public boolean shouldSkipField(FieldAttributes field) {
+            return (field.getAnnotation(Schema.class) == null);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/lang/schema/internal/SchemaBuilderImpl.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.lang.schema.internal;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+
+import com.redhat.thermostat.lang.schema.*;
+
+import com.redhat.thermostat.lang.schema.annotations.Maximum;
+import com.redhat.thermostat.lang.schema.annotations.Minimum;
+import com.redhat.thermostat.lang.schema.annotations.Schema;
+import com.redhat.thermostat.lang.schema.annotations.Type;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Component
+@Service(SchemaBuilder.class)
+public class SchemaBuilderImpl implements SchemaBuilder {
+
+    private class FieldProperties {
+        String name = "";
+        String description = "";
+        String type = "";
+        String parentType = "";
+
+        boolean hasMin;
+        long boundsMin;
+        boolean exclusiveMin;
+
+        boolean hasMax;
+        long boundsMax;
+        boolean exclusiveMax;
+
+        @Override
+        public String toString() {
+            return "FieldProperties {" +
+                    "name='" + name + '\'' +
+                    ", description='" + description + '\'' +
+                    ", type='" + type + '\'' +
+                    '}';
+        }
+    }
+
+    private class SchemaDefinition {
+        FieldProperties field = new FieldProperties();
+        Set<FieldProperties> properties = new TreeSet<>(new Comparator<FieldProperties>() {
+            @Override
+            public int compare(FieldProperties o1, FieldProperties o2) {
+                return o1.toString().compareTo(o2.toString());
+            }
+        });
+        Set<String> required = new TreeSet<>();
+    }
+
+    private GsonBuilder schemaBuilder;
+
+    private Map<String, String> schemas;
+    private Map<String, SchemaDefinition> definitions;
+
+    public SchemaBuilderImpl() {
+        this(true);
+    }
+
+    public SchemaBuilderImpl(boolean prettyPrinting) {
+        definitions = new ConcurrentHashMap<>();
+        schemas = new HashMap<>();
+
+        schemaBuilder = new GsonBuilder();
+        schemaBuilder.registerTypeAdapter(Class.class, new SchemaSerializer());
+
+        if (prettyPrinting) {
+            schemaBuilder.setPrettyPrinting();
+        }
+    }
+
+    private void checkTypeAndRegister(Class target) {
+
+        if (schemas.containsKey(target.getName())) {
+            return;
+        }
+
+        if (!target.isAnnotationPresent(Type.class)) {
+            throw new IllegalArgumentException("Unrecognised Type: must be annotated with " + Type.class);
+        }
+
+        SchemaDefinition definition = new SchemaDefinition();
+
+        definition.field.name = target.getSimpleName();
+        Type annotation = (Type) target.getAnnotation(Type.class);
+        if (!annotation.name().isEmpty()) {
+            definition.field.name = annotation.name();
+        }
+
+        definition.field.description = annotation.description();
+        if (!target.getSuperclass().equals(Object.class)) {
+            definition.field.parentType = target.getSuperclass().getSimpleName();
+        }
+
+        // let's see the rest of the schema
+        for (Field field : target.getDeclaredFields()) {
+            if (field.isAnnotationPresent(Schema.class)) {
+
+                Schema schema = field.getAnnotation(Schema.class);
+
+                FieldProperties fieldProperties = new FieldProperties();
+                fieldProperties.name = field.getName();
+                if (!schema.name().isEmpty()) {
+                    fieldProperties.name = schema.name();
+                }
+
+                fieldProperties.description = schema.description();
+                fieldProperties.type = field.getType().getSimpleName();
+
+                if (field.isAnnotationPresent(Minimum.class)) {
+                    fieldProperties.hasMin = true;
+
+                    Minimum range = field.getAnnotation(Minimum.class);
+                    fieldProperties.boundsMin = range.value();
+                    fieldProperties.exclusiveMin = range.exclusive();
+                }
+
+                if (field.isAnnotationPresent(Maximum.class)) {
+                    fieldProperties.hasMax = true;
+
+                    Maximum range = field.getAnnotation(Maximum.class);
+                    fieldProperties.boundsMax = range.value();
+                    fieldProperties.exclusiveMax = range.exclusive();
+                }
+
+                if (fieldProperties.hasMax && fieldProperties.hasMin &&
+                        fieldProperties.boundsMin > fieldProperties.boundsMax)
+                {
+                    // perhaps a better error message?
+                    throw new SchemaValidationException("maximum and minimum bounds are incompatible: " +
+                            "min: " + fieldProperties.boundsMin + ", " +
+                            "max: " + fieldProperties.boundsMax);
+                }
+
+                definition.properties.add(fieldProperties);
+                if (schema.required()) {
+                    definition.required.add(fieldProperties.name);
+                }
+            }
+        }
+
+        definitions.put(target.getName(), definition);
+
+        String schema = schemaBuilder.create().toJson(target);
+        schemas.put(target.getName(), schema);
+    }
+
+    @Override
+    public void registerType(Class target) {
+        checkTypeAndRegister(target);
+    }
+
+    @Override
+    public String getSchema(Class target) {
+        checkTypeAndRegister(target);
+
+        return schemas.get(target.getName());
+    }
+
+    private class SchemaSerializer extends TypeAdapter<Object> {
+
+        @Override
+        public void write(JsonWriter out, Object target) throws IOException {
+
+            SchemaDefinition definition = definitions.get(((Class) target).getName());
+
+            out.beginObject();
+
+            out.name("$schema").value("http://json-schema.org/draft-04/schema#");
+            out.name("title").value(definition.field.name);
+            out.name("description").value(definition.field.description);
+            out.name("type").value("object");
+            if (!definition.field.parentType.isEmpty()) {
+                out.name("extends").value(definition.field.parentType);
+            }
+
+            if (!definition.properties.isEmpty()) {
+                out.name("properties");
+                out.beginObject();
+
+                for (FieldProperties property : definition.properties) {
+
+                    out.name(property.name);
+
+                    out.beginObject();
+                    out.name("description").value(property.description);
+                    out.name("type").value(property.type);
+
+                    if (property.hasMin) {
+                        out.name("minimum").value(property.boundsMin);
+                        if (property.exclusiveMin) {
+                            out.name("exclusiveMinimum").value(true);
+                        }
+                    }
+
+                    if (property.hasMax) {
+                        out.name("maximum").value(property.boundsMax);
+                        if (property.exclusiveMax) {
+                            out.name("exclusiveMaximum").value(true);
+                        }
+                    }
+
+                    out.endObject();
+                }
+                out.endObject();
+            }
+
+            if (!definition.required.isEmpty()) {
+                out.name("required");
+                out.beginArray();
+                for (String required : definition.required) {
+                    out.value(required);
+                }
+                out.endArray();
+            }
+
+            out.endObject();
+        }
+
+        @Override
+        public Object read(JsonReader in) throws IOException {
+            throw new UnsupportedOperationException("NIY");
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/lang/schema/models/Id.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.lang.schema.models;
+
+import com.redhat.thermostat.lang.schema.annotations.Schema;
+import com.redhat.thermostat.lang.schema.annotations.Type;
+
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * A Type that represents an identifier.
+ */
+@Type(description = "The representation of a ID")
+public class Id {
+    @Schema(description = "The ID", required = true)
+    private String id;
+
+    public Id() {
+        id = UUID.randomUUID().toString();
+    }
+
+    public Id(String id) {
+        this.id = Objects.requireNonNull(id);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Id other = (Id) o;
+        return Objects.equals(this.id, other.get());
+    }
+
+    public String get() {
+        return id;
+    }
+
+    @Override
+    public int hashCode() {
+        return id != null ? id.hashCode() : 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/lang/schema/models/Pid.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.lang.schema.models;
+
+import com.redhat.thermostat.lang.schema.annotations.Schema;
+import com.redhat.thermostat.lang.schema.annotations.Type;
+
+/**
+ */
+@Type(description = "The representation of a Pid")
+public class Pid {
+    @Schema(description = "The Pid", required = true)
+    private int pid;
+
+    public Pid(int pid) {
+        this.pid = pid;
+    }
+
+    public int get() {
+        return pid;
+    }
+
+    @Override
+    public String toString() {
+        return Integer.toString(pid);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Pid pid1 = (Pid) o;
+
+        return pid == pid1.pid;
+    }
+
+    @Override
+    public int hashCode() {
+        return pid;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/lang/schema/models/ProcessState.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.lang.schema.models;
+
+import com.redhat.thermostat.lang.schema.annotations.Type;
+
+/**
+ */
+@Type(description = "Define the basic running states for a process")
+public class ProcessState {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/lang/schema/models/Timestamp.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.lang.schema.models;
+
+import com.redhat.thermostat.lang.schema.annotations.Minimum;
+import com.redhat.thermostat.lang.schema.annotations.Schema;
+import com.redhat.thermostat.lang.schema.annotations.Type;
+
+/**
+ * A Type representing the number of milliseconds elapsed since the Unix Epoch.
+ */
+@Type(description = "A Type representing the number of milliseconds elapsed since the Unix Epoch")
+public class Timestamp {
+    @Schema(description = "The number of milliseconds elapsed since the Unix Epoch", required = true)
+    @Minimum(0)
+    private long timestamp;
+
+    public Timestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public long get() {
+        return timestamp;
+    }
+
+    @Override
+    public String toString() {
+        return "" + timestamp;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof Timestamp)) return false;
+
+        Timestamp timestamp1 = (Timestamp) o;
+
+        return timestamp == timestamp1.timestamp;
+    }
+
+    @Override
+    public int hashCode() {
+        return (int) (timestamp ^ (timestamp >>> 32));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/test/java/com/redhat/thermostat/common/json/JsonUtilTest.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.json;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+import org.junit.Test;
+
+import java.util.NoSuchElementException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+public class JsonUtilTest {
+
+    private static final String JSON =
+            "{\n" +
+                    "  \"parents\" : [ \"homer\", \"marge\" ],\n" +
+                    "  \"children\" : {\n" +
+                    "    \"bart\" : {\n" +
+                    "      \"title\" : \"son\",\n" +
+                    "      \"age\" : \"14\"\n" +
+                    "      },\n" +
+                    "    \"lisa\" : {\n" +
+                    "      \"title\" : \"daughter\",\n" +
+                    "      \"age\" : \"12\"\n" +
+                    "      },\n" +
+                    "    \"maggie\" : {\n" +
+                    "      \"title\" : \"daughter\",\n" +
+                    "      \"age\" : \"1\"\n" +
+                    "      }\n" +
+                    "      \n" +
+                    "  },\n" +
+                    "  \"surname\" : \"simpsons\"\n" +
+                    "}\n";
+
+    @Test
+    public void testCapitalize() {
+        assertEquals("Fred", JsonUtil.capitalize("Fred"));
+        assertEquals("Barney", JsonUtil.capitalize("barney"));
+    }
+
+    @Test
+    public void testDeepCopy() {
+        final JsonParser parser = new JsonParser();
+        final JsonElement j0 = parser.parse(JSON);
+        final JsonElement j1 = JsonUtil.deepCopy(j0);
+        assertEquals(j0, j1);
+
+        j1.getAsJsonObject().get("children").getAsJsonObject().get("bart").getAsJsonObject().addProperty("age", 99);
+        assertNotEquals(j0, j1);
+    }
+
+    @Test
+    public void testFetchObject() {
+        final JsonParser parser = new JsonParser();
+        final JsonElement j0 = parser.parse(JSON);
+        final JsonElement bartAge = JsonUtil.fetch(j0, "children.bart.age");
+        assertEquals(14, bartAge.getAsInt());
+    }
+
+    @Test(expected = NoSuchElementException.class)
+    public void testFetchTooMuch() {
+        final JsonParser parser = new JsonParser();
+        final JsonElement j0 = parser.parse(JSON);
+        JsonUtil.fetch(j0, "children.bart.age.overflow");
+    }
+
+    @Test(expected = NoSuchElementException.class)
+    public void testFetchTooLittle() {
+        final JsonParser parser = new JsonParser();
+        final JsonElement j0 = parser.parse(JSON);
+        JsonUtil.fetch(j0, "");
+    }
+
+    @Test
+    public void testFetchArray() {
+        final JsonParser parser = new JsonParser();
+        final JsonElement j0 = parser.parse(JSON);
+        final JsonElement homer = JsonUtil.fetch(j0, "parents.0");
+        assertEquals("homer", homer.getAsString());
+        final JsonElement marge = JsonUtil.fetch(j0, "parents.1");
+        assertEquals("marge", marge.getAsString());
+    }
+
+    //@Test
+    // disable until this syntax feature is implemented
+    public void testFetchArraySquareBrackets() {
+        final JsonParser parser = new JsonParser();
+        final JsonElement j0 = parser.parse(JSON);
+        final JsonElement homer = JsonUtil.fetch(j0, "parents[0]");
+        assertEquals("homer", homer.getAsString());
+        final JsonElement marge = JsonUtil.fetch(j0, "parents[1]");
+        assertEquals("marge", marge.getAsString());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/test/java/com/redhat/thermostat/common/json/models/SchemaDefTest.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.json.models;
+
+import com.redhat.thermostat.common.yaml.JsonToYaml;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class SchemaDefTest {
+
+    @Test
+    public void testShallowFunctionality() {
+        final SchemaDef def = new SchemaDef(JsonToYaml.class);
+        assertTrue(def.getProperties().get("out") instanceof SchemaDef.SimpleType);
+        final SchemaDef.SimpleType typeOfOut = (SchemaDef.SimpleType)def.getProperties().get("out");
+        assertEquals(SchemaType.TypeClass.OBJECT, typeOfOut.getTypeClass());
+        assertEquals("Writer", typeOfOut.getTypeName());
+    }
+
+    @Test
+    public void testDeepFunctionality() {
+        SchemaDef def = new SchemaDef(JsonToYaml.class, 99);
+        assertTrue(def.getProperties().get("out") instanceof SchemaDef);
+        final SchemaDef typeOfOut = (SchemaDef)def.getProperties().get("out");
+        assertEquals(SchemaType.TypeClass.OBJECT, typeOfOut.getTypeClass());
+        assertFalse(typeOfOut.getProperties().isEmpty());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/test/java/com/redhat/thermostat/common/yaml/JsonToYamlTest.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.yaml;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import org.junit.Test;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+
+
+import static org.junit.Assert.assertEquals;
+
+public class JsonToYamlTest {
+
+    private static final File API1_YAML_FILE = new File("./src/test/resources/systems-swagger.yaml");
+    private static final File API1_JSON_FILE = new File("./src/test/resources/systems-swagger.json");
+
+    @Test
+    public void testConvert() throws IOException {
+
+        // read source JSON file
+        JsonObject goodjson = readFileToJson(API1_JSON_FILE).getAsJsonObject();
+
+        final JsonToYaml j2y = new JsonToYaml();
+
+        // convert to YAML string
+        final String yamlStr = j2y.jsonToYamlString(goodjson);
+
+        // get a temp file name
+        final File tmpFile = mktempfile("JsonToYamlTest.testConvert", ".yaml");
+
+        // write a new YAML file
+        writeFile(tmpFile, yamlStr);
+
+        // read the known good YAML file
+        final YamlToJson y2j = new YamlToJson();
+        final JsonObject goodyaml = y2j.yamlToJsonObject(API1_YAML_FILE);
+        assertEquals(goodjson, goodyaml);
+
+        // read the new YAML file
+        final JsonObject testyaml = y2j.yamlToJsonObject(tmpFile);
+        assertEquals(goodjson, testyaml);
+    }
+
+    private File mktempfile(final String prefix, final String suffix) throws IOException {
+        final File f = File.createTempFile(prefix, suffix);
+        f.deleteOnExit();
+        return f;
+    }
+
+    private JsonElement readFileToJson(File f) throws IOException {
+        try (final Reader in = new BufferedReader(new FileReader(f))) {
+            final JsonParser parser = new JsonParser();
+            return parser.parse(in);
+        } catch (IOException e) {
+            throw e;
+        }
+    }
+
+    private void writeFile(File f, String contents) throws IOException {
+        try (final Writer out = new BufferedWriter(new FileWriter(f))) {
+            out.write(contents);
+            out.close();
+        } catch (IOException e) {
+            throw e;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/test/java/com/redhat/thermostat/common/yaml/RefResolverTest.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.yaml;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.redhat.thermostat.common.json.JsonUtil;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class RefResolverTest {
+
+    private static final File API1_YAML_FILE = new File("./src/test/resources/systems-swagger.yaml");
+
+    @Test
+    public void resolverTest() throws IOException {
+        YamlToJson y2j = new YamlToJson();
+        JsonObject yaml = y2j.yamlToJsonObject(API1_YAML_FILE);
+        assertNotNull(yaml);
+
+        JsonElement getRefType = JsonUtil.fetch(yaml, "paths./systems/{systemId}.get.responses.200.schema.$ref");
+        assertTrue(getRefType.getAsString().endsWith("definitions/systems-get-response"));
+
+        // ref1 is the defintion pointed to by the reference
+        JsonElement ref1 = JsonUtil.fetch(yaml, "definitions.systems-get-response");
+
+        // resolve all refs
+        RefResolver.resolveRefs(yaml, yaml);
+
+        // get the response type, which should no longer be a reference but a copy of the definition pointed to by the reference
+        JsonElement resolvedType = JsonUtil.fetch(yaml, "paths./systems/{systemId}.get.responses.200.schema");
+        assertEquals(ref1, resolvedType);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/test/java/com/redhat/thermostat/common/yaml/YamlToJsonTest.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.yaml;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.redhat.thermostat.common.json.JsonUtil;
+import com.redhat.thermostat.common.json.models.SwaggerDef;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class YamlToJsonTest {
+
+    private static final File API1_YAML_FILE = new File("./src/test/resources/systems-swagger.yaml");
+
+    @Test
+    public void readYamlTest() throws IOException {
+        YamlToJson y2j = new YamlToJson();
+        JsonObject yaml = y2j.yamlToJsonObject(API1_YAML_FILE);
+        assertNotNull(yaml);
+        JsonElement getDescr = JsonUtil.fetch(yaml, "paths./systems/{systemId}.get.description");
+        assertNotNull(getDescr);
+        assertTrue(getDescr.isJsonPrimitive());
+        assertEquals("Get information for system {systemId}.", getDescr.getAsString());
+    }
+
+    @Test
+    public void yamlToModelTest() throws IOException {
+        YamlToJson y2j = new YamlToJson();
+        JsonObject yaml = y2j.yamlToJsonObject(API1_YAML_FILE);
+        assertNotNull(yaml);
+
+        // resolve all refs
+        RefResolver.resolveRefs(yaml, yaml);
+
+        // convert JSON to actual Java class
+        Gson gson = new Gson();
+        SwaggerDef swaggerDef = gson.fromJson(yaml, SwaggerDef.class);
+
+        final String getdescr = JsonUtil.fetch(yaml, "paths./systems/{systemId}.get.description").getAsString();
+        assertEquals(getdescr, swaggerDef.getPaths().get("/systems/{systemId}").getGETAPI().getDescription());
+    }
+
+    private static final String GPL = "GPL v2 with Classpath Exception";
+
+    private static final String YAML_WITH_NULL =
+            "info:\n" +
+            "  title: Thermostat Web Gateway JVM Information API\n" +
+            "  license:\n" +
+            "    name: " + GPL + "\n" +
+            "    url: 'http://www.gnu.org/licenses'\n" +
+            "    org:  null\n" +
+            "    phone: 416-363-6097\n" +
+            "consumes:\n" +
+            "  - application/json\n" +
+            "produces:\n" +
+            "  - application/json\n" +
+            "  - text/html; charset=utf-8\n" +
+            "basePath: /jvms/0.0.1\n";
+
+    @Test
+    public void testNull() throws IOException {
+        YamlToJson y2j = new YamlToJson();
+        JsonObject yaml = y2j.yamlToJsonObject(YAML_WITH_NULL);
+        assertEquals(GPL, JsonUtil.fetch(yaml, "info.license.name").getAsString());
+        final JsonElement nell = JsonUtil.fetch(yaml, "info.license.org");
+        assertTrue(nell.isJsonNull());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/test/java/com/redhat/thermostat/lang/schema/internal/JSONServiceTest.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.lang.schema.internal;
+
+import com.redhat.thermostat.lang.schema.annotations.Schema;
+import com.redhat.thermostat.lang.schema.annotations.Type;
+import com.redhat.thermostat.lang.schema.internal.JSONServiceImpl;
+import com.redhat.thermostat.lang.schema.models.Timestamp;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ */
+public class JSONServiceTest {
+
+    @Type(description = "Some Object for testing out")
+    public class SomeMoreComplexType {
+        @Schema(description = "Some Long", required = true)
+        private long aLong;
+
+        @Schema(description = "Some String", required = true)
+        private String aString;
+
+        public SomeMoreComplexType(long aLong, String aString) {
+            this.aLong = aLong;
+            this.aString = aString;
+
+        }
+
+        public long getALong() {
+            return aLong;
+        }
+
+        public String getAString() {
+            return aString;
+        }
+    }
+
+    @Type(description = "Some Object for testing out")
+    public class SomeMoreComplexType2 {
+        @Schema(description = "Some Long", required = true)
+        private long aLong;
+
+        // not part of the schema, won't be serialised!
+        private String aString;
+
+        public SomeMoreComplexType2(long aLong, String aString) {
+            this.aLong = aLong;
+            this.aString = aString;
+
+        }
+
+        public long getALong() {
+            return aLong;
+        }
+
+        public String getAString() {
+            return aString;
+        }
+    }
+
+    @Type(description = "Something more complex perhaps?")
+    public class CompoundType {
+        @Schema(description = "Some Long", required = true)
+        private long aLong;
+
+        @Schema
+        private SomeMoreComplexType complexType;
+
+        public CompoundType(long aLong, SomeMoreComplexType complexType) {
+            this.aLong = aLong;
+            this.complexType = complexType;
+
+        }
+
+        public long getALong() {
+            return aLong;
+        }
+
+        public SomeMoreComplexType getComplexType() {
+            return complexType;
+        }
+    }
+
+    @Type(description = "Something more complex perhaps?")
+    public class CompoundTypeMissingSchema {
+        @Schema(description = "Some Long", required = true)
+        private long aLong;
+
+        // won't be serialised
+        private SomeMoreComplexType complexType;
+
+        public CompoundTypeMissingSchema(long aLong, SomeMoreComplexType complexType) {
+            this.aLong = aLong;
+            this.complexType = complexType;
+
+        }
+
+        public long getALong() {
+            return aLong;
+        }
+
+        public SomeMoreComplexType getComplexType() {
+            return complexType;
+        }
+    }
+
+    @Type(description = "An extended type that should inherit its schema")
+    public class ExtendedType extends CompoundType {
+
+        @Schema(description = "Some other long from derived class", required = true)
+        private long anotherLong;
+
+        public ExtendedType(long aLong, long anotherLong, SomeMoreComplexType complexType) {
+            super(aLong, complexType);
+            this.anotherLong = anotherLong;
+        }
+    }
+
+    private JSONServiceImpl service;
+
+    @Before
+    public void setUp() {
+        service = new JSONServiceImpl(false);
+    }
+
+    @Test
+    public void testSimpleType() {
+        Timestamp timestamp = new Timestamp(123456L);
+        assertEquals("{\"timestamp\":\"123456\"}", service.serialiase(timestamp));
+    }
+
+    @Test
+    public void testComplexType() {
+        SomeMoreComplexType type = new SomeMoreComplexType(42, "test");
+        assertEquals("{\"aLong\":\"42\",\"aString\":\"test\"}",
+                service.serialiase(type));
+    }
+
+    @Test
+    public void testComplexType2() {
+        SomeMoreComplexType2 type = new SomeMoreComplexType2(42, "test");
+        assertEquals("{\"aLong\":\"42\"}",
+                service.serialiase(type));
+    }
+
+    @Test
+    public void testCompoundType() {
+        CompoundType type = new CompoundType(42, new SomeMoreComplexType(10, "test"));
+        assertEquals("{\"aLong\":\"42\",\"complexType\":{\"aLong\":\"10\",\"aString\":\"test\"}}",
+                service.serialiase(type));
+    }
+
+    @Test
+    public void testCompoundTypeMissingSchema() {
+        CompoundTypeMissingSchema type = new CompoundTypeMissingSchema(42, new SomeMoreComplexType(10, "test"));
+        assertEquals("{\"aLong\":\"42\"}",
+                service.serialiase(type));
+    }
+
+    @Test
+    public void testExtendedType() {
+        ExtendedType type = new ExtendedType(50, 42, new SomeMoreComplexType(10, "test"));
+        assertEquals("{\"anotherLong\":\"42\",\"aLong\":\"50\",\"complexType\":{\"aLong\":\"10\",\"aString\":\"test\"}}",
+                service.serialiase(type));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/test/java/com/redhat/thermostat/lang/schema/internal/SchemaBuilderTest.java	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.lang.schema.internal;
+
+import com.redhat.thermostat.lang.schema.SchemaBuilder;
+import com.redhat.thermostat.lang.schema.SchemaValidationException;
+
+import com.redhat.thermostat.lang.schema.annotations.Maximum;
+import com.redhat.thermostat.lang.schema.annotations.Minimum;
+import com.redhat.thermostat.lang.schema.annotations.Schema;
+import com.redhat.thermostat.lang.schema.annotations.Type;
+import com.redhat.thermostat.lang.schema.internal.SchemaBuilderImpl;
+import com.redhat.thermostat.lang.schema.models.Timestamp;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ */
+public class SchemaBuilderTest {
+
+    @Type(description = "Some Object for testing out")
+    public class SomeMoreComplexType {
+        @Schema(description = "Some Long", required = true)
+        private long aLong;
+
+        @Schema(description = "Some String", required = true)
+        private String aString;
+
+        public SomeMoreComplexType(long aLong, String aString) {
+            this.aLong = aLong;
+            this.aString = aString;
+
+        }
+
+        public long getALong() {
+            return aLong;
+        }
+
+        public String getAString() {
+            return aString;
+        }
+    }
+
+    @Type(description = "Some Object for testing out")
+    public class SomeMoreComplexType2 {
+        @Schema(description = "Some Long", required = true)
+        private long aLong;
+
+        // not part of the schema, won't be serialised!
+        private String aString;
+
+        public SomeMoreComplexType2(long aLong, String aString) {
+            this.aLong = aLong;
+            this.aString = aString;
+
+        }
+
+        public long getALong() {
+            return aLong;
+        }
+
+        public String getAString() {
+            return aString;
+        }
+    }
+
+    @Type(description = "Something more complex perhaps?")
+    public class CompoundType {
+        @Schema(description = "Some Long", required = true)
+        private long aLong;
+
+        @Schema
+        private SomeMoreComplexType complexType;
+
+        public CompoundType(long aLong, SomeMoreComplexType complexType) {
+            this.aLong = aLong;
+            this.complexType = complexType;
+
+        }
+
+        public long getALong() {
+            return aLong;
+        }
+
+        public SomeMoreComplexType getComplexType() {
+            return complexType;
+        }
+    }
+
+    @Type(description = "Something more complex perhaps?")
+    public class CompoundTypeMissingSchema {
+        @Schema(description = "Some Long", required = true)
+        private long aLong;
+
+        // won't be serialised
+        private SomeMoreComplexType complexType;
+
+        public CompoundTypeMissingSchema(long aLong, SomeMoreComplexType complexType) {
+            this.aLong = aLong;
+            this.complexType = complexType;
+        }
+
+        public long getALong() {
+            return aLong;
+        }
+
+        public SomeMoreComplexType getComplexType() {
+            return complexType;
+        }
+    }
+
+    @Type(description = "An extended type that should inherit its schema")
+    public class ExtendedType extends CompoundType {
+
+        @Schema(description = "Some other long from derived class", required = true)
+        private long anotherLong;
+
+        public ExtendedType(long aLong, long anotherLong, SomeMoreComplexType complexType) {
+            super(aLong, complexType);
+            this.anotherLong = anotherLong;
+        }
+    }
+
+    private SchemaBuilder service;
+
+    @Before
+    public void setUp() {
+        service = new SchemaBuilderImpl(false);
+    }
+
+    @Test(expected = java.lang.IllegalArgumentException.class)
+    public void testNoTypeAnnotation() {
+        String test = "primitive type";
+        service.getSchema(test.getClass());
+    }
+
+    @Test
+    public void testSimpleTypeSchema() {
+        assertEquals("{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"Timestamp\",\"description\":\"A Type representing the number of milliseconds elapsed since the Unix Epoch\",\"type\":\"object\",\"properties\":{\"timestamp\":{\"description\":\"The number of milliseconds elapsed since the Unix Epoch\",\"type\":\"long\",\"minimum\":0}},\"required\":[\"timestamp\"]}",
+                service.getSchema(Timestamp.class));
+    }
+
+    @Test
+    public void testComplexTypeSchema() {
+        assertEquals("{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"SomeMoreComplexType\",\"description\":\"Some Object for testing out\",\"type\":\"object\",\"properties\":{\"aLong\":{\"description\":\"Some Long\",\"type\":\"long\"},\"aString\":{\"description\":\"Some String\",\"type\":\"String\"}},\"required\":[\"aLong\",\"aString\"]}",
+                service.getSchema(SomeMoreComplexType.class));
+    }
+
+
+    @Test
+    public void testComplexType2Schema() {
+        assertEquals("{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"SomeMoreComplexType2\",\"description\":\"Some Object for testing out\",\"type\":\"object\",\"properties\":{\"aLong\":{\"description\":\"Some Long\",\"type\":\"long\"}},\"required\":[\"aLong\"]}",
+                service.getSchema(SomeMoreComplexType2.class));
+    }
+
+    @Test
+    public void testCompoundTypeSchema() {
+        assertEquals("{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"CompoundType\",\"description\":\"Something more complex perhaps?\",\"type\":\"object\",\"properties\":{\"aLong\":{\"description\":\"Some Long\",\"type\":\"long\"},\"complexType\":{\"description\":\"\",\"type\":\"SomeMoreComplexType\"}},\"required\":[\"aLong\"]}",
+                service.getSchema(CompoundType.class));
+    }
+
+    @Test
+    public void testCompoundTypeMissingSchemaSchema() {
+        assertEquals("{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"CompoundTypeMissingSchema\",\"description\":\"Something more complex perhaps?\",\"type\":\"object\",\"properties\":{\"aLong\":{\"description\":\"Some Long\",\"type\":\"long\"}},\"required\":[\"aLong\"]}",
+                service.getSchema(CompoundTypeMissingSchema.class));
+    }
+
+
+    @Test
+    public void testExtendedTypeSchema() {
+        assertEquals("{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"ExtendedType\",\"description\":\"An extended type that should inherit its schema\",\"type\":\"object\",\"extends\":\"CompoundType\",\"properties\":{\"anotherLong\":{\"description\":\"Some other long from derived class\",\"type\":\"long\"}},\"required\":[\"anotherLong\"]}",
+                service.getSchema(ExtendedType.class));
+    }
+
+    @Type(description = "Some Type for testing out")
+    public class ATypeWithConstraints {
+        @Schema(description = "Some Long", required = true)
+        @Minimum(2)
+        @Maximum(value = 5, exclusive = true)
+        private long aLong;
+
+        public ATypeWithConstraints(long aLong) {
+            this.aLong = aLong;
+        }
+
+        public long getALong() {
+            return aLong;
+        }
+    }
+
+    @Test
+    public void testTypeWithConstraintsSchema() {
+        assertEquals("{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"ATypeWithConstraints\",\"description\":\"Some Type for testing out\",\"type\":\"object\",\"properties\":{\"aLong\":{\"description\":\"Some Long\",\"type\":\"long\",\"minimum\":2,\"maximum\":5,\"exclusiveMaximum\":true}},\"required\":[\"aLong\"]}",
+                service.getSchema(ATypeWithConstraints.class));
+    }
+
+    @Type(description = "Some Type for testing out")
+    public class ATypeWithBadConstraints {
+        @Schema(description = "Some Long", required = true)
+        @Minimum(5)
+        @Maximum(value = 1, exclusive = true)
+        private long aLong;
+
+        public ATypeWithBadConstraints(long aLong) {
+            this.aLong = aLong;
+        }
+
+        public long getALong() {
+            return aLong;
+        }
+    }
+
+    @Test(expected = SchemaValidationException.class)
+    public void testTypeWithBadConstraintsSchema() {
+        service.getSchema(ATypeWithBadConstraints.class);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/test/resources/jvms-swagger.json	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,480 @@
+{
+  "swagger": "2.0",
+  "info": {
+    "version": "0.0.1",
+    "title": "Thermostat Web Gateway JVM Information API",
+    "license": {
+      "name": "GPL v2 with Classpath Exception",
+      "url": "http://www.gnu.org/licenses"
+    }
+  },
+  "consumes": [
+    "application/json"
+  ],
+  "produces": [
+    "application/json",
+    "text/html; charset=utf-8"
+  ],
+  "basePath": "/jvms/0.0.1",
+  "paths": {
+    "/systems/{systemId}": {
+      "parameters": [
+        {
+          "$ref": "#/parameters/system-id"
+        }
+      ],
+      "get": {
+        "description": "Get jvms for system {systemId}",
+        "parameters": [
+          {
+            "$ref": "#/parameters/limit"
+          },
+          {
+            "$ref": "#/parameters/offset"
+          },
+          {
+            "$ref": "#/parameters/sort"
+          },
+          {
+            "$ref": "#/parameters/include"
+          },
+          {
+            "$ref": "#/parameters/exclude"
+          },
+          {
+            "$ref": "#/parameters/query"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "schema": {
+              "$ref": "#/definitions/jvms-get-response"
+            }
+          }
+        }
+      },
+      "post": {
+        "description": "Add jvms for system {systemId}",
+        "parameters": [
+          {
+            "$ref": "#/parameters/jvms-post-body"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK"
+          }
+        }
+      },
+      "delete": {
+        "description": "Delete all jvms on system {systemId}",
+        "responses": {
+          "200": {
+            "description": "OK"
+          }
+        }
+      }
+    },
+    "/systems/{systemId}/jvms/{jvmId}": {
+      "parameters": [
+        {
+          "$ref": "#/parameters/system-id"
+        },
+        {
+          "$ref": "#/parameters/jvm-id"
+        }
+      ],
+      "get": {
+        "description": "Get information for the JVM with id {jvmId} running on system {systemId}",
+        "parameters": [
+          {
+            "$ref": "#/parameters/include"
+          },
+          {
+            "$ref": "#/parameters/exclude"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "schema": {
+              "$ref": "#/definitions/jvms-get-response"
+            }
+          }
+        }
+      },
+      "put": {
+        "description": "Update the JVM with id {jvmId} running on system {systemId}",
+        "responses": {
+          "200": {
+            "description": "OK"
+          }
+        },
+        "parameters": [
+          {
+            "$ref": "#/parameters/jvms-put-body"
+          }
+        ]
+      },
+      "delete": {
+        "description": "Delete the JVM with id {jvmId} running on system {systemId}",
+        "responses": {
+          "200": {
+            "description": "OK"
+          }
+        }
+      }
+    },
+    "/tree": {
+      "get": {
+        "description": "Get jvm information organized by systemId",
+        "parameters": [
+          {
+            "$ref": "#/parameters/alive-only"
+          },
+          {
+            "$ref": "#/parameters/include"
+          },
+          {
+            "$ref": "#/parameters/exclude"
+          },
+          {
+            "$ref": "#/parameters/limit"
+          },
+          {
+            "$ref": "#/parameters/offset"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "schema": {
+              "$ref": "#/definitions/tree-get-response"
+            }
+          }
+        }
+      }
+    },
+    "/update/systems/{systemId}/ts/{timeStamp}": {
+      "parameters": [
+        {
+          "$ref": "#/parameters/system-id"
+        },
+        {
+          "$ref": "#/parameters/timestamp"
+        }
+      ],
+      "put": {
+        "description": "Set last updated to {timeStamp} for jvm information on system {systemId}",
+        "parameters": [
+          {
+            "$ref": "#/parameters/update-put-body"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK"
+          }
+        }
+      }
+    }
+  },
+  "definitions": {
+    "jvm-get-info": {
+      "type": "object",
+      "properties": {
+        "systemId": {
+          "type": "string"
+        },
+        "agentId": {
+          "type": "string"
+        },
+        "jvmId": {
+          "type": "string"
+        },
+        "mainClass": {
+          "type": "string"
+        },
+        "startTime": {
+          "$ref": "#/definitions/metric"
+        },
+        "stopTime": {
+          "$ref": "#/definitions/metric"
+        },
+        "jvmPid": {
+          "type": "integer"
+        },
+        "javaVersion": {
+          "type": "string"
+        },
+        "javaHome": {
+          "type": "string"
+        },
+        "javaCommandLine": {
+          "type": "string"
+        },
+        "jvmArguments": {
+          "type": "string"
+        },
+        "jvmName": {
+          "type": "string"
+        },
+        "jvmInfo": {
+          "type": "string"
+        },
+        "jvmVersion": {
+          "type": "string"
+        },
+        "classpath": {
+          "type": "string"
+        },
+        "environment": {
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/environment-items"
+          }
+        },
+        "uid": {
+          "$ref": "#/definitions/metric"
+        },
+        "username": {
+          "type": "string"
+        },
+        "lastUpdated": {
+          "$ref": "#/definitions/metric"
+        }
+      }
+    },
+    "jvm-post-info": {
+      "type": "object",
+      "properties": {
+        "agentId": {
+          "type": "string"
+        },
+        "jvmId": {
+          "type": "string"
+        },
+        "mainClass": {
+          "type": "string"
+        },
+        "startTime": {
+          "$ref": "#/definitions/metric"
+        },
+        "stopTime": {
+          "$ref": "#/definitions/metric"
+        },
+        "jvmPid": {
+          "type": "integer"
+        },
+        "javaVersion": {
+          "type": "string"
+        },
+        "javaHome": {
+          "type": "string"
+        },
+        "javaCommandLine": {
+          "type": "string"
+        },
+        "jvmArguments": {
+          "type": "string"
+        },
+        "jvmName": {
+          "type": "string"
+        },
+        "jvmInfo": {
+          "type": "string"
+        },
+        "jvmVersion": {
+          "type": "string"
+        },
+        "classpath": {
+          "type": "string"
+        },
+        "environment": {
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/environment-items"
+          }
+        },
+        "uid": {
+          "$ref": "#/definitions/metric"
+        },
+        "username": {
+          "type": "string"
+        },
+        "lastUpdated": {
+          "$ref": "#/definitions/metric"
+        }
+      }
+    },
+    "environment-items": {
+      "type": "object",
+      "properties": {
+        "key": {
+          "type": "string"
+        },
+        "value": {
+          "type": "string"
+        }
+      }
+    },
+    "metric": {
+      "type": "object",
+      "properties": {
+        "$numberLong": {
+          "type": "string"
+        }
+      }
+    },
+    "jvms-get-response": {
+      "type": "object",
+      "properties": {
+        "response": {
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/jvm-get-info"
+          }
+        }
+      }
+    },
+    "jvms-put-body": {
+      "type": "object",
+      "properties": {
+        "set": {
+          "type": "object"
+        }
+      }
+    },
+    "jvms-post-body": {
+      "type": "array",
+      "items": {
+        "$ref": "#/definitions/jvm-post-info"
+      }
+    },
+    "update-put-body": {
+      "type": "array",
+      "description": "An array of jvm ID strings",
+      "items": {
+        "type": "string"
+      }
+    },
+    "tree-get-response": {
+      "type": "object",
+      "properties": {
+        "systemId": {
+          "type": "string"
+        },
+        "jvms": {
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/jvm-get-info"
+          }
+        }
+      }
+    }
+  },
+  "parameters": {
+    "system-id": {
+      "name": "systemId",
+      "in": "path",
+      "required": true,
+      "type": "string",
+      "description": "The system ID for the jvms"
+    },
+    "jvm-id": {
+      "name": "jvmId",
+      "in": "path",
+      "required": true,
+      "type": "string",
+      "description": "The ID of the jvm"
+    },
+    "timestamp": {
+      "name": "timeStamp",
+      "in": "path",
+      "required": true,
+      "type": "integer",
+      "format": "int64",
+      "description": "The UNIX timestamp in milliseconds to set the last_updated field for."
+    },
+    "jvms-post-body": {
+      "name": "body",
+      "in": "body",
+      "description": "The jvm information",
+      "required": true,
+      "schema": {
+        "$ref": "#/definitions/jvms-post-body"
+      }
+    },
+    "jvms-put-body": {
+      "name": "body",
+      "in": "body",
+      "description": "The JSON object containing a 'set' object. This contains single item JSON objects that specify the field to replace and the JSON value to replace with. Must not include 'systemId' or 'jvmId' fields. Example { \"set\" : { \"field\" : \"value\", \"field2\":{\"object\":\"item\"} }",
+      "required": true,
+      "schema": {
+        "$ref": "#/definitions/jvms-put-body"
+      }
+    },
+    "update-put-body": {
+      "name": "body",
+      "in": "body",
+      "description": "An array of jvmIds for which to update the last_updated field.",
+      "required": true,
+      "schema": {
+        "$ref": "#/definitions/update-put-body"
+      }
+    },
+    "limit": {
+      "name": "limit",
+      "in": "query",
+      "description": "Limit of items to return. Example '1'",
+      "type": "integer",
+      "required": false,
+      "default": 1
+    },
+    "offset": {
+      "name": "offset",
+      "in": "query",
+      "description": "Offset of items to return. Example '0'",
+      "type": "integer",
+      "required": false,
+      "default": 0
+    },
+    "sort": {
+      "name": "sort",
+      "in": "query",
+      "description": "Sort string. Comma separated list of fields prefixed with '+' for ascending or '-' for descending. Example '?sort=+a,-b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.",
+      "type": "string",
+      "required": false
+    },
+    "query": {
+      "name": "query",
+      "in": "query",
+      "description": "Query string. Comma separated list of key, comparator, value pairs. Comparator supports '==', '<=', '>=', '<', '>', '!='. Example '?query=a==b,c!=d'. Keys are fields in documents and use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.",
+      "type": "string",
+      "required": false
+    },
+    "include": {
+      "name": "include",
+      "in": "query",
+      "description": "Inclusion string. Comma separated list of fields to include in the response. Example '?include=a,b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer. Cannot be used in combination with 'exclude' parameter Overriden by 'exclude' parameter",
+      "type": "string",
+      "required": false
+    },
+    "exclude": {
+      "name": "exclude",
+      "in": "query",
+      "description": "Exclusion string. Comma separated list of fields to exclude in the response. Example '?exclude=a,b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer. Cannot be used in combination with 'include' parameter; takes precedence over 'include' parameter",
+      "type": "string",
+      "required": false
+    },
+    "alive-only": {
+      "name": "aliveOnly",
+      "in": "query",
+      "description": "Whether or not to return only JVMs that are live",
+      "type": "boolean",
+      "default": true,
+      "required": false
+    }
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/test/resources/jvms-swagger.yaml	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,337 @@
+swagger: '2.0'
+info:
+  version: 0.0.1
+  title: Thermostat Web Gateway JVM Information API
+  license:
+    name: GPL v2 with Classpath Exception
+    url: 'http://www.gnu.org/licenses'
+consumes:
+  - application/json
+produces:
+  - application/json
+  - text/html; charset=utf-8
+basePath: /jvms/0.0.1
+paths:
+  '/systems/{systemId}':
+    parameters:
+      - $ref: '#/parameters/system-id'
+    get:
+      description: 'Get jvms for system {systemId}'
+      parameters:
+        - $ref: '#/parameters/limit'
+        - $ref: '#/parameters/offset'
+        - $ref: '#/parameters/sort'
+        - $ref: '#/parameters/include'
+        - $ref: '#/parameters/exclude'
+        - $ref: '#/parameters/query'
+      responses:
+        '200':
+          description: OK
+          schema:
+            $ref: '#/definitions/jvms-get-response'
+    post:
+      description: 'Add jvms for system {systemId}'
+      parameters:
+        - $ref: '#/parameters/jvms-post-body'
+      responses:
+        '200':
+          description: OK
+    delete:
+      description: 'Delete all jvms on system {systemId}'
+      responses:
+        '200':
+          description: OK
+  '/systems/{systemId}/jvms/{jvmId}':
+    parameters:
+    - $ref: '#/parameters/system-id'
+    - $ref: '#/parameters/jvm-id'
+    get:
+      description: 'Get information for the JVM with id {jvmId} running on system {systemId}'
+      parameters:
+        - $ref: '#/parameters/include'
+        - $ref: '#/parameters/exclude'
+      responses:
+        '200':
+          description: OK
+          schema:
+            $ref: '#/definitions/jvms-get-response'
+    put:
+      description: 'Update the JVM with id {jvmId} running on system {systemId}'
+      responses:
+        '200':
+          description: OK
+      parameters:
+      - $ref: "#/parameters/jvms-put-body"
+    delete:
+      description: 'Delete the JVM with id {jvmId} running on system {systemId}'
+      responses:
+        '200':
+          description: OK
+  '/tree':
+    get:
+      description: Get jvm information organized by systemId
+      parameters:
+        - $ref: '#/parameters/alive-only'
+        - $ref: '#/parameters/include'
+        - $ref: '#/parameters/exclude'
+        - $ref: '#/parameters/limit'
+        - $ref: '#/parameters/offset'
+      responses:
+        '200':
+          description: OK
+          schema:
+            $ref: '#/definitions/tree-get-response'
+  '/update/systems/{systemId}/ts/{timeStamp}':
+    parameters:
+      - $ref: '#/parameters/system-id'
+      - $ref: '#/parameters/timestamp'
+    put:
+      description: 'Set last updated to {timeStamp} for jvm information on system {systemId}'
+      parameters:
+      - $ref: "#/parameters/update-put-body"
+      responses:
+        '200':
+          description: OK
+
+definitions:
+  jvm-get-info:
+    type: object
+    properties:
+      systemId:
+        type: string
+      agentId:
+        type: string
+      jvmId:
+        type: string
+      mainClass:
+        type: string
+      startTime:
+        $ref: '#/definitions/metric'
+      stopTime:
+        $ref: '#/definitions/metric'
+      jvmPid:
+        type: integer
+      javaVersion:
+        type: string
+      javaHome:
+        type: string
+      javaCommandLine:
+        type: string
+      jvmArguments:
+        type: string
+      jvmName:
+        type: string
+      jvmInfo:
+        type: string
+      jvmVersion:
+        type: string
+      classpath:
+        type: string
+      environment:
+        type: array
+        items:
+          $ref: '#/definitions/environment-items'
+      uid:
+        $ref: '#/definitions/metric'
+      username:
+        type: string
+      lastUpdated:
+        $ref: '#/definitions/metric'
+
+  jvm-post-info:
+    type: object
+    properties:
+      agentId:
+        type: string
+      jvmId:
+        type: string
+      mainClass:
+        type: string
+      startTime:
+        $ref: '#/definitions/metric'
+      stopTime:
+        $ref: '#/definitions/metric'
+      jvmPid:
+        type: integer
+      javaVersion:
+        type: string
+      javaHome:
+        type: string
+      javaCommandLine:
+        type: string
+      jvmArguments:
+        type: string
+      jvmName:
+        type: string
+      jvmInfo:
+        type: string
+      jvmVersion:
+        type: string
+      classpath:
+        type: string
+      environment:
+        type: array
+        items:
+          $ref: '#/definitions/environment-items'
+      uid:
+        $ref: '#/definitions/metric'
+      username:
+        type: string
+      lastUpdated:
+        $ref: '#/definitions/metric'
+  environment-items:
+    type: object
+    properties:
+      key:
+        type: string
+      value:
+        type: string
+
+  metric:
+    type: object
+    properties:
+      $numberLong:
+        type: string
+
+  jvms-get-response:
+    type: object
+    properties:
+      response:
+        type: array
+        items:
+          $ref: '#/definitions/jvm-get-info'
+  jvms-put-body:
+    type: object
+    properties:
+      set:
+        type: object
+  jvms-post-body:
+    type: array
+    items:
+      $ref: '#/definitions/jvm-post-info'
+
+  update-put-body:
+    type: array
+    description: 'An array of jvm ID strings'
+    items:
+      type: string
+
+  tree-get-response:
+    type: object
+    properties:
+      systemId:
+        type: string
+      jvms:
+        type: array
+        items:
+          $ref: '#/definitions/jvm-get-info'
+parameters:
+  system-id:
+    name: systemId
+    in: path
+    required: true
+    type: string
+    description: The system ID for the jvms
+  jvm-id:
+    name: jvmId
+    in: path
+    required: true
+    type: string
+    description: The ID of the jvm
+  timestamp:
+    name: timeStamp
+    in: path
+    required: true
+    type: integer
+    format: int64
+    description: The UNIX timestamp in milliseconds to set the last_updated field for.
+  jvms-post-body:
+    name: body
+    in: body
+    description: The jvm information
+    required: true
+    schema:
+      $ref: '#/definitions/jvms-post-body'
+  jvms-put-body:
+    name: body
+    in: body
+    description: >-
+      The JSON object containing a 'set' object. This contains single item JSON
+      objects that specify the field to replace and the JSON value to replace with.
+      Must not include 'systemId' or 'jvmId' fields. Example { "set" : {
+      "field" : "value", "field2":{"object":"item"} }
+    required: true
+    schema:
+      $ref: '#/definitions/jvms-put-body'
+  update-put-body:
+    name: body
+    in: body
+    description: >-
+      An array of jvmIds for which to update the last_updated field.
+    required: true
+    schema:
+      $ref: '#/definitions/update-put-body'
+  limit:
+    name: limit
+    in: query
+    description: Limit of items to return. Example '1'
+    type: integer
+    required: false
+    default: 1
+  offset:
+    name: offset
+    in: query
+    description: Offset of items to return. Example '0'
+    type: integer
+    required: false
+    default: 0
+  sort:
+    name: sort
+    in: query
+    description: >-
+      Sort string. Comma separated list of fields prefixed with '+' for
+      ascending or '-' for descending. Example '?sort=+a,-b' Fields use dot
+      notation for embedded documents. Example 'outer.inner' refers to field
+      inner contained in field outer.
+    type: string
+    required: false
+  query:
+    name: query
+    in: query
+    description: >-
+      Query string. Comma separated list of key, comparator, value pairs.
+      Comparator supports '==', '<=', '>=', '<', '>', '!='. Example
+      '?query=a==b,c!=d'. Keys are fields in documents and use dot notation for
+      embedded documents. Example 'outer.inner' refers to field inner contained
+      in field outer.
+    type: string
+    required: false
+  include:
+    name: include
+    in: query
+    description: >-
+      Inclusion string. Comma separated list of fields to include in the
+      response. Example '?include=a,b' Fields use dot notation for embedded
+      documents. Example 'outer.inner' refers to field inner contained in field
+      outer. Cannot be used in combination with 'exclude' parameter Overriden by
+      'exclude' parameter
+    type: string
+    required: false
+  exclude:
+    name: exclude
+    in: query
+    description: >-
+      Exclusion string. Comma separated list of fields to exclude in the
+      response. Example '?exclude=a,b' Fields use dot notation for embedded
+      documents. Example 'outer.inner' refers to field inner contained in field
+      outer. Cannot be used in combination with 'include' parameter; takes
+      precedence over 'include' parameter
+    type: string
+    required: false
+  alive-only:
+    name: aliveOnly
+    in: query
+    description: Whether or not to return only JVMs that are live
+    type: boolean
+    default: true
+    required: false
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/test/resources/systems-swagger.json	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,283 @@
+{
+  "swagger": "2.0",
+  "info": {
+    "version": "0.0.1",
+    "title": "Thermostat Web Gateway System Information API",
+    "license": {
+      "name": "GPL v2 with Classpath Exception",
+      "url": "http://www.gnu.org/licenses"
+    }
+  },
+  "consumes": [
+    "application/json"
+  ],
+  "produces": [
+    "application/json",
+    "text/html; charset=utf-8"
+  ],
+  "basePath": "/systems/0.0.1",
+  "paths": {
+    "/": {
+      "get": {
+        "description": "Get information for all systems.",
+        "parameters": [
+          {
+            "$ref": "#/parameters/limit"
+          },
+          {
+            "$ref": "#/parameters/offset"
+          },
+          {
+            "$ref": "#/parameters/sort"
+          },
+          {
+            "$ref": "#/parameters/include"
+          },
+          {
+            "$ref": "#/parameters/exclude"
+          },
+          {
+            "$ref": "#/parameters/query"
+          },
+          {
+            "$ref": "#/parameters/alive"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "schema": {
+              "$ref": "#/definitions/systems-get-response"
+            }
+          }
+        }
+      }
+    },
+    "/systems/{systemId}": {
+      "parameters": [
+        {
+          "$ref": "#/parameters/system-id"
+        }
+      ],
+      "get": {
+        "description": "Get information for system {systemId}.",
+        "parameters": [
+          {
+            "$ref": "#/parameters/limit"
+          },
+          {
+            "$ref": "#/parameters/offset"
+          },
+          {
+            "$ref": "#/parameters/sort"
+          },
+          {
+            "$ref": "#/parameters/include"
+          },
+          {
+            "$ref": "#/parameters/exclude"
+          },
+          {
+            "$ref": "#/parameters/query"
+          },
+          {
+            "$ref": "#/parameters/alive"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "schema": {
+              "$ref": "#/definitions/systems-get-response"
+            }
+          }
+        }
+      },
+      "put": {
+        "description": "Update information for system {systemId}.",
+        "parameters": [
+          {
+            "$ref": "#/parameters/systems-put-body"
+          },
+          {
+            "$ref": "#/parameters/query"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK"
+          }
+        }
+      },
+      "post": {
+        "description": "Add information for system {systemId}",
+        "parameters": [
+          {
+            "$ref": "#/parameters/system-info-array"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK"
+          }
+        }
+      },
+      "delete": {
+        "description": "Delete information for system ID {systemId}.",
+        "parameters": [
+          {
+            "$ref": "#/parameters/query"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK"
+          }
+        }
+      }
+    }
+  },
+  "definitions": {
+    "systems-get-response": {
+      "type": "object",
+      "properties": {
+        "response": {
+          "$ref": "#/definitions/system-info-array"
+        }
+      }
+    },
+    "system-info-array": {
+      "type": "array",
+      "items": {
+        "$ref": "#/definitions/system-info"
+      }
+    },
+    "system-info": {
+      "type": "object",
+      "properties": {
+        "systemId": {
+          "type": "string"
+        },
+        "agentId": {
+          "type": "string"
+        },
+        "hostname": {
+          "type": "string"
+        },
+        "osName": {
+          "type": "string"
+        },
+        "osKernel": {
+          "type": "string"
+        },
+        "osArch": {
+          "type": "string"
+        },
+        "cpuCount": {
+          "type": "integer"
+        },
+        "cpuModel": {
+          "type": "string"
+        },
+        "totalMemory": {
+          "type": "integer",
+          "format": "int64"
+        },
+        "timeCreated": {
+          "type": "integer",
+          "format": "int64"
+        },
+        "lastUpdated": {
+          "type": "integer",
+          "format": "int64"
+        }
+      }
+    },
+    "systems-put-body": {
+      "type": "object",
+      "properties": {
+        "set": {
+          "type": "object"
+        }
+      }
+    }
+  },
+  "parameters": {
+    "system-id": {
+      "name": "systemId",
+      "in": "path",
+      "required": true,
+      "type": "string"
+    },
+    "system-info-array": {
+      "name": "system-info-array",
+      "in": "body",
+      "description": "The system information",
+      "required": true,
+      "schema": {
+        "$ref": "#/definitions/system-info-array"
+      }
+    },
+    "systems-put-body": {
+      "name": "body",
+      "in": "body",
+      "description": "The JSON object containing a 'set' object. This contains single item JSON objects that specify the field to replace and the JSON value to replace with. Must not include 'systemId' field. Example { \"set\" : { \"field\" : \"value\", \"field2\":{\"object\":\"item\"} }",
+      "required": true,
+      "schema": {
+        "$ref": "#/definitions/systems-put-body"
+      }
+    },
+    "alive": {
+      "name": "alive",
+      "in": "query",
+      "description": "Whether to return only systems that are currently running",
+      "type": "boolean",
+      "required": false,
+      "default": true
+    },
+    "limit": {
+      "name": "limit",
+      "in": "query",
+      "description": "Limit of items to return. Example '1'",
+      "type": "integer",
+      "required": false,
+      "default": 1
+    },
+    "offset": {
+      "name": "offset",
+      "in": "query",
+      "description": "Offset of items to return. Example '0'",
+      "type": "integer",
+      "required": true,
+      "default": 0
+    },
+    "sort": {
+      "name": "sort",
+      "in": "query",
+      "description": "Sort string. Comma separated list of fields prefixed with '+' for ascending or '-' for descending. Example '?sort=+a,-b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.",
+      "type": "string",
+      "required": false
+    },
+    "query": {
+      "name": "query",
+      "in": "query",
+      "description": "Query string. Comma separated list of key, comparator, value pairs. Comparator supports '==', '<=', '>=', '<', '>', '!='. Example '?query=a==b,c!=d'. Keys are fields in documents and use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.",
+      "type": "string",
+      "required": false
+    },
+    "include": {
+      "name": "include",
+      "in": "query",
+      "description": "Inclusion string. Comma separated list of fields to include in the response. Example '?include=a,b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer. Cannot be used in combination with 'exclude' parameter Overriden by 'exclude' parameter",
+      "type": "string",
+      "required": false
+    },
+    "exclude": {
+      "name": "exclude",
+      "in": "query",
+      "description": "Exclusion string. Comma separated list of fields to exclude in the response. Example '?exclude=a,b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer. Cannot be used in combination with 'include' parameter; takes precedence over 'include' parameter",
+      "type": "string",
+      "required": false
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/test/resources/systems-swagger.yaml	Fri Sep 29 14:48:00 2017 -0400
@@ -0,0 +1,192 @@
+swagger: '2.0'
+info:
+  version: 0.0.1
+  title: Thermostat Web Gateway System Information API
+  license:
+    name: GPL v2 with Classpath Exception
+    url: 'http://www.gnu.org/licenses'
+consumes:
+  - application/json
+produces:
+  - application/json
+  - text/html; charset=utf-8
+basePath: /systems/0.0.1
+paths:
+  /:
+    get:
+      description: Get information for all systems.
+      parameters:
+        - $ref: '#/parameters/limit'
+        - $ref: '#/parameters/offset'
+        - $ref: '#/parameters/sort'
+        - $ref: '#/parameters/include'
+        - $ref: '#/parameters/exclude'
+        - $ref: '#/parameters/query'
+        - $ref: '#/parameters/alive'
+      responses:
+        '200':
+          description: OK
+          schema:
+            $ref: '#/definitions/systems-get-response'
+  /systems/{systemId}:
+    parameters:
+      - $ref: '#/parameters/system-id'
+    get:
+      description: Get information for system {systemId}.
+      parameters:
+        - $ref: '#/parameters/limit'
+        - $ref: '#/parameters/offset'
+        - $ref: '#/parameters/sort'
+        - $ref: '#/parameters/include'
+        - $ref: '#/parameters/exclude'
+        - $ref: '#/parameters/query'
+        - $ref: '#/parameters/alive'
+      responses:
+        '200':
+          description: OK
+          schema:
+            $ref: '#/definitions/systems-get-response'
+    put:
+      description: Update information for system {systemId}.
+      parameters:
+        - $ref: '#/parameters/systems-put-body'
+        - $ref: '#/parameters/query'
+      responses:
+        '200':
+          description: OK
+    post:
+      description: Add information for system {systemId}
+      parameters:
+        - $ref: '#/parameters/system-info-array'
+      responses:
+        '200':
+          description: OK
+    delete:
+      description: Delete information for system ID {systemId}.
+      parameters:
+        - $ref: '#/parameters/query'
+      responses:
+        '200':
+          description: OK
+definitions:
+  systems-get-response:
+    type: object
+    properties:
+      response:
+          $ref: '#/definitions/system-info-array'
+  system-info-array:
+    type: array
+    items:
+      $ref: '#/definitions/system-info'
+  system-info:
+    type: object
+    properties:
+      systemId:
+        type: string
+      agentId:
+        type: string
+      hostname:
+        type: string
+      osName:
+        type: string
+      osKernel:
+        type: string
+      osArch:
+        type: string
+      cpuCount:
+        type: integer
+      cpuModel:
+        type: string
+      totalMemory:
+        type: integer
+        format: int64
+      timeCreated:
+        type: integer
+        format: int64
+      lastUpdated:
+        type: integer
+        format: int64
+  systems-put-body:
+    type: object
+    properties:
+      "set":
+        type: object
+parameters:
+  system-id:
+    name: systemId
+    in: path
+    required: true
+    type: string
+  system-info-array:
+    name: system-info-array
+    in: body
+    description: The system information
+    required: true
+    schema:
+      $ref: '#/definitions/system-info-array'
+  systems-put-body:
+    name: body
+    in: body
+    description: >-
+      The JSON object containing a 'set' object. This contains single item JSON
+      objects that specify the field to replace and the JSON value to replace with.
+      Must not include 'systemId' field. Example { "set" : {
+      "field" : "value", "field2":{"object":"item"} }
+    required: true
+    schema:
+      $ref: '#/definitions/systems-put-body'
+  alive:
+    name: alive
+    in: query
+    description: Whether to return only systems that are currently running
+    type: boolean
+    required: false
+    default: true
+  limit:
+    name: limit
+    in: query
+    description: Limit of items to return. Example '1'
+    type: integer
+    required: false
+    default: 1
+  offset:
+    name: offset
+    in: query
+    description: Offset of items to return. Example '0'
+    type: integer
+    required: true
+    default: 0
+  sort:
+    name: sort
+    in: query
+    description: Sort string. Comma separated list of fields prefixed with '+' for ascending or '-' for descending. Example '?sort=+a,-b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.
+    type: string
+    required: false
+  query:
+    name: query
+    in: query
+    description: Query string. Comma separated list of key, comparator, value pairs. Comparator supports '==', '<=', '>=', '<', '>', '!='. Example '?query=a==b,c!=d'. Keys are fields in documents and use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.
+    type: string
+    required: false
+  include:
+    name: include
+    in: query
+    description: >-
+      Inclusion string. Comma separated list of fields to include in the
+      response. Example '?include=a,b' Fields use dot notation for embedded
+      documents. Example 'outer.inner' refers to field inner contained in field
+      outer. Cannot be used in combination with 'exclude' parameter Overriden by
+      'exclude' parameter
+    type: string
+    required: false
+  exclude:
+    name: exclude
+    in: query
+    description: >-
+      Exclusion string. Comma separated list of fields to exclude in the
+      response. Example '?exclude=a,b' Fields use dot notation for embedded
+      documents. Example 'outer.inner' refers to field inner contained in field
+      outer. Cannot be used in combination with 'include' parameter; takes
+      precedence over 'include' parameter
+    type: string
+    required: false
--- a/common/type-system/src/main/java/com/redhat/thermostat/lang/schema/JSONService.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.lang.schema;
-
-/**
- * Serialisation service for Java types into JSON.
- */
-public interface JSONService {
-    /**
-     * Serialise the object in input to JSON.
-     */
-    String serialiase(Object target);
-}
--- a/common/type-system/src/main/java/com/redhat/thermostat/lang/schema/SchemaBuilder.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.lang.schema;
-
-public interface SchemaBuilder {
-    /**
-     * Returns the Schema for the given class.
-     */
-    String getSchema(Class target);
-
-    /**
-     * Registers a type in the schema
-     */
-    void registerType(Class target);
-
-}
--- a/common/type-system/src/main/java/com/redhat/thermostat/lang/schema/SchemaValidationException.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-package com.redhat.thermostat.lang.schema;
-
-/**
- */
-public class SchemaValidationException extends RuntimeException {
-    public SchemaValidationException() {
-    }
-
-    public SchemaValidationException(String message) {
-        super(message);
-    }
-
-    public SchemaValidationException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public SchemaValidationException(Throwable cause) {
-        super(cause);
-    }
-
-    public SchemaValidationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
-        super(message, cause, enableSuppression, writableStackTrace);
-    }
-}
--- a/common/type-system/src/main/java/com/redhat/thermostat/lang/schema/annotations/Maximum.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.lang.schema.annotations;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Define the maximum value allowed for the variable it is applied to. <br />
- * If {@link #exclusive()} is true, the maximum value must be strictly lower
- * than the value specified by this annotation. The default number returned
- * by {@link #value()} is {@link Long#MAX_VALUE}.
- */
-@Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-public @interface Maximum {
-    long value() default Long.MAX_VALUE;
-    boolean exclusive() default false;
-}
--- a/common/type-system/src/main/java/com/redhat/thermostat/lang/schema/annotations/Minimum.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.lang.schema.annotations;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Define the minimum value allowed for the variable it is applied to. <br />
- * If {@link #exclusive()} is true, the minimum value must be strictly greater
- * than the value specified by this annotation. The default number returned
- * by {@link #value()} is {@link Long#MIN_VALUE}.
- */
-@Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-public @interface Minimum {
-    long value() default Long.MIN_VALUE;
-    boolean exclusive() default false;
-}
--- a/common/type-system/src/main/java/com/redhat/thermostat/lang/schema/annotations/Schema.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.lang.schema.annotations;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- */
-@Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-public @interface Schema {
-    String name() default "";
-    String description() default "";
-    boolean required() default false;
-}
--- a/common/type-system/src/main/java/com/redhat/thermostat/lang/schema/annotations/Type.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.lang.schema.annotations;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- */
-@Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface Type {
-    String name() default "";
-    String description() default "";
-}
--- a/common/type-system/src/main/java/com/redhat/thermostat/lang/schema/internal/JSONServiceImpl.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.lang.schema.internal;
-
-import com.google.gson.ExclusionStrategy;
-import com.google.gson.FieldAttributes;
-import com.google.gson.GsonBuilder;
-import com.google.gson.TypeAdapter;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
-
-import com.redhat.thermostat.lang.schema.*;
-
-import com.redhat.thermostat.lang.schema.annotations.Schema;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Service;
-
-import java.io.IOException;
-
-@Component
-@Service(JSONService.class)
-public class JSONServiceImpl implements JSONService {
-
-    private GsonBuilder builder;
-
-    public JSONServiceImpl() {
-        this(false);
-    }
-
-    public JSONServiceImpl(boolean prettyPrinting) {
-
-
-        builder = new GsonBuilder();
-        if (prettyPrinting) {
-            builder.setPrettyPrinting();
-        }
-
-        AutoAdapter autoAdapter = new AutoAdapter();
-
-        builder.registerTypeAdapter(boolean.class, autoAdapter);
-        builder.registerTypeAdapter(byte.class, autoAdapter);
-        builder.registerTypeAdapter(short.class, autoAdapter);
-        builder.registerTypeAdapter(int.class, autoAdapter);
-        builder.registerTypeAdapter(long.class, autoAdapter);
-        builder.registerTypeAdapter(double.class, autoAdapter);
-        builder.registerTypeAdapter(float.class, autoAdapter);
-
-        builder.registerTypeAdapter(Boolean.class, autoAdapter);
-        builder.registerTypeAdapter(Byte.class, autoAdapter);
-        builder.registerTypeAdapter(Short.class, autoAdapter);
-        builder.registerTypeAdapter(Integer.class, autoAdapter);
-        builder.registerTypeAdapter(Long.class, autoAdapter);
-        builder.registerTypeAdapter(Double.class, autoAdapter);
-        builder.registerTypeAdapter(Float.class, autoAdapter);
-
-        builder.addSerializationExclusionStrategy(new AutoExclusionStategy());
-
-    }
-
-    @Override
-    public String serialiase(Object target) {
-        // TODO - consider registering this class with the schema registry
-        return builder.create().toJson(target);
-    }
-
-    private class AutoAdapter extends TypeAdapter<Object> {
-
-        @Override
-        public void write(JsonWriter out, Object value) throws IOException {
-            out.value("" + value);
-        }
-
-        @Override
-        public Object read(JsonReader in) throws IOException {
-            throw new UnsupportedOperationException("read() not yet implemented");
-        }
-    }
-
-    public class AutoExclusionStategy implements ExclusionStrategy {
-
-        public boolean shouldSkipClass(Class<?> arg0) {
-            return false;
-        }
-
-        public boolean shouldSkipField(FieldAttributes field) {
-            return (field.getAnnotation(Schema.class) == null);
-        }
-    }
-}
--- a/common/type-system/src/main/java/com/redhat/thermostat/lang/schema/internal/SchemaBuilderImpl.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,277 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.lang.schema.internal;
-
-import com.google.gson.GsonBuilder;
-import com.google.gson.TypeAdapter;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
-
-import com.redhat.thermostat.lang.schema.*;
-
-import com.redhat.thermostat.lang.schema.annotations.Maximum;
-import com.redhat.thermostat.lang.schema.annotations.Minimum;
-import com.redhat.thermostat.lang.schema.annotations.Schema;
-import com.redhat.thermostat.lang.schema.annotations.Type;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Service;
-
-import java.io.IOException;
-import java.lang.reflect.Field;
-
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.ConcurrentHashMap;
-
-@Component
-@Service(SchemaBuilder.class)
-public class SchemaBuilderImpl implements SchemaBuilder {
-
-    private class FieldProperties {
-        String name = "";
-        String description = "";
-        String type = "";
-        String parentType = "";
-
-        boolean hasMin;
-        long boundsMin;
-        boolean exclusiveMin;
-
-        boolean hasMax;
-        long boundsMax;
-        boolean exclusiveMax;
-
-        @Override
-        public String toString() {
-            return "FieldProperties {" +
-                    "name='" + name + '\'' +
-                    ", description='" + description + '\'' +
-                    ", type='" + type + '\'' +
-                    '}';
-        }
-    }
-
-    private class SchemaDefinition {
-        FieldProperties field = new FieldProperties();
-        Set<FieldProperties> properties = new TreeSet<>(new Comparator<FieldProperties>() {
-            @Override
-            public int compare(FieldProperties o1, FieldProperties o2) {
-                return o1.toString().compareTo(o2.toString());
-            }
-        });
-        Set<String> required = new TreeSet<>();
-    }
-
-    private GsonBuilder schemaBuilder;
-
-    private Map<String, String> schemas;
-    private Map<String, SchemaDefinition> definitions;
-
-    public SchemaBuilderImpl() {
-        this(true);
-    }
-
-    public SchemaBuilderImpl(boolean prettyPrinting) {
-        definitions = new ConcurrentHashMap<>();
-        schemas = new HashMap<>();
-
-        schemaBuilder = new GsonBuilder();
-        schemaBuilder.registerTypeAdapter(Class.class, new SchemaSerializer());
-
-        if (prettyPrinting) {
-            schemaBuilder.setPrettyPrinting();
-        }
-    }
-
-    private void checkTypeAndRegister(Class target) {
-
-        if (schemas.containsKey(target.getName())) {
-            return;
-        }
-
-        if (!target.isAnnotationPresent(Type.class)) {
-            throw new IllegalArgumentException("Unrecognised Type: must be annotated with " + Type.class);
-        }
-
-        SchemaDefinition definition = new SchemaDefinition();
-
-        definition.field.name = target.getSimpleName();
-        Type annotation = (Type) target.getAnnotation(Type.class);
-        if (!annotation.name().isEmpty()) {
-            definition.field.name = annotation.name();
-        }
-
-        definition.field.description = annotation.description();
-        if (!target.getSuperclass().equals(Object.class)) {
-            definition.field.parentType = target.getSuperclass().getSimpleName();
-        }
-
-        // let's see the rest of the schema
-        for (Field field : target.getDeclaredFields()) {
-            if (field.isAnnotationPresent(Schema.class)) {
-
-                Schema schema = field.getAnnotation(Schema.class);
-
-                FieldProperties fieldProperties = new FieldProperties();
-                fieldProperties.name = field.getName();
-                if (!schema.name().isEmpty()) {
-                    fieldProperties.name = schema.name();
-                }
-
-                fieldProperties.description = schema.description();
-                fieldProperties.type = field.getType().getSimpleName();
-
-                if (field.isAnnotationPresent(Minimum.class)) {
-                    fieldProperties.hasMin = true;
-
-                    Minimum range = field.getAnnotation(Minimum.class);
-                    fieldProperties.boundsMin = range.value();
-                    fieldProperties.exclusiveMin = range.exclusive();
-                }
-
-                if (field.isAnnotationPresent(Maximum.class)) {
-                    fieldProperties.hasMax = true;
-
-                    Maximum range = field.getAnnotation(Maximum.class);
-                    fieldProperties.boundsMax = range.value();
-                    fieldProperties.exclusiveMax = range.exclusive();
-                }
-
-                if (fieldProperties.hasMax && fieldProperties.hasMin &&
-                        fieldProperties.boundsMin > fieldProperties.boundsMax)
-                {
-                    // perhaps a better error message?
-                    throw new SchemaValidationException("maximum and minimum bounds are incompatible: " +
-                            "min: " + fieldProperties.boundsMin + ", " +
-                            "max: " + fieldProperties.boundsMax);
-                }
-
-                definition.properties.add(fieldProperties);
-                if (schema.required()) {
-                    definition.required.add(fieldProperties.name);
-                }
-            }
-        }
-
-        definitions.put(target.getName(), definition);
-
-        String schema = schemaBuilder.create().toJson(target);
-        schemas.put(target.getName(), schema);
-    }
-
-    @Override
-    public void registerType(Class target) {
-        checkTypeAndRegister(target);
-    }
-
-    @Override
-    public String getSchema(Class target) {
-        checkTypeAndRegister(target);
-
-        return schemas.get(target.getName());
-    }
-
-    private class SchemaSerializer extends TypeAdapter<Object> {
-
-        @Override
-        public void write(JsonWriter out, Object target) throws IOException {
-
-            SchemaDefinition definition = definitions.get(((Class) target).getName());
-
-            out.beginObject();
-
-            out.name("$schema").value("http://json-schema.org/draft-04/schema#");
-            out.name("title").value(definition.field.name);
-            out.name("description").value(definition.field.description);
-            out.name("type").value("object");
-            if (!definition.field.parentType.isEmpty()) {
-                out.name("extends").value(definition.field.parentType);
-            }
-
-            if (!definition.properties.isEmpty()) {
-                out.name("properties");
-                out.beginObject();
-
-                for (FieldProperties property : definition.properties) {
-
-                    out.name(property.name);
-
-                    out.beginObject();
-                    out.name("description").value(property.description);
-                    out.name("type").value(property.type);
-
-                    if (property.hasMin) {
-                        out.name("minimum").value(property.boundsMin);
-                        if (property.exclusiveMin) {
-                            out.name("exclusiveMinimum").value(true);
-                        }
-                    }
-
-                    if (property.hasMax) {
-                        out.name("maximum").value(property.boundsMax);
-                        if (property.exclusiveMax) {
-                            out.name("exclusiveMaximum").value(true);
-                        }
-                    }
-
-                    out.endObject();
-                }
-                out.endObject();
-            }
-
-            if (!definition.required.isEmpty()) {
-                out.name("required");
-                out.beginArray();
-                for (String required : definition.required) {
-                    out.value(required);
-                }
-                out.endArray();
-            }
-
-            out.endObject();
-        }
-
-        @Override
-        public Object read(JsonReader in) throws IOException {
-            throw new UnsupportedOperationException("NIY");
-        }
-    }
-
-}
--- a/common/type-system/src/main/java/com/redhat/thermostat/lang/schema/models/Id.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.lang.schema.models;
-
-import com.redhat.thermostat.lang.schema.annotations.Schema;
-import com.redhat.thermostat.lang.schema.annotations.Type;
-
-import java.util.Objects;
-import java.util.UUID;
-
-/**
- * A Type that represents an identifier.
- */
-@Type(description = "The representation of a ID")
-public class Id {
-    @Schema(description = "The ID", required = true)
-    private String id;
-
-    public Id() {
-        id = UUID.randomUUID().toString();
-    }
-
-    public Id(String id) {
-        this.id = Objects.requireNonNull(id);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        Id other = (Id) o;
-        return Objects.equals(this.id, other.get());
-    }
-
-    public String get() {
-        return id;
-    }
-
-    @Override
-    public int hashCode() {
-        return id != null ? id.hashCode() : 0;
-    }
-}
--- a/common/type-system/src/main/java/com/redhat/thermostat/lang/schema/models/Pid.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.lang.schema.models;
-
-import com.redhat.thermostat.lang.schema.annotations.Schema;
-import com.redhat.thermostat.lang.schema.annotations.Type;
-
-/**
- */
-@Type(description = "The representation of a Pid")
-public class Pid {
-    @Schema(description = "The Pid", required = true)
-    private int pid;
-
-    public Pid(int pid) {
-        this.pid = pid;
-    }
-
-    public int get() {
-        return pid;
-    }
-
-    @Override
-    public String toString() {
-        return Integer.toString(pid);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        Pid pid1 = (Pid) o;
-
-        return pid == pid1.pid;
-    }
-
-    @Override
-    public int hashCode() {
-        return pid;
-    }
-}
--- a/common/type-system/src/main/java/com/redhat/thermostat/lang/schema/models/ProcessState.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.lang.schema.models;
-
-import com.redhat.thermostat.lang.schema.annotations.Type;
-
-/**
- */
-@Type(description = "Define the basic running states for a process")
-public class ProcessState {
-
-}
--- a/common/type-system/src/main/java/com/redhat/thermostat/lang/schema/models/Timestamp.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.lang.schema.models;
-
-import com.redhat.thermostat.lang.schema.annotations.Minimum;
-import com.redhat.thermostat.lang.schema.annotations.Schema;
-import com.redhat.thermostat.lang.schema.annotations.Type;
-
-/**
- * A Type representing the number of milliseconds elapsed since the Unix Epoch.
- */
-@Type(description = "A Type representing the number of milliseconds elapsed since the Unix Epoch")
-public class Timestamp {
-    @Schema(description = "The number of milliseconds elapsed since the Unix Epoch", required = true)
-    @Minimum(0)
-    private long timestamp;
-
-    public Timestamp(long timestamp) {
-        this.timestamp = timestamp;
-    }
-
-    public long get() {
-        return timestamp;
-    }
-
-    @Override
-    public String toString() {
-        return "" + timestamp;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (!(o instanceof Timestamp)) return false;
-
-        Timestamp timestamp1 = (Timestamp) o;
-
-        return timestamp == timestamp1.timestamp;
-    }
-
-    @Override
-    public int hashCode() {
-        return (int) (timestamp ^ (timestamp >>> 32));
-    }
-}
--- a/common/type-system/src/test/java/com/redhat/thermostat/lang/schema/internal/JSONServiceTest.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.lang.schema.internal;
-
-import com.redhat.thermostat.lang.schema.annotations.Schema;
-import com.redhat.thermostat.lang.schema.annotations.Type;
-import com.redhat.thermostat.lang.schema.models.Timestamp;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- */
-public class JSONServiceTest {
-
-    @Type(description = "Some Object for testing out")
-    public class SomeMoreComplexType {
-        @Schema(description = "Some Long", required = true)
-        private long aLong;
-
-        @Schema(description = "Some String", required = true)
-        private String aString;
-
-        public SomeMoreComplexType(long aLong, String aString) {
-            this.aLong = aLong;
-            this.aString = aString;
-
-        }
-
-        public long getALong() {
-            return aLong;
-        }
-
-        public String getAString() {
-            return aString;
-        }
-    }
-
-    @Type(description = "Some Object for testing out")
-    public class SomeMoreComplexType2 {
-        @Schema(description = "Some Long", required = true)
-        private long aLong;
-
-        // not part of the schema, won't be serialised!
-        private String aString;
-
-        public SomeMoreComplexType2(long aLong, String aString) {
-            this.aLong = aLong;
-            this.aString = aString;
-
-        }
-
-        public long getALong() {
-            return aLong;
-        }
-
-        public String getAString() {
-            return aString;
-        }
-    }
-
-    @Type(description = "Something more complex perhaps?")
-    public class CompoundType {
-        @Schema(description = "Some Long", required = true)
-        private long aLong;
-
-        @Schema
-        private SomeMoreComplexType complexType;
-
-        public CompoundType(long aLong, SomeMoreComplexType complexType) {
-            this.aLong = aLong;
-            this.complexType = complexType;
-
-        }
-
-        public long getALong() {
-            return aLong;
-        }
-
-        public SomeMoreComplexType getComplexType() {
-            return complexType;
-        }
-    }
-
-    @Type(description = "Something more complex perhaps?")
-    public class CompoundTypeMissingSchema {
-        @Schema(description = "Some Long", required = true)
-        private long aLong;
-
-        // won't be serialised
-        private SomeMoreComplexType complexType;
-
-        public CompoundTypeMissingSchema(long aLong, SomeMoreComplexType complexType) {
-            this.aLong = aLong;
-            this.complexType = complexType;
-
-        }
-
-        public long getALong() {
-            return aLong;
-        }
-
-        public SomeMoreComplexType getComplexType() {
-            return complexType;
-        }
-    }
-
-    @Type(description = "An extended type that should inherit its schema")
-    public class ExtendedType extends CompoundType {
-
-        @Schema(description = "Some other long from derived class", required = true)
-        private long anotherLong;
-
-        public ExtendedType(long aLong, long anotherLong, SomeMoreComplexType complexType) {
-            super(aLong, complexType);
-            this.anotherLong = anotherLong;
-        }
-    }
-
-    private JSONServiceImpl service;
-
-    @Before
-    public void setUp() {
-        service = new JSONServiceImpl(false);
-    }
-
-    @Test
-    public void testSimpleType() {
-        Timestamp timestamp = new Timestamp(123456L);
-        assertEquals("{\"timestamp\":\"123456\"}", service.serialiase(timestamp));
-    }
-
-    @Test
-    public void testComplexType() {
-        SomeMoreComplexType type = new SomeMoreComplexType(42, "test");
-        assertEquals("{\"aLong\":\"42\",\"aString\":\"test\"}",
-                service.serialiase(type));
-    }
-
-    @Test
-    public void testComplexType2() {
-        SomeMoreComplexType2 type = new SomeMoreComplexType2(42, "test");
-        assertEquals("{\"aLong\":\"42\"}",
-                service.serialiase(type));
-    }
-
-    @Test
-    public void testCompoundType() {
-        CompoundType type = new CompoundType(42, new SomeMoreComplexType(10, "test"));
-        assertEquals("{\"aLong\":\"42\",\"complexType\":{\"aLong\":\"10\",\"aString\":\"test\"}}",
-                service.serialiase(type));
-    }
-
-    @Test
-    public void testCompoundTypeMissingSchema() {
-        CompoundTypeMissingSchema type = new CompoundTypeMissingSchema(42, new SomeMoreComplexType(10, "test"));
-        assertEquals("{\"aLong\":\"42\"}",
-                service.serialiase(type));
-    }
-
-    @Test
-    public void testExtendedType() {
-        ExtendedType type = new ExtendedType(50, 42, new SomeMoreComplexType(10, "test"));
-        assertEquals("{\"anotherLong\":\"42\",\"aLong\":\"50\",\"complexType\":{\"aLong\":\"10\",\"aString\":\"test\"}}",
-                service.serialiase(type));
-    }
-}
--- a/common/type-system/src/test/java/com/redhat/thermostat/lang/schema/internal/SchemaBuilderTest.java	Thu Sep 28 10:50:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,253 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.lang.schema.internal;
-
-import com.redhat.thermostat.lang.schema.SchemaBuilder;
-import com.redhat.thermostat.lang.schema.SchemaValidationException;
-
-import com.redhat.thermostat.lang.schema.annotations.Maximum;
-import com.redhat.thermostat.lang.schema.annotations.Minimum;
-import com.redhat.thermostat.lang.schema.annotations.Schema;
-import com.redhat.thermostat.lang.schema.annotations.Type;
-import com.redhat.thermostat.lang.schema.models.Timestamp;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- */
-public class SchemaBuilderTest {
-
-    @Type(description = "Some Object for testing out")
-    public class SomeMoreComplexType {
-        @Schema(description = "Some Long", required = true)
-        private long aLong;
-
-        @Schema(description = "Some String", required = true)
-        private String aString;
-
-        public SomeMoreComplexType(long aLong, String aString) {
-            this.aLong = aLong;
-            this.aString = aString;
-
-        }
-
-        public long getALong() {
-            return aLong;
-        }
-
-        public String getAString() {
-            return aString;
-        }
-    }
-
-    @Type(description = "Some Object for testing out")
-    public class SomeMoreComplexType2 {
-        @Schema(description = "Some Long", required = true)
-        private long aLong;
-
-        // not part of the schema, won't be serialised!
-        private String aString;
-
-        public SomeMoreComplexType2(long aLong, String aString) {
-            this.aLong = aLong;
-            this.aString = aString;
-
-        }
-
-        public long getALong() {
-            return aLong;
-        }
-
-        public String getAString() {
-            return aString;
-        }
-    }
-
-    @Type(description = "Something more complex perhaps?")
-    public class CompoundType {
-        @Schema(description = "Some Long", required = true)
-        private long aLong;
-
-        @Schema
-        private SomeMoreComplexType complexType;
-
-        public CompoundType(long aLong, SomeMoreComplexType complexType) {
-            this.aLong = aLong;
-            this.complexType = complexType;
-
-        }
-
-        public long getALong() {
-            return aLong;
-        }
-
-        public SomeMoreComplexType getComplexType() {
-            return complexType;
-        }
-    }
-
-    @Type(description = "Something more complex perhaps?")
-    public class CompoundTypeMissingSchema {
-        @Schema(description = "Some Long", required = true)
-        private long aLong;
-
-        // won't be serialised
-        private SomeMoreComplexType complexType;
-
-        public CompoundTypeMissingSchema(long aLong, SomeMoreComplexType complexType) {
-            this.aLong = aLong;
-            this.complexType = complexType;
-        }
-
-        public long getALong() {
-            return aLong;
-        }
-
-        public SomeMoreComplexType getComplexType() {
-            return complexType;
-        }
-    }
-
-    @Type(description = "An extended type that should inherit its schema")
-    public class ExtendedType extends CompoundType {
-
-        @Schema(description = "Some other long from derived class", required = true)
-        private long anotherLong;
-
-        public ExtendedType(long aLong, long anotherLong, SomeMoreComplexType complexType) {
-            super(aLong, complexType);
-            this.anotherLong = anotherLong;
-        }
-    }
-
-    private SchemaBuilder service;
-
-    @Before
-    public void setUp() {
-        service = new SchemaBuilderImpl(false);
-    }
-
-    @Test(expected = java.lang.IllegalArgumentException.class)
-    public void testNoTypeAnnotation() {
-        String test = "primitive type";
-        service.getSchema(test.getClass());
-    }
-
-    @Test
-    public void testSimpleTypeSchema() {
-        assertEquals("{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"Timestamp\",\"description\":\"A Type representing the number of milliseconds elapsed since the Unix Epoch\",\"type\":\"object\",\"properties\":{\"timestamp\":{\"description\":\"The number of milliseconds elapsed since the Unix Epoch\",\"type\":\"long\",\"minimum\":0}},\"required\":[\"timestamp\"]}",
-                service.getSchema(Timestamp.class));
-    }
-
-    @Test
-    public void testComplexTypeSchema() {
-        assertEquals("{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"SomeMoreComplexType\",\"description\":\"Some Object for testing out\",\"type\":\"object\",\"properties\":{\"aLong\":{\"description\":\"Some Long\",\"type\":\"long\"},\"aString\":{\"description\":\"Some String\",\"type\":\"String\"}},\"required\":[\"aLong\",\"aString\"]}",
-                service.getSchema(SomeMoreComplexType.class));
-    }
-
-
-    @Test
-    public void testComplexType2Schema() {
-        assertEquals("{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"SomeMoreComplexType2\",\"description\":\"Some Object for testing out\",\"type\":\"object\",\"properties\":{\"aLong\":{\"description\":\"Some Long\",\"type\":\"long\"}},\"required\":[\"aLong\"]}",
-                service.getSchema(SomeMoreComplexType2.class));
-    }
-
-    @Test
-    public void testCompoundTypeSchema() {
-        assertEquals("{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"CompoundType\",\"description\":\"Something more complex perhaps?\",\"type\":\"object\",\"properties\":{\"aLong\":{\"description\":\"Some Long\",\"type\":\"long\"},\"complexType\":{\"description\":\"\",\"type\":\"SomeMoreComplexType\"}},\"required\":[\"aLong\"]}",
-                service.getSchema(CompoundType.class));
-    }
-
-    @Test
-    public void testCompoundTypeMissingSchemaSchema() {
-        assertEquals("{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"CompoundTypeMissingSchema\",\"description\":\"Something more complex perhaps?\",\"type\":\"object\",\"properties\":{\"aLong\":{\"description\":\"Some Long\",\"type\":\"long\"}},\"required\":[\"aLong\"]}",
-                service.getSchema(CompoundTypeMissingSchema.class));
-    }
-
-
-    @Test
-    public void testExtendedTypeSchema() {
-        assertEquals("{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"ExtendedType\",\"description\":\"An extended type that should inherit its schema\",\"type\":\"object\",\"extends\":\"CompoundType\",\"properties\":{\"anotherLong\":{\"description\":\"Some other long from derived class\",\"type\":\"long\"}},\"required\":[\"anotherLong\"]}",
-                service.getSchema(ExtendedType.class));
-    }
-
-    @Type(description = "Some Type for testing out")
-    public class ATypeWithConstraints {
-        @Schema(description = "Some Long", required = true)
-        @Minimum(2)
-        @Maximum(value = 5, exclusive = true)
-        private long aLong;
-
-        public ATypeWithConstraints(long aLong) {
-            this.aLong = aLong;
-        }
-
-        public long getALong() {
-            return aLong;
-        }
-    }
-
-    @Test
-    public void testTypeWithConstraintsSchema() {
-        assertEquals("{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"ATypeWithConstraints\",\"description\":\"Some Type for testing out\",\"type\":\"object\",\"properties\":{\"aLong\":{\"description\":\"Some Long\",\"type\":\"long\",\"minimum\":2,\"maximum\":5,\"exclusiveMaximum\":true}},\"required\":[\"aLong\"]}",
-                service.getSchema(ATypeWithConstraints.class));
-    }
-
-    @Type(description = "Some Type for testing out")
-    public class ATypeWithBadConstraints {
-        @Schema(description = "Some Long", required = true)
-        @Minimum(5)
-        @Maximum(value = 1, exclusive = true)
-        private long aLong;
-
-        public ATypeWithBadConstraints(long aLong) {
-            this.aLong = aLong;
-        }
-
-        public long getALong() {
-            return aLong;
-        }
-    }
-
-    @Test(expected = SchemaValidationException.class)
-    public void testTypeWithBadConstraintsSchema() {
-        service.getSchema(ATypeWithBadConstraints.class);
-    }
-}