davsclaus commented on code in PR #18410: URL: https://github.com/apache/camel/pull/18410#discussion_r2158320484
########## dsl/camel-jbang/camel-jbang-plugin-generate/src/main/java/org/apache/camel/dsl/jbang/core/commands/generate/CodeSchemaGenerator.java: ########## @@ -0,0 +1,331 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.dsl.jbang.core.commands.generate; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.victools.jsonschema.generator.Option; +import com.github.victools.jsonschema.generator.SchemaGenerator; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfig; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder; +import com.github.victools.jsonschema.generator.SchemaVersion; +import com.github.victools.jsonschema.module.jackson.JacksonModule; +import org.apache.camel.dsl.jbang.core.commands.CamelCommand; +import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; +import org.apache.camel.main.download.DependencyDownloaderClassLoader; +import org.apache.camel.main.download.MavenDependencyDownloader; +import org.apache.camel.tooling.maven.MavenArtifact; +import picocli.CommandLine; + +import java.io.File; +import java.nio.file.Paths; +import java.util.List; + +/** + * Command to generate JSON Schema for Camel components and Java objects. + * + * This command downloads the specified Camel component dependencies and generates + * a JSON Schema (Draft 2020-12) for the given fully qualified class name. + * + * Usage Examples: + * - camel generate schema fhir org.hl7.fhir.r4.model.Patient + * - camel generate schema http org.apache.camel.component.http.HttpConfiguration + * + * The generated schema includes: + * - Public and non-public fields (with getters) + * - Flattened enums using toString() + * - Jackson annotations support + * + * Exit Codes: + * - 0: Success + * - 1: Component not found or dependency download failed + * - 2: Class not found + * - 3: Schema generation failed + * - 4: General error + */ +@CommandLine.Command(name = "schema", + description = "Create a JSON schema for a given Camel component and Java Object") +public class CodeSchemaGenerator extends CamelCommand { + + @CommandLine.Parameters(description = "Camel component name (e.g., 'fhir', 'http', 'jms')", arity = "1") + private String camelComponent; + + @CommandLine.Parameters(description = "Fully qualified class name (e.g., 'org.hl7.fhir.r4.model.Patient')", arity = "1") + private String fullyQualifiedName; + + @CommandLine.Option(names = {"-v", "--version"}, Review Comment: We do not use shorthand args like -o -v -i -e etc as they are hard to remember for these commands that you dont use a million times a day. ########## dsl/camel-jbang/camel-jbang-plugin-generate/pom.xml: ########## @@ -93,6 +93,17 @@ <artifactId>jackson-databind</artifactId> </dependency> + <dependency> + <groupId>com.github.victools</groupId> + <artifactId>jsonschema-generator</artifactId> + <version>4.38.0</version> Review Comment: Should be in parent/pom ########## dsl/camel-jbang/camel-jbang-plugin-generate/src/main/java/org/apache/camel/dsl/jbang/core/commands/generate/CodeSchemaGenerator.java: ########## @@ -0,0 +1,331 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.dsl.jbang.core.commands.generate; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.victools.jsonschema.generator.Option; +import com.github.victools.jsonschema.generator.SchemaGenerator; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfig; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder; +import com.github.victools.jsonschema.generator.SchemaVersion; +import com.github.victools.jsonschema.module.jackson.JacksonModule; +import org.apache.camel.dsl.jbang.core.commands.CamelCommand; +import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; +import org.apache.camel.main.download.DependencyDownloaderClassLoader; +import org.apache.camel.main.download.MavenDependencyDownloader; +import org.apache.camel.tooling.maven.MavenArtifact; +import picocli.CommandLine; + +import java.io.File; +import java.nio.file.Paths; +import java.util.List; + +/** + * Command to generate JSON Schema for Camel components and Java objects. + * + * This command downloads the specified Camel component dependencies and generates + * a JSON Schema (Draft 2020-12) for the given fully qualified class name. + * + * Usage Examples: + * - camel generate schema fhir org.hl7.fhir.r4.model.Patient + * - camel generate schema http org.apache.camel.component.http.HttpConfiguration + * + * The generated schema includes: + * - Public and non-public fields (with getters) + * - Flattened enums using toString() + * - Jackson annotations support + * + * Exit Codes: + * - 0: Success + * - 1: Component not found or dependency download failed + * - 2: Class not found + * - 3: Schema generation failed + * - 4: General error + */ +@CommandLine.Command(name = "schema", + description = "Create a JSON schema for a given Camel component and Java Object") +public class CodeSchemaGenerator extends CamelCommand { + + @CommandLine.Parameters(description = "Camel component name (e.g., 'fhir', 'http', 'jms')", arity = "1") + private String camelComponent; + + @CommandLine.Parameters(description = "Fully qualified class name (e.g., 'org.hl7.fhir.r4.model.Patient')", arity = "1") + private String fullyQualifiedName; + + @CommandLine.Option(names = {"-v", "--version"}, + description = "Camel version to use (default: 4.12.0)") + private String camelVersion = "4.12.0"; // TODO get current version + + @CommandLine.Option(names = {"-o", "--output"}, + description = "Output file path (default: stdout)") + private String outputFile; + + @CommandLine.Option(names = {"--verbose"}, + description = "Enable verbose logging") + private boolean verbose = false; + + public CodeSchemaGenerator(CamelJBangMain main) { + super(main); + } + + @Override + public Integer doCall() throws Exception { + try { + if (verbose) { + + printer().println("Generating JSON Schema for component: " + camelComponent); + printer().println("Class: " + fullyQualifiedName); + printer().println("Camel version: " + camelVersion); + } + + // Validate inputs + if (camelComponent == null || camelComponent.trim().isEmpty()) { + printer().printErr("Error: Camel component name cannot be empty"); + return 4; + } + + if (fullyQualifiedName == null || fullyQualifiedName.trim().isEmpty()) { + printer().printErr("Error: Fully qualified class name cannot be empty"); + return 4; + } + + // Configure JSON Schema generator + JacksonModule jacksonModule = new JacksonModule(); + SchemaGeneratorConfig config = createSchemaGeneratorConfig(jacksonModule); + SchemaGenerator generator = new SchemaGenerator(config); + + // Download dependencies and create class loader + DependencyDownloaderClassLoader cl = getDependencyDownloaderClassLoader(camelComponent, camelVersion, verbose); + if (cl == null) { + return 1; // Error already reported + } + + // Set context class loader + ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(cl); + + // Load the target class + Class<?> targetClass = loadTargetClass(cl, fullyQualifiedName); + if (targetClass == null) { + return 2; // Error already reported + } + + // Generate schema + JsonNode schema = generateSchema(generator, targetClass); + if (schema == null) { + return 3; // Error already reported + } + + // Output schema + outputSchema(schema); + + if (verbose) { + printer().println("Schema generation completed successfully"); + } + + return 0; + + } finally { + Thread.currentThread().setContextClassLoader(originalClassLoader); + } + + } catch (Exception e) { + printer().printErr("Unexpected error during schema generation: " + e.getMessage()); + if (verbose) { + e.printStackTrace(); + } + return 4; + } + } + + /** + * Creates and configures the JSON Schema generator configuration. + */ + private SchemaGeneratorConfig createSchemaGeneratorConfig(JacksonModule jacksonModule) { + return new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_2020_12) + .with(jacksonModule) + .with(Option.PUBLIC_NONSTATIC_FIELDS) + .with(Option.NONPUBLIC_NONSTATIC_FIELDS_WITH_GETTERS) + .with(Option.NONPUBLIC_NONSTATIC_FIELDS_WITHOUT_GETTERS) + .with(Option.FLATTENED_ENUMS_FROM_TOSTRING) + .without(Option.FIELDS_DERIVED_FROM_ARGUMENTFREE_METHODS) + .without(Option.NONSTATIC_NONVOID_NONGETTER_METHODS) + .without(Option.NULLABLE_METHOD_RETURN_VALUES_BY_DEFAULT) + .without(Option.VOID_METHODS) + .without(Option.GETTER_METHODS) + .build(); + } + + /** + * Downloads dependencies and creates a class loader for the specified Camel component. + * + * @param camelComponent The name of the Camel component + * @param version The Camel version to use + * @param verbose Whether to enable verbose logging + * @return DependencyDownloaderClassLoader or null if failed + */ + private DependencyDownloaderClassLoader getDependencyDownloaderClassLoader( + String camelComponent, String version, boolean verbose) { + + try { + if (verbose) { + printer().println("Creating dependency downloader class loader..."); + } + + DependencyDownloaderClassLoader cl = new DependencyDownloaderClassLoader( + CodeSchemaGenerator.class.getClassLoader()); + + MavenDependencyDownloader downloader = new MavenDependencyDownloader(); + downloader.setClassLoader(cl); Review Comment: Can you add offline mode as well (see run etc) as some users dont want to download over the internet, but still allow maven to load from local disk (offline mode) ########## dsl/camel-jbang/camel-jbang-plugin-generate/src/main/java/org/apache/camel/dsl/jbang/core/commands/generate/CodeSchemaGenerator.java: ########## @@ -0,0 +1,331 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.dsl.jbang.core.commands.generate; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.victools.jsonschema.generator.Option; +import com.github.victools.jsonschema.generator.SchemaGenerator; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfig; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder; +import com.github.victools.jsonschema.generator.SchemaVersion; +import com.github.victools.jsonschema.module.jackson.JacksonModule; +import org.apache.camel.dsl.jbang.core.commands.CamelCommand; +import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; +import org.apache.camel.main.download.DependencyDownloaderClassLoader; +import org.apache.camel.main.download.MavenDependencyDownloader; +import org.apache.camel.tooling.maven.MavenArtifact; +import picocli.CommandLine; + +import java.io.File; +import java.nio.file.Paths; +import java.util.List; + +/** + * Command to generate JSON Schema for Camel components and Java objects. + * + * This command downloads the specified Camel component dependencies and generates + * a JSON Schema (Draft 2020-12) for the given fully qualified class name. + * + * Usage Examples: + * - camel generate schema fhir org.hl7.fhir.r4.model.Patient + * - camel generate schema http org.apache.camel.component.http.HttpConfiguration + * + * The generated schema includes: + * - Public and non-public fields (with getters) + * - Flattened enums using toString() + * - Jackson annotations support + * + * Exit Codes: + * - 0: Success + * - 1: Component not found or dependency download failed + * - 2: Class not found + * - 3: Schema generation failed + * - 4: General error + */ +@CommandLine.Command(name = "schema", + description = "Create a JSON schema for a given Camel component and Java Object") +public class CodeSchemaGenerator extends CamelCommand { + + @CommandLine.Parameters(description = "Camel component name (e.g., 'fhir', 'http', 'jms')", arity = "1") + private String camelComponent; + + @CommandLine.Parameters(description = "Fully qualified class name (e.g., 'org.hl7.fhir.r4.model.Patient')", arity = "1") + private String fullyQualifiedName; + + @CommandLine.Option(names = {"-v", "--version"}, Review Comment: Use --camel-version instead -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@camel.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org