CORD-2247: Write basic static checker for xproto

Change-Id: I63a96972e16fd8dd62d4dec840eede66cbb26368
diff --git a/lib/xos-genx/MANIFEST.in b/lib/xos-genx/MANIFEST.in
index f6da5db..a058bb4 100644
--- a/lib/xos-genx/MANIFEST.in
+++ b/lib/xos-genx/MANIFEST.in
@@ -1,2 +1,3 @@
 include xosgenx/targets/*
+include xosgenx/checkers/*
 include xosgenx/jinja2_extensions/*
diff --git a/lib/xos-genx/xos-genx-tests/attics/xosmodel_bottom.py b/lib/xos-genx/xos-genx-tests/attics/xosmodel_bottom.py
index 8e28718..734aed5 100644
--- a/lib/xos-genx/xos-genx-tests/attics/xosmodel_bottom.py
+++ b/lib/xos-genx/xos-genx-tests/attics/xosmodel_bottom.py
@@ -15,4 +15,4 @@
 
 
 def bottom():
-    return 'bottom'
\ No newline at end of file
+    return 'bottom'
diff --git a/lib/xos-genx/xos-genx-tests/attics/xosmodel_header.py b/lib/xos-genx/xos-genx-tests/attics/xosmodel_header.py
index 044eb4e..5cee4a3 100644
--- a/lib/xos-genx/xos-genx-tests/attics/xosmodel_header.py
+++ b/lib/xos-genx/xos-genx-tests/attics/xosmodel_header.py
@@ -15,4 +15,4 @@
 
 
 def header():
-    return 'header'
\ No newline at end of file
+    return 'header'
diff --git a/lib/xos-genx/xos-genx-tests/attics/xosmodel_model.py b/lib/xos-genx/xos-genx-tests/attics/xosmodel_model.py
index ca48b14..048641a 100644
--- a/lib/xos-genx/xos-genx-tests/attics/xosmodel_model.py
+++ b/lib/xos-genx/xos-genx-tests/attics/xosmodel_model.py
@@ -15,4 +15,4 @@
 
 
 def model():
-    return 'model'
\ No newline at end of file
+    return 'model'
diff --git a/lib/xos-genx/xos-genx-tests/attics/xosmodel_top.py b/lib/xos-genx/xos-genx-tests/attics/xosmodel_top.py
index 2d0adcb..79752d0 100644
--- a/lib/xos-genx/xos-genx-tests/attics/xosmodel_top.py
+++ b/lib/xos-genx/xos-genx-tests/attics/xosmodel_top.py
@@ -15,4 +15,4 @@
 
 
 def top():
-    return 'top'
\ No newline at end of file
+    return 'top'
diff --git a/lib/xos-genx/xos-genx-tests/parse_test.py b/lib/xos-genx/xos-genx-tests/parse_test.py
index 88c7372..e63c7d0 100644
--- a/lib/xos-genx/xos-genx-tests/parse_test.py
+++ b/lib/xos-genx/xos-genx-tests/parse_test.py
@@ -15,7 +15,7 @@
 
 
 import unittest
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 from helpers import FakeArgs, XProtoTestHelpers
 
 class XProtoParseTests(unittest.TestCase):
@@ -31,7 +31,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = xtarget
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn("vsg", output)
         self.assertIn("vSG Service", output)
 
@@ -60,7 +60,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = xtarget
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn("PhoneNumber", output)
 
     def test_link_extensions(self):
@@ -75,7 +75,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = xtarget
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn("VRouterService", output)
 	
 	pass
@@ -91,7 +91,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = xtarget
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn("ServiceProxy", output)
 
     def test_message_options(self):
@@ -105,7 +105,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = xtarget
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn("e1000", output)
 
 	pass
@@ -121,7 +121,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = xtarget
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn("Base", output)
 
 if __name__ == '__main__':
diff --git a/lib/xos-genx/xos-genx-tests/target_test.py b/lib/xos-genx/xos-genx-tests/target_test.py
index b45f5ed..dde39dd 100644
--- a/lib/xos-genx/xos-genx-tests/target_test.py
+++ b/lib/xos-genx/xos-genx-tests/target_test.py
@@ -16,7 +16,7 @@
 
 import unittest
 import os
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 from helpers import FakeArgs, XProtoTestHelpers, OUTPUT_DIR
 
 TEST_FILE = "test_file"
@@ -43,7 +43,7 @@
         args.inputs = ''
         args.target = target
         args.attic = OUTPUT_DIR
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn(TEST_OUTPUT, output)
 
     def test_xproto_lib(self):
@@ -54,7 +54,7 @@
         args = FakeArgs()
         args.inputs = ''
         args.target = target
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn("Eureka", output)
 
     def test_context(self):
@@ -66,7 +66,7 @@
         args.inputs = ''
         args.target = target
         args.kv='what:what is what'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn("what is what", output)
 
     def test_singularize(self):
@@ -93,7 +93,7 @@
         args = FakeArgs()
         args.inputs = proto
         args.target = target
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertEqual("one,sheep,radius,slice,network,omf_friendly", output.lstrip().rstrip().rstrip(','))
 
     def test_pluralize(self):
@@ -120,7 +120,7 @@
         args = FakeArgs()
         args.inputs = proto
         args.target = target
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertEqual("data,sheep,radii,slices,networks,omf_friendlies", output.lstrip().rstrip().rstrip(','))
 
 if __name__ == '__main__':
diff --git a/lib/xos-genx/xos-genx-tests/test_cli.py b/lib/xos-genx/xos-genx-tests/test_cli.py
index e6de65c..4beef06 100644
--- a/lib/xos-genx/xos-genx-tests/test_cli.py
+++ b/lib/xos-genx/xos-genx-tests/test_cli.py
@@ -22,7 +22,7 @@
 class Args:
     pass
 
-class XOSGeneratorTest(unittest.TestCase):
+class XOSProcessorTest(unittest.TestCase):
     """
     Testing the CLI binding for the XOS Generative Toolchain
     """
@@ -47,11 +47,10 @@
         expected_args.target = os.path.abspath(os.getcwd() + '/' + args.target)
         expected_args.output = os.path.abspath(os.getcwd() + '/' + args.output)
 
-        with patch("xosgenx.xosgen.XOSGenerator.generate") as generator:
+        with patch("xosgenx.xosgen.XOSProcessor.process") as generator:
             XosGen.init(args)
             actual_args = generator.call_args[0][0]
             self.assertEqual(actual_args.files, expected_args.files)
-            self.assertEqual(actual_args.target, expected_args.target)
             self.assertEqual(actual_args.output, expected_args.output)
 
 if __name__ == '__main__':
diff --git a/lib/xos-genx/xos-genx-tests/test_django_generator.py b/lib/xos-genx/xos-genx-tests/test_django_generator.py
index 8567d2a..0ba90b5 100644
--- a/lib/xos-genx/xos-genx-tests/test_django_generator.py
+++ b/lib/xos-genx/xos-genx-tests/test_django_generator.py
@@ -16,7 +16,7 @@
 
 import unittest
 import os
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 from helpers import FakeArgs
 
 VROUTER_XPROTO = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xproto/vrouterport.xproto")
@@ -30,7 +30,7 @@
         args = FakeArgs()
         args.files = [VROUTER_XPROTO]
         args.target = 'django.xtarget'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         fields = filter(lambda s:'Field(' in s, output.splitlines())
         self.assertEqual(len(fields), 2)
@@ -60,7 +60,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = 'django.xtarget'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         null_true = filter(lambda s: 'null = True' in s, output.splitlines())
         null_false = filter(lambda s: 'null = False' in s, output.splitlines())
diff --git a/lib/xos-genx/xos-genx-tests/test_field_graph.py b/lib/xos-genx/xos-genx-tests/test_field_graph.py
index f7f004c..38f77b7 100644
--- a/lib/xos-genx/xos-genx-tests/test_field_graph.py
+++ b/lib/xos-genx/xos-genx-tests/test_field_graph.py
@@ -17,7 +17,7 @@
 import unittest
 from xosgenx.jinja2_extensions import FieldNotFound
 from helpers import FakeArgs, OUTPUT_DIR, XProtoTestHelpers
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 
 class XProtoFieldGraphTest(unittest.TestCase):
     def test_field_graph(self):
@@ -46,7 +46,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = target
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         output =  eval(output)
         self.assertIn({'A','B','C'}, output)
         self.assertIn({'openflow_id','name'}, output)
@@ -80,10 +80,10 @@
             args = FakeArgs()
             args.inputs = xproto
             args.target = target
-            output = XOSGenerator.generate(args)
+            output = XOSProcessor.process(args)
 
         # The following call generates some output, which should disappear
-        # when Matteo merges his refactoring of XOSGenerator.
+        # when Matteo merges his refactoring of XOSProcessor.
         self.assertRaises(FieldNotFound, generate)
 
 if __name__ == '__main__':
diff --git a/lib/xos-genx/xos-genx-tests/test_general_security.py b/lib/xos-genx/xos-genx-tests/test_general_security.py
index b571294..8744a6c 100644
--- a/lib/xos-genx/xos-genx-tests/test_general_security.py
+++ b/lib/xos-genx/xos-genx-tests/test_general_security.py
@@ -15,7 +15,7 @@
 
 
 import unittest
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 from helpers import FakeArgs, XProtoTestHelpers
 
 """The function below is for eliminating warnings arising due to the missing output_security_check,
@@ -46,7 +46,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         exec(output) # This loads the generated function, which should look like this:
 
@@ -69,7 +69,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         exec(output) # This loads the generated function, which should look like this:
 
@@ -97,7 +97,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         exec(output,globals()) # This loads the generated function, which should look like this:
 
@@ -135,7 +135,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         exec(output,globals()) # This loads the generated function, which should look like this:
 
@@ -171,7 +171,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         exec(output) # This loads the generated function, which should look like this:
 
         """
@@ -202,7 +202,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         exec(output) # This loads the generated function, which should look like this:
 
         """
@@ -221,7 +221,7 @@
 	args = FakeArgs()
         args.inputs = xproto
         args.target = self.target
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         exec(output) # This loads the generated function, which should look like this:
 
         """
@@ -244,7 +244,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         """
         def output_security_check(obj, ctx):
             i2 = Credential.objects.filter((~ Q(obj_id=obj_id)))[0]
diff --git a/lib/xos-genx/xos-genx-tests/test_general_validation.py b/lib/xos-genx/xos-genx-tests/test_general_validation.py
index fbed567..0fc0092 100644
--- a/lib/xos-genx/xos-genx-tests/test_general_validation.py
+++ b/lib/xos-genx/xos-genx-tests/test_general_validation.py
@@ -15,7 +15,7 @@
 
 
 import unittest
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 from helpers import FakeArgs, XProtoTestHelpers
 import pdb
 
@@ -47,7 +47,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         exec(output) # This loads the generated function, which should look like this:
 
@@ -71,7 +71,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         exec(output) # This loads the generated function, which should look like this:
 
@@ -101,7 +101,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         exec(output) # This loads the generated function, which should look like this:
 
@@ -131,7 +131,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         exec(output) # This loads the generated function, which should look like this:
 
         """
@@ -162,7 +162,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         exec(output) # This loads the generated function, which should look like this:
 
         """
@@ -182,7 +182,7 @@
 	args = FakeArgs()
         args.inputs = xproto
         args.target = self.target
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         exec(output) # This loads the generated function, which should look like this:
 
         """
@@ -207,7 +207,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         exec(output,globals()) # This loads the generated function, which should look like this:
 
@@ -244,7 +244,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         """
         def policy_output_enforcer(obj, ctx):
diff --git a/lib/xos-genx/xos-genx-tests/test_generator.py b/lib/xos-genx/xos-genx-tests/test_generator.py
index f59bbfd..9b1a44a 100644
--- a/lib/xos-genx/xos-genx-tests/test_generator.py
+++ b/lib/xos-genx/xos-genx-tests/test_generator.py
@@ -17,7 +17,7 @@
 import unittest
 import os
 from helpers import FakeArgs, OUTPUT_DIR
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 
 TEST_EXPECTED_OUTPUT = """
     name: XOSModel
@@ -39,7 +39,7 @@
 
 TEST_ATTICS = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/attics/")
 
-class XOSGeneratorTest(unittest.TestCase):
+class XOSProcessorTest(unittest.TestCase):
     """
     Testing the XOS Generative Toolchain
     """
@@ -58,7 +58,7 @@
         args = FakeArgs()
         args.files = [TEST_XPROTO]
         args.target = TEST_TARGET
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertEqual(output, TEST_EXPECTED_OUTPUT)
 
     def test_generator_custom_target_from_inputs(self):
@@ -68,7 +68,7 @@
         args = FakeArgs()
         args.inputs = open(TEST_XPROTO).read()
         args.target = TEST_TARGET
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertEqual(output, TEST_EXPECTED_OUTPUT)
 
     def test_django_with_attic(self):
@@ -82,7 +82,7 @@
         args.output = OUTPUT_DIR
         args.dest_extension = 'py'
         args.write_to_file = 'model'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         # xosmodel has custom header attic
         self.assertIn('from xosmodel_header import *', output['XOSModel'])
@@ -113,7 +113,7 @@
         args.output = OUTPUT_DIR
         args.dest_extension = 'py'
         args.write_to_file = 'model'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         # verify files
         xosmodel = OUTPUT_DIR + '/xosmodel.py'
@@ -138,7 +138,7 @@
         args.output = OUTPUT_DIR
         args.dest_extension = 'txt'
         args.write_to_file = 'model'
-        XOSGenerator.generate(args)
+        XOSProcessor.process(args)
 
         generated_files = [f for f in os.listdir(OUTPUT_DIR) if not f.startswith('.')]
         self.assertEqual(len(generated_files), 2)
@@ -158,7 +158,7 @@
         args.target = SPLIT_TARGET
         args.output = OUTPUT_DIR
         args.write_to_file = 'target'
-        XOSGenerator.generate(args)
+        XOSProcessor.process(args)
 
         generated_files = [f for f in os.listdir(OUTPUT_DIR) if not f.startswith('.')]
         self.assertEqual(len(generated_files), 2)
@@ -176,7 +176,7 @@
         args.output = OUTPUT_DIR
         args.dest_extension = 'py'
         args.write_to_file = 'model'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         # should not print a file if options.skip_django = True
         file = OUTPUT_DIR + '/user.py'
@@ -188,7 +188,7 @@
         args.target = 'service.xtarget'
         args.output = OUTPUT_DIR
         args.write_to_file = 'target'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         model = OUTPUT_DIR + '/models.py'
         self.assertTrue(os.path.isfile(model))
diff --git a/lib/xos-genx/xos-genx-tests/test_graph.py b/lib/xos-genx/xos-genx-tests/test_graph.py
index 48978e9..cda36d0 100644
--- a/lib/xos-genx/xos-genx-tests/test_graph.py
+++ b/lib/xos-genx/xos-genx-tests/test_graph.py
@@ -15,7 +15,7 @@
 
 
 import unittest
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 from helpers import FakeArgs, XProtoTestHelpers
 
 class XProtoGraphTests(unittest.TestCase):
@@ -115,7 +115,7 @@
         args = FakeArgs()
         args.inputs = proto
         args.target = target
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         num_semis = output.count(';')
         self.assertGreater(num_semis, 3) # 3 is the number of links, each of which contains at least one field
 
@@ -216,7 +216,7 @@
         args = FakeArgs()
         args.inputs = proto
         args.target = xtarget
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         num_semis = output.count(';')
         self.assertGreater(num_semis, 3)
@@ -308,7 +308,7 @@
         args = FakeArgs()
         args.inputs = proto
         args.target = xtarget
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn('easter_egg', output)
 
 if __name__ == '__main__':
diff --git a/lib/xos-genx/xos-genx-tests/test_package.py b/lib/xos-genx/xos-genx-tests/test_package.py
index 127fc07..373a818 100644
--- a/lib/xos-genx/xos-genx-tests/test_package.py
+++ b/lib/xos-genx/xos-genx-tests/test_package.py
@@ -16,7 +16,7 @@
 
 import unittest
 import os
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 from helpers import FakeArgs, XProtoTestHelpers
 
 class XProtoPackageTest(unittest.TestCase):
@@ -46,7 +46,7 @@
         args.inputs = xproto
         args.target = target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         self.assertIn('Port,xos.core,xos.core.Port', output)
 
@@ -162,7 +162,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = target
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         self.assertIn('numberCores', output) # Instance showed up via cross-package call
         self.assertIn('ip;', output) # Network showed up via cross-package call
@@ -223,7 +223,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = target
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         self.assertIn('xos_created', output)
 
@@ -324,7 +324,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = target
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         self.assertIn('easter_egg', output)
 
@@ -430,7 +430,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = target
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         self.assertEqual(output.count('firstapp'), 2)
         self.assertEqual(output.count('networkapp'), 2)
diff --git a/lib/xos-genx/xos-genx-tests/test_policy.py b/lib/xos-genx/xos-genx-tests/test_policy.py
index 3ff700b..9e77976 100644
--- a/lib/xos-genx/xos-genx-tests/test_policy.py
+++ b/lib/xos-genx/xos-genx-tests/test_policy.py
@@ -15,7 +15,7 @@
 
 
 import unittest
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 from helpers import FakeArgs, XProtoTestHelpers
 import pdb
 
@@ -41,7 +41,7 @@
         args.inputs = xproto
         args.target = target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn("true_policy", output)
 
     def test_constant(self):
@@ -56,7 +56,7 @@
         args.inputs = xproto
         args.target = target
 
-        output = XOSGenerator.generate(args).replace('t','T')
+        output = XOSProcessor.process(args).replace('t','T')
         self.assertTrue(eval(output)) 
 
     def test_function_term(self):
@@ -70,7 +70,7 @@
         args.inputs = xproto
         args.target = target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
        
         slice = FakeArgs()
         slice.user = FakeArgs()
@@ -90,7 +90,7 @@
         args.inputs = xproto
         args.target = target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
        
         slice = FakeArgs()
         slice.user = FakeArgs()
@@ -110,7 +110,7 @@
         args.inputs = xproto
         args.target = target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
        
         slice = FakeArgs()
         slice.user = FakeArgs()
@@ -130,7 +130,7 @@
         args.inputs = xproto
         args.target = target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
        
         slice = FakeArgs()
         slice.user = FakeArgs()
@@ -150,7 +150,7 @@
         args.inputs = xproto
         args.target = target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
        
         slice = FakeArgs()
         slice.user = 'twin'
@@ -172,7 +172,7 @@
         args.inputs = xproto
         args.target = target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         slice = FakeArgs()
         slice.is_admin = False
@@ -194,7 +194,7 @@
         args.inputs = xproto
         args.target = target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         slice = FakeArgs()
         slice.is_admin = False
@@ -218,7 +218,7 @@
         args.inputs = xproto
         args.target = target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         
         Privilege = FakeArgs()
         Privilege.object_id = 1
@@ -243,7 +243,7 @@
         args.inputs = xproto
         args.target = target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         
         (op, operands), = eval(output).items()
 
@@ -263,7 +263,7 @@
         args.target = target
 
         with self.assertRaises(Exception):
-            output = XOSGenerator.generate(args)
+            output = XOSProcessor.process(args)
         
 
     def test_forall(self):
@@ -279,7 +279,7 @@
         args.inputs = xproto
         args.target = target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         (op, operands), = eval(output).items()
 
         self.assertEqual(op,'forall')
diff --git a/lib/xos-genx/xos-genx-tests/test_pure_proto.py b/lib/xos-genx/xos-genx-tests/test_pure_proto.py
index 511682e..45cb6ed 100644
--- a/lib/xos-genx/xos-genx-tests/test_pure_proto.py
+++ b/lib/xos-genx/xos-genx-tests/test_pure_proto.py
@@ -16,7 +16,7 @@
 
 
 import unittest
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 from helpers import FakeArgs, XProtoTestHelpers
 
 # Generate from xproto, then generate from equivalent proto
@@ -86,7 +86,7 @@
 		args_xproto = FakeArgs()
 		args_xproto.inputs = xproto
 		args_xproto.target = target
-		xproto_gen = XOSGenerator.generate(args_xproto)
+		xproto_gen = XOSProcessor.process(args_xproto)
 
 		count1 = len(xproto_gen.split('\n'))
 
@@ -94,7 +94,7 @@
 		args_proto.inputs = proto
 		args_proto.target = target
 		args_proto.rev = True
-		proto_gen = XOSGenerator.generate(args_proto)
+		proto_gen = XOSProcessor.process(args_proto)
 		count2 = len(proto_gen.split('\n'))
 
 		self.assertEqual(count1, count2)
@@ -117,13 +117,13 @@
 		args_xproto = FakeArgs()
 		args_xproto.inputs = xproto
 		args_xproto.target = target
-		xproto_gen = XOSGenerator.generate(args_xproto)
+		xproto_gen = XOSProcessor.process(args_xproto)
 
 		args_proto = FakeArgs()
 		args_proto.inputs = proto
 		args_proto.target = target
 		args_proto.rev = True
-		proto_gen = XOSGenerator.generate(args_proto)
+		proto_gen = XOSProcessor.process(args_proto)
 
 		self.assertEqual(proto_gen, xproto_gen)
 
diff --git a/lib/xos-genx/xos-genx-tests/test_rlinks.py b/lib/xos-genx/xos-genx-tests/test_rlinks.py
index b195249..ba025ab 100644
--- a/lib/xos-genx/xos-genx-tests/test_rlinks.py
+++ b/lib/xos-genx/xos-genx-tests/test_rlinks.py
@@ -15,7 +15,7 @@
 
 
 import unittest
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 from helpers import FakeArgs, XProtoTestHelpers
 
 class XProtoRlinkTests(unittest.TestCase):
@@ -56,7 +56,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = target
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn("'src_port': 'device_ports'", output)
         self.assertIn("'src_port': 'ports'", output)
 
diff --git a/lib/xos-genx/xos-genx-tests/test_swagger.py b/lib/xos-genx/xos-genx-tests/test_swagger.py
index f87f47a..8107870 100644
--- a/lib/xos-genx/xos-genx-tests/test_swagger.py
+++ b/lib/xos-genx/xos-genx-tests/test_swagger.py
@@ -17,13 +17,13 @@
 import unittest
 
 import yaml
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 from helpers import FakeArgs, OUTPUT_DIR
 
 class Args:
     pass
 
-class XOSGeneratorTest(unittest.TestCase):
+class XOSProcessorTest(unittest.TestCase):
 
     def test_swagger_target(self):
         """
@@ -63,7 +63,7 @@
         args.write_to_file = "single"
         args.dest_file = "swagger.yaml"
         args.quiet = False
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn("/xosapi/v1/core/instances/:", output)
         self.assertIn("/xosapi/v1/core/instances/{id}:", output)
         self.assertIn("Instance:", output)
diff --git a/lib/xos-genx/xos-genx-tests/test_tosca.py b/lib/xos-genx/xos-genx-tests/test_tosca.py
index f829273..6807028 100644
--- a/lib/xos-genx/xos-genx-tests/test_tosca.py
+++ b/lib/xos-genx/xos-genx-tests/test_tosca.py
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 import unittest
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 from helpers import FakeArgs, XProtoTestHelpers
 
 
@@ -46,7 +46,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = self.target_tosca_type
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn('string', output)
         self.assertIn('boolean', output)
         self.assertIn('integer', output)
@@ -77,7 +77,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = self.target_tosca_keys
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn('name', output)
 
     def test_xproto_fields_to_tosca_keys_custom(self):
@@ -98,7 +98,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = self.target_tosca_keys
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertNotIn('name', output)
         self.assertIn('key_1', output)
         self.assertIn('key_2', output)
@@ -120,7 +120,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = self.target_tosca_keys
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertNotIn('name', output)
         self.assertIn('provider_service_instance_id', output)
 
@@ -147,7 +147,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = self.target_tosca_keys
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn("['name', ['key_4', 'key_3'], ['key_1', 'key_2']]", output)
 
         xproto = \
@@ -166,5 +166,5 @@
             """
 
         args.inputs = xproto
-        output = XOSGenerator.generate(args)
-        self.assertIn("['name', ['key_1_id', 'key_3_id', 'key_2_id']]", output)
\ No newline at end of file
+        output = XOSProcessor.process(args)
+        self.assertIn("['name', ['key_1_id', 'key_3_id', 'key_2_id']]", output)
diff --git a/lib/xos-genx/xos-genx-tests/test_translator.py b/lib/xos-genx/xos-genx-tests/test_translator.py
index 48c1a81..2f8cc8a 100644
--- a/lib/xos-genx/xos-genx-tests/test_translator.py
+++ b/lib/xos-genx/xos-genx-tests/test_translator.py
@@ -16,7 +16,7 @@
 
 import unittest
 import os
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 from helpers import FakeArgs
 import yaml
 
@@ -37,7 +37,7 @@
         args = FakeArgs()
         args.files = [VROUTER_XPROTO]
         args.target = 'proto.xtarget'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertEqual(output, PROTO_EXPECTED_OUTPUT)
 
     def test_yaml_generator(self):
@@ -122,7 +122,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = 'modeldefs.xtarget'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         yaml_ir = yaml.load(output)
         self.assertEqual(len(yaml_ir['items']), 4)
@@ -145,7 +145,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = 'modeldefs.xtarget'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         yaml_ir = yaml.load(output)
         self.assertEqual(len(yaml_ir['items']), 1)
         self.assertIn('Bar', output)
@@ -164,7 +164,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = 'modeldefs.xtarget'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         yaml_ir = yaml.load(output)
         self.assertEqual(len(yaml_ir['items']), 1)
         self.assertIn('name', output)
@@ -184,7 +184,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = 'modeldefs.xtarget'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn("options:", output)
         self.assertIn(" {'id': 'container_vm', 'label': 'Container In VM'}", output)
 
@@ -201,7 +201,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = 'modeldefs.xtarget'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertNotIn("options:", output)
 
     def test_default_value_in_modeldef(self):
@@ -221,7 +221,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = 'modeldefs.xtarget'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn('default: "bar"', output)
         self.assertIn('default: "false"', output)
         self.assertIn('default: "true"', output)
@@ -241,7 +241,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = 'modeldefs.xtarget'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertNotIn('default:', output)
 
     def test_one_to_many_in_modeldef(self):
@@ -262,7 +262,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = 'modeldefs.xtarget'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         # Service deps model
         self.assertIn('{model: Service, type: manytoone, on_field: provider_service}', output)
         self.assertIn('{model: Service, type: manytoone, on_field: provider_service}', output)
@@ -290,7 +290,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = 'modeldefs.xtarget'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn('description: "This is the Foo model"', output)
 
     def test_model_verbose_name(self):
@@ -312,7 +312,7 @@
         args = FakeArgs()
         args.inputs = xproto
         args.target = 'modeldefs.xtarget'
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         self.assertIn('verbose_name: "Verbose Foo Name"', output)
 
 if __name__ == '__main__':
diff --git a/lib/xos-genx/xos-genx-tests/test_xos_security.py b/lib/xos-genx/xos-genx-tests/test_xos_security.py
index a07bc7b..2c704ac 100644
--- a/lib/xos-genx/xos-genx-tests/test_xos_security.py
+++ b/lib/xos-genx/xos-genx-tests/test_xos_security.py
@@ -15,7 +15,7 @@
 
 
 import unittest
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 from helpers import FakeArgs, XProtoTestHelpers
 import pdb
 import mock
@@ -48,7 +48,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         exec(output) # This loads the generated function, which should look like this:
 
@@ -87,7 +87,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         exec(output) # This loads the generated function, which should look like this:
 
         """
@@ -135,7 +135,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         exec(output) # This loads the generated function, which should look like this:
 
@@ -181,7 +181,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         exec(output) # This loads the generated function, which should look like this:
 
diff --git a/lib/xos-genx/xos-genx-tests/test_xos_validation.py b/lib/xos-genx/xos-genx-tests/test_xos_validation.py
index 69dafc5..f38f65b 100644
--- a/lib/xos-genx/xos-genx-tests/test_xos_validation.py
+++ b/lib/xos-genx/xos-genx-tests/test_xos_validation.py
@@ -15,7 +15,7 @@
 
 
 import unittest
-from xosgenx.generator import XOSGenerator
+from xosgenx.generator import XOSProcessor
 from helpers import FakeArgs, XProtoTestHelpers
 
 """The function below is for eliminating warnings arising due to the missing policy_output_validator,
@@ -42,7 +42,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         obj = FakeArgs()
         obj.isolation = 'container'
@@ -72,7 +72,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         obj = FakeArgs()
         obj.isolation = 'container'
@@ -103,7 +103,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         exec(output) # This loads the generated function, which should look like this:
 
@@ -133,7 +133,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         exec(output) # This loads the generated function, which should look like this:
 
         """
@@ -164,7 +164,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         exec(output) # This loads the generated function, which should look like this:
 
         """
@@ -184,7 +184,7 @@
 	args = FakeArgs()
         args.inputs = xproto
         args.target = self.target
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
         exec(output) # This loads the generated function, which should look like this:
 
         """
@@ -209,7 +209,7 @@
         args.inputs = xproto
         args.target = self.target
 
-        output = XOSGenerator.generate(args)
+        output = XOSProcessor.process(args)
 
         """
         def policy_output_enforcer(obj, ctx):
diff --git a/lib/xos-genx/xosgenx/checkers/model_policy.xchecker b/lib/xos-genx/xosgenx/checkers/model_policy.xchecker
new file mode 100644
index 0000000..abbdd0d
--- /dev/null
+++ b/lib/xos-genx/xosgenx/checkers/model_policy.xchecker
@@ -0,0 +1,5 @@
+{% for m in proto.messages %}
+{% if not m.options.no_policy %}
+{{ xproto_check_policy(m) }}
+{% endif %}
+{% endfor %}
diff --git a/lib/xos-genx/xosgenx/checkers/service_model_base.xchecker b/lib/xos-genx/xosgenx/checkers/service_model_base.xchecker
new file mode 100644
index 0000000..85881f0
--- /dev/null
+++ b/lib/xos-genx/xosgenx/checkers/service_model_base.xchecker
@@ -0,0 +1,32 @@
+{# Using regular variables has scoping issues. #}
+{# See: https://stackoverflow.com/questions/7537439/how-to-increment-a-variable-on-a-for-loop-in-jinja-template/7537466 #}
+{% set counter = {
+    'num_service_models': 0,
+    'num_service_instance_models': 0,
+    'num_orphaned_models': 0,
+    } %}
+{% macro increment(key) %}
+    {% if counter.update({key: counter[key] + 1}) %} {% endif %}
+{% endmacro %}
+{% for m in proto.messages %}
+{% set matched = False %}
+{% set base_names = m.bases | map(attribute='name') | list %}
+{% if 'Service' in base_names %}
+{{ increment('num_service_models') }}
+{% set matched = True %}
+{% endif %}
+{% if not matched and 'ServiceInstance' in base_names or 'Tenant' in base_names or 'TenantWithContainer' in base_names %}
+{{ increment('num_service_instance_models') }}
+{% set matched = True %}
+{% endif %}
+{% if not matched and 'XOSBase' not in base_names %}
+501 Model does not have a parent - {{ m.name }}
+{% endif %}
+{% endfor %}
+{% if counter.num_service_models !=1 %}
+502 {{ counter.num_service_models }} Service models instead of 1
+{% elif counter.num_service_instance_models !=1 %}
+503 {{ counter.num_service_instance_models }} ServiceInstance models instead of 1
+{% else %}
+200 OK
+{% endif %}
diff --git a/lib/xos-genx/xosgenx/checkers/service_options.xchecker b/lib/xos-genx/xosgenx/checkers/service_options.xchecker
new file mode 100644
index 0000000..383cdbd
--- /dev/null
+++ b/lib/xos-genx/xosgenx/checkers/service_options.xchecker
@@ -0,0 +1,12 @@
+{% set required_options = ['name','verbose_name','app_label'] %}
+
+{% for m in proto.messages %}
+{% for o in required_options %}
+{% if not options[o] and not m.options[o] %}
+504 Required option {{ o }} is missing from model {{ m.name }}
+{% endif %}
+
+{% set required_field_options = ['tosca_key'] %}
+
+{% endfor %}
+{% endfor %}
diff --git a/lib/xos-genx/xosgenx/checkers/syncstep.xchecker b/lib/xos-genx/xosgenx/checkers/syncstep.xchecker
new file mode 100644
index 0000000..836a2c2
--- /dev/null
+++ b/lib/xos-genx/xosgenx/checkers/syncstep.xchecker
@@ -0,0 +1,5 @@
+{% for m in proto.messages %}
+{% if not m.options.no_sync %}
+{{ xproto_check_synchronizer(m) }}
+{% endif %}
+{% endfor %}
diff --git a/lib/xos-genx/xosgenx/generator.py b/lib/xos-genx/xosgenx/generator.py
index 650e688..33e96b1 100755
--- a/lib/xos-genx/xosgenx/generator.py
+++ b/lib/xos-genx/xosgenx/generator.py
@@ -26,7 +26,7 @@
 loader = jinja2.PackageLoader(__name__, 'templates')
 env = jinja2.Environment(loader=loader)
 
-class XOSGenerator:
+class XOSProcessor:
 
     @staticmethod
     def _read_input_from_files(files):
@@ -78,8 +78,8 @@
     @staticmethod
     def _load_jinja2_extensions(os_template_env, attic):
 
-        os_template_env.globals['include_file'] = XOSGenerator._include_file(attic)  # Generates a function
-        os_template_env.globals['file_exists'] = XOSGenerator._file_exists(attic)  # Generates a function
+        os_template_env.globals['include_file'] = XOSProcessor._include_file(attic)  # Generates a function
+        os_template_env.globals['file_exists'] = XOSProcessor._file_exists(attic)  # Generates a function
 
         os_template_env.filters['yaml'] = yaml.dump
         for f in dir(jinja2_extensions):
@@ -168,8 +168,7 @@
         return ne_pointer
 
     @staticmethod
-    def generate(args):
-
+    def process(args, operator = None):
         # Setting defaults
         if not hasattr(args, 'attic'):
             args.attic = None
@@ -196,19 +195,25 @@
             raise Exception("[XosGenX] The output dir must be a directory!")
 
         if hasattr(args, 'files'):
-            inputs = XOSGenerator._read_input_from_files(args.files)
+            inputs = XOSProcessor._read_input_from_files(args.files)
         elif hasattr(args, 'inputs'):
             inputs = args.inputs
         else:
             raise Exception("[XosGenX] No inputs provided!")
 
-        template_path = XOSGenerator._get_template(args.target)
+        if not operator:
+            operator = args.target
+            template_path = XOSProcessor._get_template(operator)
+        else:
+            template_path = operator
+
+
         [template_folder, template_name] = os.path.split(template_path)
         os_template_loader = jinja2.FileSystemLoader(searchpath=[template_folder])
         os_template_env = jinja2.Environment(loader=os_template_loader)
-        os_template_env = XOSGenerator._load_jinja2_extensions(os_template_env, args.attic)
+        os_template_env = XOSProcessor._load_jinja2_extensions(os_template_env, args.attic)
         template = os_template_env.get_template(template_name)
-        context = XOSGenerator._add_context(args)
+        context = XOSProcessor._add_context(args)
 
         parser = plyxproto.ProtobufAnalyzer()
         try:
@@ -216,7 +221,7 @@
         except plyxproto.ParsingError, e:
             line, start, end = e.error_range
 
-            ptr = XOSGenerator._find_last_nonempty_line(inputs, start)
+            ptr = XOSProcessor._find_last_nonempty_line(inputs, start)
 
             if start == 0:
                 beginning = ''
@@ -236,14 +241,14 @@
             exit(1)
 
 
-        v = XOSGenerator._attach_parser(ast, args)
+        v = XOSProcessor._attach_parser(ast, args)
 
         if args.output is not None and args.write_to_file == "model":
             rendered = {}
             for i, model in enumerate(v.models):
                 models = {}
                 models[model] = v.models[model]
-                messages = [XOSGenerator._find_message_by_model_name(v.messages, model)]
+                messages = [XOSProcessor._find_message_by_model_name(v.messages, model)]
 
                 rendered[model] = template.render(
                     {"proto":
@@ -257,7 +262,7 @@
                         "options": v.options
                     }
                 )
-            XOSGenerator._write_file_per_model(rendered, args.output, args.dest_extension, args.quiet)
+            XOSProcessor._write_file_per_model(rendered, args.output, args.dest_extension, args.quiet)
         else:
             rendered = template.render(
                 {"proto":
@@ -272,8 +277,8 @@
                 }
             )
             if args.output is not None and args.write_to_file == "target":
-                XOSGenerator._write_split_target(rendered, args.output, args.quiet)
+                XOSProcessor._write_split_target(rendered, args.output, args.quiet)
             elif args.output is not None and args.write_to_file == "single":
-                XOSGenerator._write_single_file(rendered, args.output, args.dest_file, args.quiet)
+                XOSProcessor._write_single_file(rendered, args.output, args.dest_file, args.quiet)
 
         return rendered
diff --git a/lib/xos-genx/xosgenx/jinja2_extensions/__init__.py b/lib/xos-genx/xosgenx/jinja2_extensions/__init__.py
index a81dcb6..859594c 100644
--- a/lib/xos-genx/xosgenx/jinja2_extensions/__init__.py
+++ b/lib/xos-genx/xosgenx/jinja2_extensions/__init__.py
@@ -19,3 +19,4 @@
 from .fol2 import *
 from .gui import *
 from .tosca import *
+from .checklib import *
diff --git a/lib/xos-genx/xosgenx/jinja2_extensions/base.py b/lib/xos-genx/xosgenx/jinja2_extensions/base.py
index 5943e66..f8224b2 100644
--- a/lib/xos-genx/xosgenx/jinja2_extensions/base.py
+++ b/lib/xos-genx/xosgenx/jinja2_extensions/base.py
@@ -271,4 +271,4 @@
 
         return list
     else:
-        return False
\ No newline at end of file
+        return False
diff --git a/lib/xos-genx/xosgenx/jinja2_extensions/checklib.py b/lib/xos-genx/xosgenx/jinja2_extensions/checklib.py
new file mode 100644
index 0000000..a34fd7f
--- /dev/null
+++ b/lib/xos-genx/xosgenx/jinja2_extensions/checklib.py
@@ -0,0 +1,61 @@
+import ast
+
+def xproto_check_synchronizer(m):
+    try:
+        sync_step_path = 'synchronizer/steps/sync_%s.py'%m['name'].lower()
+        sync_step = open(sync_step_path).read()
+    except IOError:
+        return '510 Model needs a sync step %s'%sync_step_path
+
+    try:
+        sync_step_ast = ast.parse(sync_step)
+    except SyntaxError:
+        return '511 Could not parse sync step %s'%sync_step_path
+
+    classes = filter(lambda x:isinstance(x, ast.ClassDef), sync_step_ast.body)
+    found_sync_step_class = False
+
+    for c in classes:
+        base_names = [v.id for v in c.bases]
+        if 'SyncStep' in base_names or 'SyncInstanceUsingAnsible' in base_names:
+            attributes = filter(lambda x:isinstance(x, ast.Assign), c.body)
+            for a in attributes:
+                target_names = [t.id for t in a.targets]
+                values = a.value.elts if isinstance(a.value, ast.List) else [a.value]
+                value_names = [v.id for v in values]
+
+                if 'observes' in target_names and m['name'] in value_names:
+                    found_sync_step_class = True
+                    break
+
+    if not found_sync_step_class:
+        return '512 Synchronizer needs a sync step class with an observes field containing %s'%m['name']
+    else:
+        return '200 OK'
+
+
+def xproto_check_policy(m):
+    try:
+        model_policy_path = 'synchronizer/model_policies/model_policy_%s.py'%m['name'].lower()
+        model_policy = open(model_policy_path).read()
+    except IOError:
+        return '510 Model needs a model policy %s'%model_policy_path
+
+    try:
+        model_policy_ast = ast.parse(model_policy)
+    except SyntaxError:
+        return '511 Could not parse sync step %s'%model_policy_path
+
+    classes = filter(lambda x:isinstance(x, ast.ClassDef), model_policy_ast.body)
+    found_model_policy_class = False
+    for c in classes:
+        base_names = [v.id for v in c.bases]
+        if 'Policy' in base_names or 'TenantWithContainerPolicy' in base_names:
+            found_model_policy_class = True
+            break
+
+    if not found_model_policy_class:
+        return '513 Synchronizer needs a model policy class'
+    else:
+        return '200 OK'
+
diff --git a/lib/xos-genx/xosgenx/jinja2_extensions/gui.py b/lib/xos-genx/xosgenx/jinja2_extensions/gui.py
index 7c65388..50bcf0e 100644
--- a/lib/xos-genx/xosgenx/jinja2_extensions/gui.py
+++ b/lib/xos-genx/xosgenx/jinja2_extensions/gui.py
@@ -124,4 +124,4 @@
             outlist.append('- {model: %s, type: %s, on_field: %s}\n' % (l['peer']['name'], l['link_type'], on_field))
         seen.append(l['peer'])
 
-    return outlist
\ No newline at end of file
+    return outlist
diff --git a/lib/xos-genx/xosgenx/jinja2_extensions/tosca.py b/lib/xos-genx/xosgenx/jinja2_extensions/tosca.py
index 51cd2bb..9e3b4a8 100644
--- a/lib/xos-genx/xosgenx/jinja2_extensions/tosca.py
+++ b/lib/xos-genx/xosgenx/jinja2_extensions/tosca.py
@@ -62,4 +62,4 @@
 
         keys.append(of)
 
-    return keys
\ No newline at end of file
+    return keys
diff --git a/lib/xos-genx/xosgenx/xosgen.py b/lib/xos-genx/xosgenx/xosgen.py
index 7893f22..fa734b5 100755
--- a/lib/xos-genx/xosgenx/xosgen.py
+++ b/lib/xos-genx/xosgenx/xosgen.py
@@ -21,7 +21,6 @@
 
 parse = argparse.ArgumentParser(description='XOS Generative Toolchain')
 parse.add_argument('--rev', dest='rev', action='store_true',default=False, help='Convert proto to xproto')
-parse.add_argument('--target', dest='target', action='store',default=None, help='Output format, corresponding to <output>.yaml file', required=True)
 parse.add_argument('--output', dest='output', action='store',default=None, help='Destination dir')
 parse.add_argument('--attic', dest='attic', action='store',default=None, help='The location at which static files are stored')
 parse.add_argument('--kvpairs', dest='kv', action='store',default=None, help='Key value pairs to make available to the target')
@@ -31,41 +30,67 @@
 group.add_argument('--dest-file', dest='dest_file', action='store',default=None, help='Output file name (if write-to-file is set to single)')
 group.add_argument('--dest-extension', dest='dest_extension', action='store',default=None, help='Output file extension (if write-to-file is set to single)')
 
+group = parse.add_mutually_exclusive_group(required=True)
+group.add_argument('--target', dest='target', action='store',default=None, help='Output format, corresponding to <output>.yaml file')
+group.add_argument('--checkers', dest='checkers', action='store', default=None, help='Comma-separated list of static checkers')
+
 parse.add_argument('files', metavar='<input file>', nargs='+', action='store', help='xproto files to compile')
 
+CHECK = 1
+GEN = 2
+
 class XosGen:
 
     @staticmethod
     def init(args=None):
-
         if not args:
             args = parse.parse_args()
 
         args.quiet = False
 
-        # convert output to absolute path
-        if args.output is not None and not os.path.isabs(args.output):
-            args.output = os.path.abspath(os.getcwd() + '/' + args.output)
-        if not '/' in args.target:
-            # if the target is not a path, it refer to a library included one
-            args.target = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/targets/" + args.target)
-        if not os.path.isabs(args.target):
-            args.target = os.path.abspath(os.getcwd() + '/' + args.target)
+        if args.target:
+            op = GEN
+            subdir = '/targets/'
+        elif args.checkers:
+            op = CHECK
+            subdir = '/checkers/'
+        else:
+            parse.error("At least one of --target and --checkers is required")
 
-        # check if there's a line that starts with +++ in the target
-        # if so, then the output file names are left to the target to decide
-        # also, if dest-file or dest-extension are supplied, then an error is generated.
-        plusplusplus = reduce(lambda acc, line: True if line.startswith('+++') else acc, open(args.target).read().splitlines(), False)
+        operators = args.checkers.split(',') if hasattr(args, 'checkers') and args.checkers else [args.target]
 
-        if plusplusplus and args.write_to_file != 'target':
-            parse.error('%s chooses the names of the files that it generates, you must set --write-to-file to "target"' % args.target)
+        for i in xrange(len(operators)):
+            if not '/' in operators[i]:
+                # if the target is not a path, it refer to a library included one
+                operators[i] = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + subdir + operators[i])
 
+            if not os.path.isabs(operators[i]):
+                operators[i] = os.path.abspath(os.getcwd() + '/' + operators[i])
 
-        if args.write_to_file != 'single' and (args.dest_file):
-            parse.error('--dest-file requires --write-to-file to be set to "single"')
+        if op == GEN:
+            # convert output to absolute path
+            if args.output is not None and not os.path.isabs(args.output):
+                args.output = os.path.abspath(os.getcwd() + '/' + args.output)
 
-        if args.write_to_file != 'model' and (args.dest_extension):
-            parse.error('--dest-extension requires --write-to-file to be set to "model"')
+            operator = operators[0]
+            
+            # check if there's a line that starts with +++ in the target
+            # if so, then the output file names are left to the target to decide
+            # also, if dest-file or dest-extension are supplied, then an error is generated.
+            plusplusplus = reduce(lambda acc, line: True if line.startswith('+++') else acc, open(operator).read().splitlines(), False)
+
+            if plusplusplus and args.write_to_file != 'target':
+                parse.error('%s chooses the names of the files that it generates, you must set --write-to-file to "target"' % operator)
+
+            if args.write_to_file != 'single' and (args.dest_file):
+                parse.error('--dest-file requires --write-to-file to be set to "single"')
+
+            if args.write_to_file != 'model' and (args.dest_extension):
+                parse.error('--dest-extension requires --write-to-file to be set to "model"')
+            
+        else:
+            if args.write_to_file or args.dest_extension:
+                parse.error('Checkers cannot write to files')
 
         inputs = []
 
@@ -74,9 +99,28 @@
                 inputs.append(os.path.abspath(os.getcwd() + '/' + fname))
             else:
                 inputs.append(fname)
+
         args.files = inputs
 
-        generated = XOSGenerator.generate(args)
+        if op==GEN:
+            generated = XOSProcessor.process(args, operators[0])
+            if not args.output and not args.write_to_file:
+                print generated
+        elif op==CHECK:
+            for o in operators:
+                verdict_str = XOSProcessor.process(args, o)
+                vlst = verdict_str.split('\n')
 
-        if not args.output and not args.write_to_file:
-            print generated
\ No newline at end of file
+                try:
+                    verdict = next(v for v in vlst if v.strip())
+                    status_code, status_string = verdict.split(' ', 1)
+                    status_code = int(status_code)
+                except:
+                    print "Checker %s returned mangled output" % o
+                    exit(1)
+
+                if status_code != 200:
+                    print '%s: %s - %s' % (o, status_code, status_string)
+                    exit(1)
+                else:
+                    print '%s: OK'%o