Skip to content

Commit

Permalink
fix for #67
Browse files Browse the repository at this point in the history
  • Loading branch information
bartoszm committed Jan 3, 2024
1 parent 93fb379 commit e396c80
Show file tree
Hide file tree
Showing 12 changed files with 260 additions and 62 deletions.
8 changes: 6 additions & 2 deletions cli/src/main/java/com/mrv/yangtools/codegen/main/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public static void main(String[] args) {
}

void init() throws FileNotFoundException {
if (output != null && output.trim().length() > 0) {
if (output != null && !output.trim().isEmpty()) {
out = new FileOutputStream(output);
}
}
Expand Down Expand Up @@ -165,7 +165,11 @@ void generate() throws IOException, ReactorException {
generator.appendPostProcessor(new SingleParentInheritenceModel());
}

generator.appendPostProcessor(new Rfc4080PayloadWrapper());
if(!odlPathFormat) {
//TODO check if something similar is needed for ODL paths as well
generator.appendPostProcessor(new Rfc4080PayloadWrapper());
}

generator.appendPostProcessor(new RemoveUnusedDefinitions());

generator.generate(new OutputStreamWriter(out));
Expand Down
32 changes: 5 additions & 27 deletions cli/src/test/java/com/mrv/yangtools/codegen/main/Issue57.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
package com.mrv.yangtools.codegen.main;

import io.swagger.models.Swagger;
import io.swagger.parser.SwaggerParser;
import org.junit.Assert;
import org.junit.Test;
import org.kohsuke.args4j.CmdLineParser;

import java.io.ByteArrayOutputStream;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.Assert;
import org.junit.Test;

public class Issue57 {
public class Issue57 {
private static String path;

static {
Expand All @@ -35,7 +30,7 @@ public void testRegular() {
path
).collect(Collectors.toList());

Swagger swagger = runParser(args);
Swagger swagger = Utils.runParser(args);
assertContainsOnly(swagger, s -> s.endsWith("Input"),
"objects.createobject.Input","objects.updateobject.Input");
}
Expand All @@ -49,7 +44,7 @@ public void testOptimized() {
path
).collect(Collectors.toList());

Swagger swagger = runParser(args);
Swagger swagger = Utils.runParser(args);

assertContainsOnly(swagger, s -> s.endsWith("Input"), "objects.createobject.Input");
}
Expand All @@ -62,21 +57,4 @@ private void assertContainsOnly(Swagger swagger, Predicate<String> filterDefs, S
.collect(Collectors.toSet());
Assert.assertEquals(expected, result);
}

private Swagger runParser(List<String> args) {
Main main = new Main();
CmdLineParser parser = new CmdLineParser(main);
try {
parser.parseArgument(args);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
main.out = baos;
main.init();
main.generate();

return new SwaggerParser().parse(new String(baos.toByteArray(), StandardCharsets.UTF_8));
} catch (Exception e) {
throw new RuntimeException(e);
}

}
}
27 changes: 27 additions & 0 deletions cli/src/test/java/com/mrv/yangtools/codegen/main/Utils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.mrv.yangtools.codegen.main;

import io.swagger.models.Swagger;
import io.swagger.parser.SwaggerParser;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import org.kohsuke.args4j.CmdLineParser;

public interface Utils {
static Swagger runParser(List<String> args) {
Main main = new Main();
CmdLineParser parser = new CmdLineParser(main);
try {
parser.parseArgument(args);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
main.out = baos;
main.init();
main.generate();

return new SwaggerParser().parse(baos.toString(StandardCharsets.UTF_8));
} catch (Exception e) {
throw new RuntimeException(e);
}

}
}
6 changes: 6 additions & 0 deletions swagger-generator/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
<dependency>
<groupId>org.mozilla</groupId>
<artifactId>rhino</artifactId>
<version>1.7.7.2</version>
<scope>compile</scope>
</dependency>

</dependencies>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ private void generate(RpcDefinition rpc) {

private void generate(DataSchemaNode node, final int depth) {
if(depth == 0) {
log.debug("Maxmium depth level reached, skipping {} and it's childs", node.getPath());
log.debug("Maximum depth level reached, skipping {} and it's childs", node.getPath());
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ public AbstractDataObjectBuilder(EffectiveModelContext ctx, Swagger swagger, Typ
this.moduleUtils = new ModuleUtils(ctx);
this.generatedEnums = new HashMap<>();
this.orgNames = new HashMap<>();

if(swagger.getDefinitions() == null) {
swagger.setDefinitions(new LinkedHashMap<>());
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 Amartus. All rights reserved.
* Copyright (c) 2024 Amartus. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
Expand All @@ -15,6 +15,9 @@
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.RefProperty;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -33,7 +36,7 @@ public abstract class ReplaceDefinitionsProcessor implements Consumer<Swagger> {
private final Logger log = LoggerFactory.getLogger(ReplaceDefinitionsProcessor.class);
@Override
public void accept(Swagger target) {
Map<String, String> replacements = prepareForReplacement(target);
Map<String, String> replacements = optimize(prepareForReplacement(target));

log.debug("{} replacement found for definitions", replacements.size());
log.trace("replacing paths");
Expand All @@ -47,51 +50,72 @@ public void accept(Swagger target) {
});
}



private Map<String, String> optimize(Map<String, String> replacements) {
Function<String, String> last = s -> {
String replacement = replacements.get(s);
while (replacement != null) {
s = replacement;
replacement = replacements.get(s);
}
return s;

};

return replacements.entrySet().stream().map(e -> Map.entry(e.getKey(), last.apply(e.getValue())))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
}

protected abstract Map<String, String> prepareForReplacement(Swagger swagger);

private void fixModel(String name, Model m, Map<String, String> replacements) {
ModelImpl fixProperties = null;
private Optional<Model> fixModel(String name, Model m, Map<String, String> replacements) {

if(m instanceof RefModel) {
fixRefModel((RefModel) m, replacements);
return;
if(m != null && replacements.containsKey(name)) {
return Optional.empty();
}

if(m instanceof ModelImpl) {
fixProperties = (ModelImpl) m;
if(m instanceof RefModel) {
return Optional.ofNullable(fixRefModel((RefModel) m, replacements));
}

if(m instanceof ComposedModel) {
ComposedModel cm = (ComposedModel) m;
fixComposedModel(cm, replacements);
fixProperties = cm.getAllOf().stream()
.filter(c -> c instanceof ModelImpl).map(c -> (ModelImpl)c)
.findFirst().orElse(null);
Stream<Entry<String, Property>> propAll = cm.getAllOf().stream()
.flatMap(this::properties);
fixProperties(propAll, replacements);
}
fixProperties(properties(m), replacements);
return Optional.empty();
}

if(fixProperties == null) return;
if(fixProperties.getProperties() == null) {
if(fixProperties.getEnum() == null) {
log.warn("Empty model in {}", name);
}
return;
}
fixProperties.getProperties().forEach((key, value) -> {
private Stream<Entry<String, Property>> properties(Model m) {
if(m == null) return Stream.empty();
return Optional.ofNullable(m.getProperties()).stream()
.flatMap(it -> it.entrySet().stream());
}

private void fixProperties(Stream<Entry<String, Property>> properties, Map<String, String> replacements) {
properties.forEach(e -> {
var key = e.getKey();
var value = e.getValue();
if (value instanceof RefProperty) {
if (fixProperty((RefProperty) value, replacements)) {
log.debug("fixing property {} of {}", key, name);
log.debug("fixing property {}", key);
}
} else if (value instanceof ArrayProperty) {
Property items = ((ArrayProperty) value).getItems();
if (items instanceof RefProperty) {
if (fixProperty((RefProperty) items, replacements)) {
log.debug("fixing property {} of {}", key, name);
log.debug("fixing property {}", key);
}
}
}
});

}


private boolean fixProperty(RefProperty p, Map<String, String> replacements) {
if(replacements.containsKey(p.getSimpleRef())) {
p.set$ref("#/definitions/" + replacements.get(p.getSimpleRef()));
Expand All @@ -113,10 +137,12 @@ private void fixComposedModel(ComposedModel m, Map<String, String> replacements)
});
}

private void fixRefModel(RefModel model, Map<String, String> replacements) {
private Model fixRefModel(RefModel model, Map<String, String> replacements) {
if(replacements.containsKey(model.getSimpleRef())) {
model.set$ref("#/definitions/" + replacements.get(model.getSimpleRef()));
return model;
}
return null;
}

private void fixOperation(Operation operation, Map<String, String> replacements) {
Expand All @@ -138,13 +164,35 @@ private void fixParameter(Parameter p, Map<String, String> replacements) {
if(!(p instanceof BodyParameter)) return;
BodyParameter bp = (BodyParameter) p;

fixModel(null, bp.getSchema(), replacements);
fixModel(null, bp.getSchema(), replacements)
.ifPresent(m -> {
bp.setSchema(m);
var nType = toTypeName(m.getReference());
var rep = replacements.entrySet().stream()
.filter(e -> e.getValue().equals(nType))
.findFirst();
rep.ifPresent(e -> {
var nDesc = bp.getDescription().replace(e.getKey(), e.getValue());
bp.setDescription(nDesc);
});

});
}

private void fixResponse(Response r, Map<String, String> replacements) {
Model model = r.getResponseSchema();
if(model != null) {
fixModel(null, model, replacements);
fixModel(null, model, replacements)
.ifPresent(m -> {
r.setResponseSchema(m);
r.setDescription(toTypeName(m.getReference()));
});
}
}

private static String toTypeName(String ref) {
if(ref == null) return null;
var seg = ref.split("/");
return seg[seg.length - 1];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* @author bartosz.michalik@amartus.com
*/
public class Rfc4080PayloadWrapper extends PayloadWrapperProcessor {
//FIXME use only with proper path. watch out for variables etc.
@Override
protected String toProperty(String path) {
String[] split = path.split("/");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public void accept(Swagger swagger) {

}

private class Worker {
private static class Worker {
private final Map<String, TypeNode> hierarchy;
private final Swagger swagger;
private Set<String> toUnpack;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,15 @@ protected Model m(Set<String> parents, Map<String, String> properites) {

if(properites.isEmpty() && parents.isEmpty()) return new ModelImpl();

var parRef = parents.stream().map(p -> new RefModel(DEF_PREFIX + p))
.collect(Collectors.toList());


ComposedModel model = new ComposedModel();
model.setAllOf(
parents.stream()
.map(p -> new RefModel(DEF_PREFIX + p))
.collect(Collectors.toList())
);

model.setParent(parRef.get(0));
model.setInterfaces(parRef.subList(1, parRef.size()));


if(!properites.isEmpty()) {
final ModelImpl m = new ModelImpl();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.mrv.yangtools.codegen.impl.postprocessor;

import static org.junit.Assert.assertTrue;

import com.mrv.yangtools.test.utils.SwaggerHelper;
import io.swagger.models.Swagger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.Test;

public class ReplaceEmptyWithParentTest extends AbstractWithSwagger {

@Test
public void withEmptyParent() {
new ReplaceEmptyWithParent().accept(swagger);

noDanglingReferences(swagger);
}

private void noDanglingReferences(Swagger swagger) {
var path = new SwaggerHelper(swagger).getReferencesFromPaths();
var defs = new SwaggerHelper(swagger).getReferencesFromDefinitions();
var all = Stream.concat(path, defs).collect(Collectors.toSet());

var definitions = swagger.getDefinitions().keySet();
var remaining = all.stream().filter(it -> !definitions.contains(it)).collect(Collectors.toSet());
assertTrue("Dangling references: " + remaining, remaining.isEmpty());
}

}
Loading

0 comments on commit e396c80

Please sign in to comment.