process dgraph schema
diff --git a/controller/schema/dgraph_schema_store.go b/controller/schema/dgraph_schema_store.go
new file mode 100644
index 0000000..87a4d95
--- /dev/null
+++ b/controller/schema/dgraph_schema_store.go
@@ -0,0 +1,85 @@
+package schema
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"strings"
+
+	"github.com/golang/glog"
+	"github.com/itaysk/regogo"
+	"github.com/vektah/gqlparser/ast"
+	"github.com/vektah/gqlparser/parser"
+)
+
+const jsonContentType = "application/json"
+
+const getSchemaQuery = `{ "query": "{ getGQLSchema() { schema } }" }`
+
+const addSchemaQuery = `{
+  "query": "mutation { updateGQLSchema(input: {set: {schema: \"%s\"}}) { gqlSchema { id schema } } }" }`
+
+type DgraphSchemaStore struct {
+	dgraphAddress string
+	gqlSchema     string
+	schema        *ast.SchemaDocument
+}
+
+func NewDgraphSchemaStore(dgraphAddress string) (SchemaStore, error) {
+	ret := &DgraphSchemaStore{dgraphAddress: dgraphAddress, gqlSchema: ""}
+	if err := ret.fetchSchema(); err != nil {
+		return nil, err
+	}
+	return ret, nil
+}
+
+func (s *DgraphSchemaStore) Schema() *ast.SchemaDocument {
+	return s.schema
+}
+
+func (s *DgraphSchemaStore) AddSchema(gqlSchema string) error {
+	return s.SetSchema(s.gqlSchema + gqlSchema)
+}
+
+func (s *DgraphSchemaStore) SetSchema(gqlSchema string) error {
+	glog.Info("Setting GraphQL schema:")
+	glog.Info(gqlSchema)
+	req := fmt.Sprintf(addSchemaQuery, strings.ReplaceAll(strings.ReplaceAll(gqlSchema, "\n", " "), "\t", " "))
+	resp, err := http.Post(s.dgraphAddress, jsonContentType, bytes.NewReader([]byte(req)))
+	glog.Infof("Response status code: %d", resp.StatusCode)
+	if err != nil {
+		return err
+	}
+	respBody, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return err
+	}
+	glog.Infof("Result: %s", string(respBody))
+	s.gqlSchema = gqlSchema
+	return s.fetchSchema()
+}
+
+func (s *DgraphSchemaStore) fetchSchema() error {
+	glog.Infof("Getting GraphQL schema with query: %s", getSchemaQuery)
+	resp, err := http.Post(s.dgraphAddress, jsonContentType, bytes.NewReader([]byte(getSchemaQuery)))
+	if err != nil {
+		return err
+	}
+	glog.Infof("Response status code: %d", resp.StatusCode)
+	respBody, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return err
+	}
+	glog.Infof("Result: %s", string(respBody))
+	gqlSchema, err := regogo.Get(string(respBody), "input.data.getGQLSchema.schema")
+	if err != nil {
+		return err
+	}
+	schema, gqlErr := parser.ParseSchema(&ast.Source{Input: gqlSchema.String()})
+	if gqlErr != nil {
+		return gqlErr
+	}
+	s.schema = schema
+	return nil
+}
diff --git a/controller/schema/schema.go b/controller/schema/schema.go
new file mode 100644
index 0000000..a077ce3
--- /dev/null
+++ b/controller/schema/schema.go
@@ -0,0 +1,38 @@
+package schema
+
+import (
+	"github.com/vektah/gqlparser/ast"
+	"github.com/vektah/gqlparser/parser"
+)
+
+type SchemaStore interface {
+	Schema() *ast.SchemaDocument
+	SetSchema(gqlSchema string) error
+	AddSchema(gqlSchema string) error
+}
+
+type InMemorySchemaStore struct {
+	gqlSchema string
+	schema    *ast.SchemaDocument
+}
+
+func NewInMemorySchemaStore() SchemaStore {
+	return &InMemorySchemaStore{gqlSchema: ""}
+}
+
+func (s *InMemorySchemaStore) Schema() *ast.SchemaDocument {
+	return s.schema
+}
+
+func (s *InMemorySchemaStore) AddSchema(gqlSchema string) error {
+	return s.SetSchema(s.gqlSchema + gqlSchema)
+}
+
+func (s *InMemorySchemaStore) SetSchema(gqlSchema string) error {
+	schema, err := parser.ParseSchema(&ast.Source{Input: gqlSchema})
+	if err != nil {
+		return err
+	}
+	s.schema = schema
+	return nil
+}
diff --git a/controller/schema/schema_test.go b/controller/schema/schema_test.go
new file mode 100644
index 0000000..0c73694
--- /dev/null
+++ b/controller/schema/schema_test.go
@@ -0,0 +1,81 @@
+package schema
+
+import (
+	"fmt"
+	"log"
+	"testing"
+)
+
+func TestInMemorySimple(t *testing.T) {
+	s := NewInMemorySchemaStore()
+	err := s.AddSchema(`
+type M {
+  X: Int
+}`)
+	if err != nil {
+		t.Fatal(err)
+	}
+	for _, def := range s.Schema().Definitions {
+		fmt.Printf("%s - %s\n", def.Name, def.Kind)
+	}
+}
+
+func TestInMemory(t *testing.T) {
+	s := NewInMemorySchemaStore()
+	err := s.AddSchema(`
+type Image {
+  id: ID!
+  objectPath: String!
+}
+
+type ImageSegment {
+  id: ID! @search
+  upperLeftX: Float!
+  upperLeftY: Float!
+  lowerRightX: Float!
+  lowerRightY: Float!
+  sourceImage: Image!
+}
+
+extend type Image {
+  segments: [ImageSegment]
+}
+`)
+	if err != nil {
+		t.Fatal(err)
+	}
+	for _, def := range s.Schema().Definitions {
+		fmt.Printf("%s - %s\n", def.Name, def.Kind)
+	}
+}
+
+func TestDgraph(t *testing.T) {
+	s, err := NewDgraphSchemaStore("http://localhost:8080/admin")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if s.Schema() != nil {
+		for _, def := range s.Schema().Definitions {
+			fmt.Printf("%s - %s\n", def.Name, def.Kind)
+		}
+	}
+	err = s.AddSchema("type N { Y: ID! Z: Float }")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if s.Schema() != nil {
+		for _, def := range s.Schema().Definitions {
+			fmt.Printf("%s - %s\n", def.Name, def.Kind)
+		}
+	}
+	log.Print("123123")
+	err = s.AddSchema("type M { X: Int }")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if s.Schema() != nil {
+		for _, def := range s.Schema().Definitions {
+			fmt.Printf("%s - %s\n", def.Name, def.Kind)
+		}
+	}
+}