mirror of
https://github.com/jlengrand/openapi-generator.git
synced 2026-05-16 00:21:19 +00:00
[docs] Initial FeatureSet generator documentation (#5188)
* Flatten feature sets for display * [cli] Add feature set output to config-help This includes markdown and plain text outputs for config-help. * [docs] FeatureSet on generator docs
This commit is contained in:
@@ -16,10 +16,12 @@
|
||||
|
||||
package org.openapitools.codegen.meta;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.openapitools.codegen.meta.features.*;
|
||||
import org.openapitools.codegen.meta.features.annotations.AnnotationType;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -178,6 +180,167 @@ public class FeatureSet {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a flattened or "normalized" view of the featureSet. This is for simplifying user-facing display only.
|
||||
*/
|
||||
public static class FeatureSetFlattened {
|
||||
String featureCategory;
|
||||
String featureName;
|
||||
boolean isSupported;
|
||||
|
||||
List<AnnotationType> source = new ArrayList<>(3);
|
||||
|
||||
public String getFeatureCategory() {
|
||||
return featureCategory;
|
||||
}
|
||||
|
||||
public String getFeatureName() {
|
||||
return featureName;
|
||||
}
|
||||
|
||||
public boolean isSupported() {
|
||||
return isSupported;
|
||||
}
|
||||
|
||||
public List<AnnotationType> getSource() {
|
||||
return ImmutableList.copyOf(source);
|
||||
}
|
||||
}
|
||||
|
||||
public List<FeatureSetFlattened> flatten() {
|
||||
// TODO: Look at making this method function more generically.
|
||||
List<FeatureSetFlattened> states = new ArrayList<>();
|
||||
EnumSet.allOf(ClientModificationFeature.class).forEach(feat -> {
|
||||
FeatureSetFlattened state = new FeatureSetFlattened();
|
||||
state.featureCategory = ClientModificationFeature.class.getSimpleName();
|
||||
state.featureName = feat.name();
|
||||
state.isSupported = this.clientModificationFeatures.contains(feat);
|
||||
|
||||
try {
|
||||
for (Annotation an : ClientModificationFeature.class.getField(feat.name()).getAnnotations()) {
|
||||
state.source.add(AnnotationType.fromAnnotation(an.annotationType()));
|
||||
}
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
states.add(state);
|
||||
});
|
||||
EnumSet.allOf(DataTypeFeature.class).forEach(feat -> {
|
||||
FeatureSetFlattened state = new FeatureSetFlattened();
|
||||
state.featureCategory = DataTypeFeature.class.getSimpleName();
|
||||
state.featureName = feat.name();
|
||||
state.isSupported = this.dataTypeFeatures.contains(feat);
|
||||
|
||||
try {
|
||||
for (Annotation an : DataTypeFeature.class.getField(feat.name()).getAnnotations()) {
|
||||
state.source.add(AnnotationType.fromAnnotation(an.annotationType()));
|
||||
}
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
states.add(state);
|
||||
});
|
||||
EnumSet.allOf(DocumentationFeature.class).forEach(feat -> {
|
||||
FeatureSetFlattened state = new FeatureSetFlattened();
|
||||
state.featureCategory = DocumentationFeature.class.getSimpleName();
|
||||
state.featureName = feat.name();
|
||||
state.isSupported = this.documentationFeatures.contains(feat);
|
||||
|
||||
try {
|
||||
for (Annotation an : DocumentationFeature.class.getField(feat.name()).getAnnotations()) {
|
||||
state.source.add(AnnotationType.fromAnnotation(an.annotationType()));
|
||||
}
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
states.add(state);
|
||||
});
|
||||
EnumSet.allOf(SchemaSupportFeature.class).forEach(feat -> {
|
||||
FeatureSetFlattened state = new FeatureSetFlattened();
|
||||
state.featureCategory = SchemaSupportFeature.class.getSimpleName();
|
||||
state.featureName = feat.name();
|
||||
state.isSupported = this.schemaSupportFeatures.contains(feat);
|
||||
|
||||
try {
|
||||
for (Annotation an : SchemaSupportFeature.class.getField(feat.name()).getAnnotations()) {
|
||||
state.source.add(AnnotationType.fromAnnotation(an.annotationType()));
|
||||
}
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
states.add(state);
|
||||
});
|
||||
EnumSet.allOf(GlobalFeature.class).forEach(feat -> {
|
||||
FeatureSetFlattened state = new FeatureSetFlattened();
|
||||
state.featureCategory = GlobalFeature.class.getSimpleName();
|
||||
state.featureName = feat.name();
|
||||
state.isSupported = this.globalFeatures.contains(feat);
|
||||
|
||||
try {
|
||||
for (Annotation an : GlobalFeature.class.getField(feat.name()).getAnnotations()) {
|
||||
state.source.add(AnnotationType.fromAnnotation(an.annotationType()));
|
||||
}
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
states.add(state);
|
||||
});
|
||||
EnumSet.allOf(ParameterFeature.class).forEach(feat -> {
|
||||
FeatureSetFlattened state = new FeatureSetFlattened();
|
||||
state.featureCategory = ParameterFeature.class.getSimpleName();
|
||||
state.featureName = feat.name();
|
||||
state.isSupported = this.parameterFeatures.contains(feat);
|
||||
|
||||
try {
|
||||
for (Annotation an : ParameterFeature.class.getField(feat.name()).getAnnotations()) {
|
||||
state.source.add(AnnotationType.fromAnnotation(an.annotationType()));
|
||||
}
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
states.add(state);
|
||||
});
|
||||
EnumSet.allOf(SecurityFeature.class).forEach(feat -> {
|
||||
FeatureSetFlattened state = new FeatureSetFlattened();
|
||||
state.featureCategory = SecurityFeature.class.getSimpleName();
|
||||
state.featureName = feat.name();
|
||||
state.isSupported = this.securityFeatures.contains(feat);
|
||||
|
||||
try {
|
||||
for (Annotation an : SecurityFeature.class.getField(feat.name()).getAnnotations()) {
|
||||
state.source.add(AnnotationType.fromAnnotation(an.annotationType()));
|
||||
}
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
states.add(state);
|
||||
});
|
||||
EnumSet.allOf(WireFormatFeature.class).forEach(feat -> {
|
||||
FeatureSetFlattened state = new FeatureSetFlattened();
|
||||
state.featureCategory = WireFormatFeature.class.getSimpleName();
|
||||
state.featureName = feat.name();
|
||||
state.isSupported = this.wireFormatFeatures.contains(feat);
|
||||
|
||||
try {
|
||||
for (Annotation an : WireFormatFeature.class.getField(feat.name()).getAnnotations()) {
|
||||
state.source.add(AnnotationType.fromAnnotation(an.annotationType()));
|
||||
}
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
states.add(state);
|
||||
});
|
||||
|
||||
return states;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code FeatureSet} builder static inner class.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.openapitools.codegen.meta.features.annotations;
|
||||
|
||||
public enum AnnotationType {
|
||||
OAS2, OAS3, ToolingExtension;
|
||||
|
||||
public static AnnotationType fromAnnotation(Class<?> input) {
|
||||
if(input == OAS2.class) return AnnotationType.OAS2;
|
||||
if(input == OAS3.class) return AnnotationType.OAS3;
|
||||
if(input == ToolingExtension.class) return AnnotationType.ToolingExtension;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package org.openapitools.codegen.meta;
|
||||
|
||||
import org.openapitools.codegen.meta.features.*;
|
||||
import org.openapitools.codegen.meta.features.annotations.AnnotationType;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class FeatureSetTest {
|
||||
|
||||
@Test
|
||||
public void flattOnUnspecified() {
|
||||
List<FeatureSet.FeatureSetFlattened> flattened = FeatureSet.UNSPECIFIED.flatten();
|
||||
// There are 73 features at the time of writing this test. This makes sure we get a "Full" flat representation.
|
||||
int knownFeatureCount = 73;
|
||||
int checkedCount = 0;
|
||||
assertTrue(flattened.size() >= knownFeatureCount);
|
||||
|
||||
for (FeatureSet.FeatureSetFlattened f : flattened) {
|
||||
checkedCount += 1;
|
||||
assertFalse(f.isSupported);
|
||||
}
|
||||
|
||||
assertTrue(checkedCount >= knownFeatureCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flattenOnMultipleFeatures() {
|
||||
FeatureSet featureSet = FeatureSet.newBuilder()
|
||||
.includeClientModificationFeatures(ClientModificationFeature.BasePath)
|
||||
.includeDataTypeFeatures(DataTypeFeature.Int32, DataTypeFeature.Array)
|
||||
.includeGlobalFeatures(GlobalFeature.Consumes, GlobalFeature.Examples)
|
||||
.includeParameterFeatures(ParameterFeature.Body, ParameterFeature.Query)
|
||||
.includeSecurityFeatures(SecurityFeature.BearerToken, SecurityFeature.BasicAuth, SecurityFeature.OAuth2_Implicit)
|
||||
.includeDocumentationFeatures(DocumentationFeature.Model)
|
||||
.includeSchemaSupportFeatures(SchemaSupportFeature.Composite)
|
||||
.build();
|
||||
|
||||
List<FeatureSet.FeatureSetFlattened> flattened = featureSet.flatten();
|
||||
List<FeatureSet.FeatureSetFlattened> supported = new ArrayList<>();
|
||||
flattened.forEach(f -> {
|
||||
if (f.isSupported) {
|
||||
supported.add(f);
|
||||
}
|
||||
});
|
||||
|
||||
// note that the order of these checks is deterministic, but unrelated to feature inclusion order in this test.
|
||||
assertEquals(supported.size(), 12);
|
||||
|
||||
Set<AnnotationType> toolingOnly = new HashSet<AnnotationType>() {{
|
||||
add(AnnotationType.ToolingExtension);
|
||||
}};
|
||||
Set<AnnotationType> oas2Only = new HashSet<AnnotationType>() {{
|
||||
add(AnnotationType.OAS2);
|
||||
}};
|
||||
Set<AnnotationType> oas3Only = new HashSet<AnnotationType>() {{
|
||||
add(AnnotationType.OAS3);
|
||||
}};
|
||||
Set<AnnotationType> bothSpecs = new HashSet<AnnotationType>() {{
|
||||
add(AnnotationType.OAS2);
|
||||
add(AnnotationType.OAS3);
|
||||
}};
|
||||
|
||||
assertEquals(supported.get(0).featureCategory, ClientModificationFeature.class.getSimpleName());
|
||||
assertEquals(supported.get(0).featureName, ClientModificationFeature.BasePath.name());
|
||||
assertEquals(new HashSet<>(supported.get(0).source), toolingOnly);
|
||||
|
||||
assertEquals(supported.get(1).featureCategory, DataTypeFeature.class.getSimpleName());
|
||||
assertEquals(supported.get(1).featureName, DataTypeFeature.Int32.name());
|
||||
assertEquals(new HashSet<>(supported.get(1).source), bothSpecs);
|
||||
|
||||
assertEquals(supported.get(2).featureCategory, DataTypeFeature.class.getSimpleName());
|
||||
assertEquals(supported.get(2).featureName, DataTypeFeature.Array.name());
|
||||
assertEquals(new HashSet<>(supported.get(2).source), bothSpecs);
|
||||
|
||||
assertEquals(supported.get(3).featureCategory, DocumentationFeature.class.getSimpleName());
|
||||
assertEquals(supported.get(3).featureName, DocumentationFeature.Model.name());
|
||||
assertEquals(new HashSet<>(supported.get(3).source), toolingOnly);
|
||||
|
||||
assertEquals(supported.get(4).featureCategory, SchemaSupportFeature.class.getSimpleName());
|
||||
assertEquals(supported.get(4).featureName, SchemaSupportFeature.Composite.name());
|
||||
assertEquals(new HashSet<>(supported.get(4).source), bothSpecs);
|
||||
|
||||
assertEquals(supported.get(5).featureCategory, GlobalFeature.class.getSimpleName());
|
||||
assertEquals(supported.get(5).featureName, GlobalFeature.Consumes.name());
|
||||
assertEquals(new HashSet<>(supported.get(5).source), oas2Only);
|
||||
|
||||
assertEquals(supported.get(6).featureCategory, GlobalFeature.class.getSimpleName());
|
||||
assertEquals(supported.get(6).featureName, GlobalFeature.Examples.name());
|
||||
assertEquals(new HashSet<>(supported.get(6).source), bothSpecs);
|
||||
|
||||
assertEquals(supported.get(7).featureCategory, ParameterFeature.class.getSimpleName());
|
||||
assertEquals(supported.get(7).featureName, ParameterFeature.Query.name());
|
||||
assertEquals(new HashSet<>(supported.get(7).source), bothSpecs);
|
||||
|
||||
assertEquals(supported.get(8).featureCategory, ParameterFeature.class.getSimpleName());
|
||||
assertEquals(supported.get(8).featureName, ParameterFeature.Body.name());
|
||||
assertEquals(new HashSet<>(supported.get(8).source), oas2Only);
|
||||
|
||||
assertEquals(supported.get(9).featureCategory, SecurityFeature.class.getSimpleName());
|
||||
assertEquals(supported.get(9).featureName, SecurityFeature.BasicAuth.name());
|
||||
assertEquals(new HashSet<>(supported.get(9).source), bothSpecs);
|
||||
|
||||
assertEquals(supported.get(10).featureCategory, SecurityFeature.class.getSimpleName());
|
||||
assertEquals(supported.get(10).featureName, SecurityFeature.BearerToken.name());
|
||||
assertEquals(new HashSet<>(supported.get(10).source), oas3Only);
|
||||
|
||||
assertEquals(supported.get(11).featureCategory, SecurityFeature.class.getSimpleName());
|
||||
assertEquals(supported.get(11).featureName, SecurityFeature.OAuth2_Implicit.name());
|
||||
assertEquals(new HashSet<>(supported.get(11).source), bothSpecs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flattenOnSingleFeatures() {
|
||||
FeatureSet featureSet = FeatureSet.newBuilder().includeClientModificationFeatures(ClientModificationFeature.BasePath).build();
|
||||
List<FeatureSet.FeatureSetFlattened> flattened = featureSet.flatten();
|
||||
List<FeatureSet.FeatureSetFlattened> supported = new ArrayList<>();
|
||||
flattened.forEach(f -> {
|
||||
if (f.isSupported) {
|
||||
supported.add(f);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(supported.size(), 1);
|
||||
assertEquals(supported.get(0).featureCategory, ClientModificationFeature.class.getSimpleName());
|
||||
assertEquals(supported.get(0).featureName, ClientModificationFeature.BasePath.name());
|
||||
assertEquals(new HashSet<>(supported.get(0).source), new HashSet<AnnotationType>() {{
|
||||
add(AnnotationType.ToolingExtension);
|
||||
}});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user