From 5d581c3b03207047d20129b7f984b3dc788a3158 Mon Sep 17 00:00:00 2001 From: Alexey Nechaev Date: Fri, 8 May 2015 14:21:29 +0300 Subject: [PATCH] Fixes #429: Handling of composed models has been added. --- .../swagger/codegen/DefaultCodegen.java | 194 ++++++++---------- .../test/scala/Java/JavaInheritanceTest.scala | 28 +++ .../src/test/scala/Objc/ObjcModelTest.scala | 10 +- .../src/test/scala/scala/ScalaModelTest.scala | 6 +- 4 files changed, 126 insertions(+), 112 deletions(-) create mode 100644 modules/swagger-codegen/src/test/scala/Java/JavaInheritanceTest.scala diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java index cd957722483..2513bedfcb9 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java @@ -1,10 +1,30 @@ package com.wordnik.swagger.codegen; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.annotation.Nullable; + +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.google.common.base.Function; import com.google.common.collect.Lists; - import com.wordnik.swagger.codegen.examples.ExampleGenerator; import com.wordnik.swagger.models.ArrayModel; +import com.wordnik.swagger.models.ComposedModel; import com.wordnik.swagger.models.Model; import com.wordnik.swagger.models.ModelImpl; import com.wordnik.swagger.models.Operation; @@ -40,27 +60,9 @@ import com.wordnik.swagger.models.properties.RefProperty; import com.wordnik.swagger.models.properties.StringProperty; import com.wordnik.swagger.util.Json; -import javax.annotation.Nullable; -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.commons.lang.StringUtils; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class DefaultCodegen { - Logger LOGGER = LoggerFactory.getLogger(DefaultCodegen.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCodegen.class); protected String outputFolder = ""; protected Set defaultIncludes = new HashSet(); @@ -473,100 +475,28 @@ public class DefaultCodegen { m.classVarName = toVarName(name); m.modelJson = Json.pretty(model); m.externalDocs = model.getExternalDocs(); - int count = 0; if(model instanceof ArrayModel) { ArrayModel am = (ArrayModel) model; ArrayProperty arrayProperty = new ArrayProperty(am.getItems()); - CodegenProperty cp = fromProperty(name, arrayProperty); - if(cp.complexType != null && !defaultIncludes.contains(cp.complexType)) - m.imports.add(cp.complexType); - m.parent = toInstantiationType(arrayProperty); - String containerType = cp.containerType; - if(instantiationTypes.containsKey(containerType)) - m.imports.add(instantiationTypes.get(containerType)); - if(typeMapping.containsKey(containerType)) { - containerType = typeMapping.get(containerType); - cp.containerType = containerType; - m.imports.add(containerType); - } + addParentContainer(m, name, arrayProperty); } else if (model instanceof RefModel) { // TODO - } - else { + } else if (model instanceof ComposedModel) { + final ComposedModel composed = (ComposedModel) model; + final RefModel parent = (RefModel) composed.getParent(); + final String parentModel = toModelName(parent.getSimpleRef()); + m.parent = parentModel; + addImport(m, parentModel); + final ModelImpl child = (ModelImpl) composed.getChild(); + addVars(m, child.getProperties(), child.getRequired()); + } else { ModelImpl impl = (ModelImpl) model; if(impl.getAdditionalProperties() != null) { MapProperty mapProperty = new MapProperty(impl.getAdditionalProperties()); - CodegenProperty cp = fromProperty(name, mapProperty); - if(cp.complexType != null && !defaultIncludes.contains(cp.complexType)) - m.imports.add(cp.complexType); - m.parent = toInstantiationType(mapProperty); - String containerType = cp.containerType; - if(instantiationTypes.containsKey(containerType)) - m.imports.add(instantiationTypes.get(containerType)); - if(typeMapping.containsKey(containerType)) { - containerType = typeMapping.get(containerType); - cp.containerType = containerType; - m.imports.add(containerType); - } - } - if(impl.getProperties() != null && impl.getProperties().size() > 0) { - m.hasVars = true; - m.hasEnums = false; - for(String key: impl.getProperties().keySet()) { - Property prop = impl.getProperties().get(key); - - if(prop == null) { - LOGGER.warn("null property for " + key); - } - else { - CodegenProperty cp; - try{ - cp = fromProperty(key, prop); - } - catch(Exception e) { - System.out.println("failed to process model " + name); - throw new RuntimeException(e); - } - cp.required = null; - if(impl.getRequired() != null) { - for(String req : impl.getRequired()) { - if(key.equals(req)) - cp.required = true; - } - } - if(cp.complexType != null && !defaultIncludes.contains(cp.complexType)) { - m.imports.add(cp.complexType); - } - m.vars.add(cp); - count += 1; - if (cp.isEnum) - m.hasEnums = true; - if(count != impl.getProperties().keySet().size()) - cp.hasMore = new Boolean(true); - if(cp.isContainer != null) { - String arrayImport = typeMapping.get("array"); - if(arrayImport != null && - !languageSpecificPrimitives.contains(arrayImport) && - !defaultIncludes.contains(arrayImport)) - m.imports.add(arrayImport); - } - - if(cp.complexType != null && - !languageSpecificPrimitives.contains(cp.complexType) && - !defaultIncludes.contains(cp.complexType)) - m.imports.add(cp.complexType); - - if(cp.baseType != null && - !languageSpecificPrimitives.contains(cp.baseType) && - !defaultIncludes.contains(cp.baseType)) - m.imports.add(cp.baseType); - } - } - } - else { - m.emptyVars = true; + addParentContainer(m, name, mapProperty); } + addVars(m, impl.getProperties(), impl.getRequired()); } return m; } @@ -1149,6 +1079,62 @@ public class DefaultCodegen { co.baseName = tag; } + private void addParentContainer(CodegenModel m, String name, Property property) { + final CodegenProperty tmp = fromProperty(name, property); + addImport(m, tmp.complexType); + m.parent = toInstantiationType(property); + final String containerType = tmp.containerType; + final String instantiationType = instantiationTypes.get(containerType); + if (instantiationType != null) { + addImport(m, instantiationType); + } + final String mappedType = typeMapping.get(containerType); + if (mappedType != null) { + addImport(m, mappedType); + } + } + + private void addImport(CodegenModel m, String type) { + if (type != null && !languageSpecificPrimitives.contains(type) && !defaultIncludes.contains(type)) { + m.imports.add(type); + } + } + + private void addVars(CodegenModel m, Map properties, Collection required) { + if (properties != null && properties.size() > 0) { + m.hasVars = true; + m.hasEnums = false; + final int totalCount = properties.size(); + final Set mandatory = required == null ? Collections. emptySet() : new HashSet(required); + int count = 0; + for (Map.Entry entry : properties.entrySet()) { + final String key = entry.getKey(); + final Property prop = entry.getValue(); + + if (prop == null) { + LOGGER.warn("null property for " + key); + } else { + final CodegenProperty cp = fromProperty(key, prop); + cp.required = mandatory.contains(key) ? true : null; + if (cp.isEnum) { + m.hasEnums = true; + } + count += 1; + if (count != totalCount) + cp.hasMore = true; + if (cp.isContainer != null) { + addImport(m, typeMapping.get("array")); + } + addImport(m, cp.baseType); + addImport(m, cp.complexType); + m.vars.add(cp); + } + } + } else { + m.emptyVars = true; + } + } + /* underscore and camelize are copied from Twitter elephant bird * https://github.com/twitter/elephant-bird/blob/master/core/src/main/java/com/twitter/elephantbird/util/Strings.java */ diff --git a/modules/swagger-codegen/src/test/scala/Java/JavaInheritanceTest.scala b/modules/swagger-codegen/src/test/scala/Java/JavaInheritanceTest.scala new file mode 100644 index 00000000000..1b6cfc0ecfd --- /dev/null +++ b/modules/swagger-codegen/src/test/scala/Java/JavaInheritanceTest.scala @@ -0,0 +1,28 @@ +package Java + +import scala.collection.JavaConverters._ + +import org.junit.runner.RunWith +import org.scalatest.FlatSpec +import org.scalatest.Matchers +import org.scalatest.junit.JUnitRunner +import com.wordnik.swagger.codegen.languages.JavaClientCodegen +import com.wordnik.swagger.models.ComposedModel +import com.wordnik.swagger.models.ModelImpl +import com.wordnik.swagger.models.RefModel +import com.wordnik.swagger.models.properties.StringProperty + +@RunWith(classOf[JUnitRunner]) +class JavaInheritanceTest extends FlatSpec with Matchers { + it should "convert a composed model" in { + val model = new ComposedModel().parent(new RefModel("Base")).child(new ModelImpl().additionalProperties(new StringProperty())) + + val codegen = new JavaClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be("sample") + cm.classname should be("Sample") + cm.parent should be("Base") + cm.imports.asScala should be (Set("Base")) + } +} diff --git a/modules/swagger-codegen/src/test/scala/Objc/ObjcModelTest.scala b/modules/swagger-codegen/src/test/scala/Objc/ObjcModelTest.scala index 6255c4deacc..4de884885e4 100644 --- a/modules/swagger-codegen/src/test/scala/Objc/ObjcModelTest.scala +++ b/modules/swagger-codegen/src/test/scala/Objc/ObjcModelTest.scala @@ -1,4 +1,4 @@ -package objc +package Objc import com.wordnik.swagger.codegen.languages.ObjcClientCodegen import com.wordnik.swagger.util.Json @@ -217,8 +217,8 @@ class ObjcModelTest extends FlatSpec with Matchers { cm.description should be ("an array model") cm.vars.size should be (0) cm.parent should be ("NSMutableArray") - cm.imports.size should be (3) - (cm.imports.asScala.toSet & Set("SWGChildren", "NSArray", "NSMutableArray")).size should be (3) + cm.imports.size should be (1) + (cm.imports.asScala.toSet & Set("SWGChildren")).size should be (1) } it should "convert an map model" in { @@ -234,8 +234,8 @@ class ObjcModelTest extends FlatSpec with Matchers { cm.description should be ("an map model") cm.vars.size should be (0) cm.parent should be ("NSMutableDictionary") - cm.imports.size should be (3) - (cm.imports.asScala.toSet & Set("SWGChildren", "NSDictionary", "NSMutableDictionary")).size should be (3) + cm.imports.size should be (1) + (cm.imports.asScala.toSet & Set("SWGChildren")).size should be (1) } it should "create proper imports per #316" in { diff --git a/modules/swagger-codegen/src/test/scala/scala/ScalaModelTest.scala b/modules/swagger-codegen/src/test/scala/scala/ScalaModelTest.scala index 090e4cd5ffe..39d76ca168c 100644 --- a/modules/swagger-codegen/src/test/scala/scala/ScalaModelTest.scala +++ b/modules/swagger-codegen/src/test/scala/scala/ScalaModelTest.scala @@ -1,4 +1,4 @@ -package Java +package scala import com.wordnik.swagger.codegen.languages.ScalaClientCodegen import com.wordnik.swagger.util.Json @@ -218,8 +218,8 @@ class ScalaModelTest extends FlatSpec with Matchers { cm.description should be ("an array model") cm.vars.size should be (0) cm.parent should be ("ListBuffer[Children]") - cm.imports.size should be (3) - (cm.imports.asScala.toSet & Set("List", "ListBuffer", "Children")).size should be (3) + cm.imports.size should be (2) + (cm.imports.asScala.toSet & Set("ListBuffer", "Children")).size should be (2) } it should "convert an map model" in {