Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import static org.brapi.schematools.core.response.Response.fail;
import static org.brapi.schematools.core.response.Response.success;
import static org.brapi.schematools.core.utils.BrAPITypeUtils.unwrapType;
import static org.brapi.schematools.core.utils.BrAPITypeUtils.validateBrAPIMetadata;
import static org.brapi.schematools.core.utils.BrAPITypeUtils.mergeMetadata;
import static org.brapi.schematools.core.utils.StringUtils.toSingular;

/**
Expand Down Expand Up @@ -162,7 +164,7 @@ private Response<BrAPIClass> dereference(BrAPIClass type, Map<String, BrAPIType>
.name(brAPIAllOfType.getName())
.description(brAPIAllOfType.getDescription())
.module(brAPIAllOfType.getModule())
.metadata(brAPIAllOfType.getMetadata() != null ? brAPIAllOfType.getMetadata().toBuilder().build() : null)
.metadata(mergeBrAPITypeMetadata(brAPIAllOfType, typeMap))
.interfaces(extractInterfaces(brAPIAllOfType, typeMap)) ;

brAPIAllOfType.getExamples().forEach(builder::example);
Expand All @@ -175,6 +177,7 @@ private Response<BrAPIClass> dereference(BrAPIClass type, Map<String, BrAPIType>
}
}


private Response<List<BrAPIClass>> validate(List<BrAPIClass> brAPIClasses) {
Map<String, BrAPIClass> classesMap = brAPIClasses.stream().collect(Collectors.toMap(BrAPIType::getName, Function.identity()));

Expand Down Expand Up @@ -207,28 +210,6 @@ private Response<BrAPIType> validateType(final Map<String, BrAPIClass> classesMa
}
}

private Response<BrAPIMetadata> validateBrAPIMetadata(BrAPIClass brAPIClass) {
BrAPIMetadata metadata = brAPIClass.getMetadata();

if (metadata != null) {
int i = 0;
if (metadata.isPrimaryModel()) {
++i;
}
if (metadata.isRequest()) {
++i;
}
if (metadata.isParameters()) {
++i;
}
if (i > 1) {
return fail(Response.ErrorType.VALIDATION, String.format("In class '%s', 'primaryModel', 'request', 'properties', 'interface' are mutually exclusive, only one can be set to to true", brAPIClass.getName()));
}
}

return success(metadata);
}

private Response<BrAPIObjectProperty> validateProperty(Map<String, BrAPIClass> classesMap, BrAPIObjectType brAPIObjectType, BrAPIObjectProperty property) {
BrAPIType propertyType = property.getType();

Expand Down Expand Up @@ -289,7 +270,6 @@ private Response<BrAPIObjectProperty> validateProperty(Map<String, BrAPIClass> c
}

private List<BrAPIObjectProperty> extractProperties(List<BrAPIObjectProperty> properties, BrAPIType brAPIType, Map<String, BrAPIType> typeMap) {

if (brAPIType instanceof BrAPIObjectType brAPIObjectType) {
properties.addAll(brAPIObjectType.getProperties());
} else {
Expand Down Expand Up @@ -324,6 +304,27 @@ private boolean isInterface(BrAPIClass brAPIClass) {
return brAPIClass.getMetadata() != null && brAPIClass.getMetadata().isInterfaceClass();
}

private BrAPIMetadata mergeBrAPITypeMetadata(BrAPIType brAPIType, Map<String, BrAPIType> typeMap) {
if (brAPIType instanceof BrAPIObjectType brAPIObjectType) {
return brAPIObjectType.getMetadata() ;
} else {
if (brAPIType instanceof BrAPIAllOfType brAPIAllOfType) {
BrAPIMetadata metadata = brAPIAllOfType.getMetadata() ;

for(BrAPIType type : brAPIAllOfType.getAllTypes()) {
metadata = mergeMetadata(metadata, mergeBrAPITypeMetadata(type, typeMap)) ;
}

return metadata ;
} else {
if (brAPIType instanceof BrAPIReferenceType brAPIReferenceType) {
return mergeBrAPITypeMetadata(typeMap.get(brAPIReferenceType.getName()), typeMap);
}
}
}

return null;
}

private Response<List<BrAPIClass>> createBrAPISchemas(Path path) {
return createBrAPISchemas(path, findModule(path));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import static org.brapi.schematools.core.utils.StringUtils.toPlural;

/**
* Provides options for the generation of Controlled Vocabulary Endpoints
* Provides options for the generation of Controlled Vocabulary
*/
@Getter(AccessLevel.PRIVATE)
@Setter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import static org.brapi.schematools.core.utils.BrAPITypeUtils.unwrapType;
import static org.brapi.schematools.core.utils.StringUtils.escapeSingleSQLQuotes;
import static org.brapi.schematools.core.utils.StringUtils.removeCarriageReturns;
import static org.brapi.schematools.core.utils.StringUtils.toPlural;
import static org.brapi.schematools.core.utils.StringUtils.toSentenceCase;

@Slf4j
public class ANSICreateTableDDLGenerator implements CreateTableDDLGenerator {
Expand Down Expand Up @@ -52,42 +54,33 @@ public Response<String> generateDDLForObjectType(BrAPIObjectType brAPIObjectType
private class Generator {
private final BrAPIObjectType brAPIObjectType;
private final List<LinkTable> linkTables = new ArrayList<>();
private final List<ControlledVocabularyTable> controlledVocabularyTables = new ArrayList<>();
private int indent = 0 ;

public Generator(BrAPIObjectType brAPIObjectType) {
this.brAPIObjectType = brAPIObjectType;
}

public Response<String> generate() {

if (brAPIObjectType.getMetadata() != null && brAPIObjectType.getMetadata().getControlledVocabularyProperties() != null
&& !brAPIObjectType.getMetadata().getControlledVocabularyProperties().isEmpty()) {
brAPIObjectType.getProperties()
.stream()
.filter(property -> brAPIObjectType.getMetadata().getControlledVocabularyProperties().contains(property.getName()))
.map(property -> new ControlledVocabularyTable(brAPIObjectType, property))
.forEach(controlledVocabularyTables::add) ;
}

return createTableDefinition(
createTableName(brAPIObjectType),
() -> createTableDescription(brAPIObjectType),
() -> createColumnDefinitions(brAPIObjectType),
getTableDescription(brAPIObjectType),
findClusterColumns(brAPIObjectType)
).conditionalMapResultToResponse(!linkTables.isEmpty(), this::appendLinkTableDefinitions);
}

private Response<String> appendLinkTableDefinitions(String ddl) {
StringBuilder builder = new StringBuilder(ddl);

appendNewLine(builder) ;

return linkTables.stream()
.map(this::appendLinkTableDefinition)
.collect(Response.toList())
.mapResult(result -> String.join(newLine(), result))
.mapResult(builder::append)
.mapResult(StringBuilder::toString);
}

private Response<String> appendLinkTableDefinition(LinkTable linkTable) {
return createTableDefinition(
createLinkTableFullName(linkTable),
() -> createTableDescription(linkTable),
() -> createColumnDefinitions(linkTable),
getLinkTableDescription(linkTable),
findClusterColumns(linkTable));
)
.conditionalMapResultToResponse(options.isGeneratingLinkTables() && !linkTables.isEmpty(), this::appendLinkTableDefinitions)
.conditionalMapResultToResponse(options.getControlledVocabulary().isGenerating() && !controlledVocabularyTables.isEmpty(), this::appendControlledVocabularyDefinitions);
}

private Response<String> createTableDefinition(String tableName,
Expand Down Expand Up @@ -232,18 +225,6 @@ private List<String> findClusterColumns(BrAPIObjectType brAPIObjectType) {
return clusterColumns;
}

private List<String> findClusterColumns(LinkTable linkTable) {
if (linkTable.getDereferenceItemType() instanceof BrAPIObjectType childBrAPIObjectType) {
List<BrAPIObjectProperty> linkProperties = new ArrayList<>(options.getProperties().getLinkPropertiesFor(childBrAPIObjectType));
linkProperties.addAll(options.getProperties().getLinkPropertiesFor(linkTable.getParentType()));

return linkProperties.stream().map(BrAPIObjectProperty::getName).collect(Collectors.toList());

} else {
return Collections.emptyList() ;
}
}

private LinkType getLinkPropertiesFor(BrAPIObjectType brAPIObjectType, BrAPIObjectProperty brAPIObjectProperty, BrAPIType dereferenceType) {
return options.getProperties().getLinkTypeFor(brAPIObjectType, brAPIObjectProperty, dereferenceType).onFailDoWithResponse(this::warn).orElseResult(LinkType.NONE);
}
Expand Down Expand Up @@ -302,16 +283,56 @@ private Response<String> createTableDescription(BrAPIObjectType brAPIObjectType)

return success(builder.toString());
}

private Response<LinkType> getLinkTypeFor(BrAPIObjectType brAPIObjectType, BrAPIObjectProperty property) {
BrAPIType unwrappedType = unwrapType(property.getType());
BrAPIType dereferencedType = brAPIClassCache.dereferenceType(unwrappedType);

return options.getProperties().getLinkTypeFor(brAPIObjectType, property, dereferencedType);
}

private Response<String> appendLinkTableDefinitions(String ddl) {
StringBuilder builder = new StringBuilder(ddl);

appendNewLine(builder) ;

return linkTables.stream()
.map(this::appendLinkTableDefinition)
.collect(Response.toList())
.mapResult(result -> String.join(newLine(), result))
.mapResult(builder::append)
.mapResult(StringBuilder::toString);
}

private Response<String> appendLinkTableDefinition(LinkTable linkTable) {
return createTableDefinition(
createLinkTableFullName(linkTable),
() -> createTableDescription(linkTable),
() -> createColumnDefinitions(linkTable),
getTableComment(linkTable),
findClusterColumns(linkTable));
}

private String createLinkTableFullName(LinkTable linkedTable) {
return metadata.getTablePrefix() != null ?
metadata.getTablePrefix() + createLinkTableName(linkedTable) : createLinkTableName(linkedTable);
}

private String createLinkTableName(LinkTable linkedTable) {
return linkedTable.getDereferencedItemType().getName() + "By" + linkedTable.getParentType().getName();
}

private Response<String> createColumnDefinitions(LinkTable linkTable) {
if (linkTable.getDereferenceItemType() instanceof BrAPIObjectType childBrAPIObjectType) {
if (linkTable.getDereferencedItemType() instanceof BrAPIObjectType childBrAPIObjectType) {
List<BrAPIObjectProperty> linkProperties = new ArrayList<>(options.getProperties().getLinkPropertiesFor(childBrAPIObjectType));
linkProperties.addAll(options.getProperties().getLinkPropertiesFor(linkTable.getParentType()));

return createLinkObjectDefinition(linkProperties);

} else {
return fail(Response.ErrorType.VALIDATION, String.format("Cannot create link table column definitions from for '%s' to non-object type '%s'", linkTable.getParentType().getName(), linkTable.getDereferenceItemType().getName()));
return fail(Response.ErrorType.VALIDATION,
String.format("Cannot create link table column definitions from for '%s' to non-object type '%s'",
linkTable.getParentType().getName(), linkTable.getDereferencedItemType().getName()));
}
}

Expand All @@ -326,7 +347,7 @@ private Response<String> createTableDescription(LinkTable linkTable) {
builder.append(String.format("Creates a lookup table for property '%s' for '%s' to '%s'",
linkTable.getProperty().getName(),
linkTable.getParentType().getName(),
linkTable.getDereferenceItemType().getName()
linkTable.getDereferencedItemType().getName()
)) ;

appendNewLine(builder) ;
Expand All @@ -335,11 +356,80 @@ private Response<String> createTableDescription(LinkTable linkTable) {
return success(builder.toString());
}

private Response<LinkType> getLinkTypeFor(BrAPIObjectType brAPIObjectType, BrAPIObjectProperty property) {
BrAPIType unwrappedType = unwrapType(property.getType());
BrAPIType dereferencedType = brAPIClassCache.dereferenceType(unwrappedType);
private String getTableComment(LinkTable linkedTable) {
return String.format("Link table for %s to %s on property %s", linkedTable.getParentType().getName(), linkedTable.getDereferencedItemType().getName(), linkedTable.getProperty().getName());
}

return options.getProperties().getLinkTypeFor(brAPIObjectType, property, dereferencedType);
private List<String> findClusterColumns(LinkTable linkTable) {
if (linkTable.getDereferencedItemType() instanceof BrAPIObjectType childBrAPIObjectType) {
List<BrAPIObjectProperty> linkProperties = new ArrayList<>(options.getProperties().getLinkPropertiesFor(childBrAPIObjectType));
linkProperties.addAll(options.getProperties().getLinkPropertiesFor(linkTable.getParentType()));

return linkProperties.stream().map(BrAPIObjectProperty::getName).collect(Collectors.toList());

} else {
return Collections.emptyList() ;
}
}

private Response<String> appendControlledVocabularyDefinitions(String ddl) {
StringBuilder builder = new StringBuilder(ddl);

appendNewLine(builder) ;

return controlledVocabularyTables.stream()
.map(this::appendControlledVocabularyDefinition)
.collect(Response.toList())
.mapResult(result -> String.join(newLine(), result))
.mapResult(builder::append)
.mapResult(StringBuilder::toString);
}

private Response<String> appendControlledVocabularyDefinition(ControlledVocabularyTable controlledVocabularyTable) {
return createTableDefinition(
createControlledVocabularyFullName(controlledVocabularyTable),
() -> createTableDescription(controlledVocabularyTable),
() -> createColumnDefinitions(controlledVocabularyTable),
getTableComment(controlledVocabularyTable),
findClusterColumns(controlledVocabularyTable));
}

private String createControlledVocabularyFullName(ControlledVocabularyTable controlledVocabularyTable) {
return metadata.getTablePrefix() != null ?
metadata.getTablePrefix() + createControlledVocabularyName(controlledVocabularyTable) : createControlledVocabularyName(controlledVocabularyTable);
}

private String createControlledVocabularyName(ControlledVocabularyTable controlledVocabularyTable) {
return toSentenceCase(toPlural(controlledVocabularyTable.getProperty().getName())) ;
}

private Response<String> createColumnDefinitions(ControlledVocabularyTable controlledVocabularyTable) {

return createColumnDefinition(controlledVocabularyTable.getParentType(), controlledVocabularyTable.getProperty()) ;
}

private Response<String> createTableDescription(ControlledVocabularyTable controlledVocabularyTable) {

StringBuilder builder = new StringBuilder();

appendNewLine(builder) ;
builder.append(SQLGenerator.COMMENT_START);

appendNewLine(builder) ;
builder.append(options.getControlledVocabulary().getDescriptionFor(controlledVocabularyTable.getParentType(), controlledVocabularyTable.getProperty()));

appendNewLine(builder) ;
builder.append(SQLGenerator.COMMENT_END);

return success(builder.toString());
}

private String getTableComment(ControlledVocabularyTable controlledVocabularyTable) {
return String.format("Controlled Vocabulary table for property %s on %s", controlledVocabularyTable.getProperty().getName(), controlledVocabularyTable.getParentType().getName());
}

private List<String> findClusterColumns(ControlledVocabularyTable controlledVocabularyTable) {
return Collections.emptyList() ;
}

private Response<String> addColumnComment(BrAPIObjectType brAPIObjectType, BrAPIObjectProperty property, String columnDefinition) {
Expand Down Expand Up @@ -429,7 +519,9 @@ private Response<String> createLinkObjectDefinition(BrAPIObjectType parentType,
List<BrAPIObjectProperty> linkPropertiesFor = options.getProperties().getLinkPropertiesFor(brAPIObjectType);

if (linkPropertiesFor.isEmpty()) {
return fail(Response.ErrorType.VALIDATION, String.format("No link properties for property '%s' in '%s' with item type '%s'", property.getName(), parentType.getName(), brAPIObjectType.getName()));
return fail(Response.ErrorType.VALIDATION,
String.format("No link properties for property '%s' in '%s' with item type '%s'",
property.getName(), parentType.getName(), brAPIObjectType.getName()));
}

return createLinkObjectDefinition(linkPropertiesFor);
Expand Down Expand Up @@ -578,25 +670,20 @@ private Response<String> createArrayColumnType(BrAPIType itemType) {
fail(Response.ErrorType.VALIDATION, String.format("Unknown embedded array type '%s'", itemType.getName()));
};
}

private String createLinkTableFullName(LinkTable linkedTable) {
return metadata.getTablePrefix() != null ? metadata.getTablePrefix() + createLinkTableName(linkedTable) : createLinkTableName(linkedTable);
}

private String createLinkTableName(LinkTable linkedTable) {
return linkedTable.getDereferenceItemType().getName() + "By" + linkedTable.getParentType().getName();
}

private String getLinkTableDescription(LinkTable linkedTable) {
return String.format("Link table for %s to %s on property %s", linkedTable.getParentType().getName(), linkedTable.getDereferenceItemType().getName(), linkedTable.getProperty().getName());
}
}

@AllArgsConstructor
@Getter
private static class LinkTable {
private final BrAPIObjectType parentType;
private final BrAPIObjectProperty property;
private final BrAPIType dereferenceItemType;
private final BrAPIType dereferencedItemType;
}

@AllArgsConstructor
@Getter
private static class ControlledVocabularyTable {
private final BrAPIObjectType parentType;
private final BrAPIObjectProperty property;
}
}
Loading
Loading