From: Jakub Morvay Date: Fri, 4 Nov 2016 08:46:10 +0000 (+0000) Subject: Merge "Bug 6731 - add valid example values" X-Git-Tag: release/carbon~140 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=4dac2dcf6e0f92a64e4303a0d6db788a6da41404;hp=9c0f7d90a86e898cb2dd5e32fdd9120f87633ed0;p=netconf.git Merge "Bug 6731 - add valid example values" --- diff --git a/restconf/sal-rest-docgen/pom.xml b/restconf/sal-rest-docgen/pom.xml index b323cc5380..838b84a9c7 100644 --- a/restconf/sal-rest-docgen/pom.xml +++ b/restconf/sal-rest-docgen/pom.xml @@ -33,6 +33,11 @@ + + com.github.mifmif + generex + 1.0.0 + com.fasterxml.jackson.core jackson-annotations @@ -107,6 +112,11 @@ org.opendaylight.yangtools yang-data-api + + dk.brics.automaton + automaton + 1.11-8 + @@ -119,6 +129,7 @@ MD SAL Rest Api Doc Generator + generex, automaton !org.apache.maven.plugin.logging, !org.apache.maven.project, !org.opendaylight.yangtools.yang2sources.spi, @@ -142,4 +153,4 @@ - + \ No newline at end of file diff --git a/restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/impl/ModelGenerator.java b/restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/impl/ModelGenerator.java index 24768e8368..b7fcdd0d8b 100644 --- a/restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/impl/ModelGenerator.java +++ b/restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/impl/ModelGenerator.java @@ -9,11 +9,15 @@ package org.opendaylight.netconf.sal.rest.doc.impl; import static org.opendaylight.netconf.sal.rest.doc.util.RestDocgenUtil.resolveNodesName; -import com.google.common.base.Preconditions; +import com.google.common.base.Optional; +import com.mifmif.common.regex.Generex; import java.io.IOException; +import java.net.URI; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Set; +import java.util.regex.Pattern; import javax.annotation.concurrent.NotThreadSafe; import org.json.JSONArray; import org.json.JSONException; @@ -21,7 +25,6 @@ import org.json.JSONObject; import org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder; import org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder.Post; import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode; -import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; @@ -32,23 +35,30 @@ import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath; import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.TypedSchemaNode; import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit; import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair; import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint; +import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint; import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition; +import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl; +import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -60,10 +70,10 @@ public class ModelGenerator { private static final Logger LOG = LoggerFactory.getLogger(ModelGenerator.class); + private static final Pattern STRIP_PATTERN = Pattern.compile("\\[[^\\[\\]]*\\]"); private static final String BASE_64 = "base64"; private static final String BINARY_ENCODING_KEY = "binaryEncoding"; private static final String MEDIA_KEY = "media"; - private static final String ONE_OF_KEY = "oneOf"; private static final String UNIQUE_ITEMS_KEY = "uniqueItems"; private static final String MAX_ITEMS = "maxItems"; private static final String MIN_ITEMS = "minItems"; @@ -80,55 +90,42 @@ public class ModelGenerator { private static final String OBJECT_TYPE = "object"; private static final String ARRAY_TYPE = "array"; private static final String ENUM = "enum"; - private static final String INTEGER = "integer"; - private static final String NUMBER = "number"; - private static final String BOOLEAN = "boolean"; - private static final String STRING = "string"; private static final String ID_KEY = "id"; private static final String SUB_TYPES_KEY = "subTypes"; + private static final String UNIQUE_EMPTY_IDENTIFIER = "unique_empty_identifier"; private Module topLevelModule; public ModelGenerator() { } - private static String jsonTypeFor(final TypeDefinition type) { - if (type instanceof BooleanTypeDefinition) { - return BOOLEAN; - } else if (type instanceof DecimalTypeDefinition) { - return NUMBER; - } else if (type instanceof EnumTypeDefinition) { - return ENUM; - } else if (type instanceof IntegerTypeDefinition) { - return INTEGER; - } else if (type instanceof UnsignedIntegerTypeDefinition) { - return INTEGER; - } else if (type instanceof StringTypeDefinition) { - return STRING; - } - - // TODO: Binary type - return null; - } - + /** + * Creates Json models from provided module according to swagger spec + * + * @param module - Yang module to be converted + * @param schemaContext - SchemaContext of all Yang files used by Api Doc + * @return JSONObject containing data used for creating examples and models in Api Doc + * @throws IOException + * @throws JSONException + */ public JSONObject convertToJsonSchema(final Module module, final SchemaContext schemaContext) throws IOException, JSONException { final JSONObject models = new JSONObject(); + models.put(UNIQUE_EMPTY_IDENTIFIER, new JSONObject()); topLevelModule = module; - processModules(module, models); + processModules(module, models, schemaContext); processContainersAndLists(module, models, schemaContext); processRPCs(module, models, schemaContext); processIdentities(module, models); return models; } - private void processModules(final Module module, final JSONObject models) throws JSONException { + private void processModules(final Module module, final JSONObject models, final SchemaContext schemaContext) throws JSONException { createConcreteModelForPost(models, module.getName() + BaseYangSwaggerGenerator.MODULE_NAME_SUFFIX, - createPropertiesForPost(module, module.getName())); + createPropertiesForPost(module, schemaContext, module.getName())); } private void processContainersAndLists(final Module module, final JSONObject models, final SchemaContext schemaContext) throws IOException, JSONException { - final String moduleName = module.getName(); for (final DataSchemaNode childNode : module.getChildNodes()) { @@ -161,7 +158,7 @@ public class ModelGenerator { final JSONObject childSchema = getSchemaTemplate(); childSchema.put(TYPE_KEY, OBJECT_TYPE); childSchema.put(PROPERTIES_KEY, properties); - childSchema.put("id", filename); + childSchema.put(ID_KEY, filename); models.put(filename, childSchema); processTopData(filename, models, input); @@ -174,7 +171,7 @@ public class ModelGenerator { final JSONObject childSchema = getSchemaTemplate(); childSchema.put(TYPE_KEY, OBJECT_TYPE); childSchema.put(PROPERTIES_KEY, properties); - childSchema.put("id", filename); + childSchema.put(ID_KEY, filename); models.put(filename, childSchema); processTopData(filename, models, output); @@ -182,7 +179,7 @@ public class ModelGenerator { } } - private static JSONObject processTopData(final String filename, final JSONObject models, final SchemaNode schemaNode) { + private JSONObject processTopData(final String filename, final JSONObject models, final SchemaNode schemaNode) { final JSONObject items = new JSONObject(); items.put(REF_KEY, filename); @@ -192,7 +189,7 @@ public class ModelGenerator { dataNodeProperties.putOpt(DESCRIPTION_KEY, schemaNode.getDescription()); final JSONObject properties = new JSONObject(); - properties.put(schemaNode.getQName().getLocalName(), dataNodeProperties); + properties.put(topLevelModule.getName() + ":" + schemaNode.getQName().getLocalName(), dataNodeProperties); final JSONObject finalChildSchema = getSchemaTemplate(); finalChildSchema.put(TYPE_KEY, OBJECT_TYPE); finalChildSchema.put(PROPERTIES_KEY, properties); @@ -205,10 +202,8 @@ public class ModelGenerator { /** * Processes the 'identity' statement in a yang model and maps it to a 'model' in the Swagger JSON spec. * - * @param module - * The module from which the identity stmt will be processed - * @param models - * The JSONObject in which the parsed identity will be put as a 'model' obj + * @param module The module from which the identity stmt will be processed + * @param models The JSONObject in which the parsed identity will be put as a 'model' obj */ private static void processIdentities(final Module module, final JSONObject models) throws JSONException { @@ -240,6 +235,7 @@ public class ModelGenerator { subTypes.put(derivedId.getQName().getLocalName()); } identityObj.put(SUB_TYPES_KEY, subTypes); + } } else { /** @@ -257,7 +253,6 @@ public class ModelGenerator { private JSONObject processDataNodeContainer(final DataNodeContainer dataNode, final String parentName, final JSONObject models, final boolean isConfig, final SchemaContext schemaContext) throws JSONException, IOException { if (dataNode instanceof ListSchemaNode || dataNode instanceof ContainerSchemaNode) { - Preconditions.checkArgument(dataNode instanceof SchemaNode, "Data node should be also schema node"); final Iterable containerChildren = dataNode.getChildNodes(); final String localName = ((SchemaNode) dataNode).getQName().getLocalName(); final JSONObject properties = processChildren(containerChildren, parentName + "/" + localName, models, isConfig, schemaContext); @@ -268,12 +263,12 @@ public class ModelGenerator { childSchema.put(TYPE_KEY, OBJECT_TYPE); childSchema.put(PROPERTIES_KEY, properties); - childSchema.put("id", nodeName); + childSchema.put(ID_KEY, nodeName); models.put(nodeName, childSchema); if (isConfig) { createConcreteModelForPost(models, localName, - createPropertiesForPost(dataNode, parentName + "/" + localName)); + createPropertiesForPost(dataNode, schemaContext, parentName + "/" + localName)); } return processTopData(nodeName, models, (SchemaNode) dataNode); @@ -282,16 +277,16 @@ public class ModelGenerator { } private static void createConcreteModelForPost(final JSONObject models, final String localName, - final JSONObject properties) throws JSONException { + final JSONObject properties) throws JSONException { final String nodePostName = OperationBuilder.CONFIG + localName + Post.METHOD_NAME; final JSONObject postSchema = getSchemaTemplate(); postSchema.put(TYPE_KEY, OBJECT_TYPE); - postSchema.put("id", nodePostName); + postSchema.put(ID_KEY, nodePostName); postSchema.put(PROPERTIES_KEY, properties); models.put(nodePostName, postSchema); } - private JSONObject createPropertiesForPost(final DataNodeContainer dataNodeContainer, final String parentName) + private JSONObject createPropertiesForPost(final DataNodeContainer dataNodeContainer, final SchemaContext schemaContext, final String parentName) throws JSONException { final JSONObject properties = new JSONObject(); for (final DataSchemaNode childNode : dataNodeContainer.getChildNodes()) { @@ -303,18 +298,13 @@ public class ModelGenerator { property.put(ITEMS_KEY, items); properties.put(childNode.getQName().getLocalName(), property); } else if (childNode instanceof LeafSchemaNode) { - final JSONObject property = processLeafNode((LeafSchemaNode) childNode); + final JSONObject property = processLeafNode((LeafSchemaNode) childNode, schemaContext); properties.put(childNode.getQName().getLocalName(), property); } } return properties; } - private JSONObject processChildren(final Iterable nodes, final String moduleName, - final JSONObject models, final SchemaContext schemaContext) throws JSONException, IOException { - return processChildren(nodes, moduleName, models, true, schemaContext); - } - /** * Processes the nodes. */ @@ -327,17 +317,21 @@ public class ModelGenerator { final String name = resolveNodesName(node, topLevelModule, schemaContext); final JSONObject property; if (node instanceof LeafSchemaNode) { - property = processLeafNode((LeafSchemaNode) node); + property = processLeafNode((LeafSchemaNode) node, schemaContext); } else if (node instanceof ListSchemaNode) { property = processDataNodeContainer((ListSchemaNode) node, parentName, models, isConfig, schemaContext); } else if (node instanceof LeafListSchemaNode) { - property = processLeafListNode((LeafListSchemaNode) node); + property = processLeafListNode((LeafListSchemaNode) node, schemaContext); } else if (node instanceof ChoiceSchemaNode) { - property = processChoiceNode((ChoiceSchemaNode) node, parentName, models, schemaContext); + if (((ChoiceSchemaNode) node).getCases().iterator().hasNext()) { + processChoiceNode(((ChoiceSchemaNode) node).getCases().iterator().next().getChildNodes(), + parentName, models, schemaContext, isConfig, properties); + } + continue; } else if (node instanceof AnyXmlSchemaNode) { property = processAnyXMLNode((AnyXmlSchemaNode) node); @@ -350,46 +344,70 @@ public class ModelGenerator { throw new IllegalArgumentException("Unknown DataSchemaNode type: " + node.getClass()); } property.putOpt(DESCRIPTION_KEY, node.getDescription()); - properties.put(name, property); + properties.put(topLevelModule.getName() + ":" + name, property); } } return properties; } - private JSONObject processLeafListNode(final LeafListSchemaNode listNode) throws JSONException { + private JSONObject processLeafListNode(final LeafListSchemaNode listNode, final SchemaContext schemaContext) throws JSONException { final JSONObject props = new JSONObject(); props.put(TYPE_KEY, ARRAY_TYPE); final JSONObject itemsVal = new JSONObject(); - processTypeDef(listNode.getType(), itemsVal); + final ConstraintDefinition constraints = listNode.getConstraints(); + final Optional maxOptional = Optional.fromNullable(constraints.getMaxElements()); + if (maxOptional.or(2) >= 2) { + processTypeDef(listNode.getType(), listNode, itemsVal, schemaContext); + processTypeDef(listNode.getType(), listNode, itemsVal, schemaContext); + } else { + processTypeDef(listNode.getType(), listNode, itemsVal, schemaContext); + } props.put(ITEMS_KEY, itemsVal); - final ConstraintDefinition constraints = listNode.getConstraints(); + processConstraints(constraints, props); return props; } - private JSONObject processChoiceNode(final ChoiceSchemaNode choiceNode, final String parentName, final JSONObject models, - final SchemaContext schemaContext) throws JSONException, IOException { + private void processChoiceNode(final Iterable nodes, final String moduleName, final JSONObject models, + final SchemaContext schemaContext, final boolean isConfig, final JSONObject properties) + throws JSONException, IOException { + for (final DataSchemaNode node : nodes) { + final String name = resolveNodesName(node, topLevelModule, schemaContext); + final JSONObject property; - final Set cases = choiceNode.getCases(); + if (node instanceof LeafSchemaNode) { + property = processLeafNode((LeafSchemaNode) node, schemaContext); - final JSONArray choiceProps = new JSONArray(); - for (final ChoiceCaseNode choiceCase : cases) { - final String choiceName = choiceCase.getQName().getLocalName(); - final JSONObject choiceProp = processChildren(choiceCase.getChildNodes(), parentName, models, schemaContext); - final JSONObject choiceObj = new JSONObject(); - choiceObj.put(choiceName, choiceProp); - choiceObj.put(TYPE_KEY, OBJECT_TYPE); - choiceProps.put(choiceObj); - } + } else if (node instanceof ListSchemaNode) { + property = processDataNodeContainer((ListSchemaNode) node, moduleName, models, isConfig, + schemaContext); + + } else if (node instanceof LeafListSchemaNode) { + property = processLeafListNode((LeafListSchemaNode) node, schemaContext); - final JSONObject oneOfProps = new JSONObject(); - oneOfProps.put(ONE_OF_KEY, choiceProps); - oneOfProps.put(TYPE_KEY, OBJECT_TYPE); + } else if (node instanceof ChoiceSchemaNode) { + if (((ChoiceSchemaNode) node).getCases().iterator().hasNext()) + processChoiceNode(((ChoiceSchemaNode) node).getCases().iterator().next().getChildNodes(), + moduleName, models, schemaContext, isConfig, properties); + continue; - return oneOfProps; + } else if (node instanceof AnyXmlSchemaNode) { + property = processAnyXMLNode((AnyXmlSchemaNode) node); + + } else if (node instanceof ContainerSchemaNode) { + property = processDataNodeContainer((ContainerSchemaNode) node, moduleName, models, isConfig, + schemaContext); + + } else { + throw new IllegalArgumentException("Unknown DataSchemaNode type: " + node.getClass()); + } + + property.putOpt(DESCRIPTION_KEY, node.getDescription()); + properties.put(name, property); + } } private static void processConstraints(final ConstraintDefinition constraints, final JSONObject props) throws JSONException { @@ -406,14 +424,13 @@ public class ModelGenerator { } } - private JSONObject processLeafNode(final LeafSchemaNode leafNode) throws JSONException { + private JSONObject processLeafNode(final LeafSchemaNode leafNode, final SchemaContext schemaContext) throws JSONException { final JSONObject property = new JSONObject(); final String leafDescription = leafNode.getDescription(); property.put(DESCRIPTION_KEY, leafDescription); - processConstraints(leafNode.getConstraints(), property); - processTypeDef(leafNode.getType(), property); + processTypeDef(leafNode.getType(), leafNode, property, schemaContext); return property; } @@ -425,67 +442,122 @@ public class ModelGenerator { property.put(DESCRIPTION_KEY, leafDescription); processConstraints(leafNode.getConstraints(), property); + final String localName = leafNode.getQName().getLocalName(); + property.put(TYPE_KEY, "example of anyxml " + localName); return property; } - private void processTypeDef(final TypeDefinition leafTypeDef, final JSONObject property) throws JSONException { - if (leafTypeDef instanceof BinaryTypeDefinition) { - processBinaryType((BinaryTypeDefinition) leafTypeDef, property); - } else if (leafTypeDef instanceof BitsTypeDefinition) { - processBitsType((BitsTypeDefinition) leafTypeDef, property); - } else if (leafTypeDef instanceof EnumTypeDefinition) { - processEnumType((EnumTypeDefinition) leafTypeDef, property); - } else if (leafTypeDef instanceof IdentityrefTypeDefinition) { - property.putOpt(TYPE_KEY, - ((IdentityrefTypeDefinition) leafTypeDef).getIdentity().getQName().getLocalName()); - } else if (leafTypeDef instanceof StringTypeDefinition) { - processStringType((StringTypeDefinition) leafTypeDef, property); - } else if (leafTypeDef instanceof UnionTypeDefinition) { - processUnionType((UnionTypeDefinition) leafTypeDef, property); - } else { - String jsonType = jsonTypeFor(leafTypeDef); - if (jsonType == null) { - jsonType = "object"; + private String processTypeDef(final TypeDefinition leafTypeDef, final DataSchemaNode node, + final JSONObject property, final SchemaContext schemaContext) throws JSONException { + final String jsonType; + if (leafTypeDef.getDefaultValue() == null) { + if (leafTypeDef instanceof BinaryTypeDefinition) { + jsonType = processBinaryType(property); + + } else if (leafTypeDef instanceof BitsTypeDefinition) { + jsonType = processBitsType((BitsTypeDefinition) leafTypeDef, property); + + } else if (leafTypeDef instanceof EnumTypeDefinition) { + jsonType = processEnumType((EnumTypeDefinition) leafTypeDef, property); + + } else if (leafTypeDef instanceof IdentityrefTypeDefinition) { + final String name = topLevelModule.getName(); + jsonType = name + ":" + ((IdentityrefTypeDefinition) leafTypeDef).getIdentity().getQName().getLocalName(); + + } else if (leafTypeDef instanceof StringTypeDefinition) { + jsonType = processStringType(leafTypeDef, property, node.getQName().getLocalName()); + + } else if (leafTypeDef instanceof UnionTypeDefinition) { + jsonType = processUnionType((UnionTypeDefinition) leafTypeDef, property, schemaContext, node); + + } else if (leafTypeDef instanceof EmptyTypeDefinition) { + jsonType = UNIQUE_EMPTY_IDENTIFIER; + + } else if (leafTypeDef instanceof LeafrefTypeDefinition) { + return processLeafRef(node, property, schemaContext, leafTypeDef); + + } else if (leafTypeDef instanceof BooleanTypeDefinition) { + jsonType = "true"; + + } else if (leafTypeDef instanceof DecimalTypeDefinition) { + jsonType = String.valueOf(((DecimalTypeDefinition) leafTypeDef).getRangeConstraints() + .iterator().next().getMin()); + + } else if (leafTypeDef instanceof IntegerTypeDefinition) { + jsonType = String.valueOf(((IntegerTypeDefinition) leafTypeDef).getRangeConstraints() + .iterator().next().getMin()); + + } else if (leafTypeDef instanceof UnsignedIntegerTypeDefinition) { + jsonType = String.valueOf(((UnsignedIntegerTypeDefinition) leafTypeDef).getRangeConstraints() + .iterator().next().getMin()); + + } else { + jsonType = OBJECT_TYPE; + } - property.putOpt(TYPE_KEY, jsonType); + } else { + jsonType = String.valueOf(leafTypeDef.getDefaultValue()); } + property.putOpt(TYPE_KEY, jsonType); + return jsonType; } - private static void processBinaryType(final BinaryTypeDefinition binaryType, final JSONObject property) throws JSONException { - property.put(TYPE_KEY, STRING); + private String processLeafRef(final DataSchemaNode node, final JSONObject property, final SchemaContext schemaContext, + final TypeDefinition leafTypeDef) { + RevisionAwareXPath xPath = ((LeafrefTypeDefinition) leafTypeDef).getPathStatement(); + final URI namespace = leafTypeDef.getQName().getNamespace(); + final Date revision = leafTypeDef.getQName().getRevision(); + final Module module = schemaContext.findModuleByNamespaceAndRevision(namespace, revision); + final SchemaNode schemaNode; + + final String xPathString = STRIP_PATTERN.matcher(xPath.toString()).replaceAll(""); + xPath = new RevisionAwareXPathImpl(xPathString, xPath.isAbsolute()); + + if (xPath.isAbsolute()) { + schemaNode = SchemaContextUtil.findDataSchemaNode(schemaContext, module, xPath); + } else { + schemaNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, module, node, xPath); + } + + return processTypeDef(((TypedSchemaNode) schemaNode).getType(), (DataSchemaNode) schemaNode, property, schemaContext); + } + + private static String processBinaryType(final JSONObject property) throws JSONException { final JSONObject media = new JSONObject(); media.put(BINARY_ENCODING_KEY, BASE_64); property.put(MEDIA_KEY, media); + return "bin1 bin2"; } - private static void processEnumType(final EnumTypeDefinition enumLeafType, final JSONObject property) throws JSONException { + private static String processEnumType(final EnumTypeDefinition enumLeafType, final JSONObject property) throws JSONException { final List enumPairs = enumLeafType.getValues(); final List enumNames = new ArrayList<>(); for (final EnumPair enumPair : enumPairs) { enumNames.add(enumPair.getName()); } + property.putOpt(ENUM, new JSONArray(enumNames)); + return enumLeafType.getValues().iterator().next().getName(); } - private static void processBitsType(final BitsTypeDefinition bitsType, final JSONObject property) throws JSONException { - property.put(TYPE_KEY, ARRAY_TYPE); + private static String processBitsType(final BitsTypeDefinition bitsType, final JSONObject property) throws JSONException { property.put(MIN_ITEMS, 0); property.put(UNIQUE_ITEMS_KEY, true); - final JSONArray enumValues = new JSONArray(); - + final List enumNames = new ArrayList<>(); final List bits = bitsType.getBits(); for (final Bit bit : bits) { - enumValues.put(bit.getName()); + enumNames.add(bit.getName()); } - final JSONObject itemsValue = new JSONObject(); - itemsValue.put(ENUM, enumValues); - property.put(ITEMS_KEY, itemsValue); + property.put(ENUM, new JSONArray(enumNames)); + + return enumNames.iterator().next() + " " + enumNames.get(enumNames.size() - 1); } - private static void processStringType(final StringTypeDefinition stringType, final JSONObject property) throws JSONException { - StringTypeDefinition type = stringType; - List lengthConstraints = stringType.getLengthConstraints(); + private static String processStringType(final TypeDefinition stringType, final JSONObject property, final String nodeName) + throws JSONException { + StringTypeDefinition type = (StringTypeDefinition) stringType; + List lengthConstraints = ((StringTypeDefinition) stringType).getLengthConstraints(); while (lengthConstraints.isEmpty() && type.getBaseType() != null) { type = type.getBaseType(); lengthConstraints = type.getLengthConstraints(); @@ -499,20 +571,26 @@ public class ModelGenerator { property.putOpt(MIN_LENGTH_KEY, min); property.putOpt(MAX_LENGTH_KEY, max); } - - property.put(TYPE_KEY, STRING); + if (type.getPatternConstraints().iterator().hasNext()) { + final PatternConstraint pattern = type.getPatternConstraints().iterator().next(); + String regex = pattern.getRegularExpression(); + regex = regex.substring(1, regex.length() - 1); + final Generex generex = new Generex(regex); + return generex.random(); + } else { + return "Some " + nodeName; + } } - private static void processUnionType(final UnionTypeDefinition unionType, final JSONObject property) throws JSONException { - final StringBuilder type = new StringBuilder(); + private String processUnionType(final UnionTypeDefinition unionType, final JSONObject property, + final SchemaContext schemaContext, final DataSchemaNode node) + throws JSONException { + final List unionNames = new ArrayList<>(); for (final TypeDefinition typeDef : unionType.getTypes()) { - if (type.length() > 0) { - type.append(" or "); - } - type.append(jsonTypeFor(typeDef)); + unionNames.add(processTypeDef(typeDef, node, property, schemaContext)); } - - property.put(TYPE_KEY, type); + property.put(ENUM, new JSONArray(unionNames)); + return unionNames.iterator().next(); } /** @@ -525,4 +603,4 @@ public class ModelGenerator { return schemaJSON; } -} +} \ No newline at end of file diff --git a/restconf/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGeneratorTest.java b/restconf/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGeneratorTest.java index 0202905080..f744da7906 100644 --- a/restconf/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGeneratorTest.java +++ b/restconf/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGeneratorTest.java @@ -37,9 +37,6 @@ import org.opendaylight.netconf.sal.rest.doc.swagger.ResourceList; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaContext; -/** - * - */ public class ApiDocGeneratorTest { public static final String HTTP_HOST = "http://host"; @@ -114,7 +111,7 @@ public class ApiDocGeneratorTest { * Tries to find operation with name {@code operationName} and with summary {@code summary} */ private boolean findOperation(final List operations, final String operationName, final String type, - final String... searchedParameters) { + final String... searchedParameters) { final Set filteredOperations = findOperations(operations, operationName); for (final Operation operation : filteredOperations) { if (operation.getType().equals(type)) { @@ -172,18 +169,18 @@ public class ApiDocGeneratorTest { final JSONObject configLstTop = models.getJSONObject("toaster2(config)lst-TOP"); assertNotNull(configLstTop); - containsReferences(configLstTop, "lst", "toaster2(config)"); + containsReferences(configLstTop, "toaster2:lst", "toaster2(config)"); final JSONObject configLst = models.getJSONObject("toaster2(config)lst"); assertNotNull(configLst); - containsReferences(configLst, "lst1", "toaster2/lst(config)"); - containsReferences(configLst, "cont1", "toaster2/lst(config)"); + containsReferences(configLst, "toaster2:lst1", "toaster2/lst(config)"); + containsReferences(configLst, "toaster2:cont1", "toaster2/lst(config)"); final JSONObject configLst1Top = models.getJSONObject("toaster2/lst(config)lst1-TOP"); assertNotNull(configLst1Top); - containsReferences(configLst1Top, "lst1", "toaster2/lst(config)"); + containsReferences(configLst1Top, "toaster2:lst1", "toaster2/lst(config)"); final JSONObject configLst1 = models.getJSONObject("toaster2/lst(config)lst1"); assertNotNull(configLst1); @@ -191,24 +188,24 @@ public class ApiDocGeneratorTest { final JSONObject configCont1Top = models.getJSONObject("toaster2/lst(config)cont1-TOP"); assertNotNull(configCont1Top); - containsReferences(configCont1Top, "cont1", "toaster2/lst(config)"); + containsReferences(configCont1Top, "toaster2:cont1", "toaster2/lst(config)"); final JSONObject configCont1 = models.getJSONObject("toaster2/lst(config)cont1"); assertNotNull(configCont1); - containsReferences(configCont1, "cont11", "toaster2/lst/cont1(config)"); - containsReferences(configCont1, "lst11", "toaster2/lst/cont1(config)"); + containsReferences(configCont1, "toaster2:cont11", "toaster2/lst/cont1(config)"); + containsReferences(configCont1, "toaster2:lst11", "toaster2/lst/cont1(config)"); final JSONObject configCont11Top = models.getJSONObject("toaster2/lst/cont1(config)cont11-TOP"); assertNotNull(configCont11Top); - containsReferences(configCont11Top, "cont11", "toaster2/lst/cont1(config)"); + containsReferences(configCont11Top, "toaster2:cont11", "toaster2/lst/cont1(config)"); final JSONObject configCont11 = models.getJSONObject("toaster2/lst/cont1(config)cont11"); assertNotNull(configCont11); final JSONObject configlst11Top = models.getJSONObject("toaster2/lst/cont1(config)lst11-TOP"); assertNotNull(configlst11Top); - containsReferences(configlst11Top, "lst11", "toaster2/lst/cont1(config)"); + containsReferences(configlst11Top, "toaster2:lst11", "toaster2/lst/cont1(config)"); final JSONObject configLst11 = models.getJSONObject("toaster2/lst/cont1(config)lst11"); assertNotNull(configLst11); } catch (final JSONException e) { @@ -232,7 +229,7 @@ public class ApiDocGeneratorTest { assertNotNull(itemsInNodeInProperties); final String itemRef = itemsInNodeInProperties.getString("$ref"); - assertEquals(prefix + childObject, itemRef); + assertEquals(prefix + childObject.split(":")[1], itemRef); } @Test @@ -249,7 +246,7 @@ public class ApiDocGeneratorTest { // testing bugs.opendaylight.org bug 1290. UnionType model type. final String jsonString = doc.getModels().toString(); assertTrue(jsonString.contains( - "testUnion\":{\"type\":\"integer or string\",\"required\":false}")); + "testUnion\":{\"type\":\"-2147483648\",\"required\":false,\"enum\":[\"-2147483648\",\"Some testUnion\"]}")); } } } @@ -267,12 +264,12 @@ public class ApiDocGeneratorTest { final JSONObject models = doc.getModels(); final JSONObject inputTop = models.getJSONObject("(make-toast)input-TOP"); - final String testString = "{\"input\":{\"type\":\"object\",\"items\":{\"$ref\":\"(make-toast)input\"}}}"; + final String testString = "{\"toaster:input\":{\"type\":\"object\",\"items\":{\"$ref\":\"(make-toast)input\"}}}"; assertEquals(testString, inputTop.getJSONObject("properties").toString()); final JSONObject input = models.getJSONObject("(make-toast)input"); final JSONObject properties = input.getJSONObject("properties"); - assertTrue(properties.has("toasterDoneness")); - assertTrue(properties.has("toasterToastType")); + assertTrue(properties.has("toaster:toasterDoneness")); + assertTrue(properties.has("toaster:toasterToastType")); } } } @@ -360,12 +357,12 @@ public class ApiDocGeneratorTest { final JSONObject configToaster = topLevelJson.getJSONObject("toaster2(config)toaster"); assertNotNull("(config)toaster JSON object missing", configToaster); // without module prefix - containsProperties(configToaster, "toasterSlot"); + containsProperties(configToaster, "toaster2:toasterSlot"); final JSONObject toasterSlot = topLevelJson.getJSONObject("toaster2/toaster(config)toasterSlot"); assertNotNull("(config)toasterSlot JSON object missing", toasterSlot); // with module prefix - containsProperties(toasterSlot, "toaster-augmented:slotInfo"); + containsProperties(toasterSlot, "toaster2:toaster-augmented:slotInfo"); } catch (final JSONException e) { fail("Json exception while reading JSON object. Original message " + e.getMessage()); @@ -380,4 +377,4 @@ public class ApiDocGeneratorTest { assertNotNull(property + " is missing", concretePropertyObject); } } -} +} \ No newline at end of file