-
-
Notifications
You must be signed in to change notification settings - Fork 441
UpgradeTool: Add Yaml configuration upgrader to convert tags list to map #4762
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
Conversation
Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
bf2f0da
to
60844f8
Compare
@@ -121,7 +101,7 @@ public void itemCopyUnitToMetadata() { | |||
logger.debug("{}: Already contains a 'unit' metadata, skipping it", itemName); | |||
} else { | |||
String unit = null; | |||
if (!noLink) { | |||
if (linkStorage != null && thingStorage != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the test on noLink
no more needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code is equivalent, except that this one helps avoid compiler warnings about possible unchecked null value.
...gradetool/src/main/java/org/openhab/core/tools/internal/YamlConfigurationV1TagsUpgrader.java
Outdated
Show resolved
Hide resolved
Great job regarding tool refactoring to make it more modular. I see your comment about the output loosing space and comments, that is a little annoying... |
Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
5079651
to
d8b10b2
Compare
If I run the upgrade tool just for upgrading tags, it requires the userdata folder. Can you avoid that?
Then if I provide the userdata folder, it runs and converts my YAML file but also tries to generate JSON file in userdata filder , as if it was not running only YAML upgrade:
I see I need to provide my paths with this syntax |
The userdata folder is required to save the current state of the upgrade tool, marking that the yaml tag step was performed.
|
I can make it so that when:
wdyt?
Unfortunately I don't have any Windows machine to test Java's behaviour, but I'll investigate this. |
@lolodomo can you try this on a
On Linux |
Looks like a good idea. |
|
Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
That means that providing a Windows style path should work. |
Maybe I have to doubled the back slashes ? |
No, it should be just standard one backslash. The doubling is just to escape it within Java's string literal. It needs to work with the standard Windows path convention on Windows otherwise it's a bug. Can you paste me the output when you give it You can run it from inside D:\conf in case it uses your current directory. |
With your last version. Without userdata:
With userdata:
|
Ok, I found the problem, I have to put my paths inside double quotes like that:
|
Windows command shell must be escaping backslashes? |
Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
4283911
to
de9a253
Compare
it now prints the directories before being interpreted by Path.of. Could you run it without double quotes? I'm curious what the program "sees". |
It simply consider that `\c is c. The backslash is then ignored.
if I double the backslash without double quotes, it also works:
I believe there is nothing more to investigate regarding Windows path. It is working as expected, I just have to provide paths properly, either by using double quotes around my path or by doubling baskslashes. Can you have a look regarding your idea to not log in JSON DB? |
I might print a warning if something like this is detected "[a-z]:[a-z]" - but that won't help if people gave a relative path e.g.
This was done a few commits back dd0fefb So if you specified --command but not --userdata it won't try to save the state. |
It crashes in that case!
|
Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
fixed |
Looks good now:
I am going to look at your code changes. |
tools/upgradetool/src/main/java/org/openhab/core/tools/UpgradeTool.java
Outdated
Show resolved
Hide resolved
tools/upgradetool/src/main/java/org/openhab/core/tools/UpgradeTool.java
Outdated
Show resolved
Hide resolved
Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
I've modified the directory behaviour so that:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
With the last changes, with a first call that do convert and a second call that do nothing:
|
Was this a request to change something? |
Not at all, it was just to show how it behaves as expected ;) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR refactors the Upgrade Tool by splitting each upgrade task into its own class, adds new CLI options, and introduces a YAML tags upgrader.
- Introduce
Upgrader
interface and move each upgrade task into a dedicated class - Add
YamlConfigurationV1TagsUpgrader
to convert V1 YAML tags lists into maps - Enhance
UpgradeTool
with--list-commands
,--userdata
, and--conf
options
Reviewed Changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
File | Description |
---|---|
tools/upgradetool/src/main/java/org/openhab/core/tools/internal/YamlConfigurationV1TagsUpgrader.java | New class converting YAML tags list to map |
tools/upgradetool/src/main/java/org/openhab/core/tools/internal/ScriptProfileUpgrader.java | Extract script profile upgrader into its own class |
tools/upgradetool/src/main/java/org/openhab/core/tools/internal/JSProfileUpgrader.java | Extract JS profile upgrader into its own class |
tools/upgradetool/src/main/java/org/openhab/core/tools/internal/ItemUnitToMetadataUpgrader.java | Extract item-unit-to-metadata upgrader into its own class |
tools/upgradetool/src/main/java/org/openhab/core/tools/Upgrader.java | Add Upgrader interface |
tools/upgradetool/src/main/java/org/openhab/core/tools/UpgradeTool.java | Load all upgraders dynamically; add new CLI options |
tools/upgradetool/pom.xml | Add Jackson YAML dependencies |
return path; | ||
} else { | ||
logger.warn( | ||
"The '{}' directory '{}' does not exist. Some tasks may fail. To set it, either set the environment variable ${{}} or provide a directory through the --{} option.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The placeholder $ {{}}
in the log message won’t print the environment variable name correctly. Replace it with a standard {}
placeholder so env
is substituted properly.
"The '{}' directory '{}' does not exist. Some tasks may fail. To set it, either set the environment variable ${{}} or provide a directory through the --{} option.", | |
"The '{}' directory '{}' does not exist. Some tasks may fail. To set it, either set the environment variable '{}' or provide a directory through the --{} option.", |
Copilot uses AI. Check for mistakes.
JsonStorage<ItemChannelLink> linkStorage = new JsonStorage<>(linkJsonDatabasePath.toFile(), null, 5, 0, 0, | ||
List.of()); | ||
|
||
List.copyOf(linkStorage.getKeys()).forEach(linkUid -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The iteration and update logic in ScriptProfileUpgrader
and JSProfileUpgrader
are nearly identical. Consider extracting common storage traversal and update steps into a shared utility or abstract base class to reduce duplication.
Copilot uses AI. Check for mistakes.
String command = commandLine.hasOption(OPT_COMMAND) ? commandLine.getOptionValue(OPT_COMMAND) : null; | ||
|
||
if (command != null && UPGRADERS.stream().filter(u -> u.getName().equals(command)).findAny().isEmpty()) { | ||
println("Unknown command: " + command); | ||
System.exit(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When an unknown command is encountered, it’s better to exit with a non-zero status (System.exit(1)
) to signal failure rather than 0
.
System.exit(0); | |
System.exit(1); |
Copilot uses AI. Check for mistakes.
fileContent.properties().forEach(entry -> { | ||
String key = entry.getKey(); | ||
JsonNode node = entry.getValue(); | ||
if (key.equals("tags")) { | ||
ObjectNode tagsMap = objectMapper.createObjectNode(); | ||
for (JsonNode tag : node) { | ||
if (tag.hasNonNull("uid")) { | ||
String uid = tag.get("uid").asText(); | ||
((ObjectNode) tag).remove("uid"); | ||
tagsMap.set(uid, tag); | ||
} else { | ||
logger.warn("Tag {} does not have a uid, skipping", tag); | ||
} | ||
} | ||
((ObjectNode) fileContent).set(key, tagsMap); | ||
} | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Iterating over all properties to find and replace tags
is less direct. You can retrieve the tags
node directly via fileContent.get("tags")
, transform it, and then replace it without scanning every property.
fileContent.properties().forEach(entry -> { | |
String key = entry.getKey(); | |
JsonNode node = entry.getValue(); | |
if (key.equals("tags")) { | |
ObjectNode tagsMap = objectMapper.createObjectNode(); | |
for (JsonNode tag : node) { | |
if (tag.hasNonNull("uid")) { | |
String uid = tag.get("uid").asText(); | |
((ObjectNode) tag).remove("uid"); | |
tagsMap.set(uid, tag); | |
} else { | |
logger.warn("Tag {} does not have a uid, skipping", tag); | |
} | |
} | |
((ObjectNode) fileContent).set(key, tagsMap); | |
} | |
}); | |
if (tagsNode != null && tagsNode.isArray()) { | |
ObjectNode tagsMap = objectMapper.createObjectNode(); | |
for (JsonNode tag : tagsNode) { | |
if (tag.hasNonNull("uid")) { | |
String uid = tag.get("uid").asText(); | |
((ObjectNode) tag).remove("uid"); | |
tagsMap.set(uid, tag); | |
} else { | |
logger.warn("Tag {} does not have a uid, skipping", tag); | |
} | |
} | |
((ObjectNode) fileContent).set("tags", tagsMap); | |
} |
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Take the copilot comments as an fyi, there doesn't seem to be any problematic in the code.
Input file criteria:
Output file will
version: 1
.yaml.org
yaml.org.1
See #3666 (comment)
Requires: openhab/openhab-distro#1740