Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(xml-support): implement parsing and serialisation from/to Camel XML IO files #2009

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

mmelko
Copy link
Contributor

@mmelko mmelko commented Feb 13, 2025

  • This PR enables parsing From XML IO files to the Kaoto model and back
    • All the functionality is in src/serializers/xml
  • XML format is enabled in the Code view when XML is pasted.
  • When XML is detected, XMLCamelResourceSerializer is created in the CamelResource.
  • Parsing and processing relies on the provided Camel Catalog. Due to differences between catalogs, or missing features manual handling of some cases was necessary.
  • All Entities Camel Yaml Dsl entities currently supported in Kaoto can be parsed and serialized
  • Serializer Selector is added in the Web UI:
    • the selector is NOT added into VS Code
Screenshot 2025-02-20 at 21 54 18

Fixed issues:

@mmelko mmelko force-pushed the xml-support branch 3 times, most recently from c8dd60b to 5f8bb32 Compare February 13, 2025 22:10
Copy link

codecov bot commented Feb 13, 2025

Codecov Report

Attention: Patch coverage is 78.49315% with 157 lines in your changes missing coverage. Please review.

Project coverage is 78.66%. Comparing base (c04c425) to head (010d834).

Files with missing lines Patch % Lines
packages/ui/src/utils/camel-uri-helper.ts 2.12% 46 Missing ⚠️
...i/src/serializers/xml-camel-resource-serializer.ts 20.51% 31 Missing ⚠️
...tToolbar/SerializerSelector/SerializerSelector.tsx 0.00% 19 Missing ⚠️
...serializers/xml/serializers/step-xml-serializer.ts 86.77% 16 Missing ⚠️
...erializers/xml/serializers/kaoto-xml-serializer.ts 68.75% 15 Missing ⚠️
packages/ui/src/serializers/xml/xml-utils.ts 85.00% 6 Missing ⚠️
...ckages/ui/src/models/camel/camel-route-resource.ts 42.85% 4 Missing ⚠️
.../src/serializers/yaml-camel-resource-serializer.ts 66.66% 4 Missing ⚠️
...ts/Visualization/ContextToolbar/ContextToolbar.tsx 0.00% 3 Missing ⚠️
packages/ui/src/models/camel/camel-k-resource.ts 25.00% 3 Missing ⚠️
... and 7 more
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #2009      +/-   ##
============================================
+ Coverage     78.60%   78.66%   +0.06%     
  Complexity      367      367              
============================================
  Files           471      486      +15     
  Lines         14848    15552     +704     
  Branches       2758     2926     +168     
============================================
+ Hits          11671    12234     +563     
- Misses         3089     3230     +141     
  Partials         88       88              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@@ -101,7 +102,7 @@ export const SourceCode: FunctionComponent<SourceCodeProps> = (props) => {
code={props.code}
onCodeChange={props.onCodeChange}
customControls={customControls}
language={Language.yaml}
language={isXML(props.code) ? Language.xml : Language.yaml}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[curious-question] Do we already know this information from the resource's serializer?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. Serializers are considered at the resource level when CamelResources are being created, which happens in the useEntities hook

const [isOpen, setIsOpen] = useState(false);
const [selected, setSelected] = useState<'XML' | 'YAML'>(camelResource.getSerializer().getLabel() as 'XML' | 'YAML');

function onSelect(serializer: string) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to use function here? Couldn't we use an arrow function like the other components?

export const SerializerSelector: FunctionComponent = () => {
const { camelResource, updateSourceCodeFromEntities } = useContext(EntitiesContext)!;
const [isOpen, setIsOpen] = useState(false);
const [selected, setSelected] = useState<'XML' | 'YAML'>(camelResource.getSerializer().getLabel() as 'XML' | 'YAML');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems we're leaking this casting in many different places. What do you think starting from the very root? Meaning that at the top-most interface, we define a DSL property of type XML | YAML, and from that point, the serializer would have a method that returns one value statically. From there, we propagate that information up to this [selected, setSelected], and we won't need the <'XML' | 'YAML'> part as the type will be inferred from the serializer method.

Continuing on that path, I would leave it up to the camel resource how to instantiate the serializer, meaning that in the onSelect callback we would pass the serializer string and then the camel resource would change the serializer if finds it, otherwise it could throw an error.

In an ideal scenario, we would like to create new objects to the camel resource.

onSelect={(_event, value) => onSelect(value as string)}
onOpenChange={(isOpen) => setIsOpen(isOpen)}
toggle={toggle}
style={{ width: '20rem' }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we please move this to a dedicated SCSS file?

Comment on lines 39 to 40
onSelect={(_event, value) => onSelect(value as string)}
onOpenChange={(isOpen) => setIsOpen(isOpen)}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the onSelect attribute expects a void callback, but instead of providing one, we're passing a function that returns the output of the onSelect callback, could we write it in a void fashion, so it doesn't get decorated with return?

This:

() => doSomething();

get's transpiled to:

() => {
  return doSomething();
}

So for functions that don't need to return anything, is better to write them accordingly

Suggested change
onSelect={(_event, value) => onSelect(value as string)}
onOpenChange={(isOpen) => setIsOpen(isOpen)}
onSelect={(_event, value) => {
onSelect(value as string) }
}
onOpenChange={(isOpen) => {
setIsOpen(isOpen) }
}

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2023 Red Hat, Inc.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Copyright (C) 2023 Red Hat, Inc.
* Copyright (C) 2025 Red Hat, Inc.

* limitations under the License.
*/

import { describe } from 'node:test';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems suspicious 👀 , we're using jest, so this might break in older nodejs versions.

import { describe } from 'node:test';

});

it('should parse rest verbs correctly', () => {
const xml = `
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it possible to use an XML file instead? Even if it's not valid due to not having the <camel> tag, at least we would get a bit of autocompletion and coloring 😄 .

Coloring is important 😇

splitEntity,
throttleEntity,
} from '../../../stubs/eip-entity-snippets';
describe('parser basics', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
describe('parser basics', () => {
describe('parser basics', () => {

Comment on lines 34 to 45
export type EntityDefinition =
| CamelRouteVisualEntity
| CamelErrorHandlerVisualEntity
| CamelRestVisualEntity
| BeansEntity
| CamelInterceptFromVisualEntity
| CamelInterceptSendToEndpointVisualEntity
| CamelInterceptVisualEntity
| CamelRouteConfigurationVisualEntity
| CamelOnCompletionVisualEntity
| CamelOnExceptionVisualEntity
| CamelRestConfigurationVisualEntity;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it might be better to move this type somewhere else, maybe a bit higher in the structure, as this might come handy for other code.

@mmelko mmelko force-pushed the xml-support branch 2 times, most recently from 7aabd4a to 279cbdf Compare February 18, 2025 14:52
@mmelko mmelko force-pushed the xml-support branch 2 times, most recently from 862fe59 to 8849b16 Compare February 20, 2025 20:15
@mmelko mmelko changed the title [DRAFT] feat(xml-support): implement parsing and serialisation from/to Camel XML IO files feat(xml-support): implement parsing and serialisation from/to Camel XML IO files Feb 20, 2025
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
3 Security Hotspots

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants