com.metaeffekt.mirror.contents.msrcdata.MsrcSupersedeNode 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.mirror.contents.msrcdata;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.json.JSONObject;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
public class MsrcSupersedeNode {
private final String kbId;
private final String articleUrl;
private final String downloadUrl;
private final Map productRelations = new HashMap<>();
public MsrcSupersedeNode(String kbId) {
this(kbId, null, null);
}
public MsrcSupersedeNode(String kbId, String articleUrl, String downloadUrl) {
this.kbId = kbId;
this.articleUrl = articleUrl;
this.downloadUrl = downloadUrl;
}
public void addSupersededBy(String product, MsrcSupersedeNode node) {
productRelations.computeIfAbsent(product, k -> new MsrcSupersedeNodeRelations()).addSupersededBy(node);
}
public void addSupersededBy(String product, Collection supersededBy) {
productRelations.computeIfAbsent(product, k -> new MsrcSupersedeNodeRelations()).addSupersededBy(supersededBy);
}
public void addSupersedes(String product, MsrcSupersedeNode node) {
productRelations.computeIfAbsent(product, k -> new MsrcSupersedeNodeRelations()).addSupersedes(node);
}
public void addSupersedes(String product, Collection superseded) {
productRelations.computeIfAbsent(product, k -> new MsrcSupersedeNodeRelations()).addSupersedes(superseded);
}
public void addAffectsVulnerability(String product, String vulnerabilityId) {
productRelations.computeIfAbsent(product, k -> new MsrcSupersedeNodeRelations()).addAffectsVulnerability(vulnerabilityId);
}
public void addAffectsVulnerability(String product, Collection vulnerabilityIds) {
productRelations.computeIfAbsent(product, k -> new MsrcSupersedeNodeRelations()).addAffectsVulnerability(vulnerabilityIds);
}
public String getKbId() {
return kbId;
}
public String getArticleUrl() {
return articleUrl;
}
public String getDownloadUrl() {
return downloadUrl;
}
public Map getProductRelations() {
return productRelations;
}
public Set getProductNames() {
return productRelations.keySet();
}
public MsrcSupersedeNodeRelations getProductRelationsByProduct(String product) {
return productRelations.get(product);
}
public boolean containsVulnerability(String vulnerability) {
return productRelations.values().stream().anyMatch(p -> p.getAffectsVulnerabilities().contains(vulnerability));
}
public boolean containsVulnerability(String vulnerability, String product) {
return productRelations.containsKey(product) && productRelations.get(product).getAffectsVulnerabilities().contains(vulnerability);
}
public boolean containsSupersededKbId(String kbId) {
return productRelations.values().stream().anyMatch(p -> p.getSupersedes().stream().anyMatch(s -> s.getKbId().equals(kbId)));
}
public boolean containsSupersededKbId(String kbId, String product) {
return productRelations.containsKey(product) && productRelations.get(product).getSupersedes().stream().anyMatch(s -> s.getKbId().equals(kbId));
}
public boolean containsSupersededByKbId(String kbId) {
return productRelations.values().stream().anyMatch(p -> p.getSupersededBy().stream().anyMatch(s -> s.getKbId().equals(kbId)));
}
public boolean containsSupersededByKbId(String kbId, String product) {
return productRelations.containsKey(product) && productRelations.get(product).getSupersededBy().stream().anyMatch(s -> s.getKbId().equals(kbId));
}
@Override
public String toString() {
return kbId;
}
public JSONObject toJson() {
return new JSONObject()
.put("kbId", kbId)
.put("articleUrl", articleUrl)
.put("downloadUrl", downloadUrl)
.put("rel", productRelations.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().toJson())));
}
public Document toDocument() {
final Document doc = new Document();
doc.add(new TextField("kbId", kbId, Field.Store.YES));
if (articleUrl != null) doc.add(new TextField("articleUrl", articleUrl, Field.Store.YES));
if (downloadUrl != null) doc.add(new TextField("downloadUrl", downloadUrl, Field.Store.YES));
final JSONObject relationJson = new JSONObject(productRelations.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().toJson())));
doc.add(new TextField("rel", relationJson.toString(), Field.Store.YES));
return doc;
}
public static MsrcSupersedeNode fromJson(JSONObject json, Map nodes) {
final MsrcSupersedeNode node = nodes.computeIfAbsent(json.getString("kbId"), kb -> {
final String articleUrl = json.optString("articleUrl", null);
final String downloadUrl = json.optString("downloadUrl", null);
return new MsrcSupersedeNode(kb, articleUrl, downloadUrl);
});
final JSONObject productRelationsJson = json.getJSONObject("rel");
for (String product : productRelationsJson.keySet()) {
final MsrcSupersedeNodeRelations parsed = MsrcSupersedeNodeRelations.fromJson(productRelationsJson.getJSONObject(product), nodes);
node.productRelations.put(product, parsed);
}
return node;
}
public static MsrcSupersedeNode fromDocument(Document document, Map nodes) {
final MsrcSupersedeNode node;
synchronized (nodes) { // see MsrcKbChainIndexQuery#findNodeByKbId
node = nodes.computeIfAbsent(document.get("kbId"), kb -> {
final String articleUrl = document.get("articleUrl");
final String downloadUrl = document.get("downloadUrl");
return new MsrcSupersedeNode(kb, articleUrl, downloadUrl);
});
}
final JSONObject productRelationsJson = new JSONObject(document.get("rel"));
for (String product : productRelationsJson.keySet()) {
final MsrcSupersedeNodeRelations parsed = MsrcSupersedeNodeRelations.fromJson(productRelationsJson.getJSONObject(product), nodes);
node.productRelations.put(product, parsed);
}
return node;
}
public static Map mergeNodes(Collection> nodeArrays) {
final Map mergedNodes = new HashMap<>();
for (Collection nodes : nodeArrays) {
nodes.forEach(node -> mergedNodes.computeIfAbsent(node.getKbId(), cloneNodeWithBaseProperties(node)));
}
for (Collection nodes : nodeArrays) {
MsrcSupersedeNode.mergeNodesDeepCopyAllNodes(mergedNodes, nodes);
}
return mergedNodes;
}
private static Function cloneNodeWithBaseProperties(MsrcSupersedeNode node) {
return kb -> {
final String articleUrl = node.getArticleUrl();
final String downloadUrl = node.getDownloadUrl();
return new MsrcSupersedeNode(kb, articleUrl, downloadUrl);
};
}
private static void mergeNodesDeepCopyAllNodes(Map mergedNodes, Collection nodes) {
for (MsrcSupersedeNode referenceNode : nodes) {
final MsrcSupersedeNode node = mergedNodes.get(referenceNode.getKbId());
for (String productName : referenceNode.getProductNames()) {
final MsrcSupersedeNodeRelations relation = referenceNode.getProductRelationsByProduct(productName);
for (String vulnerability : relation.getAffectsVulnerabilities()) {
node.addAffectsVulnerability(productName, vulnerability);
}
for (MsrcSupersedeNode supersededByNode : relation.getSupersededBy()) {
final MsrcSupersedeNode otherNode = mergedNodes.computeIfAbsent(supersededByNode.getKbId(), cloneNodeWithBaseProperties(supersededByNode));
node.addSupersededBy(productName, otherNode);
otherNode.addSupersedes(productName, node);
}
for (MsrcSupersedeNode supersededNode : relation.getSupersedes()) {
final MsrcSupersedeNode otherNode = mergedNodes.computeIfAbsent(supersededNode.getKbId(), cloneNodeWithBaseProperties(supersededNode));
node.addSupersedes(productName, otherNode);
otherNode.addSupersededBy(productName, node);
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy