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

Probable bug: method that nullifies model #1735

Merged
merged 4 commits into from
Oct 1, 2024

Conversation

cstamas
Copy link
Member

@cstamas cstamas commented Sep 21, 2024

As discovered by @desruisseaux , this method is once used for "change detection" (if result is not null, apply change), and once directly where it -- probably by mistake -- nullifies the field value.

@gnodet

@cstamas cstamas requested a review from gnodet September 21, 2024 14:54
@cstamas cstamas self-assigned this Sep 21, 2024
@cstamas cstamas marked this pull request as ready for review September 21, 2024 15:43
@cstamas cstamas changed the title Sus method that nullifies model Probably bug: method that nullifies model Sep 21, 2024
@cstamas cstamas changed the title Probably bug: method that nullifies model Probable bug: method that nullifies model Sep 21, 2024
/**
* Returns aligned path or {@code null} if no need for change.
*/
private String mayAlignToBaseDirectoryOrNull(String path, Path basedir) {
String newPath = pathTranslator.alignToBaseDirectory(path, basedir);
return Objects.equals(path, newPath) ? null : newPath;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the above line should be removed.

@@ -107,7 +107,7 @@ private <T> List<T> map(List<T> resources, Function<T, T> mapper) {

private Resource alignToBaseDirectory(Resource resource, Path basedir) {
if (resource != null) {
String newDir = alignToBaseDirectory(resource.getDirectory(), basedir);
String newDir = mayAlignToBaseDirectoryOrNull(resource.getDirectory(), basedir);
if (newDir != null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This check should be changed to if (!Objects.equals(newDir, resource.getDirectory())

/**
* Returns aligned path or {@code null} if no need for change.
*/
private String mayAlignToBaseDirectoryOrNull(String path, Path basedir) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove this new method.

@gnodet
Copy link
Contributor

gnodet commented Sep 23, 2024

Originally, the code had the following:

    private String alignToBaseDirectory(String path, Path basedir) {
        return pathTranslator.alignToBaseDirectory(path, basedir);
    }

without the null return value.
We should restore this behavior and inline the equality check into the caller method.

@desruisseaux
Copy link
Contributor

A slight amendment is to modify the method as below (with null return value replaced by the old value). It may allow to reuse more existing objects compared to inline equality check in alignToBaseDirectory(Resource), because alignToBaseDirectory(String) is also invoked directly elsewhere.

/**
 * Returns a path relocated to the given base directory. If the result of this operation
 * is the same path as before, then this method returns the old {@code path} instance.
 * It is okay for the caller to compare the {@link String} instances using the identity
 * comparator for detecting changes.
 *
 * @param path the path to relocate, or {@code null}
 * @param basedir the new base directory
 * @return relocated path, or {@code null} if the given path was null
 */
private String alignToBaseDirectory(String path, Path basedir) {
    String newPath = pathTranslator.alignToBaseDirectory(path, basedir);
    return Objects.equals(path, newPath) ? path : newPath;
}

And replace null check by identity check:

/**
 * Returns a resource with all properties identical to the given resource, except the paths
 * which are resolved according the given {@code basedir}. If the paths are unchanged, then
 * this method returns the previous instance.
 *
 * @param resource the resource to relocate, or {@code null}
 * @param basedir the new base directory
 * @return relocated resource, or {@code null} if the given resource was null
 */
@SuppressWarnings("StringEquality") // Identity comparison is ok in this method.
private Resource alignToBaseDirectory(Resource resource, Path basedir) {
    if (resource != null) {
        String oldDir = resource.getDirectory();
        String newDir = alignToBaseDirectory(oldDir, basedir);
        if (newDir != oldDir) {
            return resource.withDirectory(newDir);
        }
    }
    return resource;
}

@gnodet
Copy link
Contributor

gnodet commented Sep 23, 2024

A slight amendment is to modify the method as below (with null return value replaced by the old value). It may allow to reuse more existing objects compared to inline equality check in alignToBaseDirectory(Resource), because alignToBaseDirectory(String) is also invoked directly elsewhere.

/**
 * Returns a path relocated to the given base directory. If the result of this operation
 * is the same path as before, then this method returns the old {@code path} instance.
 * It is okay for the caller to compare the {@link String} instances using the identity
 * comparator for detecting changes.
 *
 * @param path the path to relocate, or {@code null}
 * @param basedir the new base directory
 * @return relocated path, or {@code null} if the given path was null
 */
private String alignToBaseDirectory(String path, Path basedir) {
    String newPath = pathTranslator.alignToBaseDirectory(path, basedir);
    return Objects.equals(path, newPath) ? path : newPath;
}

And replace null check by identity check:

/**
 * Returns a resource with all properties identical to the given resource, except the paths
 * which are resolved according the given {@code basedir}. If the paths are unchanged, then
 * this method returns the previous instance.
 *
 * @param resource the resource to relocate, or {@code null}
 * @param basedir the new base directory
 * @return relocated resource, or {@code null} if the given resource was null
 */
@SuppressWarnings("StringEquality") // Identity comparison is ok in this method.
private Resource alignToBaseDirectory(Resource resource, Path basedir) {
    if (resource != null) {
        String oldDir = resource.getDirectory();
        String newDir = alignToBaseDirectory(oldDir, basedir);
        if (newDir != oldDir) {
            return resource.withDirectory(newDir);
        }
    }
    return resource;
}

Good point. In order to optimise things further, I think the above function needs to return null when nothing has changed. Or the map method could be adapted to check for object identity equality rather than null.

@desruisseaux
Copy link
Contributor

In order to optimise things further, I think the above function needs to return null when nothing has changed. Or the map method could be adapted to check for object identity equality rather than null.

I was thinking to cascade the identity checks, as map is used not only for Resource.

@gnodet gnodet added this to the 4.0.0-beta-5 milestone Oct 1, 2024
Copy link
Contributor

@gnodet gnodet left a comment

Choose a reason for hiding this comment

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

LGTM
@desruisseaux do you want to add anything to this PR ?

@desruisseaux
Copy link
Contributor

Nothing to add. Thanks

@gnodet gnodet merged commit 1062d05 into apache:master Oct 1, 2024
13 checks passed
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.

3 participants