All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.metaeffekt.artifact.analysis.utils.InventorySearch Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2021-2024 the original author or authors.
 *
 * Licensed 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 com.metaeffekt.artifact.analysis.utils;

import com.metaeffekt.resource.InventoryResource;
import org.metaeffekt.core.inventory.processor.model.Artifact;
import org.metaeffekt.core.inventory.processor.model.Inventory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

import static org.metaeffekt.core.inventory.processor.model.Constants.ASTERISK;

public class InventorySearch {

    private final static Logger LOG = LoggerFactory.getLogger(InventorySearch.class);

    private Inventory inventory;

    private Map> checksumArtifactMap = new HashMap<>();

    private Map> idArtifactMap = new HashMap<>();

    private Set artifactsWithWildcard = new HashSet<>();

    public InventorySearch(InventoryResource inventoryResource) {
        this(inventoryResource.getInventory());
    }

    public InventorySearch(Inventory inventory) {
        this.inventory = inventory == null ? new Inventory() : inventory;

        for (Artifact artifact : this.inventory.getArtifacts()) {
            contributeToMaps(artifact);
        }
    }

    private void contributeToMaps(Artifact artifact) {
        final String checksum = modulateChecksum(artifact);
        final String id = modulateId(artifact);

        checksumArtifactMap.computeIfAbsent(checksum, s -> new HashSet<>()).add(artifact);
        idArtifactMap.computeIfAbsent(id, s -> new HashSet<>()).add(artifact);

        if (id.contains(ASTERISK) && StringUtils.isEmpty(checksum)) {
            artifactsWithWildcard.add(artifact);
        }

        // support . matching
        if (StringUtils.hasText(artifact.getGroupId())) {
            final String compositeId = artifact.getGroupId() + "." + artifact.getId();
            idArtifactMap.computeIfAbsent(compositeId, s -> new HashSet<>()).add(artifact);
        }
    }

    private static String modulateChecksum(Artifact artifact) {
        String checksum = artifact.getChecksum();
        if (!StringUtils.hasText(checksum)) {
            checksum = artifact.get("Checksum (MD5)");
        }
        if (!StringUtils.hasText(checksum)) {
            checksum = null;
        }
        return checksum;
    }

    public Artifact findArtifactByIdAndChecksum(Artifact artifact) {
        if (artifact == null) return null;

        final String id = modulateId(artifact);
        final String checksum = modulateChecksum(artifact);

        if (id == null || checksum == null) {
            return null;
        }

        final Set artifacts = checksumArtifactMap.get(checksum);
        final Set artifactsById = idArtifactMap.get(id);
        if (artifacts != null && artifactsById != null) {
            final Set commonSet = new HashSet<>(artifacts);
            commonSet.retainAll(artifactsById);
            if (!commonSet.isEmpty()) {
                if (commonSet.size() > 1) {
                    LOG.warn("More than one artifact matches id and checksum!");
                }
                return commonSet.iterator().next();
            }
        }
        return null;
    }

    private static String modulateId(Artifact artifact) {
        return artifact.getId();
    }

    public Artifact findArtifactById(Artifact artifact) {
        if (artifact == null) return null;

        final String id = modulateId(artifact);

        if (id == null) return null;

        final Set artifacts = idArtifactMap.get(id);
        if (artifacts != null) {
            for (Artifact candidate : artifacts) {
                return candidate;
            }
        }
        return null;
    }

    public void close() {
        this.inventory = null;
    }

    public void add(Artifact artifact) {
        if (artifact == null) return;

        contributeToMaps(artifact);

        this.inventory.getArtifacts().add(artifact);
    }

    // FIXME: not yet optimized
    public Artifact findArtifactWildcardMatchingId(Artifact artifact) {
        int maximumMatchLength = -1;
        Artifact longestIdMatchCandidate = null;
        for (Artifact candidate : artifactsWithWildcard) {
            if (matchesOnId(artifact.getId(), candidate, true)) {
                int idLength = candidate.getId().length();
                if (candidate.getId().contains("*") && org.apache.commons.lang3.StringUtils.isEmpty(candidate.getChecksum())) {
                    if (idLength > maximumMatchLength) {
                        longestIdMatchCandidate = candidate;
                        maximumMatchLength = idLength;
                    }
                }
            }
        }
        return longestIdMatchCandidate;
    }

    // FIXME: this duplicates an inaccessible method from core
    private boolean matchesOnId(String id, Artifact candidate, boolean allowWildcards) {
        final String candidateId = candidate.getId();

        if (id == null && candidateId == null) {
            return true;
        }

        if (candidateId == null) {
            return false;
        }

        // check the ids match (exact)
        if (id != null) {
            if (id.equals(candidateId)) {
                return true;
            }
        }

        // check the ids match (allow wildcard)
        if (allowWildcards && ASTERISK.equals(candidate.getVersion())) {
            // check the wildcard is really used in the candidate id
            final int index = candidateId.indexOf(ASTERISK);
            if (index != -1) {
                String prefix = candidateId.substring(0, index);
                String suffix = candidateId.substring(index + 1);
                if (id.startsWith(prefix) && id.endsWith(suffix)) {
                    return true;
                }
            }
        }

        // NOTE: in this case, no VERSION_PLACEHOLDER agnostic match is appropriate

        return false;
    }

    public List getArtifacts() {
        return Collections.unmodifiableList(this.inventory.getArtifacts());
    }

    public Set findAllWithId(String id) {
        final Set artifacts = idArtifactMap.get(id);
        if (artifacts == null) return Collections.emptySet();
        return artifacts;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy