Skip to content

Commit

Permalink
Story/915/configurable tabulators (finos#791)
Browse files Browse the repository at this point in the history
* add config for tabulators

* Test updated rosettta configuration

* save

* Implement new tabulator naming logic

* rename

* test config tabulate generation

* add configurable tabulator test

* update gitignore so that it doesn't ignore code inside report folders
  • Loading branch information
davidalk authored Jul 12, 2024
1 parent 2508d17 commit 0f7f74a
Show file tree
Hide file tree
Showing 16 changed files with 371 additions and 18 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ plugin.xml_gen
**/*.iml
.checkstyle
.classpath
rosetta-profiling/dependency-reduced-pom.xml

**/.settings
**/src-gen/
Expand All @@ -27,4 +28,4 @@ com.regnosys.rosetta.web/
.tycho-consumer-pom.xml

# CVE scan reports
reports/
./reports/
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public RosettaConfiguration get() {
return new RosettaConfiguration(
new RosettaModelConfiguration("Just another Rosetta model"),
List.of(),
new RosettaGeneratorsConfiguration(n -> true)
new RosettaGeneratorsConfiguration()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ public class RosettaConfiguration {
private final List<RosettaDependencyConfiguration> dependencies;
private final RosettaGeneratorsConfiguration generators;

public RosettaConfiguration(RosettaModelConfiguration model, List<RosettaDependencyConfiguration> dependencies,
public RosettaConfiguration(RosettaModelConfiguration model,
List<RosettaDependencyConfiguration> dependencies,
RosettaGeneratorsConfiguration generators) {
this.model = model;
this.dependencies = dependencies;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.regnosys.rosetta.config;

import java.util.List;
import java.util.function.Predicate;

import javax.inject.Inject;
Expand All @@ -9,18 +10,24 @@
@ProvidedBy(RosettaGeneratorsConfiguration.Provider.class)
public class RosettaGeneratorsConfiguration {
private final Predicate<String> namespaceFilter;
private final RosettaTabulatorConfiguration rosettaTabulatorConfiguration;

public RosettaGeneratorsConfiguration() {
this(n -> true);
this(n -> true, new RosettaTabulatorConfiguration(List.of()));
}
public RosettaGeneratorsConfiguration(Predicate<String> namespaceFilter) {
public RosettaGeneratorsConfiguration(Predicate<String> namespaceFilter, RosettaTabulatorConfiguration tabulators) {
this.namespaceFilter = namespaceFilter;
this.rosettaTabulatorConfiguration = tabulators;
}

public Predicate<String> getNamespaceFilter() {
return namespaceFilter;
}

public RosettaTabulatorConfiguration getTabulators() {
return rosettaTabulatorConfiguration;
}

public static class Provider implements javax.inject.Provider<RosettaGeneratorsConfiguration> {
private final RosettaConfiguration config;
@Inject
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.regnosys.rosetta.config;

import java.util.List;

import javax.inject.Inject;

public class RosettaTabulatorConfiguration {
private final List<String> annotations;

public RosettaTabulatorConfiguration(List<String> annotations) {
this.annotations = annotations;
}

public List<String> getAnnotations() {
return annotations;
}

public static class Provider implements javax.inject.Provider<RosettaTabulatorConfiguration> {
private final RosettaConfiguration config;
@Inject
public Provider(RosettaConfiguration config) {
this.config = config;
}

@Override
public RosettaTabulatorConfiguration get() {
return config.getGenerators().getTabulators();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.regnosys.rosetta.config.RosettaConfiguration;
import com.regnosys.rosetta.config.RosettaGeneratorsConfiguration;
import com.regnosys.rosetta.config.RosettaModelConfiguration;
import com.regnosys.rosetta.config.RosettaTabulatorConfiguration;

public class FileBasedRosettaConfigurationProvider implements Provider<RosettaConfiguration> {
private static final Logger LOGGER = LoggerFactory.getLogger(FileBasedRosettaConfigurationProvider.class);
Expand All @@ -33,7 +34,8 @@ public FileBasedRosettaConfigurationProvider(DefaultRosettaConfigurationProvider
this.mapper = new ObjectMapper(new YAMLFactory())
.addMixIn(RosettaConfiguration.class, RosettaConfigurationMixin.class)
.addMixIn(RosettaModelConfiguration.class, RosettaModelConfigurationMixin.class)
.addMixIn(RosettaGeneratorsConfiguration.class, RosettaGeneratorsConfigurationMixin.class);
.addMixIn(RosettaGeneratorsConfiguration.class, RosettaGeneratorsConfigurationMixin.class)
.addMixIn(RosettaTabulatorConfiguration.class, RosettaTabulatorConfigurationMixin.class);
mapper.configOverride(RosettaGeneratorsConfiguration.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
mapper.configOverride(NamespaceFilter.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
mapper.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.regnosys.rosetta.config.RosettaTabulatorConfiguration;

public abstract class RosettaGeneratorsConfigurationMixin {
@JsonCreator
public RosettaGeneratorsConfigurationMixin(
@JsonProperty("namespaces") @JsonDeserialize(as=NamespaceFilter.class) Predicate<String> namespaceFilter) {}
@JsonProperty("namespaces") @JsonDeserialize(as=NamespaceFilter.class) Predicate<String> namespaceFilter,
@JsonProperty("tabulators") RosettaTabulatorConfiguration tabulators) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.regnosys.rosetta.config.file;

import java.util.List;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public abstract class RosettaTabulatorConfigurationMixin {
@JsonCreator
public RosettaTabulatorConfigurationMixin(@JsonProperty("annotations") List<String> annotations ) {}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,17 @@ import com.regnosys.rosetta.rosetta.RosettaReport
import com.regnosys.rosetta.rosetta.RosettaRule
import com.regnosys.rosetta.generator.java.types.JavaTypeUtil
import com.regnosys.rosetta.rosetta.simple.Function
import com.regnosys.rosetta.config.RosettaConfiguration

class TabulatorGenerator {
private interface TabulatorContext {
def boolean needsTabulator(Data type)
def boolean isTabulated(Attribute attr)
def JavaClass<Tabulator<?>> toTabulatorJavaClass(Data type)
def Optional<RosettaRule> getRule(Attribute attr)
def Function getFunction()
}

@org.eclipse.xtend.lib.annotations.Data
private static class ReportTabulatorContext implements TabulatorContext {
extension RosettaExtensions
Expand Down Expand Up @@ -79,7 +82,12 @@ class TabulatorGenerator {
Optional.ofNullable(ruleMap.get(attr))
}

override getFunction() {
throw new UnsupportedOperationException("getFunction not available for ReportTabulatorContext")
}

}
@Deprecated
@org.eclipse.xtend.lib.annotations.Data
private static class ProjectionTabulatorContext implements TabulatorContext {
extension JavaTypeTranslator
Expand All @@ -94,15 +102,44 @@ class TabulatorGenerator {
}

override toTabulatorJavaClass(Data type) {
type.toTabulatorJavaClass(projection)
type.toProjectionTabulatorJavaClass(projection)
}

override getRule(Attribute attr) {
Optional.empty
}

override getFunction() {
projection
}


}
@org.eclipse.xtend.lib.annotations.Data
private static class FunctionTabulatorContext implements TabulatorContext {
extension JavaTypeTranslator
Function function

override needsTabulator(Data type) {
true
}

override isTabulated(Attribute attr) {
true
}

override toTabulatorJavaClass(Data type) {
type.toTabulatorJavaClass(function)
}

override getRule(Attribute attr) {
Optional.empty
}

}

@Inject RosettaTypeProvider typeProvider
@Inject RosettaConfiguration rosettaConfiguration
@Inject extension JavaTypeTranslator typeTranslator
@Inject extension ImportManagerExtension

Expand Down Expand Up @@ -132,25 +169,25 @@ class TabulatorGenerator {
}

def generate(IFileSystemAccess2 fsa, Function func) {
if (func.isProjection) {
val tabulatorClass = func.toProjectionTabulatorJavaClass
if (func.isFunctionTabulatable) {
val tabulatorClass = func.toApplicableTabulatorClass
val topScope = new JavaScope(tabulatorClass.packageName)

val projectionType = typeProvider.getRTypeOfSymbol(func.output)
if (projectionType instanceof RDataType) {
val context = new ProjectionTabulatorContext(typeTranslator, func)
val context = createFunctionTabulatorContext(typeTranslator, func)

val classBody = projectionType.data.mainTabulatorClassBody(context, topScope, tabulatorClass)
val content = buildClass(tabulatorClass.packageName, classBody, topScope)
fsa.generateFile(tabulatorClass.canonicalName.withForwardSlashes + ".java", content)

recursivelyGenerateProjectionTypeTabulators(fsa, projectionType.data, context, newHashSet)
recursivelyGenerateFunctionTypeTabulators(fsa, projectionType.data, context, newHashSet)
}
}
}
private def void recursivelyGenerateProjectionTypeTabulators(IFileSystemAccess2 fsa, Data type, ProjectionTabulatorContext context, Set<Data> visited) {
private def void recursivelyGenerateFunctionTypeTabulators(IFileSystemAccess2 fsa, Data type, TabulatorContext context, Set<Data> visited) {
if (visited.add(type)) {
val tabulatorClass = type.toTabulatorJavaClass(context.projection)
val tabulatorClass = context.toTabulatorJavaClass(type)
val topScope = new JavaScope(tabulatorClass.packageName)

val classBody = type.tabulatorClassBody(context, topScope, tabulatorClass)
Expand All @@ -161,7 +198,7 @@ class TabulatorGenerator {
.allNonOverridesAttributes
.map[typeProvider.getRTypeOfSymbol(it)]
.filter(RDataType)
.forEach[recursivelyGenerateProjectionTypeTabulators(fsa, data, context, visited)]
.forEach[recursivelyGenerateFunctionTypeTabulators(fsa, data, context, visited)]
}
}

Expand All @@ -171,8 +208,29 @@ class TabulatorGenerator {
new ReportTabulatorContext(extensions, typeTranslator, ruleMap, ruleSource)
}

private def boolean isProjection(Function func) {
func.annotations.findFirst[annotation.name == "projection"] !== null
private def boolean isFunctionTabulatable(Function func) {
if (shouldGenerateLegacyTabulator) {
return func.isAnnotatedWith("projection")
} else {
val annotations = rosettaConfiguration.generators.tabulators.annotations
annotations.findFirst[func.isAnnotatedWith(it)] !== null
}
}

private def boolean isAnnotatedWith(Function func, String with) {
func.annotations.findFirst[annotation.name == with] !== null
}

private def boolean shouldGenerateLegacyTabulator() {
(rosettaConfiguration.generators.tabulators.annotations ?: List.of()).empty
}

private def TabulatorContext createFunctionTabulatorContext(JavaTypeTranslator typeTranslator, Function func) {
shouldGenerateLegacyTabulator ? new ProjectionTabulatorContext(typeTranslator, func) : new FunctionTabulatorContext(typeTranslator, func)
}

private def JavaClass<Tabulator<?>> toApplicableTabulatorClass(Function func) {
shouldGenerateLegacyTabulator ? func.toProjectionTabulatorJavaClass : func.toTabulatorJavaClass
}

private def StringConcatenationClient mainTabulatorClassBody(Data inputType, TabulatorContext context, JavaScope topScope, JavaClass<Tabulator<?>> tabulatorClass) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,16 +153,28 @@ private Optional<RosettaExternalRuleSource> findContainingSuperRuleSource(Data t
}
return Optional.ofNullable(ruleSource.getSuperRuleSource()).flatMap(s -> findContainingSuperRuleSource(type, s));
}
@Deprecated
public JavaClass<Tabulator<?>> toProjectionTabulatorJavaClass(Function projection) {
return generatedJavaClassService.toJavaProjectionTabulator(getSymbolId(projection));
}
public JavaClass<Tabulator<?>> toTabulatorJavaClass(Data type, Function projection) {
@Deprecated
public JavaClass<Tabulator<?>> toProjectionTabulatorJavaClass(Data type, Function projection) {
ModelSymbolId typeId = getSymbolId(type);
ModelSymbolId projectionId = getSymbolId(projection);
DottedPath packageName = projectionId.getNamespace().child("projections");
String simpleName = typeId.getName() + projection.getName() + "TypeTabulator";
return new GeneratedJavaClass<>(packageName, simpleName, new com.fasterxml.jackson.core.type.TypeReference<Tabulator<?>>() {});
}
public JavaClass<Tabulator<?>> toTabulatorJavaClass(Function function) {
return generatedJavaClassService.toJavaFunctionTabulator(getSymbolId(function));
}
public JavaClass<Tabulator<?>> toTabulatorJavaClass(Data type, Function function) {
ModelSymbolId typeId = getSymbolId(type);
ModelSymbolId projectionId = getSymbolId(function);
DottedPath packageName = projectionId.getNamespace().child("tabulator");
String simpleName = typeId.getName() + function.getName() + "TypeTabulator";
return new GeneratedJavaClass<>(packageName, simpleName, new com.fasterxml.jackson.core.type.TypeReference<Tabulator<?>>() {});
}
public JavaClass<?> toDeepPathUtilJavaClass(Data choiceType) {
ModelSymbolId typeId = getSymbolId(choiceType);
DottedPath packageName = typeId.getNamespace().child("util");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,19 @@ public JavaClass<Tabulator<?>> toJavaReportTabulator(ModelReportId id) {
return new GeneratedJavaClass<>(packageName, simpleName, new TypeReference<Tabulator<?>>() {});
}

@Deprecated
public JavaClass<Tabulator<?>> toJavaProjectionTabulator(ModelSymbolId id) {
DottedPath packageName = id.getNamespace().child("projections");
String simpleName = id.getName() + "ProjectionTabulator";
return new GeneratedJavaClass<>(packageName, simpleName, new TypeReference<Tabulator<?>>() {});
}

public JavaClass<Tabulator<?>> toJavaFunctionTabulator(ModelSymbolId id) {
DottedPath packageName = id.getNamespace().child("tabulator");
String simpleName = id.getName() + "Tabulator";
return new GeneratedJavaClass<>(packageName, simpleName, new TypeReference<Tabulator<?>>() {});
}

public JavaClass<RosettaFunction> toJavaFunction(ModelSymbolId id) {
DottedPath packageName = id.getNamespace().child("functions");
String simpleName = id.getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;

import com.google.inject.Guice;
Expand Down Expand Up @@ -35,6 +36,13 @@ public Class<? extends RosettaConfigurationFileProvider> bindRosettaConfiguratio
assertFalse(filter.test("foo"));
assertTrue(filter.test("abc.def"));
assertFalse(filter.test("abc.def.sub"));

assertNotNull(config.getGenerators().getTabulators());
List<String> annotations = config.getGenerators().getTabulators().getAnnotations();
assertEquals(2, annotations.size());
assertTrue(annotations.contains("projection"));
assertTrue(annotations.contains("enrich"));

}

private static class MyConfigFileProvider extends RosettaConfigurationFileProvider {
Expand All @@ -44,3 +52,4 @@ public URL get() {
}
}
}
;
Loading

0 comments on commit 0f7f74a

Please sign in to comment.