#!/usr/bin/env python3 """Generate pure fluent API classes for all entities.""" import os template = '''package org.openmetadata.sdk.fluent; import java.util.*; import org.openmetadata.schema.api.data.Create{entity}; import org.openmetadata.schema.entity.data.{entity}; import org.openmetadata.sdk.client.OpenMetadataClient; /** * Pure Fluent API for {entity} operations. * * Usage: *
 * import static org.openmetadata.sdk.fluent.{plural}.*;
 *
 * // Create
 * {entity} {lower} = create()
 *     .name("{lower}_name")
 *     .withDescription("Description")
 *     .execute();
 *
 * // Find and load
 * {entity} {lower} = find({lower}Id)
 *     .includeOwner()
 *     .includeTags()
 *     .fetch();
 *
 * // Update
 * {entity} updated = find({lower}Id)
 *     .fetch()
 *     .withDescription("Updated description")
 *     .save();
 *
 * // Delete
 * find({lower}Id)
 *     .delete()
 *     .confirm();
 *
 * // List
 * list()
 *     .limit(50)
 *     .forEach({lower} -> process({lower}));
 * 
*/ public final class {plural} {{ private static OpenMetadataClient defaultClient; private {plural}() {{}} // Prevent instantiation public static void setDefaultClient(OpenMetadataClient client) {{ defaultClient = client; }} private static OpenMetadataClient getClient() {{ if (defaultClient == null) {{ throw new IllegalStateException("Client not initialized. Call {plural}.setDefaultClient() first."); }} return defaultClient; }} // ==================== Creation ==================== public static {entity}Creator create() {{ return new {entity}Creator(getClient()); }} public static {entity} create(Create{entity} request) {{ return getClient().{service}().create(request); }} // ==================== Finding/Retrieval ==================== public static {entity}Finder find(String id) {{ return new {entity}Finder(getClient(), id); }} public static {entity}Finder find(UUID id) {{ return find(id.toString()); }} public static {entity}Finder findByName(String fqn) {{ return new {entity}Finder(getClient(), fqn, true); }} // ==================== Listing ==================== public static {entity}Lister list() {{ return new {entity}Lister(getClient()); }} // ==================== Creator ==================== public static class {entity}Creator {{ private final OpenMetadataClient client; private final Create{entity} request = new Create{entity}(); {entity}Creator(OpenMetadataClient client) {{ this.client = client; }} public {entity}Creator name(String name) {{ request.setName(name); return this; }} public {entity}Creator withDescription(String description) {{ request.setDescription(description); return this; }} public {entity}Creator withDisplayName(String displayName) {{ request.setDisplayName(displayName); return this; }} {additionalCreatorMethods} public {entity} execute() {{ return client.{service}().create(request); }} public {entity} now() {{ return execute(); }} }} // ==================== Finder ==================== public static class {entity}Finder {{ private final OpenMetadataClient client; private final String identifier; private final boolean isFqn; private final Set includes = new HashSet<>(); {entity}Finder(OpenMetadataClient client, String identifier) {{ this(client, identifier, false); }} {entity}Finder(OpenMetadataClient client, String identifier, boolean isFqn) {{ this.client = client; this.identifier = identifier; this.isFqn = isFqn; }} public {entity}Finder includeOwner() {{ includes.add("owner"); return this; }} public {entity}Finder includeTags() {{ includes.add("tags"); return this; }} public {entity}Finder includeAll() {{ includes.addAll(Arrays.asList("owner", "tags", "followers", "domain")); return this; }} public Fluent{entity} fetch() {{ {entity} {lower}; if (includes.isEmpty()) {{ {lower} = isFqn ? client.{service}().getByName(identifier) : client.{service}().get(identifier); }} else {{ String fields = String.join(",", includes); {lower} = isFqn ? client.{service}().getByName(identifier, fields) : client.{service}().get(identifier, fields); }} return new Fluent{entity}({lower}, client); }} public {entity}Deleter delete() {{ return new {entity}Deleter(client, identifier); }} }} // ==================== Deleter ==================== public static class {entity}Deleter {{ private final OpenMetadataClient client; private final String id; private boolean recursive = false; private boolean hardDelete = false; {entity}Deleter(OpenMetadataClient client, String id) {{ this.client = client; this.id = id; }} public {entity}Deleter recursively() {{ this.recursive = true; return this; }} public {entity}Deleter permanently() {{ this.hardDelete = true; return this; }} public void confirm() {{ Map params = new HashMap<>(); if (recursive) params.put("recursive", "true"); if (hardDelete) params.put("hardDelete", "true"); client.{service}().delete(id, params); }} }} // ==================== Lister ==================== public static class {entity}Lister {{ private final OpenMetadataClient client; private final Map filters = new HashMap<>(); private Integer limit; private String after; {entity}Lister(OpenMetadataClient client) {{ this.client = client; }} public {entity}Lister limit(int limit) {{ this.limit = limit; return this; }} public {entity}Lister after(String cursor) {{ this.after = cursor; return this; }} public List fetch() {{ var params = new org.openmetadata.sdk.models.ListParams(); if (limit != null) params.setLimit(limit); if (after != null) params.setAfter(after); filters.forEach(params::addFilter); var response = client.{service}().list(params); List items = new ArrayList<>(); for ({entity} item : response.getData()) {{ items.add(new Fluent{entity}(item, client)); }} return items; }} public void forEach(java.util.function.Consumer action) {{ fetch().forEach(action); }} }} // ==================== Fluent Entity ==================== public static class Fluent{entity} {{ private final {entity} {lower}; private final OpenMetadataClient client; private boolean modified = false; public Fluent{entity}({entity} {lower}, OpenMetadataClient client) {{ this.{lower} = {lower}; this.client = client; }} public {entity} get() {{ return {lower}; }} public Fluent{entity} withDescription(String description) {{ {lower}.setDescription(description); modified = true; return this; }} public Fluent{entity} withDisplayName(String displayName) {{ {lower}.setDisplayName(displayName); modified = true; return this; }} public Fluent{entity} save() {{ if (modified) {{ {entity} updated = client.{service}().update({lower}.getId().toString(), {lower}); {lower}.setVersion(updated.getVersion()); modified = false; }} return this; }} public {entity}Deleter delete() {{ return new {entity}Deleter(client, {lower}.getId().toString()); }} {additionalFluentMethods} }} }} ''' # Entity configurations entities = { "Database": { "service": "databases", "package": "org.openmetadata.schema.entity.data", "additionalCreatorMethods": ''' public DatabaseCreator in(String service) { request.setService(service); return this; }''', "additionalFluentMethods": "" }, "DatabaseSchema": { "service": "databaseSchemas", "package": "org.openmetadata.schema.entity.data", "additionalCreatorMethods": ''' public DatabaseSchemaCreator in(String database) { request.setDatabase(database); return this; }''', "additionalFluentMethods": "" }, "Table": { "service": "tables", "package": "org.openmetadata.schema.entity.data", "additionalCreatorMethods": "", "additionalFluentMethods": "" }, "Dashboard": { "service": "dashboards", "package": "org.openmetadata.schema.entity.data", "additionalCreatorMethods": ''' public DashboardCreator in(String service) { request.setService(service); return this; } public DashboardCreator withCharts(String... chartIds) { request.setCharts(Arrays.asList(chartIds)); return this; }''', "additionalFluentMethods": ''' public FluentDashboard addChart(String chartId) { // Add chart logic modified = true; return this; }''' }, "Chart": { "service": "charts", "package": "org.openmetadata.schema.entity.data", "additionalCreatorMethods": ''' public ChartCreator in(String service) { request.setService(service); return this; }''', "additionalFluentMethods": "" }, "Pipeline": { "service": "pipelines", "package": "org.openmetadata.schema.entity.data", "additionalCreatorMethods": ''' public PipelineCreator in(String service) { request.setService(service); return this; }''', "additionalFluentMethods": "" }, "Topic": { "service": "topics", "package": "org.openmetadata.schema.entity.data", "additionalCreatorMethods": ''' public TopicCreator in(String service) { request.setService(service); return this; } public TopicCreator withPartitions(int partitions) { request.setPartitions(partitions); return this; } public TopicCreator withReplicationFactor(int factor) { request.setReplicationFactor(factor); return this; }''', "additionalFluentMethods": "" }, "Container": { "service": "containers", "package": "org.openmetadata.schema.entity.data", "additionalCreatorMethods": ''' public ContainerCreator in(String service) { request.setService(service); return this; }''', "additionalFluentMethods": "" }, "MlModel": { "service": "mlModels", "package": "org.openmetadata.schema.entity.data", "additionalCreatorMethods": ''' public MlModelCreator in(String service) { request.setService(service); return this; }''', "additionalFluentMethods": "" }, "SearchIndex": { "service": "searchIndexes", "package": "org.openmetadata.schema.entity.data", "additionalCreatorMethods": ''' public SearchIndexCreator in(String service) { request.setService(service); return this; }''', "additionalFluentMethods": "" }, "StoredProcedure": { "service": "storedProcedures", "package": "org.openmetadata.schema.entity.data", "additionalCreatorMethods": ''' public StoredProcedureCreator in(String databaseSchema) { request.setDatabaseSchema(databaseSchema); return this; }''', "additionalFluentMethods": "" }, "Query": { "service": "queries", "package": "org.openmetadata.schema.entity.data", "additionalCreatorMethods": ''' public QueryCreator withQuery(String sql) { request.setQuery(sql); return this; }''', "additionalFluentMethods": "" }, "User": { "service": "users", "package": "org.openmetadata.schema.entity.teams", "additionalCreatorMethods": ''' public UserCreator withEmail(String email) { request.setEmail(email); return this; } public UserCreator inTeams(UUID... teamIds) { request.setTeams(Arrays.asList(teamIds)); return this; }''', "additionalFluentMethods": ''' public FluentUser joinTeam(String teamId) { // Add team logic modified = true; return this; }''' }, "Team": { "service": "teams", "package": "org.openmetadata.schema.entity.teams", "additionalCreatorMethods": ''' public TeamCreator withUsers(UUID... userIds) { request.setUsers(Arrays.asList(userIds)); return this; }''', "additionalFluentMethods": ''' public FluentTeam addUser(String userId) { // Add user logic modified = true; return this; }''' }, "Role": { "service": "roles", "package": "org.openmetadata.schema.entity.teams", "additionalCreatorMethods": "", "additionalFluentMethods": "" }, "Policy": { "service": "policies", "package": "org.openmetadata.schema.entity.policies", "additionalCreatorMethods": "", "additionalFluentMethods": "" }, "Glossary": { "service": "glossaries", "package": "org.openmetadata.schema.entity.data", "additionalCreatorMethods": "", "additionalFluentMethods": "" }, "GlossaryTerm": { "service": "glossaryTerms", "package": "org.openmetadata.schema.entity.data", "additionalCreatorMethods": ''' public GlossaryTermCreator in(String glossary) { request.setGlossary(glossary); return this; }''', "additionalFluentMethods": "" }, "Classification": { "service": "classifications", "package": "org.openmetadata.schema.entity.classification", "additionalCreatorMethods": "", "additionalFluentMethods": "" }, "Tag": { "service": "tags", "package": "org.openmetadata.schema.entity.classification", "additionalCreatorMethods": ''' public TagCreator in(String classification) { request.setClassification(classification); return this; }''', "additionalFluentMethods": "" }, "DataProduct": { "service": "dataProducts", "package": "org.openmetadata.schema.entity.domains", "additionalCreatorMethods": ''' public DataProductCreator in(String domain) { request.setDomain(domain); return this; }''', "additionalFluentMethods": "" }, "Domain": { "service": "domains", "package": "org.openmetadata.schema.entity.domains", "additionalCreatorMethods": "", "additionalFluentMethods": "" }, "TestSuite": { "service": "testSuites", "package": "org.openmetadata.schema.tests", "additionalCreatorMethods": "", "additionalFluentMethods": "" }, "TestCase": { "service": "testCases", "package": "org.openmetadata.schema.tests", "additionalCreatorMethods": ''' public TestCaseCreator in(String testSuite) { request.setTestSuite(testSuite); return this; }''', "additionalFluentMethods": "" }, "TestDefinition": { "service": "testDefinitions", "package": "org.openmetadata.schema.tests", "additionalCreatorMethods": "", "additionalFluentMethods": "" }, "Metric": { "service": "metrics", "package": "org.openmetadata.schema.entity.data", "additionalCreatorMethods": "", "additionalFluentMethods": "" }, "DashboardDataModel": { "service": "dashboardDataModels", "package": "org.openmetadata.schema.entity.data", "additionalCreatorMethods": ''' public DashboardDataModelCreator in(String service) { request.setService(service); return this; }''', "additionalFluentMethods": "" } } # Generate files output_dir = "openmetadata-sdk/src/main/java/org/openmetadata/sdk/fluent" for entity, config in entities.items(): plural = entity + "s" if not entity.endswith("y") else entity[:-1] + "ies" lower = entity[0].lower() + entity[1:] content = template.format( entity=entity, plural=plural, lower=lower, service=config["service"], additionalCreatorMethods=config.get("additionalCreatorMethods", ""), additionalFluentMethods=config.get("additionalFluentMethods", "") ) # Fix package imports based on entity package content = content.replace( "org.openmetadata.schema.entity.data." + entity, config["package"] + "." + entity ) content = content.replace( "org.openmetadata.schema.api.data.Create" + entity, config["package"].replace(".entity.", ".api.") + ".Create" + entity ) filename = f"{output_dir}/{plural}.java.new" with open(filename, 'w') as f: f.write(content) print(f"Generated {filename}") print("\nPure fluent API files generated!")