From 8042355dbce937f3fc9aee668ca1b377409010e1 Mon Sep 17 00:00:00 2001 From: Colin Dixon Date: Wed, 11 Feb 2015 08:58:39 -0800 Subject: [PATCH] Get parser runnable jar file to work with real TTPs * Change parser's main function to create a simple TTP and print it in JSON instead of just printing a string. * Created a utils module which provides tools for converting between TTPs and JSON/XML. * Refactored a lot of the functions from the ttp-model's tests to the util module. Change-Id: I667f120606217557711a0c7d778aea9f26146baf Signed-off-by: Colin Dixon --- .../org/opendaylight/ttp/parser/Main.java | 55 ++++++- pom.xml | 1 + ttp-model/pom.xml | 7 +- .../ttp/model/test/TTPYangModelTest.java | 141 ++--------------- utils/pom.xml | 51 ++++++ .../org/opendaylight/ttp/utils/TTPUtils.java | 146 ++++++++++++++++++ 6 files changed, 263 insertions(+), 138 deletions(-) create mode 100644 utils/pom.xml create mode 100644 utils/src/main/java/org/opendaylight/ttp/utils/TTPUtils.java diff --git a/parser/src/main/java/org/opendaylight/ttp/parser/Main.java b/parser/src/main/java/org/opendaylight/ttp/parser/Main.java index 1bc8367..5cb4388 100644 --- a/parser/src/main/java/org/opendaylight/ttp/parser/Main.java +++ b/parser/src/main/java/org/opendaylight/ttp/parser/Main.java @@ -1,10 +1,55 @@ package org.opendaylight.ttp.parser; -//import org.opendaylight.ttp.model.test.TTPYangModelTest; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; + +import javax.ws.rs.WebApplicationException; + +import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider; +import org.opendaylight.controller.sal.restconf.impl.StructuredData; +import org.opendaylight.ttp.utils.TTPUtils; +import org.opendaylight.yang.gen.v1.urn.onf.ttp.rev140711.table.type.pattern.properties.NDMMetadata; +import org.opendaylight.yang.gen.v1.urn.onf.ttp.rev140711.table.type.pattern.properties.NDMMetadataBuilder; +import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; public class Main { - public static void main(String args[]) { - //TTPYangModelTest.main(args); - System.out.println("Does this work?"); - } + public static void main(String args[]) throws WebApplicationException, IOException { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + SchemaContext schemaContext = TTPUtils.getSchemaContext(); + BindingIndependentMappingService mappingService = TTPUtils.getMappingService(schemaContext); + + String expectedJson = "{\"NDM_metadata\": {\"authority\": \"org.opennetworking.fawg\",\"type\": \"TTPv1\",\"name\": \"L2-L3-ACLs\",\"version\": \"1.0.0\",\"OF_protocol_version\": \"1.3.3\",\"doc\": [\"Example of a TTP supporting L2 (unicast, multicast, flooding), L3 (unicast only),\", \"and an ACL table.\"]}}"; + NDMMetadata NDMmeta = new NDMMetadataBuilder() + .setAuthority("org.opennetworking.fawg") + .setType("TTPv1") + .setName("L2-L3-ACLs") + .setVersion("1.0.0") + .setOFProtocolVersion("1.3.3") + .setDoc(Arrays + .asList("Example of a TTP supporting L2 (unicast, multicast, flooding), L3 (unicast only),", + "and an ACL table.")).build(); + + String jsonString = TTPUtils.jsonStringFromDataObject(NDMmeta, mappingService, schemaContext); + JsonParser jp = new JsonParser(); + JsonElement je = jp.parse(expectedJson); + String prettyExpectedJson = gson.toJson(je); + System.out.println("Generated JSON:\n" + jsonString); + System.out.println("Expected JSON:\n" + prettyExpectedJson); + + ByteArrayOutputStream s = new ByteArrayOutputStream(); + StructuredData sd = TTPUtils.structuredDataFromDataObject(NDMmeta, mappingService, + schemaContext); + // ignore all the nulls + StructuredDataToXmlProvider.INSTANCE.writeTo(sd, null, null, null, null, null, s); + System.out.println("Formatted XML From StructuredDataToXmlProvider:"); + String structuredDataXML = s.toString(); + System.out.println(structuredDataXML); + } } diff --git a/pom.xml b/pom.xml index f10faa7..b55d8ba 100644 --- a/pom.xml +++ b/pom.xml @@ -18,6 +18,7 @@ parser + utils ttp-model features distribution-karaf diff --git a/ttp-model/pom.xml b/ttp-model/pom.xml index 61cbafe..a6acf02 100644 --- a/ttp-model/pom.xml +++ b/ttp-model/pom.xml @@ -20,7 +20,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true @@ -174,9 +173,13 @@ org.skyscreamer jsonassert - 1.2.3 test + + org.opendaylight.ttp + utils + ${project.version} + diff --git a/ttp-model/src/test/java/org/opendaylight/ttp/model/test/TTPYangModelTest.java b/ttp-model/src/test/java/org/opendaylight/ttp/model/test/TTPYangModelTest.java index 1def985..223c238 100644 --- a/ttp-model/src/test/java/org/opendaylight/ttp/model/test/TTPYangModelTest.java +++ b/ttp-model/src/test/java/org/opendaylight/ttp/model/test/TTPYangModelTest.java @@ -24,6 +24,7 @@ import org.junit.Test; import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider; import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider; import org.opendaylight.controller.sal.restconf.impl.StructuredData; +import org.opendaylight.ttp.utils.TTPUtils; import org.opendaylight.yang.gen.v1.urn.onf.ttp.rev140711.MatchSetProperties.MatchType; import org.opendaylight.yang.gen.v1.urn.onf.ttp.rev140711.flow_mod.properties.InstructionSet; import org.opendaylight.yang.gen.v1.urn.onf.ttp.rev140711.flow_mod.properties.InstructionSetBuilder; @@ -131,22 +132,8 @@ public class TTPYangModelTest { @BeforeClass public static void oneTimeSetup() { - System.out.println("Building context"); - context = getSchemaContext(); - System.out.println("Context built"); - System.out.println("Building mapping service"); - mappingService = new RuntimeGeneratedMappingServiceImpl(ClassPool.getDefault()); - ((RuntimeGeneratedMappingServiceImpl)mappingService).onGlobalContextUpdated(context); - System.out.println("Mapping service built"); - } - - static final SchemaContext getSchemaContext() { - Iterable moduleInfos; - // TODO: make this load fewer things - moduleInfos = BindingReflections.loadModuleInfos(); - ModuleInfoBackedContext moduleContext = ModuleInfoBackedContext.create(); - moduleContext.addModuleInfos(moduleInfos); - return moduleContext.tryToCreateSchemaContext().get(); + context = TTPUtils.getSchemaContext(); + mappingService = TTPUtils.getMappingService(context); } /* @@ -174,7 +161,7 @@ public class TTPYangModelTest { * test NDM_metadata slug XML conversion via Document and Document writers */ System.out.println("Generating document"); - Document doc = documentFromDataObject(NDMmeta); + Document doc = documentFromDataObject(NDMmeta, mappingService); System.out.println("Generated document"); System.out.println("Formatted XML From Document:"); @@ -187,7 +174,7 @@ public class TTPYangModelTest { * test NDM_metadata slug XML conversion via StructuredDataToXmlProvider */ ByteArrayOutputStream s = new ByteArrayOutputStream(); - StructuredData sd = structuredDataFromDataObject(NDMmeta); + StructuredData sd = TTPUtils.structuredDataFromDataObject(NDMmeta, mappingService, context); // ignore all the nulls StructuredDataToXmlProvider.INSTANCE.writeTo(sd, null, null, null, null, null, s); System.out.println("Formatted XML From StructuredDataToXmlProvider:"); @@ -463,53 +450,12 @@ public class TTPYangModelTest { Parameters param2 = new ParametersBuilder().setDefault(new Default("RandomString")).setName("string").build(); System.out.println("Param1.default:\n "+param1.getDefault()+"\nParam2.default:\n "+param2.getDefault()); TableTypePattern ttp = new TableTypePatternBuilder().setParameters(Arrays.asList(param1, param2)).build(); - System.out.println("Schema: "+getSchemaNodeForDataObject(context, ttp)); - System.out.println("XXXYYY:\n"+jsonStringFromDataObject(ttp)); - } - - /** - * DON'T CALL THIS IN PRODUCTION CODE EVER!!! UNTIL IT IS FIXED! - *

- * Return the {@link DataSchemaNode} - * - * @param context - * @param d - * @deprecated - */ - public DataSchemaNode getSchemaNodeForDataObject(SchemaContext context, DataObject d) { - QName qn = BindingReflections.findQName(d.getClass()); - - Set allTheNodes = getAllTheNode(context); - - // TODO: create a map to make this faster!!!! - for ( DataSchemaNode dsn : allTheNodes ) { - if(dsn instanceof DataNodeContainer) { - allTheNodes.addAll(((DataNodeContainer)dsn).getChildNodes()); - } - if (dsn.getQName().equals(qn)) { - return dsn; - } - } - return null; - } - - public Set getAllTheNode(SchemaContext context) { - Set nodes = new HashSet(); - getAllTheNodesHelper(context, nodes); - return nodes; - } - - private void getAllTheNodesHelper(DataNodeContainer dcn, Set nodes) { - for ( DataSchemaNode dsn : dcn.getChildNodes() ) { - if (dsn instanceof DataNodeContainer){ - getAllTheNodesHelper((DataNodeContainer)dsn, nodes); - } - nodes.add(dsn); - } + System.out.println("Schema: "+TTPUtils.getSchemaNodeForDataObject(context, ttp)); + System.out.println("XXXYYY:\n"+TTPUtils.jsonStringFromDataObject(ttp, mappingService, context)); } private void assertConvertedJSONEquals(String expectedJson, DataObject data) throws Exception { - String jsonString = jsonStringFromDataObject(data); + String jsonString = TTPUtils.jsonStringFromDataObject(data, mappingService, context); JsonElement je = jp.parse(expectedJson); String prettyExpectedJson = gson.toJson(je); @@ -550,8 +496,8 @@ public class TTPYangModelTest { * @param data * @return */ - public Document documentFromDataObject(DataObject data) { - return documentFromCompositeNode(compositeNodeFromDataObject(data)); + public Document documentFromDataObject(DataObject data, BindingIndependentMappingService mappingService) { + return documentFromCompositeNode(TTPUtils.compositeNodeFromDataObject(data, mappingService)); } /** @@ -563,71 +509,4 @@ public class TTPYangModelTest { return XmlDocumentUtils.toDocument(compNode, XmlUtils.DEFAULT_XML_CODEC_PROVIDER); } - /** - * - * @param d - * @return - */ - public CompositeNode compositeNodeFromDataObject(DataObject d) { - return mappingService.toDataDom(d); - } - - /** - * - * @param compNode - * @return - */ -// private StructuredData structuredDataFromCompositeNode(CompositeNode compNode) { -// // Create structured data, the null is an unused mountpoint -// // final true/false is to turn on/off pretty printing -// DataSchemaNode NDM_metadata = null; -// //first solution -// NDM_metadata = getSchemaNodeForDataObject(context, null); -// //second solution -// ControllerContext controllerContext = ControllerContext.getInstance(); -// controllerContext.setSchemas(context); -// InstanceIdWithSchemaNode iiAndSchema = controllerContext.toInstanceIdentifier("/onf-ttp:opendaylight-ttps/table-type-patterns/table-type-pattern/NDM_metadata"); -// NDM_metadata = iiAndSchema.getSchemaNode(); -// -// return new StructuredData(compNode, NDM_metadata, null, true); -// } - - /** - * - * @param d - * @return - */ - public StructuredData structuredDataFromDataObject(DataObject d) { - DataSchemaNode NDM_metadata = null; - NDM_metadata = getSchemaNodeForDataObject(context, d); - return new StructuredData(compositeNodeFromDataObject(d), NDM_metadata, null, true); - } - - /** - * - * @param d - * @return - * @throws WebApplicationException - * @throws IOException - */ - public String jsonStringFromStructuredData(StructuredData d) throws WebApplicationException, IOException{ - ByteArrayOutputStream s = new ByteArrayOutputStream(); - StructuredDataToJsonProvider.INSTANCE.writeTo(d, null, null, null, null, null, s); - return s.toString(); - } - - /** - * Converts a {@link DataObject} to a JSON representation in a string using the relevant YANG - * schema if it is present. This defaults to using a {@link SchemaContextListener} if running an - * OSGi environment or {@link BindingReflections#loadModuleInfos()} if run while not in an OSGi - * environment or if the schema isn't available via {@link SchemaContextListener}. - * - * @param d - * @return - * @throws WebApplicationException - * @throws IOException - */ - public String jsonStringFromDataObject(DataObject d) throws WebApplicationException, IOException{ - return jsonStringFromStructuredData(structuredDataFromDataObject(d)); - } } diff --git a/utils/pom.xml b/utils/pom.xml new file mode 100644 index 0000000..4737f3b --- /dev/null +++ b/utils/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + + org.opendaylight.ttp + ttp-parent + 0.1.0-SNAPSHOT + ../ + + utils + jar + + + + + org.jboss.resteasy + jaxrs-api + + + + + + sal-binding-broker-impl + org.opendaylight.controller + ${controller.version} + + + org.opendaylight.controller + sal-rest-connector + ${controller.version} + + + + + + + org.apache.felix + maven-bundle-plugin + ${bundle.plugin.version} + true + + + org.opendaylight.l2switch.L2SwitchProvider + + ${project.build.directory}/META-INF + + + + + + diff --git a/utils/src/main/java/org/opendaylight/ttp/utils/TTPUtils.java b/utils/src/main/java/org/opendaylight/ttp/utils/TTPUtils.java new file mode 100644 index 0000000..9696370 --- /dev/null +++ b/utils/src/main/java/org/opendaylight/ttp/utils/TTPUtils.java @@ -0,0 +1,146 @@ +package org.opendaylight.ttp.utils; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +import javax.ws.rs.WebApplicationException; + +import javassist.ClassPool; + +import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider; +import org.opendaylight.controller.sal.restconf.impl.StructuredData; +import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext; +import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.YangModuleInfo; +import org.opendaylight.yangtools.yang.binding.util.BindingReflections; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; + +public class TTPUtils { + + public static final SchemaContext getSchemaContext() { + System.out.println("Building context"); + Iterable moduleInfos; + // TODO: make this load fewer things + moduleInfos = BindingReflections.loadModuleInfos(); + ModuleInfoBackedContext moduleContext = ModuleInfoBackedContext.create(); + moduleContext.addModuleInfos(moduleInfos); + SchemaContext ret = moduleContext.tryToCreateSchemaContext().get(); + System.out.println("Context built"); + return ret; + } + + /** + * + * @param d + * @return + * @throws WebApplicationException + * @throws IOException + */ + public static final String jsonStringFromStructuredData(StructuredData d) + throws WebApplicationException, IOException { + ByteArrayOutputStream s = new ByteArrayOutputStream(); + StructuredDataToJsonProvider.INSTANCE.writeTo(d, null, null, null, null, null, s); + return s.toString(); + } + + public static final BindingIndependentMappingService getMappingService(SchemaContext context) { + context = getSchemaContext(); + System.out.println("Building mapping service"); + BindingIndependentMappingService mappingService = new RuntimeGeneratedMappingServiceImpl( + ClassPool.getDefault()); + ((RuntimeGeneratedMappingServiceImpl) mappingService).onGlobalContextUpdated(context); + System.out.println("Mapping service built"); + return mappingService; + } + + /** + * Converts a {@link DataObject} to a JSON representation in a string using the relevant YANG + * schema if it is present. This defaults to using a {@link SchemaContextListener} if running an + * OSGi environment or {@link BindingReflections#loadModuleInfos()} if run while not in an OSGi + * environment or if the schema isn't available via {@link SchemaContextListener}. + * + * @param d + * @return + * @throws WebApplicationException + * @throws IOException + */ + public static final String jsonStringFromDataObject(DataObject d, + BindingIndependentMappingService mappingService, SchemaContext context) + throws WebApplicationException, IOException { + return jsonStringFromStructuredData(structuredDataFromDataObject(d, mappingService, context)); + } + + /** + * + * @param d + * @return + */ + public static final StructuredData structuredDataFromDataObject(DataObject d, + BindingIndependentMappingService mappingService, SchemaContext context) { + DataSchemaNode NDM_metadata = null; + NDM_metadata = getSchemaNodeForDataObject(context, d); + return new StructuredData(compositeNodeFromDataObject(d, mappingService), NDM_metadata, + null, true); + } + + public static final Set getAllTheNode(SchemaContext context) { + Set nodes = new HashSet(); + getAllTheNodesHelper(context, nodes); + return nodes; + } + + private static final void getAllTheNodesHelper(DataNodeContainer dcn, Set nodes) { + for (DataSchemaNode dsn : dcn.getChildNodes()) { + if (dsn instanceof DataNodeContainer) { + getAllTheNodesHelper((DataNodeContainer) dsn, nodes); + } + nodes.add(dsn); + } + } + + /** + * DON'T CALL THIS IN PRODUCTION CODE EVER!!! UNTIL IT IS FIXED! + *

+ * Return the {@link DataSchemaNode} + * + * @param context + * @param d + * @deprecated + */ + public static final DataSchemaNode getSchemaNodeForDataObject(SchemaContext context, + DataObject d) { + QName qn = BindingReflections.findQName(d.getClass()); + + Set allTheNodes = getAllTheNode(context); + + // TODO: create a map to make this faster!!!! + for (DataSchemaNode dsn : allTheNodes) { + if (dsn instanceof DataNodeContainer) { + allTheNodes.addAll(((DataNodeContainer) dsn).getChildNodes()); + } + if (dsn.getQName().equals(qn)) { + return dsn; + } + } + return null; + } + + /** + * + * @param d + * @return + */ + public static final CompositeNode compositeNodeFromDataObject(DataObject d, + BindingIndependentMappingService mappingSerivce) { + return mappingSerivce.toDataDom(d); + } + +} -- 2.36.6